diff --git a/demo/Readme.md b/demo/Readme.md new file mode 100644 index 0000000..0bf82b5 --- /dev/null +++ b/demo/Readme.md @@ -0,0 +1,26 @@ +# Demo deployment of Azure infrastrucure for ChatUiT + +This template make it easy for you to deploy an environment to run ChatUiT in your own Azure tennant. It creates an Azure Cosmos DB account and Azure Web App, then automatically deploys the ChatUiT web app hosted on GitHub and injects the Cosmos DB endpoint and auth key into the Web App's Application Settings allowing it to connect automatically upon first run. + +This sample is useful for a demo deployment of ChatUiT and have the web app automatically connect to Cosmos DB in a single operation without having to manually add connection information to Application Settings in the portal. + +## Prerequisites + +1. An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?ref=microsoft.com&utm_source=microsoft.com&utm_medium=docs&utm_campaign=visualstudio) +2. Open AI endpoint with enabled models. [Create and deploy an Azure OpenAI Service resource](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/create-resource?pivots=web-portal) +3. Entra ID app registration to use for login. [Register an application with the Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app?tabs=certificate) + +## Deployment + +Below are the parameters which can be user configured in the parameters file including: + +| Parameter | Description | +|-------------------|--------------------------------------------| +| `azureAdClientId` | The Client ID of the App registration | +| `endpoints` | The URL for the OpenAI endpoint | +| `models` | List of the models available | +| `deployment1` | Key for the deployment to use | + +[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FUiT-ITA%2FChatUiT2%2Fmaster%2Fdemo%2Fazuredeploy.json) + +[![Visualize](https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/1-CONTRIBUTION-GUIDE/images/visualizebutton.svg?sanitize=true)](http://armviz.io/#/?load=https%3A%2F%2Fraw.githubusercontent.com%2FUiT-ITA%2FChatUiT2%2Fmaster%2Fdemo%2Fazuredeploy.json) \ No newline at end of file diff --git a/demo/azuredeploy.json b/demo/azuredeploy.json new file mode 100644 index 0000000..5d0adb4 --- /dev/null +++ b/demo/azuredeploy.json @@ -0,0 +1,12719 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "10313002348063971883" + } + }, + "parameters": { + "azureAdClientId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The Entra ID client ID for the application." + } + }, + "endpoints": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The endpoints for the deployment." + } + }, + "models": { + "type": "string", + "defaultValue": "[[{\"Name\":\"GPT-4o\",\"Description\":\"Best model\",\"DeploymentName\":\"gpt-4o\",\"MaxContext\":128000,\"MaxTokens\":4096,\"DeploymentType\":\"AzureOpenAI\",\"Deployment\":\"Deployment1\"},{\"Name\":\"GPT-4o-Mini\",\"Description\":\"Good and fast\",\"DeploymentName\":\"gpt-4o-mini\",\"MaxContext\":128000,\"MaxTokens\":16000,\"DeploymentType\":\"AzureOpenAI\",\"Deployment\":\"Deployment1\"}]", + "metadata": { + "description": "The models available for the deployment." + } + }, + "deployment1": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "The key for the deployment to use." + } + }, + "chatUitGitUrl": { + "type": "string", + "defaultValue": "https://github.com/UiT-ITA/ChatUiT2", + "metadata": { + "description": "The URL for the GitHub repository that contains the project to deploy." + } + }, + "chatUitGitBranch": { + "type": "string", + "defaultValue": "master", + "metadata": { + "description": "The branch of the GitHub repository to use." + } + } + }, + "variables": { + "location": "[resourceGroup().location]", + "resourceGroupName": "[toLower(resourceGroup().name)]", + "uniquePrefix": "[toLower(substring(uniqueString(resourceGroup().id), 0, 6))]" + }, + "resources": [ + { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2024-04-01", + "name": "[format('{0}/{1}', format('{0}{1}-webapp', variables('resourceGroupName'), variables('uniquePrefix')), 'connectionstrings')]", + "properties": { + "MongoDB": { + "type": "Custom", + "value": "[format('@Microsoft.KeyVault(SecretUri={0})', reference(resourceId('Microsoft.Resources/deployments', 'cosmosModule'), '2022-09-01').outputs.exportedSecrets.value.primaryWriteConnectionString.secretUri)]" + }, + "KeyVault": { + "type": "Custom", + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'keyVaultModule'), '2022-09-01').outputs.uri.value]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', 'cosmosModule')]", + "[resourceId('Microsoft.Resources/deployments', 'keyVaultModule')]", + "[resourceId('Microsoft.Resources/deployments', 'webAppModule')]" + ] + }, + { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2024-04-01", + "name": "[format('{0}/{1}', format('{0}{1}-webapp', variables('resourceGroupName'), variables('uniquePrefix')), 'appsettings')]", + "properties": { + "AzureAd__ClientId": "[parameters('azureAdClientId')]", + "Endpoints": "[parameters('endpoints')]", + "Models": "[parameters('models')]", + "Deployment1": "[format('@Microsoft.KeyVault(SecretUri={0}secrets/deployment1)', reference(resourceId('Microsoft.Resources/deployments', 'keyVaultModule'), '2022-09-01').outputs.uri.value)]" + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', 'keyVaultModule')]", + "[resourceId('Microsoft.Resources/deployments', 'webAppModule')]" + ] + }, + { + "type": "Microsoft.Web/sites/sourcecontrols", + "apiVersion": "2024-04-01", + "name": "[format('{0}/{1}', format('{0}{1}-webapp', variables('resourceGroupName'), variables('uniquePrefix')), 'web')]", + "properties": { + "repoUrl": "[parameters('chatUitGitUrl')]", + "branch": "[parameters('chatUitGitBranch')]", + "isManualIntegration": true + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', 'webAppModule')]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "appServicePlanModule", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}{1}-asp', variables('resourceGroupName'), variables('uniquePrefix'))]" + }, + "reserved": { + "value": true + }, + "skuName": { + "value": "S1" + }, + "location": { + "value": "[variables('location')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "16804783505428777103" + }, + "name": "App Service Plan", + "description": "This module deploys an App Service Plan.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 60, + "metadata": { + "description": "Required. Name of the app service plan." + } + }, + "skuName": { + "type": "string", + "defaultValue": "P1v3", + "metadata": { + "example": " 'F1'\n 'B1'\n 'P1v3'\n 'I1v2'\n 'FC1'\n ", + "description": "Optional. The name of the SKU will Determine the tier, size, family of the App Service Plan. This defaults to P1v3 to leverage availability zones." + } + }, + "skuCapacity": { + "type": "int", + "defaultValue": 3, + "metadata": { + "description": "Optional. Number of workers associated with the App Service Plan. This defaults to 3, to leverage availability zones." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "kind": { + "type": "string", + "defaultValue": "App", + "allowedValues": [ + "App", + "Elastic", + "FunctionApp", + "Windows", + "Linux" + ], + "metadata": { + "description": "Optional. Kind of server OS." + } + }, + "reserved": { + "type": "bool", + "defaultValue": "[equals(parameters('kind'), 'Linux')]", + "metadata": { + "description": "Conditional. Defaults to false when creating Windows/app App Service Plan. Required if creating a Linux App Service Plan and must be set to true." + } + }, + "appServiceEnvironmentId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The Resource ID of the App Service Environment to use for the App Service Plan." + } + }, + "workerTierName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Target worker tier assigned to the App Service plan." + } + }, + "perSiteScaling": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If true, apps assigned to this App Service plan can be scaled independently. If false, apps assigned to this App Service plan will scale to all instances of the plan." + } + }, + "elasticScaleEnabled": { + "type": "bool", + "defaultValue": "[greater(parameters('maximumElasticWorkerCount'), 1)]", + "metadata": { + "description": "Optional. Enable/Disable ElasticScaleEnabled App Service Plan." + } + }, + "maximumElasticWorkerCount": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "Optional. Maximum number of total workers allowed for this ElasticScaleEnabled App Service Plan." + } + }, + "targetWorkerCount": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. Scaling worker count." + } + }, + "targetWorkerSize": { + "type": "int", + "defaultValue": 0, + "allowedValues": [ + 0, + 1, + 2 + ], + "metadata": { + "description": "Optional. The instance size of the hosting plan (small, medium, or large)." + } + }, + "zoneRedundant": { + "type": "bool", + "defaultValue": "[if(or(startsWith(parameters('skuName'), 'P'), startsWith(parameters('skuName'), 'EP')), true(), false())]", + "metadata": { + "description": "Optional. Zone Redundant server farms can only be used on Premium or ElasticPremium SKU tiers within ZRS Supported regions (https://learn.microsoft.com/en-us/azure/storage/common/redundancy-regions-zrs)." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.web-serverfarm.{0}.{1}', replace('0.3.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "appServicePlan": { + "type": "Microsoft.Web/serverfarms", + "apiVersion": "2022-09-01", + "name": "[parameters('name')]", + "kind": "[parameters('kind')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "capacity": "[if(equals(parameters('skuName'), 'FC1'), null(), parameters('skuCapacity'))]", + "tier": "[if(equals(parameters('skuName'), 'FC1'), 'FlexConsumption', null())]" + }, + "properties": { + "workerTierName": "[parameters('workerTierName')]", + "hostingEnvironmentProfile": "[if(not(empty(parameters('appServiceEnvironmentId'))), createObject('id', parameters('appServiceEnvironmentId')), null())]", + "perSiteScaling": "[parameters('perSiteScaling')]", + "maximumElasticWorkerCount": "[parameters('maximumElasticWorkerCount')]", + "elasticScaleEnabled": "[parameters('elasticScaleEnabled')]", + "reserved": "[parameters('reserved')]", + "targetWorkerCount": "[parameters('targetWorkerCount')]", + "targetWorkerSizeId": "[parameters('targetWorkerSize')]", + "zoneRedundant": "[parameters('zoneRedundant')]" + } + }, + "appServicePlan_diagnosticSettings": { + "copy": { + "name": "appServicePlan_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Web/serverfarms/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "metrics", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics'))))]", + "input": { + "category": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')].category]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')], 'enabled'), true())]", + "timeGrain": null + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "appServicePlan" + ] + }, + "appServicePlan_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Web/serverfarms/{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": [ + "appServicePlan" + ] + }, + "appServicePlan_roleAssignments": { + "copy": { + "name": "appServicePlan_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Web/serverfarms/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Web/serverfarms', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "appServicePlan" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the app service plan was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the app service plan." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the app service plan." + }, + "value": "[resourceId('Microsoft.Web/serverfarms', parameters('name'))]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('appServicePlan', '2022-09-01', 'full').location]" + } + } + } + } + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "webAppModule", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}{1}-webapp', variables('resourceGroupName'), variables('uniquePrefix'))]" + }, + "location": { + "value": "[variables('location')]" + }, + "kind": { + "value": "app,linux" + }, + "serverFarmResourceId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', 'appServicePlanModule'), '2022-09-01').outputs.resourceId.value]" + }, + "managedIdentities": { + "value": { + "systemAssigned": true + } + }, + "siteConfig": { + "value": { + "linuxFxVersion": "DOTNETCORE|8.0" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "1919125099206523269" + }, + "name": "Web/Function Apps", + "description": "This module deploys a Web or Function App.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the site." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "functionapp", + "functionapp,linux", + "functionapp,workflowapp", + "functionapp,workflowapp,linux", + "functionapp,linux,container", + "functionapp,linux,container,azurecontainerapps", + "app,linux", + "app", + "linux,api", + "api", + "app,linux,container", + "app,container,windows" + ], + "metadata": { + "description": "Required. Type of site to deploy." + } + }, + "serverFarmResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the app service plan to use for the site." + } + }, + "managedEnvironmentId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Azure Resource Manager ID of the customers selected Managed Environment on which to host this app." + } + }, + "httpsOnly": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Configures a site to accept only HTTPS requests. Issues redirect for HTTP requests." + } + }, + "clientAffinityEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. If client affinity is enabled." + } + }, + "appServiceEnvironmentResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the app service environment to use for this resource." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "keyVaultAccessIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the assigned identity to be used to access a key vault with." + } + }, + "storageAccountRequired": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Checks if Customer provided storage account is required." + } + }, + "virtualNetworkSubnetId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Azure Resource Manager ID of the Virtual network and subnet to be joined by Regional VNET Integration. This must be of the form /subscriptions/{subscriptionName}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{vnetName}/subnets/{subnetName}." + } + }, + "vnetContentShareEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. To enable accessing content over virtual network." + } + }, + "vnetImagePullEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. To enable pulling image over Virtual Network." + } + }, + "vnetRouteAllEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Virtual Network Route All enabled. This causes all outbound traffic to have Virtual Network Security Groups and User Defined Routes applied." + } + }, + "scmSiteAlsoStopped": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Stop SCM (KUDU) site when the app is stopped." + } + }, + "siteConfig": { + "type": "object", + "defaultValue": { + "alwaysOn": true, + "minTlsVersion": "1.2", + "ftpsState": "FtpsOnly" + }, + "metadata": { + "description": "Optional. The site config object. The defaults are set to the following values: alwaysOn: true, minTlsVersion: '1.2', ftpsState: 'FtpsOnly'." + } + }, + "functionAppConfig": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The Function App configuration object." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions." + } + }, + "storageAccountUseIdentityAuthentication": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If the provided storage account requires Identity based authentication ('allowSharedKeyAccess' is set to false). When set to true, the minimum role assignment required for the App Service Managed Identity to the storage account is 'Storage Blob Data Owner'." + } + }, + "apiManagementConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The web settings api management configuration." + } + }, + "msDeployConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The extension MSDeployment configuration." + } + }, + "appInsightResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the app insight to leverage for this resource." + } + }, + "appSettingsKeyValuePairs": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The app settings-value pairs except for AzureWebJobsStorage, AzureWebJobsDashboard, APPINSIGHTS_INSTRUMENTATIONKEY and APPLICATIONINSIGHTS_CONNECTION_STRING." + } + }, + "authSettingV2Configuration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The auth settings V2 configuration." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "logsConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The logs settings configuration." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "slots": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Configuration for deployment slots for an app." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "clientCertEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. To enable client certificate authentication (TLS mutual authentication)." + } + }, + "clientCertExclusionPaths": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Client certificate authentication comma-separated exclusion paths." + } + }, + "clientCertMode": { + "type": "string", + "defaultValue": "Optional", + "allowedValues": [ + "Optional", + "OptionalInteractiveUser", + "Required" + ], + "metadata": { + "description": "Optional. This composes with ClientCertEnabled setting.\n- ClientCertEnabled=false means ClientCert is ignored.\n- ClientCertEnabled=true and ClientCertMode=Required means ClientCert is required.\n- ClientCertEnabled=true and ClientCertMode=Optional means ClientCert is optional or accepted.\n" + } + }, + "cloningInfo": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. If specified during app creation, the app is cloned from a source app." + } + }, + "containerSize": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Size of the function container." + } + }, + "dailyMemoryTimeQuota": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Maximum allowed daily memory-time quota (applicable on dynamic apps only)." + } + }, + "enabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Setting this value to false disables the app (takes the app offline)." + } + }, + "hostNameSslStates": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Hostname SSL states are used to manage the SSL bindings for app's hostnames." + } + }, + "hyperV": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Hyper-V sandbox." + } + }, + "redundancyMode": { + "type": "string", + "defaultValue": "None", + "allowedValues": [ + "ActiveActive", + "Failover", + "GeoRedundant", + "Manual", + "None" + ], + "metadata": { + "description": "Optional. Site redundancy mode." + } + }, + "basicPublishingCredentialsPolicies": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The site publishing credential policy names which are associated with the sites." + } + }, + "hybridConnectionRelays": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Names of hybrid connection relays to connect app with." + } + }, + "publicNetworkAccess": { + "type": "string", + "nullable": true, + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned, UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', 'None')), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "App Compliance Automation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f37683f-2463-46b6-9ce7-9b788b988ba2')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.web-site.{0}.{1}', replace('0.11.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" + } + } + } + } + }, + "app": { + "type": "Microsoft.Web/sites", + "apiVersion": "2023-12-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "kind": "[parameters('kind')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "properties": { + "managedEnvironmentId": "[if(not(empty(parameters('managedEnvironmentId'))), parameters('managedEnvironmentId'), null())]", + "serverFarmId": "[parameters('serverFarmResourceId')]", + "clientAffinityEnabled": "[parameters('clientAffinityEnabled')]", + "httpsOnly": "[parameters('httpsOnly')]", + "hostingEnvironmentProfile": "[if(not(empty(parameters('appServiceEnvironmentResourceId'))), createObject('id', parameters('appServiceEnvironmentResourceId')), null())]", + "storageAccountRequired": "[parameters('storageAccountRequired')]", + "keyVaultReferenceIdentity": "[parameters('keyVaultAccessIdentityResourceId')]", + "virtualNetworkSubnetId": "[parameters('virtualNetworkSubnetId')]", + "siteConfig": "[parameters('siteConfig')]", + "functionAppConfig": "[parameters('functionAppConfig')]", + "clientCertEnabled": "[parameters('clientCertEnabled')]", + "clientCertExclusionPaths": "[parameters('clientCertExclusionPaths')]", + "clientCertMode": "[parameters('clientCertMode')]", + "cloningInfo": "[parameters('cloningInfo')]", + "containerSize": "[parameters('containerSize')]", + "dailyMemoryTimeQuota": "[parameters('dailyMemoryTimeQuota')]", + "enabled": "[parameters('enabled')]", + "hostNameSslStates": "[parameters('hostNameSslStates')]", + "hyperV": "[parameters('hyperV')]", + "redundancyMode": "[parameters('redundancyMode')]", + "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), parameters('publicNetworkAccess'), if(not(empty(parameters('privateEndpoints'))), 'Disabled', 'Enabled'))]", + "vnetContentShareEnabled": "[parameters('vnetContentShareEnabled')]", + "vnetImagePullEnabled": "[parameters('vnetImagePullEnabled')]", + "vnetRouteAllEnabled": "[parameters('vnetRouteAllEnabled')]", + "scmSiteAlsoStopped": "[parameters('scmSiteAlsoStopped')]" + } + }, + "app_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Web/sites/{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": [ + "app" + ] + }, + "app_diagnosticSettings": { + "copy": { + "name": "app_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Web/sites/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "metrics", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics'))))]", + "input": { + "category": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')].category]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')], 'enabled'), true())]", + "timeGrain": null + } + }, + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "app" + ] + }, + "app_roleAssignments": { + "copy": { + "name": "app_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Web/sites/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Web/sites', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "app" + ] + }, + "app_appsettings": { + "condition": "[or(or(not(empty(parameters('appSettingsKeyValuePairs'))), not(empty(parameters('appInsightResourceId')))), not(empty(parameters('storageAccountResourceId'))))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Site-Config-AppSettings', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "appName": { + "value": "[parameters('name')]" + }, + "kind": { + "value": "[parameters('kind')]" + }, + "storageAccountResourceId": { + "value": "[parameters('storageAccountResourceId')]" + }, + "storageAccountUseIdentityAuthentication": { + "value": "[parameters('storageAccountUseIdentityAuthentication')]" + }, + "appInsightResourceId": { + "value": "[parameters('appInsightResourceId')]" + }, + "appSettingsKeyValuePairs": { + "value": "[parameters('appSettingsKeyValuePairs')]" + }, + "currentAppSettings": "[if(not(empty(resourceId('Microsoft.Web/sites', parameters('name')))), createObject('value', list(format('{0}/config/appsettings', resourceId('Microsoft.Web/sites', parameters('name'))), '2023-12-01').properties), createObject('value', createObject()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "10845600494881775271" + }, + "name": "Site App Settings", + "description": "This module deploys a Site App Setting.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "appName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent site resource. Required if the template is used in a standalone deployment." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "functionapp", + "functionapp,linux", + "functionapp,workflowapp", + "functionapp,workflowapp,linux", + "functionapp,linux,container", + "functionapp,linux,container,azurecontainerapps", + "app,linux", + "app", + "linux,api", + "api", + "app,linux,container", + "app,container,windows" + ], + "metadata": { + "description": "Required. Type of site to deploy." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions." + } + }, + "storageAccountUseIdentityAuthentication": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If the provided storage account requires Identity based authentication ('allowSharedKeyAccess' is set to false). When set to true, the minimum role assignment required for the App Service Managed Identity to the storage account is 'Storage Blob Data Owner'." + } + }, + "appInsightResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the app insight to leverage for this resource." + } + }, + "appSettingsKeyValuePairs": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The app settings key-value pairs except for AzureWebJobsStorage, AzureWebJobsDashboard, APPINSIGHTS_INSTRUMENTATIONKEY and APPLICATIONINSIGHTS_CONNECTION_STRING." + } + }, + "currentAppSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The current app settings." + } + } + }, + "resources": { + "app": { + "existing": true, + "type": "Microsoft.Web/sites", + "apiVersion": "2023-12-01", + "name": "[parameters('appName')]" + }, + "appInsight": { + "condition": "[not(empty(parameters('appInsightResourceId')))]", + "existing": true, + "type": "Microsoft.Insights/components", + "apiVersion": "2020-02-02", + "subscriptionId": "[split(coalesce(parameters('appInsightResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(parameters('appInsightResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(parameters('appInsightResourceId'), 'dummyName'), '/'))]" + }, + "storageAccount": { + "condition": "[not(empty(parameters('storageAccountResourceId')))]", + "existing": true, + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2023-05-01", + "subscriptionId": "[split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))]" + }, + "appSettings": { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}', parameters('appName'), 'appsettings')]", + "kind": "[parameters('kind')]", + "properties": "[union(coalesce(parameters('currentAppSettings'), createObject()), coalesce(parameters('appSettingsKeyValuePairs'), createObject()), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/')), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), '2023-05-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), union(createObject('AzureWebJobsStorage__accountName', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), createObject('AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob)), createObject())), if(not(empty(parameters('appInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('appInsight').ConnectionString), createObject()))]", + "dependsOn": [ + "app", + "appInsight", + "storageAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the site config." + }, + "value": "appsettings" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the site config." + }, + "value": "[resourceId('Microsoft.Web/sites/config', parameters('appName'), 'appsettings')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the site config was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app" + ] + }, + "app_authsettingsv2": { + "condition": "[not(empty(parameters('authSettingV2Configuration')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Site-Config-AuthSettingsV2', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "appName": { + "value": "[parameters('name')]" + }, + "kind": { + "value": "[parameters('kind')]" + }, + "authSettingV2Configuration": { + "value": "[coalesce(parameters('authSettingV2Configuration'), createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "7782125422759995841" + }, + "name": "Site Auth Settings V2 Config", + "description": "This module deploys a Site Auth Settings V2 Configuration.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "appName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent site resource. Required if the template is used in a standalone deployment." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "functionapp", + "functionapp,linux", + "functionapp,workflowapp", + "functionapp,workflowapp,linux", + "functionapp,linux,container", + "functionapp,linux,container,azurecontainerapps", + "app,linux", + "app", + "linux,api", + "api", + "app,linux,container", + "app,container,windows" + ], + "metadata": { + "description": "Required. Type of site to deploy." + } + }, + "authSettingV2Configuration": { + "type": "object", + "metadata": { + "description": "Required. The auth settings V2 configuration." + } + } + }, + "resources": [ + { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}', parameters('appName'), 'authsettingsV2')]", + "kind": "[parameters('kind')]", + "properties": "[parameters('authSettingV2Configuration')]" + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the site config." + }, + "value": "authsettingsV2" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the site config." + }, + "value": "[resourceId('Microsoft.Web/sites/config', parameters('appName'), 'authsettingsV2')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the site config was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app" + ] + }, + "app_logssettings": { + "condition": "[not(empty(coalesce(parameters('logsConfiguration'), createObject())))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Site-Config-Logs', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "appName": { + "value": "[parameters('name')]" + }, + "logsConfiguration": { + "value": "[parameters('logsConfiguration')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "2527104715221107836" + }, + "name": "Site logs Config", + "description": "This module deploys a Site logs Configuration.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "appName": { + "type": "string", + "metadata": { + "description": "Required. The name of the parent site resource." + } + }, + "logsConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The logs settings configuration." + } + } + }, + "resources": { + "app": { + "existing": true, + "type": "Microsoft.Web/sites", + "apiVersion": "2023-12-01", + "name": "[parameters('appName')]" + }, + "webSettings": { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}', parameters('appName'), 'logs')]", + "kind": "string", + "properties": "[parameters('logsConfiguration')]", + "dependsOn": [ + "app" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the site config." + }, + "value": "logs" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the site config." + }, + "value": "[resourceId('Microsoft.Web/sites/config', parameters('appName'), 'logs')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the site config was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app", + "app_appsettings" + ] + }, + "app_websettings": { + "condition": "[not(empty(coalesce(parameters('apiManagementConfiguration'), createObject())))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Site-Config-Web', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "appName": { + "value": "[parameters('name')]" + }, + "apiManagementConfiguration": { + "value": "[parameters('apiManagementConfiguration')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "18186736059685095806" + }, + "name": "Site Api Management Config", + "description": "This module deploys a Site Api Management Configuration.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "appName": { + "type": "string", + "metadata": { + "description": "Required. The name of the parent site resource." + } + }, + "apiManagementConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The web settings api management configuration." + } + } + }, + "resources": { + "app": { + "existing": true, + "type": "Microsoft.Web/sites", + "apiVersion": "2023-12-01", + "name": "[parameters('appName')]" + }, + "webSettings": { + "type": "Microsoft.Web/sites/config", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}', parameters('appName'), 'web')]", + "kind": "string", + "properties": "[parameters('apiManagementConfiguration')]", + "dependsOn": [ + "app" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the site config." + }, + "value": "web" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the site config." + }, + "value": "[resourceId('Microsoft.Web/sites/config', parameters('appName'), 'web')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the site config was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app" + ] + }, + "extension_msdeploy": { + "condition": "[not(empty(parameters('msDeployConfiguration')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Site-Extension-MSDeploy', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "appName": { + "value": "[parameters('name')]" + }, + "msDeployConfiguration": { + "value": "[coalesce(parameters('msDeployConfiguration'), createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "10249716032875912201" + }, + "name": "Site Deployment Extension ", + "description": "This module deploys a Site extension for MSDeploy.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "appName": { + "type": "string", + "metadata": { + "description": "Required. The name of the parent site resource." + } + }, + "msDeployConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Sets the MSDeployment Properties." + } + } + }, + "resources": { + "app": { + "existing": true, + "type": "Microsoft.Web/sites", + "apiVersion": "2023-12-01", + "name": "[parameters('appName')]" + }, + "msdeploy": { + "type": "Microsoft.Web/sites/extensions", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}', parameters('appName'), 'MSDeploy')]", + "kind": "MSDeploy", + "properties": "[parameters('msDeployConfiguration')]", + "dependsOn": [ + "app" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the MSDeploy Package." + }, + "value": "MSDeploy" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Site Extension." + }, + "value": "[resourceId('Microsoft.Web/sites/extensions', parameters('appName'), 'MSDeploy')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the site config was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app" + ] + }, + "app_slots": { + "copy": { + "name": "app_slots", + "count": "[length(coalesce(parameters('slots'), createArray()))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Slot-{1}', uniqueString(deployment().name, parameters('location')), coalesce(parameters('slots'), createArray())[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('slots'), createArray())[copyIndex()].name]" + }, + "appName": { + "value": "[parameters('name')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "kind": { + "value": "[parameters('kind')]" + }, + "serverFarmResourceId": { + "value": "[parameters('serverFarmResourceId')]" + }, + "httpsOnly": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'httpsOnly'), parameters('httpsOnly'))]" + }, + "appServiceEnvironmentResourceId": { + "value": "[parameters('appServiceEnvironmentResourceId')]" + }, + "clientAffinityEnabled": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'clientAffinityEnabled'), parameters('clientAffinityEnabled'))]" + }, + "managedIdentities": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'managedIdentities'), parameters('managedIdentities'))]" + }, + "keyVaultAccessIdentityResourceId": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'keyVaultAccessIdentityResourceId'), parameters('keyVaultAccessIdentityResourceId'))]" + }, + "storageAccountRequired": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'storageAccountRequired'), parameters('storageAccountRequired'))]" + }, + "virtualNetworkSubnetId": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'virtualNetworkSubnetId'), parameters('virtualNetworkSubnetId'))]" + }, + "siteConfig": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'siteConfig'), parameters('siteConfig'))]" + }, + "functionAppConfig": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'functionAppConfig'), parameters('functionAppConfig'))]" + }, + "storageAccountResourceId": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'storageAccountResourceId'), parameters('storageAccountResourceId'))]" + }, + "storageAccountUseIdentityAuthentication": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'storageAccountUseIdentityAuthentication'), parameters('storageAccountUseIdentityAuthentication'))]" + }, + "appInsightResourceId": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'appInsightResourceId'), parameters('appInsightResourceId'))]" + }, + "authSettingV2Configuration": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'authSettingV2Configuration'), parameters('authSettingV2Configuration'))]" + }, + "msDeployConfiguration": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'msDeployConfiguration'), parameters('msDeployConfiguration'))]" + }, + "diagnosticSettings": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'diagnosticSettings')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "appSettingsKeyValuePairs": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'appSettingsKeyValuePairs'), parameters('appSettingsKeyValuePairs'))]" + }, + "basicPublishingCredentialsPolicies": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'basicPublishingCredentialsPolicies'), parameters('basicPublishingCredentialsPolicies'))]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateEndpoints": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'privateEndpoints'), createArray())]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "clientCertEnabled": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'clientCertEnabled')]" + }, + "clientCertExclusionPaths": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'clientCertExclusionPaths')]" + }, + "clientCertMode": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'clientCertMode')]" + }, + "cloningInfo": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'cloningInfo')]" + }, + "containerSize": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'containerSize')]" + }, + "customDomainVerificationId": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'customDomainVerificationId')]" + }, + "dailyMemoryTimeQuota": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'dailyMemoryTimeQuota')]" + }, + "enabled": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'enabled')]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + }, + "hostNameSslStates": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'hostNameSslStates')]" + }, + "hyperV": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'hyperV')]" + }, + "publicNetworkAccess": { + "value": "[coalesce(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'publicNetworkAccess'), if(or(not(empty(tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'privateEndpoints'))), not(empty(parameters('privateEndpoints')))), 'Disabled', 'Enabled'))]" + }, + "redundancyMode": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'redundancyMode')]" + }, + "vnetContentShareEnabled": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'vnetContentShareEnabled')]" + }, + "vnetImagePullEnabled": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'vnetImagePullEnabled')]" + }, + "vnetRouteAllEnabled": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'vnetRouteAllEnabled')]" + }, + "hybridConnectionRelays": { + "value": "[tryGet(coalesce(parameters('slots'), createArray())[copyIndex()], 'hybridConnectionRelays')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "2418467213841620758" + }, + "name": "Web/Function App Deployment Slots", + "description": "This module deploys a Web or Function App Deployment Slot.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the slot." + } + }, + "appName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent site resource. Required if the template is used in a standalone deployment." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "functionapp", + "functionapp,linux", + "functionapp,workflowapp", + "functionapp,workflowapp,linux", + "functionapp,linux,container", + "functionapp,linux,container,azurecontainerapps", + "app,linux", + "app", + "linux,api", + "api", + "app,linux,container", + "app,container,windows" + ], + "metadata": { + "description": "Required. Type of site to deploy." + } + }, + "serverFarmResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the app service plan to use for the slot." + } + }, + "httpsOnly": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Configures a slot to accept only HTTPS requests. Issues redirect for HTTP requests." + } + }, + "clientAffinityEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. If client affinity is enabled." + } + }, + "appServiceEnvironmentResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the app service environment to use for this resource." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "keyVaultAccessIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the assigned identity to be used to access a key vault with." + } + }, + "storageAccountRequired": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Checks if Customer provided storage account is required." + } + }, + "virtualNetworkSubnetId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Azure Resource Manager ID of the Virtual network and subnet to be joined by Regional VNET Integration. This must be of the form /subscriptions/{subscriptionName}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/virtualNetworks/{vnetName}/subnets/{subnetName}." + } + }, + "siteConfig": { + "type": "object", + "defaultValue": { + "alwaysOn": true + }, + "metadata": { + "description": "Optional. The site config object." + } + }, + "functionAppConfig": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The Function App config object." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions." + } + }, + "storageAccountUseIdentityAuthentication": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If the provided storage account requires Identity based authentication ('allowSharedKeyAccess' is set to false). When set to true, the minimum role assignment required for the App Service Managed Identity to the storage account is 'Storage Blob Data Owner'." + } + }, + "appInsightResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the app insight to leverage for this resource." + } + }, + "appSettingsKeyValuePairs": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The app settings-value pairs except for AzureWebJobsStorage, AzureWebJobsDashboard, APPINSIGHTS_INSTRUMENTATIONKEY and APPLICATIONINSIGHTS_CONNECTION_STRING." + } + }, + "authSettingV2Configuration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The auth settings V2 configuration." + } + }, + "msDeployConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The extension MSDeployment configuration." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "clientCertEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. To enable client certificate authentication (TLS mutual authentication)." + } + }, + "clientCertExclusionPaths": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Client certificate authentication comma-separated exclusion paths." + } + }, + "clientCertMode": { + "type": "string", + "defaultValue": "Optional", + "allowedValues": [ + "Optional", + "OptionalInteractiveUser", + "Required" + ], + "metadata": { + "description": "Optional. 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": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. If specified during app creation, the app is cloned from a source app." + } + }, + "containerSize": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Size of the function container." + } + }, + "customDomainVerificationId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Unique identifier that verifies the custom domains assigned to the app. Customer will add this ID to a txt record for verification." + } + }, + "dailyMemoryTimeQuota": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Maximum allowed daily memory-time quota (applicable on dynamic apps only)." + } + }, + "enabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Setting this value to false disables the app (takes the app offline)." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "hostNameSslStates": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Hostname SSL states are used to manage the SSL bindings for app's hostnames." + } + }, + "hyperV": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Hyper-V sandbox." + } + }, + "publicNetworkAccess": { + "type": "string", + "nullable": true, + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Allow or block all public traffic." + } + }, + "redundancyMode": { + "type": "string", + "defaultValue": "None", + "allowedValues": [ + "ActiveActive", + "Failover", + "GeoRedundant", + "Manual", + "None" + ], + "metadata": { + "description": "Optional. Site redundancy mode." + } + }, + "basicPublishingCredentialsPolicies": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The site publishing credential policy names which are associated with the site slot." + } + }, + "vnetContentShareEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. To enable accessing content over virtual network." + } + }, + "vnetImagePullEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. To enable pulling image over Virtual Network." + } + }, + "vnetRouteAllEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Virtual Network Route All enabled. This causes all outbound traffic to have Virtual Network Security Groups and User Defined Routes applied." + } + }, + "hybridConnectionRelays": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Names of hybrid connection relays to connect app with." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned, UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "App Compliance Automation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f37683f-2463-46b6-9ce7-9b788b988ba2')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Web Plan Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b')]", + "Website Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'de139f84-1756-47ae-9be6-808fbbe84772')]" + } + }, + "resources": { + "app": { + "existing": true, + "type": "Microsoft.Web/sites", + "apiVersion": "2023-12-01", + "name": "[parameters('appName')]" + }, + "slot": { + "type": "Microsoft.Web/sites/slots", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}', parameters('appName'), parameters('name'))]", + "location": "[parameters('location')]", + "kind": "[parameters('kind')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "properties": { + "serverFarmId": "[parameters('serverFarmResourceId')]", + "clientAffinityEnabled": "[parameters('clientAffinityEnabled')]", + "httpsOnly": "[parameters('httpsOnly')]", + "hostingEnvironmentProfile": "[if(not(empty(parameters('appServiceEnvironmentResourceId'))), createObject('id', parameters('appServiceEnvironmentResourceId')), null())]", + "storageAccountRequired": "[parameters('storageAccountRequired')]", + "keyVaultReferenceIdentity": "[parameters('keyVaultAccessIdentityResourceId')]", + "virtualNetworkSubnetId": "[parameters('virtualNetworkSubnetId')]", + "siteConfig": "[parameters('siteConfig')]", + "functionAppConfig": "[parameters('functionAppConfig')]", + "clientCertEnabled": "[parameters('clientCertEnabled')]", + "clientCertExclusionPaths": "[parameters('clientCertExclusionPaths')]", + "clientCertMode": "[parameters('clientCertMode')]", + "cloningInfo": "[parameters('cloningInfo')]", + "containerSize": "[parameters('containerSize')]", + "customDomainVerificationId": "[parameters('customDomainVerificationId')]", + "dailyMemoryTimeQuota": "[parameters('dailyMemoryTimeQuota')]", + "enabled": "[parameters('enabled')]", + "hostNameSslStates": "[parameters('hostNameSslStates')]", + "hyperV": "[parameters('hyperV')]", + "publicNetworkAccess": "[parameters('publicNetworkAccess')]", + "redundancyMode": "[parameters('redundancyMode')]", + "vnetContentShareEnabled": "[parameters('vnetContentShareEnabled')]", + "vnetImagePullEnabled": "[parameters('vnetImagePullEnabled')]", + "vnetRouteAllEnabled": "[parameters('vnetRouteAllEnabled')]" + }, + "dependsOn": [ + "app" + ] + }, + "slot_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Web/sites/{0}/slots/{1}', parameters('appName'), 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": [ + "slot" + ] + }, + "slot_diagnosticSettings": { + "copy": { + "name": "slot_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Web/sites/{0}/slots/{1}', parameters('appName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "metrics", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics'))))]", + "input": { + "category": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')].category]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')], 'enabled'), true())]", + "timeGrain": null + } + }, + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "slot" + ] + }, + "slot_roleAssignments": { + "copy": { + "name": "slot_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Web/sites/{0}/slots/{1}', parameters('appName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Web/sites/slots', parameters('appName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "slot" + ] + }, + "slot_appsettings": { + "condition": "[not(empty(parameters('appSettingsKeyValuePairs')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Slot-{1}-Config-AppSettings', uniqueString(deployment().name, parameters('location')), parameters('name'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "slotName": { + "value": "[parameters('name')]" + }, + "appName": { + "value": "[parameters('appName')]" + }, + "kind": { + "value": "[parameters('kind')]" + }, + "storageAccountResourceId": { + "value": "[parameters('storageAccountResourceId')]" + }, + "storageAccountUseIdentityAuthentication": { + "value": "[parameters('storageAccountUseIdentityAuthentication')]" + }, + "appInsightResourceId": { + "value": "[parameters('appInsightResourceId')]" + }, + "appSettingsKeyValuePairs": { + "value": "[parameters('appSettingsKeyValuePairs')]" + }, + "currentAppSettings": "[if(not(empty(resourceId('Microsoft.Web/sites/slots', parameters('appName'), parameters('name')))), createObject('value', list(format('{0}/config/appsettings', resourceId('Microsoft.Web/sites/slots', parameters('appName'), parameters('name'))), '2023-12-01').properties), createObject('value', createObject()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "3011151783207983935" + }, + "name": "Site Slot App Settings", + "description": "This module deploys a Site Slot App Setting.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "slotName": { + "type": "string", + "metadata": { + "description": "Required. Slot name to be configured." + } + }, + "appName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent site resource. Required if the template is used in a standalone deployment." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "functionapp", + "functionapp,linux", + "functionapp,workflowapp", + "functionapp,workflowapp,linux", + "functionapp,linux,container", + "functionapp,linux,container,azurecontainerapps", + "app,linux", + "app", + "linux,api", + "api", + "app,linux,container", + "app,container,windows" + ], + "metadata": { + "description": "Required. Type of site to deploy." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Required if app of kind functionapp. Resource ID of the storage account to manage triggers and logging function executions." + } + }, + "storageAccountUseIdentityAuthentication": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If the provided storage account requires Identity based authentication ('allowSharedKeyAccess' is set to false). When set to true, the minimum role assignment required for the App Service Managed Identity to the storage account is 'Storage Blob Data Owner'." + } + }, + "appInsightResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the app insight to leverage for this resource." + } + }, + "appSettingsKeyValuePairs": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. The app settings key-value pairs except for AzureWebJobsStorage, AzureWebJobsDashboard, APPINSIGHTS_INSTRUMENTATIONKEY and APPLICATIONINSIGHTS_CONNECTION_STRING." + } + }, + "currentAppSettings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The current app settings." + } + } + }, + "resources": { + "app::slot": { + "existing": true, + "type": "Microsoft.Web/sites/slots", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}', parameters('appName'), parameters('slotName'))]", + "dependsOn": [ + "app" + ] + }, + "app": { + "existing": true, + "type": "Microsoft.Web/sites", + "apiVersion": "2023-12-01", + "name": "[parameters('appName')]" + }, + "appInsight": { + "condition": "[not(empty(parameters('appInsightResourceId')))]", + "existing": true, + "type": "Microsoft.Insights/components", + "apiVersion": "2020-02-02", + "subscriptionId": "[split(coalesce(parameters('appInsightResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(parameters('appInsightResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(parameters('appInsightResourceId'), 'dummyName'), '/'))]" + }, + "storageAccount": { + "condition": "[not(empty(parameters('storageAccountResourceId')))]", + "existing": true, + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2023-05-01", + "subscriptionId": "[split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))]" + }, + "slotSettings": { + "type": "Microsoft.Web/sites/slots/config", + "apiVersion": "2022-09-01", + "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), 'appsettings')]", + "kind": "[parameters('kind')]", + "properties": "[union(coalesce(parameters('currentAppSettings'), createObject()), coalesce(parameters('appSettingsKeyValuePairs'), createObject()), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/')), listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('storageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('storageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), '2023-05-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), union(createObject('AzureWebJobsStorage__accountName', last(split(coalesce(parameters('storageAccountResourceId'), 'dummyName'), '/'))), createObject('AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob)), createObject())), if(not(empty(parameters('appInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('appInsight').ConnectionString), createObject()))]", + "dependsOn": [ + "appInsight", + "app::slot", + "storageAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the slot config." + }, + "value": "appsettings" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the slot config." + }, + "value": "[resourceId('Microsoft.Web/sites/slots/config', parameters('appName'), parameters('slotName'), 'appsettings')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the slot config was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app", + "slot" + ] + }, + "slot_authsettingsv2": { + "condition": "[not(empty(parameters('authSettingV2Configuration')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Slot-{1}-Config-AuthSettingsV2', uniqueString(deployment().name, parameters('location')), parameters('name'))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "slotName": { + "value": "[parameters('name')]" + }, + "appName": { + "value": "[parameters('appName')]" + }, + "kind": { + "value": "[parameters('kind')]" + }, + "authSettingV2Configuration": { + "value": "[coalesce(parameters('authSettingV2Configuration'), createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "7842363652527859767" + }, + "name": "Site Slot Auth Settings V2 Config", + "description": "This module deploys a Site Auth Settings V2 Configuration.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "appName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent site resource. Required if the template is used in a standalone deployment." + } + }, + "slotName": { + "type": "string", + "metadata": { + "description": "Required. Slot name to be configured." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "functionapp", + "functionapp,linux", + "functionapp,workflowapp", + "functionapp,workflowapp,linux", + "functionapp,linux,container", + "functionapp,linux,container,azurecontainerapps", + "app,linux", + "app", + "linux,api", + "api", + "app,linux,container", + "app,container,windows" + ], + "metadata": { + "description": "Required. Type of site to deploy." + } + }, + "authSettingV2Configuration": { + "type": "object", + "metadata": { + "description": "Required. The auth settings V2 configuration." + } + } + }, + "resources": [ + { + "type": "Microsoft.Web/sites/slots/config", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), 'authsettingsV2')]", + "kind": "[parameters('kind')]", + "properties": "[parameters('authSettingV2Configuration')]" + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the slot config." + }, + "value": "authsettingsV2" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the slot config." + }, + "value": "[resourceId('Microsoft.Web/sites/slots/config', parameters('appName'), parameters('slotName'), 'authsettingsV2')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the slot config was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app", + "slot" + ] + }, + "slot_basicPublishingCredentialsPolicies": { + "copy": { + "name": "slot_basicPublishingCredentialsPolicies", + "count": "[length(coalesce(parameters('basicPublishingCredentialsPolicies'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Slot-Publish-Cred-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "appName": { + "value": "[parameters('appName')]" + }, + "slotName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('basicPublishingCredentialsPolicies'), createArray())[copyIndex()].name]" + }, + "allow": { + "value": "[tryGet(coalesce(parameters('basicPublishingCredentialsPolicies'), createArray())[copyIndex()], 'allow')]" + }, + "location": { + "value": "[parameters('location')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "1564349757337430633" + }, + "name": "Web Site Slot Basic Publishing Credentials Policies", + "description": "This module deploys a Web Site Slot Basic Publishing Credentials Policy.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "allowedValues": [ + "scm", + "ftp" + ], + "metadata": { + "description": "Required. The name of the resource." + } + }, + "allow": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Set to true to enable or false to disable a publishing method." + } + }, + "appName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent web site. Required if the template is used in a standalone deployment." + } + }, + "slotName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent web site slot. Required if the template is used in a standalone deployment." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + } + }, + "resources": [ + { + "type": "Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}/{2}', parameters('appName'), parameters('slotName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "allow": "[parameters('allow')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the basic publishing credential policy." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the basic publishing credential policy." + }, + "value": "[resourceId('Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies', parameters('appName'), parameters('slotName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the basic publishing credential policy was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference(resourceId('Microsoft.Web/sites/slots/basicPublishingCredentialsPolicies', parameters('appName'), parameters('slotName'), parameters('name')), '2023-12-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "app", + "slot" + ] + }, + "slot_hybridConnectionRelays": { + "copy": { + "name": "slot_hybridConnectionRelays", + "count": "[length(coalesce(parameters('hybridConnectionRelays'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Slot-HybridConnectionRelay-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "hybridConnectionResourceId": { + "value": "[coalesce(parameters('hybridConnectionRelays'), createArray())[copyIndex()].resourceId]" + }, + "appName": { + "value": "[parameters('appName')]" + }, + "slotName": { + "value": "[parameters('name')]" + }, + "sendKeyName": { + "value": "[tryGet(coalesce(parameters('hybridConnectionRelays'), createArray())[copyIndex()], 'sendKeyName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "12569198723769767672" + }, + "name": "Web/Function Apps Slot Hybrid Connection Relay", + "description": "This module deploys a Site Slot Hybrid Connection Namespace Relay.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "hybridConnectionResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the relay namespace hybrid connection." + } + }, + "slotName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the site slot. Required if the template is used in a standalone deployment." + } + }, + "appName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent web site. Required if the template is used in a standalone deployment." + } + }, + "sendKeyName": { + "type": "string", + "defaultValue": "defaultSender", + "metadata": { + "description": "Optional. Name of the authorization rule send key to use." + } + } + }, + "resources": [ + { + "type": "Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}/{2}/{3}', parameters('appName'), parameters('slotName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]", + "properties": { + "serviceBusNamespace": "[split(parameters('hybridConnectionResourceId'), '/')[8]]", + "serviceBusSuffix": "[split(substring(reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces', split(parameters('hybridConnectionResourceId'), '/')[8]), '2021-11-01').serviceBusEndpoint, indexOf(reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces', split(parameters('hybridConnectionResourceId'), '/')[8]), '2021-11-01').serviceBusEndpoint, '.servicebus')), ':')[0]]", + "relayName": "[split(parameters('hybridConnectionResourceId'), '/')[10]]", + "relayArmUri": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces/hybridConnections', split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]", + "hostname": "[split(json(reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces/hybridConnections', split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '2021-11-01').userMetadata)[0].value, ':')[0]]", + "port": "[int(split(json(reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces/hybridConnections', split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '2021-11-01').userMetadata)[0].value, ':')[1])]", + "sendKeyName": "[parameters('sendKeyName')]", + "sendKeyValue": "[listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces/hybridConnections/authorizationRules', split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10], parameters('sendKeyName')), '2021-11-01').primaryKey]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the hybrid connection relay.." + }, + "value": "[format('{0}/{1}/{2}/{3}', parameters('appName'), parameters('slotName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the hybrid connection relay." + }, + "value": "[resourceId('Microsoft.Web/sites/slots/hybridConnectionNamespaces/relays', split(format('{0}/{1}/{2}/{3}', parameters('appName'), parameters('slotName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '/')[0], split(format('{0}/{1}/{2}/{3}', parameters('appName'), parameters('slotName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '/')[1], split(format('{0}/{1}/{2}/{3}', parameters('appName'), parameters('slotName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '/')[2], split(format('{0}/{1}/{2}/{3}', parameters('appName'), parameters('slotName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '/')[3])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the resource was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app", + "slot" + ] + }, + "slot_extensionMSdeploy": { + "condition": "[not(empty(parameters('msDeployConfiguration')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Site-Extension-MSDeploy', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "appName": { + "value": "[parameters('appName')]" + }, + "msDeployConfiguration": { + "value": "[coalesce(parameters('msDeployConfiguration'), createObject())]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "10249716032875912201" + }, + "name": "Site Deployment Extension ", + "description": "This module deploys a Site extension for MSDeploy.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "appName": { + "type": "string", + "metadata": { + "description": "Required. The name of the parent site resource." + } + }, + "msDeployConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Sets the MSDeployment Properties." + } + } + }, + "resources": { + "app": { + "existing": true, + "type": "Microsoft.Web/sites", + "apiVersion": "2023-12-01", + "name": "[parameters('appName')]" + }, + "msdeploy": { + "type": "Microsoft.Web/sites/extensions", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}', parameters('appName'), 'MSDeploy')]", + "kind": "MSDeploy", + "properties": "[parameters('msDeployConfiguration')]", + "dependsOn": [ + "app" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the MSDeploy Package." + }, + "value": "MSDeploy" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Site Extension." + }, + "value": "[resourceId('Microsoft.Web/sites/extensions', parameters('appName'), 'MSDeploy')]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the site config was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app" + ] + }, + "slot_privateEndpoints": { + "copy": { + "name": "slot_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-slot-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'resourceGroupName'), '')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Web/sites', parameters('appName')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), format('sites-{0}', parameters('name'))), copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Web/sites', parameters('appName')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), format('sites-{0}', parameters('name'))), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Web/sites', parameters('appName')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), format('sites-{0}', parameters('name')))))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Web/sites', parameters('appName')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), format('sites-{0}', parameters('name'))), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Web/sites', parameters('appName')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), format('sites-{0}', parameters('name')))), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroup": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1277254088602407590" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "5805178546717255803" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDnsZoneConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", + "input": { + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" + } + } + } + ] + }, + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" + } + } + } + }, + "dependsOn": [ + "app", + "slot" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the slot." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the slot." + }, + "value": "[resourceId('Microsoft.Web/sites/slots', parameters('appName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the slot was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('slot', '2023-12-01', 'full'), 'identity'), 'principalId'), '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('slot', '2023-12-01', 'full').location]" + }, + "privateEndpoints": { + "type": "array", + "metadata": { + "description": "The private endpoints of the slot." + }, + "copy": { + "count": "[length(if(not(empty(parameters('privateEndpoints'))), array(parameters('privateEndpoints')), createArray()))]", + "input": { + "name": "[reference(format('slot_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('slot_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('slot_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('slot_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('slot_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + } + } + } + } + } + }, + "dependsOn": [ + "app" + ] + }, + "app_basicPublishingCredentialsPolicies": { + "copy": { + "name": "app_basicPublishingCredentialsPolicies", + "count": "[length(coalesce(parameters('basicPublishingCredentialsPolicies'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-Site-Publish-Cred-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "webAppName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('basicPublishingCredentialsPolicies'), createArray())[copyIndex()].name]" + }, + "allow": { + "value": "[tryGet(coalesce(parameters('basicPublishingCredentialsPolicies'), createArray())[copyIndex()], 'allow')]" + }, + "location": { + "value": "[parameters('location')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "15847824660831257384" + }, + "name": "Web Site Basic Publishing Credentials Policies", + "description": "This module deploys a Web Site Basic Publishing Credentials Policy.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "allowedValues": [ + "scm", + "ftp" + ], + "metadata": { + "description": "Required. The name of the resource." + } + }, + "allow": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Set to true to enable or false to disable a publishing method." + } + }, + "webAppName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent web site. Required if the template is used in a standalone deployment." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + } + }, + "resources": [ + { + "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}', parameters('webAppName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "allow": "[parameters('allow')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the basic publishing credential policy." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the basic publishing credential policy." + }, + "value": "[resourceId('Microsoft.Web/sites/basicPublishingCredentialsPolicies', parameters('webAppName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the basic publishing credential policy was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference(resourceId('Microsoft.Web/sites/basicPublishingCredentialsPolicies', parameters('webAppName'), parameters('name')), '2023-12-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "app" + ] + }, + "app_hybridConnectionRelays": { + "copy": { + "name": "app_hybridConnectionRelays", + "count": "[length(coalesce(parameters('hybridConnectionRelays'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-HybridConnectionRelay-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "hybridConnectionResourceId": { + "value": "[coalesce(parameters('hybridConnectionRelays'), createArray())[copyIndex()].resourceId]" + }, + "appName": { + "value": "[parameters('name')]" + }, + "sendKeyName": { + "value": "[tryGet(coalesce(parameters('hybridConnectionRelays'), createArray())[copyIndex()], 'sendKeyName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "9545759447796150909" + }, + "name": "Web/Function Apps Hybrid Connection Relay", + "description": "This module deploys a Site Hybrid Connection Namespace Relay.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "hybridConnectionResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the relay namespace hybrid connection." + } + }, + "appName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent web site. Required if the template is used in a standalone deployment." + } + }, + "sendKeyName": { + "type": "string", + "defaultValue": "defaultSender", + "metadata": { + "description": "Optional. Name of the authorization rule send key to use." + } + } + }, + "resources": [ + { + "type": "Microsoft.Web/sites/hybridConnectionNamespaces/relays", + "apiVersion": "2023-12-01", + "name": "[format('{0}/{1}/{2}', parameters('appName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]", + "properties": { + "serviceBusNamespace": "[split(parameters('hybridConnectionResourceId'), '/')[8]]", + "serviceBusSuffix": "[split(substring(reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces', split(parameters('hybridConnectionResourceId'), '/')[8]), '2021-11-01').serviceBusEndpoint, indexOf(reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces', split(parameters('hybridConnectionResourceId'), '/')[8]), '2021-11-01').serviceBusEndpoint, '.servicebus')), ':')[0]]", + "relayName": "[split(parameters('hybridConnectionResourceId'), '/')[10]]", + "relayArmUri": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces/hybridConnections', split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]", + "hostname": "[split(json(reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces/hybridConnections', split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '2021-11-01').userMetadata)[0].value, ':')[0]]", + "port": "[int(split(json(reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces/hybridConnections', split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '2021-11-01').userMetadata)[0].value, ':')[1])]", + "sendKeyName": "[parameters('sendKeyName')]", + "sendKeyValue": "[listKeys(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('hybridConnectionResourceId'), '/')[2], split(parameters('hybridConnectionResourceId'), '/')[4]), 'Microsoft.Relay/namespaces/hybridConnections/authorizationRules', split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10], parameters('sendKeyName')), '2021-11-01').primaryKey]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the hybrid connection relay.." + }, + "value": "[format('{0}/{1}/{2}', parameters('appName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10])]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the hybrid connection relay." + }, + "value": "[resourceId('Microsoft.Web/sites/hybridConnectionNamespaces/relays', split(format('{0}/{1}/{2}', parameters('appName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '/')[0], split(format('{0}/{1}/{2}', parameters('appName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '/')[1], split(format('{0}/{1}/{2}', parameters('appName'), split(parameters('hybridConnectionResourceId'), '/')[8], split(parameters('hybridConnectionResourceId'), '/')[10]), '/')[2])]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the resource was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "app" + ] + }, + "app_privateEndpoints": { + "copy": { + "name": "app_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-app-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'resourceGroupName'), '')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Web/sites', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'sites'), copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Web/sites', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'sites'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Web/sites', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'sites')))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.Web/sites', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'sites'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.Web/sites', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'sites')), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroup": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1277254088602407590" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "5805178546717255803" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDnsZoneConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", + "input": { + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" + } + } + } + ] + }, + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" + } + } + } + }, + "dependsOn": [ + "app" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the site." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the site." + }, + "value": "[resourceId('Microsoft.Web/sites', parameters('name'))]" + }, + "slots": { + "type": "array", + "metadata": { + "description": "The list of the slots." + }, + "copy": { + "count": "[length(coalesce(parameters('slots'), createArray()))]", + "input": "[format('{0}-Slot-{1}', uniqueString(deployment().name, parameters('location')), coalesce(parameters('slots'), createArray())[copyIndex()].name)]" + } + }, + "slotResourceIds": { + "type": "array", + "metadata": { + "description": "The list of the slot resource ids." + }, + "copy": { + "count": "[length(coalesce(parameters('slots'), createArray()))]", + "input": "[reference(format('app_slots[{0}]', copyIndex())).outputs.resourceId.value]" + } + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the site was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('app', '2023-12-01', 'full'), 'identity'), 'principalId'), '')]" + }, + "slotSystemAssignedMIPrincipalIds": { + "type": "array", + "metadata": { + "description": "The principal ID of the system assigned identity of slots." + }, + "copy": { + "count": "[length(coalesce(parameters('slots'), createArray()))]", + "input": "[reference(format('app_slots[{0}]', copyIndex())).outputs.systemAssignedMIPrincipalId.value]" + } + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('app', '2023-12-01', 'full').location]" + }, + "defaultHostname": { + "type": "string", + "metadata": { + "description": "Default hostname of the app." + }, + "value": "[reference('app').defaultHostName]" + }, + "customDomainVerificationId": { + "type": "string", + "metadata": { + "description": "Unique identifier that verifies the custom domains assigned to the app. Customer will add this ID to a txt record for verification." + }, + "value": "[reference('app').customDomainVerificationId]" + }, + "privateEndpoints": { + "type": "array", + "metadata": { + "description": "The private endpoints of the site." + }, + "copy": { + "count": "[length(if(not(empty(parameters('privateEndpoints'))), array(parameters('privateEndpoints')), createArray()))]", + "input": { + "name": "[reference(format('app_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('app_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('app_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('app_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('app_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + } + } + }, + "slotPrivateEndpoints": { + "type": "array", + "metadata": { + "description": "The private endpoints of the slots." + }, + "copy": { + "count": "[length(coalesce(parameters('slots'), createArray()))]", + "input": "[reference(format('app_slots[{0}]', copyIndex())).outputs.privateEndpoints.value]" + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', 'appServicePlanModule')]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "keyVaultModule", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}{1}-kv', variables('resourceGroupName'), variables('uniquePrefix'))]" + }, + "location": { + "value": "[variables('location')]" + }, + "sku": { + "value": "standard" + }, + "enableRbacAuthorization": { + "value": true + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Key Vault Secrets Officer", + "principalId": "[reference(resourceId('Microsoft.Resources/deployments', 'webAppModule'), '2022-09-01').outputs.systemAssignedMIPrincipalId.value]", + "principalType": "ServicePrincipal" + } + ] + }, + "secrets": { + "value": [ + { + "name": "deployment1", + "value": "[parameters('deployment1')]" + } + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "16222620938316410281" + }, + "name": "Key Vaults", + "description": "This module deploys a Key Vault.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The subresource to deploy the private endpoint for. For example \"vault\", \"mysqlServer\" or \"dataFactory\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "accessPoliciesType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tenant ID that is used for authenticating requests to the key vault." + } + }, + "objectId": { + "type": "string", + "metadata": { + "description": "Required. The object ID of a user, service principal or security group in the tenant for the vault." + } + }, + "applicationId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Application ID of the client making request on behalf of a principal." + } + }, + "permissions": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "create", + "decrypt", + "delete", + "encrypt", + "get", + "getrotationpolicy", + "import", + "list", + "purge", + "recover", + "release", + "restore", + "rotate", + "setrotationpolicy", + "sign", + "unwrapKey", + "update", + "verify", + "wrapKey" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to keys." + } + }, + "secrets": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "delete", + "get", + "list", + "purge", + "recover", + "restore", + "set" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to secrets." + } + }, + "certificates": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "create", + "delete", + "deleteissuers", + "get", + "getissuers", + "import", + "list", + "listissuers", + "managecontacts", + "manageissuers", + "purge", + "recover", + "restore", + "setissuers", + "update" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to certificates." + } + }, + "storage": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "delete", + "deletesas", + "get", + "getsas", + "list", + "listsas", + "purge", + "recover", + "regeneratekey", + "restore", + "set", + "setsas", + "update" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to storage accounts." + } + } + }, + "metadata": { + "description": "Required. Permissions the identity has for keys, secrets and certificates." + } + } + } + }, + "nullable": true + }, + "secretsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributes": { + "type": "object", + "properties": { + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Defines whether the secret is enabled or disabled." + } + }, + "exp": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Defines when the secret will become invalid. Defined in seconds since 1970-01-01T00:00:00Z." + } + }, + "nbf": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. If set, defines the date from which onwards the secret becomes valid. Defined in seconds since 1970-01-01T00:00:00Z." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Contains attributes of the secret." + } + }, + "contentType": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The content type of the secret." + } + }, + "value": { + "type": "securestring", + "metadata": { + "description": "Required. The value of the secret. NOTE: \"value\" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + } + }, + "nullable": true + }, + "keysType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the key." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributes": { + "type": "object", + "properties": { + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Defines whether the key is enabled or disabled." + } + }, + "exp": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Defines when the key will become invalid. Defined in seconds since 1970-01-01T00:00:00Z." + } + }, + "nbf": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. If set, defines the date from which onwards the key becomes valid. Defined in seconds since 1970-01-01T00:00:00Z." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Contains attributes of the key." + } + }, + "curveName": { + "type": "string", + "allowedValues": [ + "P-256", + "P-256K", + "P-384", + "P-521" + ], + "nullable": true, + "metadata": { + "description": "Optional. The elliptic curve name. Only works if \"keySize\" equals \"EC\" or \"EC-HSM\". Default is \"P-256\"." + } + }, + "keyOps": { + "type": "array", + "allowedValues": [ + "decrypt", + "encrypt", + "import", + "release", + "sign", + "unwrapKey", + "verify", + "wrapKey" + ], + "nullable": true, + "metadata": { + "description": "Optional. The allowed operations on this key." + } + }, + "keySize": { + "type": "int", + "allowedValues": [ + 2048, + 3072, + 4096 + ], + "nullable": true, + "metadata": { + "description": "Optional. The key size in bits. Only works if \"keySize\" equals \"RSA\" or \"RSA-HSM\". Default is \"4096\"." + } + }, + "kty": { + "type": "string", + "allowedValues": [ + "EC", + "EC-HSM", + "RSA", + "RSA-HSM" + ], + "nullable": true, + "metadata": { + "description": "Optional. The type of the key. Default is \"EC\"." + } + }, + "releasePolicy": { + "type": "object", + "properties": { + "contentType": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Content type and version of key release policy." + } + }, + "data": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Blob encoding the policy rules under which the key can be released." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Key release policy." + } + }, + "rotationPolicy": { + "$ref": "#/definitions/rotationPoliciesType", + "nullable": true, + "metadata": { + "description": "Optional. Key rotation policy." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + } + }, + "nullable": true + }, + "rotationPoliciesType": { + "type": "object", + "properties": { + "attributes": { + "type": "object", + "properties": { + "expiryTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The expiration time for the new key version. It should be in ISO8601 format. Eg: \"P90D\", \"P1Y\"." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The attributes of key rotation policy." + } + }, + "lifetimeActions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "action": { + "type": "object", + "properties": { + "type": { + "type": "string", + "allowedValues": [ + "Notify", + "Rotate" + ], + "nullable": true, + "metadata": { + "description": "Optional. The type of action." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The action of key rotation policy lifetimeAction." + } + }, + "trigger": { + "type": "object", + "properties": { + "timeAfterCreate": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The time duration after key creation to rotate the key. It only applies to rotate. It will be in ISO 8601 duration format. Eg: \"P90D\", \"P1Y\"." + } + }, + "timeBeforeExpiry": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The time duration before key expiring to rotate or notify. It will be in ISO 8601 duration format. Eg: \"P90D\", \"P1Y\"." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The trigger of key rotation policy lifetimeAction." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The lifetimeActions for key rotation action." + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "maxLength": 24, + "metadata": { + "description": "Required. Name of the Key Vault. Must be globally unique." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "accessPolicies": { + "$ref": "#/definitions/accessPoliciesType", + "metadata": { + "description": "Optional. All access policies to create." + } + }, + "secrets": { + "$ref": "#/definitions/secretsType", + "nullable": true, + "metadata": { + "description": "Optional. All secrets to create." + } + }, + "keys": { + "$ref": "#/definitions/keysType", + "nullable": true, + "metadata": { + "description": "Optional. All keys to create." + } + }, + "enableVaultForDeployment": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Specifies if the vault is enabled for deployment by script or compute." + } + }, + "enableVaultForTemplateDeployment": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Specifies if the vault is enabled for a template deployment." + } + }, + "enableVaultForDiskEncryption": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios." + } + }, + "enableSoftDelete": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Switch to enable/disable Key Vault's soft delete feature." + } + }, + "softDeleteRetentionInDays": { + "type": "int", + "defaultValue": 90, + "metadata": { + "description": "Optional. softDelete data retention days. It accepts >=7 and <=90." + } + }, + "enableRbacAuthorization": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored. When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. Note that management actions are always authorized with RBAC." + } + }, + "createMode": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The vault's create mode to indicate whether the vault need to be recovered or not. - recover or default." + } + }, + "enablePurgeProtection": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Provide 'true' to enable Key Vault's purge protection feature." + } + }, + "sku": { + "type": "string", + "defaultValue": "premium", + "allowedValues": [ + "premium", + "standard" + ], + "metadata": { + "description": "Optional. Specifies the SKU for the vault." + } + }, + "networkAcls": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Rules governing the accessibility of the resource from specific network locations." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and networkAcls are not set." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + }, + { + "name": "formattedAccessPolicies", + "count": "[length(coalesce(parameters('accessPolicies'), createArray()))]", + "input": { + "applicationId": "[coalesce(tryGet(coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')], 'applicationId'), '')]", + "objectId": "[coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')].objectId]", + "permissions": "[coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[coalesce(tryGet(coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')], 'tenantId'), tenant().tenantId)]" + } + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Certificates Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a4417e6f-fecd-4de8-b567-7b0420556985')]", + "Key Vault Certificate User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db79e9a7-68ee-4b58-9aeb-b90e7c24fcba')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.keyvault-vault.{0}.{1}', replace('0.10.2', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "keyVault": { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "enabledForDeployment": "[parameters('enableVaultForDeployment')]", + "enabledForTemplateDeployment": "[parameters('enableVaultForTemplateDeployment')]", + "enabledForDiskEncryption": "[parameters('enableVaultForDiskEncryption')]", + "enableSoftDelete": "[parameters('enableSoftDelete')]", + "softDeleteRetentionInDays": "[parameters('softDeleteRetentionInDays')]", + "enableRbacAuthorization": "[parameters('enableRbacAuthorization')]", + "createMode": "[parameters('createMode')]", + "enablePurgeProtection": "[if(parameters('enablePurgeProtection'), parameters('enablePurgeProtection'), null())]", + "tenantId": "[subscription().tenantId]", + "accessPolicies": "[variables('formattedAccessPolicies')]", + "sku": { + "name": "[parameters('sku')]", + "family": "A" + }, + "networkAcls": "[if(not(empty(coalesce(parameters('networkAcls'), createObject()))), createObject('bypass', tryGet(parameters('networkAcls'), 'bypass'), 'defaultAction', tryGet(parameters('networkAcls'), 'defaultAction'), 'virtualNetworkRules', coalesce(tryGet(parameters('networkAcls'), 'virtualNetworkRules'), createArray()), 'ipRules', coalesce(tryGet(parameters('networkAcls'), 'ipRules'), createArray())), null())]", + "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), parameters('publicNetworkAccess'), if(and(not(empty(coalesce(parameters('privateEndpoints'), createArray()))), empty(coalesce(parameters('networkAcls'), createObject()))), 'Disabled', null()))]" + } + }, + "keyVault_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_diagnosticSettings": { + "copy": { + "name": "keyVault_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "metrics", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics'))))]", + "input": { + "category": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')].category]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')], 'enabled'), true())]", + "timeGrain": null + } + }, + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_roleAssignments": { + "copy": { + "name": "keyVault_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.KeyVault/vaults', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_accessPolicies": { + "condition": "[not(empty(parameters('accessPolicies')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-KeyVault-AccessPolicies', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[parameters('name')]" + }, + "accessPolicies": { + "value": "[parameters('accessPolicies')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "15469258025112973480" + }, + "name": "Key Vault Access Policies", + "description": "This module deploys a Key Vault Access Policy.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "accessPoliciesType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "tenantId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The tenant ID that is used for authenticating requests to the key vault." + } + }, + "objectId": { + "type": "string", + "metadata": { + "description": "Required. The object ID of a user, service principal or security group in the tenant for the vault." + } + }, + "applicationId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Application ID of the client making request on behalf of a principal." + } + }, + "permissions": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "create", + "decrypt", + "delete", + "encrypt", + "get", + "getrotationpolicy", + "import", + "list", + "purge", + "recover", + "release", + "restore", + "rotate", + "setrotationpolicy", + "sign", + "unwrapKey", + "update", + "verify", + "wrapKey" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to keys." + } + }, + "secrets": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "delete", + "get", + "list", + "purge", + "recover", + "restore", + "set" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to secrets." + } + }, + "certificates": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "create", + "delete", + "deleteissuers", + "get", + "getissuers", + "import", + "list", + "listissuers", + "managecontacts", + "manageissuers", + "purge", + "recover", + "restore", + "setissuers", + "update" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to certificates." + } + }, + "storage": { + "type": "array", + "allowedValues": [ + "all", + "backup", + "delete", + "deletesas", + "get", + "getsas", + "list", + "listsas", + "purge", + "recover", + "regeneratekey", + "restore", + "set", + "setsas", + "update" + ], + "nullable": true, + "metadata": { + "description": "Optional. Permissions to storage accounts." + } + } + }, + "metadata": { + "description": "Required. Permissions the identity has for keys, secrets and certificates." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent key vault. Required if the template is used in a standalone deployment." + } + }, + "accessPolicies": { + "$ref": "#/definitions/accessPoliciesType", + "metadata": { + "description": "Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault's tenant ID." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedAccessPolicies", + "count": "[length(coalesce(parameters('accessPolicies'), createArray()))]", + "input": { + "applicationId": "[coalesce(tryGet(coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')], 'applicationId'), '')]", + "objectId": "[coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')].objectId]", + "permissions": "[coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')].permissions]", + "tenantId": "[coalesce(tryGet(coalesce(parameters('accessPolicies'), createArray())[copyIndex('formattedAccessPolicies')], 'tenantId'), tenant().tenantId)]" + } + } + ] + }, + "resources": { + "keyVault": { + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('keyVaultName')]" + }, + "policies": { + "type": "Microsoft.KeyVault/vaults/accessPolicies", + "apiVersion": "2022-07-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), 'add')]", + "properties": { + "accessPolicies": "[variables('formattedAccessPolicies')]" + }, + "dependsOn": [ + "keyVault" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the access policies assignment was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the access policies assignment." + }, + "value": "add" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the access policies assignment." + }, + "value": "[resourceId('Microsoft.KeyVault/vaults/accessPolicies', parameters('keyVaultName'), 'add')]" + } + } + } + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_secrets": { + "copy": { + "name": "keyVault_secrets", + "count": "[length(coalesce(parameters('secrets'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-KeyVault-Secret-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('secrets'), createArray())[copyIndex()].name]" + }, + "value": { + "value": "[coalesce(parameters('secrets'), createArray())[copyIndex()].value]" + }, + "keyVaultName": { + "value": "[parameters('name')]" + }, + "attributesEnabled": { + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributes'), 'enabled')]" + }, + "attributesExp": { + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributes'), 'exp')]" + }, + "attributesNbf": { + "value": "[tryGet(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'attributes'), 'nbf')]" + }, + "contentType": { + "value": "[tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'contentType')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('secrets'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "10121697157844029321" + }, + "name": "Key Vault Secrets", + "description": "This module deploys a Key Vault Secret.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent key vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "contentType": { + "type": "securestring", + "nullable": true, + "metadata": { + "description": "Optional. The content type of the secret." + } + }, + "value": { + "type": "securestring", + "metadata": { + "description": "Required. The value of the secret. NOTE: \"value\" will never be returned from the service, as APIs using this model are is intended for internal use in ARM deployments. Users should use the data-plane REST service for interaction with vault secrets." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Key Vault Secrets Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7')]", + "Key Vault Secrets User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "keyVault": { + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('keyVaultName')]" + }, + "secret": { + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2022-07-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "contentType": "[parameters('contentType')]", + "attributes": { + "enabled": "[parameters('attributesEnabled')]", + "exp": "[parameters('attributesExp')]", + "nbf": "[parameters('attributesNbf')]" + }, + "value": "[parameters('value')]" + }, + "dependsOn": [ + "keyVault" + ] + }, + "secret_roleAssignments": { + "copy": { + "name": "secret_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/secrets/{1}', parameters('keyVaultName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "secret" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the secret." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the secret." + }, + "value": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the secret was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_keys": { + "copy": { + "name": "keyVault_keys", + "count": "[length(coalesce(parameters('keys'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-KeyVault-Key-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('keys'), createArray())[copyIndex()].name]" + }, + "keyVaultName": { + "value": "[parameters('name')]" + }, + "attributesEnabled": { + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'enabled')]" + }, + "attributesExp": { + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'exp')]" + }, + "attributesNbf": { + "value": "[tryGet(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'attributes'), 'nbf')]" + }, + "curveName": "[if(and(not(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA')), not(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA-HSM'))), createObject('value', coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'curveName'), 'P-256')), createObject('value', null()))]", + "keyOps": { + "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'keyOps')]" + }, + "keySize": "[if(or(equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA'), equals(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'RSA-HSM')), createObject('value', coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'keySize'), 4096)), createObject('value', null()))]", + "releasePolicy": { + "value": "[coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'releasePolicy'), createObject())]" + }, + "kty": { + "value": "[coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'kty'), 'EC')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "rotationPolicy": { + "value": "[tryGet(coalesce(parameters('keys'), createArray())[copyIndex()], 'rotationPolicy')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "796741209006922272" + }, + "name": "Key Vault Keys", + "description": "This module deploys a Key Vault Key.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent key vault. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the key." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "attributesEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Determines whether the object is enabled." + } + }, + "attributesExp": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Expiry date in seconds since 1970-01-01T00:00:00Z. For security reasons, it is recommended to set an expiration date whenever possible." + } + }, + "attributesNbf": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Not before date in seconds since 1970-01-01T00:00:00Z." + } + }, + "curveName": { + "type": "string", + "defaultValue": "P-256", + "allowedValues": [ + "P-256", + "P-256K", + "P-384", + "P-521" + ], + "metadata": { + "description": "Optional. The elliptic curve name." + } + }, + "keyOps": { + "type": "array", + "nullable": true, + "allowedValues": [ + "decrypt", + "encrypt", + "import", + "sign", + "unwrapKey", + "verify", + "wrapKey" + ], + "metadata": { + "description": "Optional. Array of JsonWebKeyOperation." + } + }, + "keySize": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The key size in bits. For example: 2048, 3072, or 4096 for RSA." + } + }, + "kty": { + "type": "string", + "defaultValue": "EC", + "allowedValues": [ + "EC", + "EC-HSM", + "RSA", + "RSA-HSM" + ], + "metadata": { + "description": "Optional. The type of the key." + } + }, + "releasePolicy": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Key release policy." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "rotationPolicy": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Key rotation policy properties object." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Key Vault Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '00482a5a-887f-4fb3-b363-3b7fe8e74483')]", + "Key Vault Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f25e0fa2-a7c8-4377-a976-54943a77a395')]", + "Key Vault Crypto Officer": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '14b46e9e-c2b7-41b4-b07b-48a6ebf60603')]", + "Key Vault Crypto Service Encryption User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6')]", + "Key Vault Crypto User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424')]", + "Key Vault Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '21090545-7ca7-4776-b22c-e363652d74d2')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "keyVault": { + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('keyVaultName')]" + }, + "key": { + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2022-07-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": "[shallowMerge(createArray(createObject('attributes', createObject('enabled', parameters('attributesEnabled'), 'exp', parameters('attributesExp'), 'nbf', parameters('attributesNbf')), 'curveName', parameters('curveName'), 'keyOps', parameters('keyOps'), 'keySize', parameters('keySize'), 'kty', parameters('kty'), 'release_policy', coalesce(parameters('releasePolicy'), createObject())), if(empty(parameters('rotationPolicy')), createObject(), createObject('rotationPolicy', parameters('rotationPolicy')))))]", + "dependsOn": [ + "keyVault" + ] + }, + "key_roleAssignments": { + "copy": { + "name": "key_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.KeyVault/vaults/{0}/keys/{1}', parameters('keyVaultName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "key" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the key." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the key." + }, + "value": "[resourceId('Microsoft.KeyVault/vaults/keys', parameters('keyVaultName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the key was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "keyVault" + ] + }, + "keyVault_privateEndpoints": { + "copy": { + "name": "keyVault_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-keyVault-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'resourceGroupName'), '')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.KeyVault/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault'), copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.KeyVault/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.KeyVault/vaults', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault')))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.KeyVault/vaults', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault'), copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.KeyVault/vaults', parameters('name')), 'groupIds', createArray(coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'vault')), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroup": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1277254088602407590" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "5805178546717255803" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDnsZoneConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", + "input": { + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" + } + } + } + ] + }, + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" + } + } + } + }, + "dependsOn": [ + "keyVault" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the key vault." + }, + "value": "[resourceId('Microsoft.KeyVault/vaults', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the key vault was created in." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the key vault." + }, + "value": "[parameters('name')]" + }, + "uri": { + "type": "string", + "metadata": { + "description": "The URI of the key vault." + }, + "value": "[reference('keyVault').vaultUri]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('keyVault', '2022-07-01', 'full').location]" + }, + "privateEndpoints": { + "type": "array", + "metadata": { + "description": "The private endpoints of the key vault." + }, + "copy": { + "count": "[length(if(not(empty(parameters('privateEndpoints'))), array(parameters('privateEndpoints')), createArray()))]", + "input": { + "name": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('keyVault_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + } + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', 'webAppModule')]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "cosmosModule", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}{1}-db', variables('resourceGroupName'), variables('uniquePrefix'))]" + }, + "secretsExportConfiguration": { + "value": { + "keyVaultResourceId": "[reference(resourceId('Microsoft.Resources/deployments', 'keyVaultModule'), '2022-09-01').outputs.resourceId.value]", + "primaryWriteConnectionStringSecretName": "primaryWriteConnectionString" + } + }, + "mongodbDatabases": { + "value": [ + { + "name": "Users", + "collections": [ + { + "name": "ChatMessages", + "shardKey": { + "Username": "Hash" + }, + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + } + ] + }, + { + "name": "Chats", + "shardKey": { + "Username": "Hash" + }, + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + } + ] + }, + { + "name": "Files", + "shardKey": { + "Username": "Hash" + }, + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + } + ] + }, + { + "name": "Instructions", + "shardKey": {}, + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + } + ] + }, + { + "name": "Users", + "shardKey": { + "Username": "Hash" + }, + "indexes": [ + { + "key": { + "keys": [ + "_id" + ] + } + }, + { + "key": { + "keys": [ + "$**" + ] + } + } + ] + } + ] + } + ] + }, + "location": { + "value": "[variables('location')]" + }, + "networkRestrictions": { + "value": { + "ipRules": [], + "virtualNetworkRules": [], + "publicNetworkAccess": "Enabled" + } + }, + "capabilitiesToAdd": { + "value": [ + "EnableMongo", + "EnableServerless" + ] + }, + "backupPolicyContinuousTier": { + "value": "Continuous7Days" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "4957092988679141197" + }, + "name": "DocumentDB Database Accounts", + "description": "This module deploys a DocumentDB Database Account.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "metadata": { + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + } + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "failoverLocationsType": { + "type": "object", + "properties": { + "failoverPriority": { + "type": "int", + "metadata": { + "description": "Required. The failover priority of the region. A failover priority of 0 indicates a write region. The maximum value for a failover priority = (total number of regions - 1). Failover priority values must be unique for each of the regions in which the database account exists." + } + }, + "isZoneRedundant": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Default to true. Flag to indicate whether or not this region is an AvailabilityZone region." + } + }, + "locationName": { + "type": "string", + "metadata": { + "description": "Required. The name of the region." + } + } + } + }, + "sqlRoleDefinitionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the SQL Role Definition." + } + }, + "dataAction": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. An array of data actions that are allowed." + } + }, + "roleName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A user-friendly name for the Role Definition. Must be unique for the database account." + } + }, + "roleType": { + "type": "string", + "allowedValues": [ + "BuiltInRole", + "CustomRole" + ], + "nullable": true, + "metadata": { + "description": "Optional. Indicates whether the Role Definition was built-in or user created." + } + } + } + }, + "nullable": true + }, + "sqlDatabaseType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the SQL database ." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Default to 400. Request units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." + } + }, + "autoscaleSettingsMaxThroughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." + } + }, + "containers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the container." + } + }, + "paths": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, + "maxLength": 3, + "metadata": { + "description": "Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1." + } + }, + "analyticalStorageTtl": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." + } + }, + "autoscaleSettingsMaxThroughput": { + "type": "int", + "nullable": true, + "maxValue": 1000000, + "metadata": { + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." + } + }, + "conflictResolutionPolicy": { + "type": "object", + "properties": { + "conflictResolutionPath": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Conditional. The conflict resolution path in the case of LastWriterWins mode. Required if `mode` is set to 'LastWriterWins'." + } + }, + "conflictResolutionProcedure": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Conditional. The procedure to resolve conflicts in the case of custom mode. Required if `mode` is set to 'Custom'." + } + }, + "mode": { + "type": "string", + "allowedValues": [ + "Custom", + "LastWriterWins" + ], + "metadata": { + "description": "Required. Indicates the conflict resolution mode." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions." + } + }, + "defaultTtl": { + "type": "int", + "nullable": true, + "minValue": -1, + "maxValue": 2147483647, + "metadata": { + "description": "Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." + } + }, + "indexingPolicy": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Indexing policy of the container." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "Hash", + "MultiHash" + ], + "nullable": true, + "metadata": { + "description": "Optional. Default to Hash. Indicates the kind of algorithm used for partitioning." + } + }, + "version": { + "type": "int", + "allowedValues": [ + 1, + 2 + ], + "nullable": true, + "metadata": { + "description": "Optional. Default to 1 for Hash and 2 for MultiHash - 1 is not allowed for MultiHash. Version of the partition key definition." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." + } + }, + "uniqueKeyPolicyKeys": { + "type": "array", + "items": { + "type": "object", + "properties": { + "paths": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. List of paths must be unique for each document in the Azure Cosmos DB service." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of containers to deploy in the SQL database." + } + } + } + }, + "secretsExportConfigurationType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the key vault where to store the secrets of this module." + } + }, + "primaryWriteKeySecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The primary write key secret name to create." + } + }, + "primaryReadOnlyKeySecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The primary readonly key secret name to create." + } + }, + "primaryWriteConnectionStringSecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The primary write connection string secret name to create." + } + }, + "primaryReadonlyConnectionStringSecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The primary readonly connection string secret name to create." + } + }, + "secondaryWriteKeySecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The primary write key secret name to create." + } + }, + "secondaryReadonlyKeySecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The primary readonly key secret name to create." + } + }, + "secondaryWriteConnectionStringSecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The primary write connection string secret name to create." + } + }, + "secondaryReadonlyConnectionStringSecretName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The primary readonly connection string secret name to create." + } + } + } + }, + "secretsOutputType": { + "type": "object", + "properties": {}, + "additionalProperties": { + "$ref": "#/definitions/secretSetType", + "metadata": { + "description": "An exported secret's references." + } + } + }, + "networkRestrictionsType": { + "type": "object", + "properties": { + "ipRules": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A single IPv4 address or a single IPv4 address range in CIDR format. Provided IPs must be well-formatted and cannot be contained in one of the following ranges: 10.0.0.0/8, 100.64.0.0/10, 172.16.0.0/12, 192.168.0.0/16, since these are not enforceable by the IP address filter. Example of valid inputs: \"23.40.210.245\" or \"23.40.210.0/8\"." + } + }, + "networkAclBypass": { + "type": "string", + "allowedValues": [ + "AzureServices", + "None" + ], + "nullable": true, + "metadata": { + "description": "Optional. Default to AzureServices. Specifies the network ACL bypass for Azure services." + } + }, + "publicNetworkAccess": { + "type": "string", + "allowedValues": [ + "Disabled", + "Enabled" + ], + "nullable": true, + "metadata": { + "description": "Optional. Default to Enabled. Whether requests from Public Network are allowed." + } + }, + "virtualNetworkRules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of a subnet." + } + } + } + }, + "metadata": { + "description": "Required. List of Virtual Network ACL rules configured for the Cosmos DB account.." + } + } + } + }, + "secretSetType": { + "type": "object", + "properties": { + "secretResourceId": { + "type": "string", + "metadata": { + "description": "The resourceId of the exported secret." + } + }, + "secretUri": { + "type": "string", + "metadata": { + "description": "The secret URI of the exported secret." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "modules/keyVaultExport.bicep" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Database Account." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Default to current resource group scope location. Location for all resources." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Database Account resource." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "databaseAccountOfferType": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Standard" + ], + "metadata": { + "description": "Optional. Default to Standard. The offer type for the Azure Cosmos DB database account." + } + }, + "locations": { + "type": "array", + "items": { + "$ref": "#/definitions/failoverLocationsType" + }, + "defaultValue": [], + "metadata": { + "description": "Optional. Default to the location where the account is deployed. Locations enabled for the Cosmos DB account." + } + }, + "defaultConsistencyLevel": { + "type": "string", + "defaultValue": "Session", + "allowedValues": [ + "Eventual", + "ConsistentPrefix", + "Session", + "BoundedStaleness", + "Strong" + ], + "metadata": { + "description": "Optional. Default to Session. The default consistency level of the Cosmos DB account." + } + }, + "disableLocalAuth": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Opt-out of local authentication and ensure only MSI and AAD can be used exclusively for authentication." + } + }, + "enableAnalyticalStorage": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Flag to indicate whether to enable storage analytics." + } + }, + "automaticFailover": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable automatic failover for regions." + } + }, + "enableFreeTier": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Flag to indicate whether Free Tier is enabled." + } + }, + "enableMultipleWriteLocations": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables the account to write in multiple locations. Periodic backup must be used if enabled." + } + }, + "disableKeyBasedMetadataWriteAccess": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Disable write operations on metadata resources (databases, containers, throughput) via account keys." + } + }, + "maxStalenessPrefix": { + "type": "int", + "defaultValue": 100000, + "minValue": 1, + "maxValue": 2147483647, + "metadata": { + "description": "Optional. Default to 100000. Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 1000000. Multi Region: 100000 to 1000000." + } + }, + "maxIntervalInSeconds": { + "type": "int", + "defaultValue": 300, + "minValue": 5, + "maxValue": 86400, + "metadata": { + "description": "Optional. Default to 300. Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400." + } + }, + "serverVersion": { + "type": "string", + "defaultValue": "4.2", + "allowedValues": [ + "3.2", + "3.6", + "4.0", + "4.2" + ], + "metadata": { + "description": "Optional. Default to 4.2. Specifies the MongoDB server version to use." + } + }, + "sqlDatabases": { + "type": "array", + "items": { + "$ref": "#/definitions/sqlDatabaseType" + }, + "defaultValue": [], + "metadata": { + "description": "Optional. SQL Databases configurations." + } + }, + "sqlRoleAssignmentsPrincipalIds": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. SQL Role Definitions configurations." + } + }, + "sqlRoleDefinitions": { + "$ref": "#/definitions/sqlRoleDefinitionsType", + "metadata": { + "description": "Optional. SQL Role Definitions configurations." + } + }, + "mongodbDatabases": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. MongoDB Databases configurations." + } + }, + "gremlinDatabases": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Gremlin Databases configurations." + } + }, + "tables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Table configurations." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalIds' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "capabilitiesToAdd": { + "type": "array", + "items": { + "type": "string" + }, + "defaultValue": [], + "allowedValues": [ + "EnableCassandra", + "EnableTable", + "EnableGremlin", + "EnableMongo", + "DisableRateLimitingResponses", + "EnableServerless" + ], + "metadata": { + "description": "Optional. List of Cosmos DB capabilities for the account." + } + }, + "backupPolicyType": { + "type": "string", + "defaultValue": "Continuous", + "allowedValues": [ + "Periodic", + "Continuous" + ], + "metadata": { + "description": "Optional. Default to Continuous. Describes the mode of backups. Periodic backup must be used if multiple write locations are used." + } + }, + "backupPolicyContinuousTier": { + "type": "string", + "defaultValue": "Continuous30Days", + "allowedValues": [ + "Continuous30Days", + "Continuous7Days" + ], + "metadata": { + "description": "Optional. Default to Continuous30Days. Configuration values for continuous mode backup." + } + }, + "backupIntervalInMinutes": { + "type": "int", + "defaultValue": 240, + "minValue": 60, + "maxValue": 1440, + "metadata": { + "description": "Optional. Default to 240. An integer representing the interval in minutes between two backups. Only applies to periodic backup type." + } + }, + "backupRetentionIntervalInHours": { + "type": "int", + "defaultValue": 8, + "minValue": 2, + "maxValue": 720, + "metadata": { + "description": "Optional. Default to 8. An integer representing the time (in hours) that each backup is retained. Only applies to periodic backup type." + } + }, + "backupStorageRedundancy": { + "type": "string", + "defaultValue": "Local", + "allowedValues": [ + "Geo", + "Local", + "Zone" + ], + "metadata": { + "description": "Optional. Default to Local. Enum to indicate type of backup residency. Only applies to periodic backup type." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "secretsExportConfiguration": { + "$ref": "#/definitions/secretsExportConfigurationType", + "nullable": true, + "metadata": { + "description": "Optional. Key vault reference and secret settings for the module's secrets export." + } + }, + "networkRestrictions": { + "$ref": "#/definitions/networkRestrictionsType", + "defaultValue": { + "ipRules": [], + "virtualNetworkRules": [], + "publicNetworkAccess": "Disabled" + }, + "metadata": { + "description": "Optional. The network configuration of this module. Defaults to `{ ipRules: [], virtualNetworkRules: [], publicNetworkAccess: 'Disabled' }`." + } + }, + "minimumTlsVersion": { + "type": "string", + "defaultValue": "Tls12", + "allowedValues": [ + "Tls", + "Tls11", + "Tls12" + ], + "metadata": { + "description": "Optional. Default to TLS 1.2. Enum to indicate the minimum allowed TLS version. Azure Cosmos DB for MongoDB RU and Apache Cassandra only work with TLS 1.2 or later." + } + } + }, + "variables": { + "copy": [ + { + "name": "databaseAccount_locations", + "count": "[length(parameters('locations'))]", + "input": { + "failoverPriority": "[parameters('locations')[copyIndex('databaseAccount_locations')].failoverPriority]", + "locationName": "[parameters('locations')[copyIndex('databaseAccount_locations')].locationName]", + "isZoneRedundant": "[coalesce(tryGet(parameters('locations')[copyIndex('databaseAccount_locations')], 'isZoneRedundant'), true())]" + } + }, + { + "name": "capabilities", + "count": "[length(parameters('capabilitiesToAdd'))]", + "input": { + "name": "[parameters('capabilitiesToAdd')[copyIndex('capabilities')]]" + } + }, + { + "name": "ipRules", + "count": "[length(coalesce(tryGet(parameters('networkRestrictions'), 'ipRules'), createArray()))]", + "input": { + "ipAddressOrRange": "[coalesce(tryGet(parameters('networkRestrictions'), 'ipRules'), createArray())[copyIndex('ipRules')]]" + } + }, + { + "name": "virtualNetworkRules", + "count": "[length(coalesce(tryGet(parameters('networkRestrictions'), 'virtualNetworkRules'), createArray()))]", + "input": { + "id": "[coalesce(tryGet(parameters('networkRestrictions'), 'virtualNetworkRules'), createArray())[copyIndex('virtualNetworkRules')].subnetResourceId]", + "ignoreMissingVnetServiceEndpoint": false + } + }, + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "consistencyPolicy": { + "Eventual": { + "defaultConsistencyLevel": "Eventual" + }, + "ConsistentPrefix": { + "defaultConsistencyLevel": "ConsistentPrefix" + }, + "Session": { + "defaultConsistencyLevel": "Session" + }, + "BoundedStaleness": { + "defaultConsistencyLevel": "BoundedStaleness", + "maxStalenessPrefix": "[parameters('maxStalenessPrefix')]", + "maxIntervalInSeconds": "[parameters('maxIntervalInSeconds')]" + }, + "Strong": { + "defaultConsistencyLevel": "Strong" + } + }, + "defaultFailoverLocation": [ + { + "failoverPriority": 0, + "locationName": "[parameters('location')]", + "isZoneRedundant": true + } + ], + "kind": "[if(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('gremlinDatabases')))), 'GlobalDocumentDB', if(not(empty(parameters('mongodbDatabases'))), 'MongoDB', 'GlobalDocumentDB'))]", + "backupPolicy": "[if(equals(parameters('backupPolicyType'), 'Continuous'), createObject('type', parameters('backupPolicyType'), 'continuousModeProperties', createObject('tier', parameters('backupPolicyContinuousTier'))), createObject('type', parameters('backupPolicyType'), 'periodicModeProperties', createObject('backupIntervalInMinutes', parameters('backupIntervalInMinutes'), 'backupRetentionIntervalInHours', parameters('backupRetentionIntervalInHours'), 'backupStorageRedundancy', parameters('backupStorageRedundancy'))))]", + "databaseAccountProperties": "[union(createObject('databaseAccountOfferType', parameters('databaseAccountOfferType'), 'backupPolicy', variables('backupPolicy'), 'minimalTlsVersion', parameters('minimumTlsVersion')), if(or(or(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('mongodbDatabases')))), not(empty(parameters('gremlinDatabases')))), not(empty(parameters('tables')))), createObject('consistencyPolicy', variables('consistencyPolicy')[parameters('defaultConsistencyLevel')], 'enableMultipleWriteLocations', parameters('enableMultipleWriteLocations'), 'locations', if(empty(variables('databaseAccount_locations')), variables('defaultFailoverLocation'), variables('databaseAccount_locations')), 'ipRules', variables('ipRules'), 'virtualNetworkRules', variables('virtualNetworkRules'), 'networkAclBypass', coalesce(tryGet(parameters('networkRestrictions'), 'networkAclBypass'), 'AzureServices'), 'publicNetworkAccess', coalesce(tryGet(parameters('networkRestrictions'), 'publicNetworkAccess'), 'Enabled'), 'isVirtualNetworkFilterEnabled', or(not(empty(variables('ipRules'))), not(empty(variables('virtualNetworkRules')))), 'capabilities', variables('capabilities'), 'enableFreeTier', parameters('enableFreeTier'), 'enableAutomaticFailover', parameters('automaticFailover'), 'enableAnalyticalStorage', parameters('enableAnalyticalStorage')), createObject()), if(or(not(empty(parameters('sqlDatabases'))), not(empty(parameters('tables')))), createObject('disableLocalAuth', parameters('disableLocalAuth'), 'disableKeyBasedMetadataWriteAccess', parameters('disableKeyBasedMetadataWriteAccess')), createObject()), if(not(empty(parameters('mongodbDatabases'))), createObject('apiProperties', createObject('serverVersion', parameters('serverVersion'))), createObject()))]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Cosmos DB Account Reader Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8')]", + "Cosmos DB Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '230815da-be43-4aae-9cb4-875f7bd000aa')]", + "CosmosBackupOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb')]", + "CosmosRestoreOperator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5432c526-bc82-444a-b7ba-57c5b0b5b34f')]", + "DocumentDB Account Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5bd9cd88-fe45-4216-938b-f97437e15450')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.documentdb-databaseaccount.{0}.{1}', replace('0.8.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" + } + } + } + } + }, + "databaseAccount": { + "type": "Microsoft.DocumentDB/databaseAccounts", + "apiVersion": "2023-04-15", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "kind": "[variables('kind')]", + "properties": "[variables('databaseAccountProperties')]" + }, + "databaseAccount_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.DocumentDB/databaseAccounts/{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": [ + "databaseAccount" + ] + }, + "databaseAccount_diagnosticSettings": { + "copy": { + "name": "databaseAccount_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.DocumentDB/databaseAccounts/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "metrics", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics'))))]", + "input": { + "category": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')].category]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')], 'enabled'), true())]", + "timeGrain": null + } + }, + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "databaseAccount_roleAssignments": { + "copy": { + "name": "databaseAccount_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.DocumentDB/databaseAccounts/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "databaseAccount_sqlDatabases": { + "copy": { + "name": "databaseAccount_sqlDatabases", + "count": "[length(parameters('sqlDatabases'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-sqldb-{1}', uniqueString(deployment().name, parameters('location')), parameters('sqlDatabases')[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('sqlDatabases')[copyIndex()].name]" + }, + "containers": { + "value": "[tryGet(parameters('sqlDatabases')[copyIndex()], 'containers')]" + }, + "throughput": { + "value": "[tryGet(parameters('sqlDatabases')[copyIndex()], 'throughput')]" + }, + "databaseAccountName": { + "value": "[parameters('name')]" + }, + "autoscaleSettingsMaxThroughput": { + "value": "[tryGet(parameters('sqlDatabases')[copyIndex()], 'autoscaleSettingsMaxThroughput')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "10274585444287252550" + }, + "name": "DocumentDB Database Account SQL Databases", + "description": "This module deploys a SQL Database in a CosmosDB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Database Account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the SQL database ." + } + }, + "containers": { + "type": "array", + "items": { + "type": "object" + }, + "defaultValue": [], + "metadata": { + "description": "Optional. Array of containers to deploy in the SQL database." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Request units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." + } + }, + "autoscaleSettingsMaxThroughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the SQL database resource." + } + } + }, + "resources": { + "databaseAccount": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts", + "apiVersion": "2023-04-15", + "name": "[parameters('databaseAccountName')]" + }, + "sqlDatabase": { + "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "resource": { + "id": "[parameters('name')]" + }, + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(equals(parameters('autoscaleSettingsMaxThroughput'), null()), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "container": { + "copy": { + "name": "container", + "count": "[length(parameters('containers'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-sqldb-{1}', uniqueString(deployment().name, parameters('name')), parameters('containers')[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "databaseAccountName": { + "value": "[parameters('databaseAccountName')]" + }, + "sqlDatabaseName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('containers')[copyIndex()].name]" + }, + "analyticalStorageTtl": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'analyticalStorageTtl')]" + }, + "autoscaleSettingsMaxThroughput": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'autoscaleSettingsMaxThroughput')]" + }, + "conflictResolutionPolicy": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'conflictResolutionPolicy')]" + }, + "defaultTtl": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'defaultTtl')]" + }, + "indexingPolicy": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'indexingPolicy')]" + }, + "kind": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'kind')]" + }, + "version": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'version')]" + }, + "paths": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'paths')]" + }, + "throughput": "[if(and(or(not(equals(parameters('throughput'), null())), not(equals(parameters('autoscaleSettingsMaxThroughput'), null()))), equals(tryGet(parameters('containers')[copyIndex()], 'throughput'), null())), createObject('value', -1), createObject('value', tryGet(parameters('containers')[copyIndex()], 'throughput')))]", + "uniqueKeyPolicyKeys": { + "value": "[tryGet(parameters('containers')[copyIndex()], 'uniqueKeyPolicyKeys')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "165408036680070575" + }, + "name": "DocumentDB Database Account SQL Database Containers", + "description": "This module deploys a SQL Database Container in a CosmosDB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Database Account. Required if the template is used in a standalone deployment." + } + }, + "sqlDatabaseName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent SQL Database. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the container." + } + }, + "analyticalStorageTtl": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. Default to 0. Indicates how long data should be retained in the analytical store, for a container. Analytical store is enabled when ATTL is set with a value other than 0. If the value is set to -1, the analytical store retains all historical data, irrespective of the retention of the data in the transactional store." + } + }, + "conflictResolutionPolicy": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The conflict resolution policy for the container. Conflicts and conflict resolution policies are applicable if the Azure Cosmos DB account is configured with multiple write regions." + } + }, + "defaultTtl": { + "type": "int", + "defaultValue": -1, + "minValue": -1, + "maxValue": 2147483647, + "metadata": { + "description": "Optional. Default to -1. Default time to live (in seconds). With Time to Live or TTL, Azure Cosmos DB provides the ability to delete items automatically from a container after a certain time period. If the value is set to \"-1\", it is equal to infinity, and items don't expire by default." + } + }, + "throughput": { + "type": "int", + "defaultValue": 400, + "metadata": { + "description": "Optional. Default to 400. Request Units per second. Will be ignored if autoscaleSettingsMaxThroughput is used." + } + }, + "autoscaleSettingsMaxThroughput": { + "type": "int", + "nullable": true, + "maxValue": 1000000, + "metadata": { + "description": "Optional. Specifies the Autoscale settings and represents maximum throughput, the resource can scale up to. The autoscale throughput should have valid throughput values between 1000 and 1000000 inclusive in increments of 1000. If value is set to null, then autoscale will be disabled." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the SQL Database resource." + } + }, + "paths": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, + "maxLength": 3, + "metadata": { + "description": "Required. List of paths using which data within the container can be partitioned. For kind=MultiHash it can be up to 3. For anything else it needs to be exactly 1." + } + }, + "indexingPolicy": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Indexing policy of the container." + } + }, + "uniqueKeyPolicyKeys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The unique key policy configuration containing a list of unique keys that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service." + } + }, + "kind": { + "type": "string", + "defaultValue": "Hash", + "allowedValues": [ + "Hash", + "MultiHash" + ], + "metadata": { + "description": "Optional. Default to Hash. Indicates the kind of algorithm used for partitioning." + } + }, + "version": { + "type": "int", + "defaultValue": 1, + "allowedValues": [ + 1, + 2 + ], + "metadata": { + "description": "Optional. Default to 1 for Hash and 2 for MultiHash - 1 is not allowed for MultiHash. Version of the partition key definition." + } + } + }, + "variables": { + "copy": [ + { + "name": "partitionKeyPaths", + "count": "[length(parameters('paths'))]", + "input": "[if(startsWith(parameters('paths')[copyIndex('partitionKeyPaths')], '/'), parameters('paths')[copyIndex('partitionKeyPaths')], format('/{0}', parameters('paths')[copyIndex('partitionKeyPaths')]))]" + } + ], + "containerResourceParams": "[union(createObject('conflictResolutionPolicy', parameters('conflictResolutionPolicy'), 'defaultTtl', parameters('defaultTtl'), 'id', parameters('name'), 'indexingPolicy', if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null()), 'partitionKey', createObject('paths', variables('partitionKeyPaths'), 'kind', parameters('kind'), 'version', if(equals(parameters('kind'), 'MultiHash'), 2, parameters('version'))), 'uniqueKeyPolicy', if(not(empty(parameters('uniqueKeyPolicyKeys'))), createObject('uniqueKeys', parameters('uniqueKeyPolicyKeys')), null())), if(not(equals(parameters('analyticalStorageTtl'), 0)), createObject('analyticalStorageTtl', parameters('analyticalStorageTtl')), createObject()))]" + }, + "resources": { + "databaseAccount::sqlDatabase": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), parameters('sqlDatabaseName'))]", + "dependsOn": [ + "databaseAccount" + ] + }, + "databaseAccount": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts", + "apiVersion": "2023-04-15", + "name": "[parameters('databaseAccountName')]" + }, + "container": { + "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}/{2}', parameters('databaseAccountName'), parameters('sqlDatabaseName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "resource": "[variables('containerResourceParams')]", + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', if(and(equals(parameters('autoscaleSettingsMaxThroughput'), null()), not(equals(parameters('throughput'), -1))), parameters('throughput'), null()), 'autoscaleSettings', if(not(equals(parameters('autoscaleSettingsMaxThroughput'), null())), createObject('maxThroughput', parameters('autoscaleSettingsMaxThroughput')), null())))]" + }, + "dependsOn": [ + "databaseAccount::sqlDatabase" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the container." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the container." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers', parameters('databaseAccountName'), parameters('sqlDatabaseName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the container was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "sqlDatabase" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the SQL database." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the SQL database." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', parameters('databaseAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the SQL database was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "databaseAccount_sqlRoleDefinitions": { + "copy": { + "name": "databaseAccount_sqlRoleDefinitions", + "count": "[length(coalesce(parameters('sqlRoleDefinitions'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-sqlrd-{1}', uniqueString(deployment().name, parameters('location')), coalesce(parameters('sqlRoleDefinitions'), createArray())[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('sqlRoleDefinitions'), createArray())[copyIndex()].name]" + }, + "databaseAccountName": { + "value": "[parameters('name')]" + }, + "dataActions": { + "value": "[tryGet(coalesce(parameters('sqlRoleDefinitions'), createArray())[copyIndex()], 'dataActions')]" + }, + "roleName": { + "value": "[tryGet(coalesce(parameters('sqlRoleDefinitions'), createArray())[copyIndex()], 'roleName')]" + }, + "roleType": { + "value": "[tryGet(coalesce(parameters('sqlRoleDefinitions'), createArray())[copyIndex()], 'roleType')]" + }, + "principalIds": { + "value": "[parameters('sqlRoleAssignmentsPrincipalIds')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "13088569006752107887" + }, + "name": "DocumentDB Database Account SQL Role.", + "description": "This module deploys SQL Role Definision and Assignment in a CosmosDB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Database Account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the SQL Role." + } + }, + "dataActions": { + "type": "array", + "defaultValue": [ + "Microsoft.DocumentDB/databaseAccounts/readMetadata", + "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*", + "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*" + ], + "metadata": { + "description": "Optional. An array of data actions that are allowed." + } + }, + "principalIds": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Ids needs to be granted." + } + }, + "roleName": { + "type": "string", + "defaultValue": "Reader Writer", + "metadata": { + "description": "Optional. A user-friendly name for the Role Definition. Must be unique for the database account." + } + }, + "roleType": { + "type": "string", + "defaultValue": "CustomRole", + "allowedValues": [ + "CustomRole", + "BuiltInRole" + ], + "metadata": { + "description": "Optional. Indicates whether the Role Definition was built-in or user created." + } + } + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('sql-role-definition-{0}', uniqueString(parameters('name')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "databaseAccountName": { + "value": "[parameters('databaseAccountName')]" + }, + "dataActions": { + "value": "[parameters('dataActions')]" + }, + "roleName": { + "value": "[parameters('roleName')]" + }, + "roleType": { + "value": "[parameters('roleType')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "5054354703268051893" + }, + "name": "DocumentDB Database Account SQL Role Definitions.", + "description": "This module deploys a SQL Role Definision in a CosmosDB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Database Account. Required if the template is used in a standalone deployment." + } + }, + "dataActions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. An array of data actions that are allowed." + } + }, + "roleName": { + "type": "string", + "defaultValue": "Reader Writer", + "metadata": { + "description": "Optional. A user-friendly name for the Role Definition. Must be unique for the database account." + } + }, + "roleType": { + "type": "string", + "defaultValue": "CustomRole", + "allowedValues": [ + "CustomRole", + "BuiltInRole" + ], + "metadata": { + "description": "Optional. Indicates whether the Role Definition was built-in or user created." + } + } + }, + "resources": [ + { + "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), guid(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('databaseAccountName')), parameters('databaseAccountName'), 'sql-role'))]", + "properties": { + "assignableScopes": [ + "[resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('databaseAccountName'))]" + ], + "permissions": [ + { + "dataActions": "[parameters('dataActions')]" + } + ], + "roleName": "[parameters('roleName')]", + "type": "[parameters('roleType')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the SQL database." + }, + "value": "[guid(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('databaseAccountName')), parameters('databaseAccountName'), 'sql-role')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the SQL database." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions', parameters('databaseAccountName'), guid(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('databaseAccountName')), parameters('databaseAccountName'), 'sql-role'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the SQL database was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + } + }, + { + "copy": { + "name": "sqlRoleAssignment", + "count": "[length(parameters('principalIds'))]", + "mode": "serial", + "batchSize": 1 + }, + "condition": "[not(empty(parameters('principalIds')[copyIndex()]))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('sql-role-assign-{0}', uniqueString(parameters('principalIds')[copyIndex()]))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[guid(reference(resourceId('Microsoft.Resources/deployments', format('sql-role-definition-{0}', uniqueString(parameters('name')))), '2022-09-01').outputs.resourceId.value, parameters('principalIds')[copyIndex()], resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('databaseAccountName')))]" + }, + "databaseAccountName": { + "value": "[parameters('databaseAccountName')]" + }, + "roleDefinitionId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('sql-role-definition-{0}', uniqueString(parameters('name')))), '2022-09-01').outputs.resourceId.value]" + }, + "principalId": { + "value": "[parameters('principalIds')[copyIndex()]]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "4561927123418147924" + }, + "name": "DocumentDB Database Account SQL Role Assignments.", + "description": "This module deploys a SQL Role Assignment in a CosmosDB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Database Account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the SQL Role Assignment." + } + }, + "principalId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Id needs to be granted." + } + }, + "roleDefinitionId": { + "type": "string", + "metadata": { + "description": "Required. Id of the SQL Role Definition." + } + } + }, + "resources": [ + { + "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), parameters('name'))]", + "properties": { + "principalId": "[parameters('principalId')]", + "roleDefinitionId": "[parameters('roleDefinitionId')]", + "scope": "[resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('databaseAccountName'))]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the SQL Role Assignment was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('sql-role-definition-{0}', uniqueString(parameters('name'))))]" + ] + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the SQL Role Definition and Assignment were created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "databaseAccount_mongodbDatabases": { + "copy": { + "name": "databaseAccount_mongodbDatabases", + "count": "[length(parameters('mongodbDatabases'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-mongodb-{1}', uniqueString(deployment().name, parameters('location')), parameters('mongodbDatabases')[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "databaseAccountName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('mongodbDatabases')[copyIndex()].name]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('mongodbDatabases')[copyIndex()], 'tags'), parameters('tags'))]" + }, + "collections": { + "value": "[tryGet(parameters('mongodbDatabases')[copyIndex()], 'collections')]" + }, + "throughput": { + "value": "[tryGet(parameters('mongodbDatabases')[copyIndex()], 'throughput')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "1169635175830874795" + }, + "name": "DocumentDB Database Account MongoDB Databases", + "description": "This module deploys a MongoDB Database within a CosmosDB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Cosmos DB database account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the mongodb database." + } + }, + "throughput": { + "type": "int", + "defaultValue": 400, + "metadata": { + "description": "Optional. Request Units per second." + } + }, + "collections": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Collections in the mongodb database." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "databaseAccount": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts", + "apiVersion": "2023-04-15", + "name": "[parameters('databaseAccountName')]" + }, + "mongodbDatabase": { + "type": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "resource": { + "id": "[parameters('name')]" + }, + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', parameters('throughput')))]" + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "mongodbDatabase_collections": { + "copy": { + "name": "mongodbDatabase_collections", + "count": "[length(parameters('collections'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-collection-{1}', uniqueString(deployment().name, parameters('name')), parameters('collections')[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "databaseAccountName": { + "value": "[parameters('databaseAccountName')]" + }, + "mongodbDatabaseName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('collections')[copyIndex()].name]" + }, + "indexes": { + "value": "[parameters('collections')[copyIndex()].indexes]" + }, + "shardKey": { + "value": "[parameters('collections')[copyIndex()].shardKey]" + }, + "throughput": { + "value": "[tryGet(parameters('collections')[copyIndex()], 'throughput')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "1358778299011674509" + }, + "name": "DocumentDB Database Account MongoDB Database Collections", + "description": "This module deploys a MongoDB Database Collection.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Cosmos DB database account. Required if the template is used in a standalone deployment." + } + }, + "mongodbDatabaseName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent mongodb database. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the collection." + } + }, + "throughput": { + "type": "int", + "defaultValue": 400, + "metadata": { + "description": "Optional. Request Units per second." + } + }, + "indexes": { + "type": "array", + "metadata": { + "description": "Required. Indexes for the collection." + } + }, + "shardKey": { + "type": "object", + "metadata": { + "description": "Required. ShardKey for the collection." + } + } + }, + "resources": [ + { + "type": "Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}/{2}', parameters('databaseAccountName'), parameters('mongodbDatabaseName'), parameters('name'))]", + "properties": { + "options": "[if(contains(reference(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('databaseAccountName')), '2023-04-15').capabilities, createObject('name', 'EnableServerless')), null(), createObject('throughput', parameters('throughput')))]", + "resource": { + "id": "[parameters('name')]", + "indexes": "[parameters('indexes')]", + "shardKey": "[parameters('shardKey')]" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the mongodb database collection." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the mongodb database collection." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections', parameters('databaseAccountName'), parameters('mongodbDatabaseName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the mongodb database collection was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "mongodbDatabase" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the mongodb database." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the mongodb database." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/mongodbDatabases', parameters('databaseAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the mongodb database was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "databaseAccount_gremlinDatabases": { + "copy": { + "name": "databaseAccount_gremlinDatabases", + "count": "[length(parameters('gremlinDatabases'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-gremlin-{1}', uniqueString(deployment().name, parameters('location')), parameters('gremlinDatabases')[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "databaseAccountName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('gremlinDatabases')[copyIndex()].name]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('gremlinDatabases')[copyIndex()], 'tags'), parameters('tags'))]" + }, + "graphs": { + "value": "[tryGet(parameters('gremlinDatabases')[copyIndex()], 'graphs')]" + }, + "maxThroughput": { + "value": "[tryGet(parameters('gremlinDatabases')[copyIndex()], 'maxThroughput')]" + }, + "throughput": { + "value": "[tryGet(parameters('gremlinDatabases')[copyIndex()], 'throughput')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "14612267479855031826" + }, + "name": "DocumentDB Database Account Gremlin Databases", + "description": "This module deploys a Gremlin Database within a CosmosDB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Gremlin database." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Gremlin database resource." + } + }, + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Gremlin database. Required if the template is used in a standalone deployment." + } + }, + "graphs": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of graphs to deploy in the Gremlin database." + } + }, + "maxThroughput": { + "type": "int", + "defaultValue": 4000, + "metadata": { + "description": "Optional. Represents maximum throughput, the resource can scale up to. Cannot be set together with `throughput`. If `throughput` is set to something else than -1, this autoscale setting is ignored." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Request Units per second (for example 10000). Cannot be set together with `maxThroughput`." + } + } + }, + "resources": { + "databaseAccount": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts", + "apiVersion": "2023-04-15", + "name": "[parameters('databaseAccountName')]" + }, + "gremlinDatabase": { + "type": "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), createObject(), createObject('autoscaleSettings', if(equals(parameters('throughput'), null()), createObject('maxThroughput', parameters('maxThroughput')), null()), 'throughput', parameters('throughput')))]", + "resource": { + "id": "[parameters('name')]" + } + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "gremlinDatabase_gremlinGraphs": { + "copy": { + "name": "gremlinDatabase_gremlinGraphs", + "count": "[length(parameters('graphs'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-gremlindb-{1}', uniqueString(deployment().name, parameters('name')), parameters('graphs')[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('graphs')[copyIndex()].name]" + }, + "gremlinDatabaseName": { + "value": "[parameters('name')]" + }, + "databaseAccountName": { + "value": "[parameters('databaseAccountName')]" + }, + "indexingPolicy": { + "value": "[tryGet(parameters('graphs')[copyIndex()], 'indexingPolicy')]" + }, + "partitionKeyPaths": "[if(not(empty(parameters('graphs')[copyIndex()].partitionKeyPaths)), createObject('value', parameters('graphs')[copyIndex()].partitionKeyPaths), createObject('value', createArray()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "5396990720772518636" + }, + "name": "DocumentDB Database Accounts Gremlin Databases Graphs", + "description": "This module deploys a DocumentDB Database Accounts Gremlin Database Graph.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the graph." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Gremlin graph resource." + } + }, + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Database Account. Required if the template is used in a standalone deployment." + } + }, + "gremlinDatabaseName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Gremlin Database. Required if the template is used in a standalone deployment." + } + }, + "indexingPolicy": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Indexing policy of the graph." + } + }, + "partitionKeyPaths": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of paths using which data within the container can be partitioned." + } + } + }, + "resources": { + "databaseAccount::gremlinDatabase": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), parameters('gremlinDatabaseName'))]", + "dependsOn": [ + "databaseAccount" + ] + }, + "databaseAccount": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts", + "apiVersion": "2023-04-15", + "name": "[parameters('databaseAccountName')]" + }, + "gremlinGraph": { + "type": "Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/graphs", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}/{2}', parameters('databaseAccountName'), parameters('gremlinDatabaseName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "resource": { + "id": "[parameters('name')]", + "indexingPolicy": "[if(not(empty(parameters('indexingPolicy'))), parameters('indexingPolicy'), null())]", + "partitionKey": { + "paths": "[if(not(empty(parameters('partitionKeyPaths'))), parameters('partitionKeyPaths'), null())]" + } + } + }, + "dependsOn": [ + "databaseAccount::gremlinDatabase" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the graph." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the graph." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/gremlinDatabases/graphs', parameters('databaseAccountName'), parameters('gremlinDatabaseName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the graph was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "gremlinDatabase" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the Gremlin database." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Gremlin database." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/gremlinDatabases', parameters('databaseAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the Gremlin database was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "databaseAccount_tables": { + "copy": { + "name": "databaseAccount_tables", + "count": "[length(parameters('tables'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-table-{1}', uniqueString(deployment().name, parameters('location')), parameters('tables')[copyIndex()].name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "databaseAccountName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('tables')[copyIndex()].name]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('tables')[copyIndex()], 'tags'), parameters('tags'))]" + }, + "maxThroughput": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'maxThroughput')]" + }, + "throughput": { + "value": "[tryGet(parameters('tables')[copyIndex()], 'throughput')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "15712676324433329983" + }, + "name": "Azure Cosmos DB account tables", + "description": "This module deploys a table within an Azure Cosmos DB Account.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the table." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for the table." + } + }, + "databaseAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Cosmos DB account. Required if the template is used in a standalone deployment." + } + }, + "maxThroughput": { + "type": "int", + "defaultValue": 4000, + "metadata": { + "description": "Optional. Represents maximum throughput, the resource can scale up to. Cannot be set together with `throughput`. If `throughput` is set to something else than -1, this autoscale setting is ignored." + } + }, + "throughput": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Request Units per second (for example 10000). Cannot be set together with `maxThroughput`." + } + } + }, + "resources": { + "databaseAccount": { + "existing": true, + "type": "Microsoft.DocumentDB/databaseAccounts", + "apiVersion": "2023-04-15", + "name": "[parameters('databaseAccountName')]" + }, + "table": { + "type": "Microsoft.DocumentDB/databaseAccounts/tables", + "apiVersion": "2023-04-15", + "name": "[format('{0}/{1}', parameters('databaseAccountName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "options": "[if(contains(reference('databaseAccount').capabilities, createObject('name', 'EnableServerless')), createObject(), createObject('autoscaleSettings', if(equals(parameters('throughput'), null()), createObject('maxThroughput', parameters('maxThroughput')), null()), 'throughput', parameters('throughput')))]", + "resource": { + "id": "[parameters('name')]" + } + }, + "dependsOn": [ + "databaseAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the table." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the table." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts/tables', parameters('databaseAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the table was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "databaseAccount_privateEndpoints": { + "copy": { + "name": "databaseAccount_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-databaseAccount-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "resourceGroup": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'resourceGroupName'), '')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex()))]" + }, + "privateLinkServiceConnections": "[if(not(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true())), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), 'groupIds', createArray(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service))))), createObject('value', null()))]", + "manualPrivateLinkServiceConnections": "[if(equals(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'isManualConnection'), true()), createObject('value', createArray(createObject('name', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateLinkServiceConnectionName'), format('{0}-{1}-{2}', last(split(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '/')), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service, copyIndex())), 'properties', createObject('privateLinkServiceId', resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), 'groupIds', createArray(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service), 'requestMessage', coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualConnectionRequestMessage'), 'Manual approval required.'))))), createObject('value', null()))]", + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroup": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "1277254088602407590" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + } + }, + "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.29.47.4906", + "templateHash": "5805178546717255803" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDnsZoneConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", + "input": { + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" + } + } + } + ] + }, + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-11-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" + }, + "groupId": { + "type": "string", + "metadata": { + "description": "The group Id for the private endpoint Group." + }, + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" + } + } + } + }, + "dependsOn": [ + "databaseAccount" + ] + }, + "secretsExport": { + "condition": "[not(equals(parameters('secretsExportConfiguration'), null()))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-secrets-kv', uniqueString(deployment().name, parameters('location')))]", + "subscriptionId": "[split(coalesce(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '////'), '/')[4]]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "keyVaultName": { + "value": "[last(split(coalesce(tryGet(parameters('secretsExportConfiguration'), 'keyVaultResourceId'), '//'), '/'))]" + }, + "secretsToSet": { + "value": "[union(createArray(), if(contains(parameters('secretsExportConfiguration'), 'primaryWriteKeySecretName'), createArray(createObject('name', parameters('secretsExportConfiguration').primaryWriteKeySecretName, 'value', listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').primaryMasterKey)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'primaryReadOnlyKeySecretName'), createArray(createObject('name', parameters('secretsExportConfiguration').primaryReadOnlyKeySecretName, 'value', listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').primaryReadonlyMasterKey)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'primaryWriteConnectionStringSecretName'), createArray(createObject('name', parameters('secretsExportConfiguration').primaryWriteConnectionStringSecretName, 'value', listConnectionStrings(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').connectionStrings[0].connectionString)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'primaryReadonlyConnectionStringSecretName'), createArray(createObject('name', parameters('secretsExportConfiguration').primaryReadonlyConnectionStringSecretName, 'value', listConnectionStrings(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').connectionStrings[2].connectionString)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'secondaryWriteKeySecretName'), createArray(createObject('name', parameters('secretsExportConfiguration').secondaryWriteKeySecretName, 'value', listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').secondaryMasterKey)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'secondaryReadonlyKeySecretName'), createArray(createObject('name', parameters('secretsExportConfiguration').secondaryReadonlyKeySecretName, 'value', listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').secondaryReadonlyMasterKey)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'secondaryWriteConnectionStringSecretName'), createArray(createObject('name', parameters('secretsExportConfiguration').secondaryWriteConnectionStringSecretName, 'value', listConnectionStrings(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').connectionStrings[1].connectionString)), createArray()), if(contains(parameters('secretsExportConfiguration'), 'secondaryReadonlyConnectionStringSecretName'), createArray(createObject('name', parameters('secretsExportConfiguration').secondaryReadonlyConnectionStringSecretName, 'value', listConnectionStrings(resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name')), '2023-04-15').connectionStrings[3].connectionString)), createArray()))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "12263717469683062316" + } + }, + "definitions": { + "secretSetType": { + "type": "object", + "properties": { + "secretResourceId": { + "type": "string", + "metadata": { + "description": "The resourceId of the exported secret." + } + }, + "secretUri": { + "type": "string", + "metadata": { + "description": "The secret URI of the exported secret." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "secretToSetType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret to set." + } + }, + "value": { + "type": "securestring", + "metadata": { + "description": "Required. The value of the secret to set." + } + } + } + } + }, + "parameters": { + "keyVaultName": { + "type": "string", + "metadata": { + "description": "Required. The name of the Key Vault to set the ecrets in." + } + }, + "secretsToSet": { + "type": "array", + "items": { + "$ref": "#/definitions/secretToSetType" + }, + "metadata": { + "description": "Required. The secrets to set in the Key Vault." + } + } + }, + "resources": { + "keyVault": { + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2022-07-01", + "name": "[parameters('keyVaultName')]" + }, + "secrets": { + "copy": { + "name": "secrets", + "count": "[length(parameters('secretsToSet'))]" + }, + "type": "Microsoft.KeyVault/vaults/secrets", + "apiVersion": "2023-07-01", + "name": "[format('{0}/{1}', parameters('keyVaultName'), parameters('secretsToSet')[copyIndex()].name)]", + "properties": { + "value": "[parameters('secretsToSet')[copyIndex()].value]" + }, + "dependsOn": [ + "keyVault" + ] + } + }, + "outputs": { + "secretsSet": { + "type": "array", + "items": { + "$ref": "#/definitions/secretSetType" + }, + "metadata": { + "description": "The references to the secrets exported to the provided Key Vault." + }, + "copy": { + "count": "[length(range(0, length(coalesce(parameters('secretsToSet'), createArray()))))]", + "input": { + "secretResourceId": "[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), parameters('secretsToSet')[range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()]].name)]", + "secretUri": "[reference(format('secrets[{0}]', range(0, length(coalesce(parameters('secretsToSet'), createArray())))[copyIndex()])).secretUri]" + } + } + } + } + } + }, + "dependsOn": [ + "databaseAccount" + ] + } + }, + "outputs": { + "exportedSecrets": { + "$ref": "#/definitions/secretsOutputType", + "metadata": { + "description": "The references to the secrets exported to the provided Key Vault." + }, + "value": "[if(not(equals(parameters('secretsExportConfiguration'), null())), toObject(reference('secretsExport').outputs.secretsSet.value, lambda('secret', last(split(lambdaVariables('secret').secretResourceId, '/'))), lambda('secret', lambdaVariables('secret'))), createObject())]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the database account." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the database account." + }, + "value": "[resourceId('Microsoft.DocumentDB/databaseAccounts', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the database account was created in." + }, + "value": "[resourceGroup().name]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[coalesce(tryGet(tryGet(reference('databaseAccount', '2023-04-15', 'full'), 'identity'), 'principalId'), '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('databaseAccount', '2023-04-15', 'full').location]" + }, + "endpoint": { + "type": "string", + "metadata": { + "description": "The endpoint of the database account." + }, + "value": "[reference('databaseAccount').documentEndpoint]" + }, + "privateEndpoints": { + "type": "array", + "metadata": { + "description": "The private endpoints of the database account." + }, + "copy": { + "count": "[length(if(not(empty(parameters('privateEndpoints'))), array(parameters('privateEndpoints')), createArray()))]", + "input": { + "name": "[reference(format('databaseAccount_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('databaseAccount_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('databaseAccount_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('databaseAccount_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('databaseAccount_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + } + } + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', 'keyVaultModule')]" + ] + } + ] +} \ No newline at end of file diff --git a/demo/main.bicep b/demo/main.bicep new file mode 100644 index 0000000..e861ce2 --- /dev/null +++ b/demo/main.bicep @@ -0,0 +1,262 @@ +// Parameters +@description('The Entra ID client ID for the application.') +param azureAdClientId string = '' + +@description('The endpoints for the deployment.') +param endpoints string = '' + +@description('The models available for the deployment.') +param models string = '[{"Name":"GPT-4o","Description":"Best model","DeploymentName":"gpt-4o","MaxContext":128000,"MaxTokens":4096,"DeploymentType":"AzureOpenAI","Deployment":"Deployment1"},{"Name":"GPT-4o-Mini","Description":"Good and fast","DeploymentName":"gpt-4o-mini","MaxContext":128000,"MaxTokens":16000,"DeploymentType":"AzureOpenAI","Deployment":"Deployment1"}]' + +@description('The key for the deployment to use.') +param deployment1 string = '' + +@description('The URL for the GitHub repository that contains the project to deploy.') +param chatUitGitUrl string = 'https://github.com/UiT-ITA/ChatUiT2' + +@description('The branch of the GitHub repository to use.') +param chatUitGitBranch string = 'master' + +// Variables +var location = resourceGroup().location +var resourceGroupName = toLower(resourceGroup().name) +var uniquePrefix = toLower(substring(uniqueString(resourceGroup().id), 0, 6)) + +// Create an App Service Plan +module asp 'br/public:avm/res/web/serverfarm:0.3.0' = { + name: 'appServicePlanModule' + params: { + name: '${resourceGroupName}${uniquePrefix}-asp' + reserved: true + skuName: 'S1' + location: location + } +} + +// Create a Web App +module webapp 'br/public:avm/res/web/site:0.11.1' = { + name: 'webAppModule' + params: { + name: '${resourceGroupName}${uniquePrefix}-webapp' + location: location + kind: 'app,linux' + serverFarmResourceId: asp.outputs.resourceId + managedIdentities: { + systemAssigned: true + } + siteConfig: { + linuxFxVersion: 'DOTNETCORE|8.0' + } + } +} + +var webAppPrincipalId = webapp.outputs.systemAssignedMIPrincipalId + +// Create a Key Vault +module keyVault 'br/public:avm/res/key-vault/vault:0.10.2' = { + name: 'keyVaultModule' + params: { + name: '${resourceGroupName}${uniquePrefix}-kv' + location: location + sku: 'standard' + enableRbacAuthorization: true + roleAssignments: [ + { + roleDefinitionIdOrName: 'Key Vault Secrets Officer' + principalId: webAppPrincipalId + principalType: 'ServicePrincipal' + } + ] + secrets: [ + { + name: 'deployment1' + value: deployment1 + } + ] + } +} + +// Create a Cosmos DB account for MongoDB +module cosmos 'br/public:avm/res/document-db/database-account:0.8.1' = { + name: 'cosmosModule' + params: { + name: '${resourceGroupName}${uniquePrefix}-db' + secretsExportConfiguration: { + keyVaultResourceId: keyVault.outputs.resourceId + primaryWriteConnectionStringSecretName: 'primaryWriteConnectionString' + } + mongodbDatabases:[ + { + name: 'Users' + collections: [ + { + name: 'ChatMessages' + shardKey: { + Username: 'Hash' + } + indexes: [ + { + key: { + keys: [ + '_id' + ] + } + } + { + key: { + keys: [ + '$**' + ] + } + } + ] + } + { + name: 'Chats' + shardKey: { + Username: 'Hash' + } + indexes: [ + { + key: { + keys: [ + '_id' + ] + } + } + { + key: { + keys: [ + '$**' + ] + } + } + ] + } + { + name: 'Files' + shardKey: { + Username: 'Hash' + } + indexes: [ + { + key: { + keys: [ + '_id' + ] + } + } + { + key: { + keys: [ + '$**' + ] + } + } + ] + } + { + name: 'Instructions' + shardKey: { + } + indexes: [ + { + key: { + keys: [ + '_id' + ] + } + } + { + key: { + keys: [ + '$**' + ] + } + } + ] + } + { + name: 'Users' + shardKey: { + Username: 'Hash' + } + indexes: [ + { + key: { + keys: [ + '_id' + ] + } + } + { + key: { + keys: [ + '$**' + ] + } + } + ] + } + ] + } + ] + location: location + networkRestrictions:{ + ipRules: [] + virtualNetworkRules: [] + publicNetworkAccess: 'Enabled' + } + capabilitiesToAdd: [ + 'EnableMongo' + 'EnableServerless' + ] + backupPolicyContinuousTier: 'Continuous7Days' + } +} + +// Import the existing Web App to reference it in the app settings +resource webappExisting 'Microsoft.Web/sites@2024-04-01' existing = { + name: '${resourceGroupName}${uniquePrefix}-webapp' + dependsOn: [ + webapp + ] +} + +// Assign the connection string to the Web App +resource connectionStrings 'Microsoft.Web/sites/config@2024-04-01' = { + name: 'connectionstrings' + parent: webappExisting + properties: { + MongoDB: { + type: 'Custom' + value: '@Microsoft.KeyVault(SecretUri=${cosmos.outputs.exportedSecrets.primaryWriteConnectionString.secretUri})' + } + KeyVault: { + type: 'Custom' + value: keyVault.outputs.uri + } + } +} + +resource appSettings 'Microsoft.Web/sites/config@2024-04-01' = { + name: 'appsettings' + parent: webappExisting + properties: { + AzureAd__ClientId: azureAdClientId + Endpoints: endpoints + Models: models + Deployment1: '@Microsoft.KeyVault(SecretUri=${keyVault.outputs.uri}secrets/deployment1)' + } +} + +// Add a source control configuration to the Web App +resource webappSrc 'Microsoft.Web/sites/sourcecontrols@2024-04-01' = { + parent: webappExisting + name: 'web' + properties: { + repoUrl: chatUitGitUrl + branch: chatUitGitBranch + isManualIntegration: true + } +}