From 77126364b3bec6bc3a19d9839986684699173b3c Mon Sep 17 00:00:00 2001 From: Daniel Scholl Date: Mon, 22 Jan 2024 18:44:49 -0600 Subject: [PATCH] Created template. --- azuredeploy.json | 2603 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 2178 insertions(+), 425 deletions(-) diff --git a/azuredeploy.json b/azuredeploy.json index 24d73d95..cef56996 100644 --- a/azuredeploy.json +++ b/azuredeploy.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.24.24.22086", - "templateHash": "1161476867458258788" + "templateHash": "7201082717854836225" } }, "parameters": { @@ -729,7 +729,25 @@ "HighSpec": { "vmSize": "Standard_DS5_v2" } - } + }, + "configMaps": { + "workloadIdentityTemplate": "values.yaml: |\n azureWorkloadIdentity:\n tenantId: \"{0}\"\n clientId: \"{1}\"\n serviceAccount:\n create: true\n name: \"\"\n", + "appConfigTemplate": "values.yaml: |\n azureWorkloadIdentity:\n clientId: \"{0}\"\n appConfiguration:\n endpoint: \"{1}\"\n" + }, + "appSettings": [ + { + "name": "Settings:FontColor", + "value": "Green", + "contentType": "text/plain", + "label": "ConfigMap-Sample" + }, + { + "name": "Settings:Message", + "value": "Hello from App Configuration", + "contentType": "text/plain", + "label": "ConfigMap-Sample" + } + ] }, "resources": [ { @@ -19792,7 +19810,7 @@ "_generator": { "name": "bicep", "version": "0.24.24.22086", - "templateHash": "14862025164983561930" + "templateHash": "125255005146302743" } }, "parameters": { @@ -20341,7 +20359,7 @@ }, "variables": { "autoScale": "[greater(parameters('agentCountMax'), parameters('agentCount'))]", - "name": "[format('aks-{0}', uniqueString(resourceGroup().id, parameters('resourceName')))]", + "name": "[format('aks-{0}{1}', replace(parameters('resourceName'), '-', ''), uniqueString(resourceGroup().id, parameters('resourceName')))]", "serviceMeshProfileObj": { "istio": { "components": { @@ -20698,158 +20716,1016 @@ { "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-espool1', variables('serviceLayerConfig').name)]", + "name": "[format('{0}-user-managed-identity', variables('serviceLayerConfig').name)]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { - "AksName": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name)), '2022-09-01').outputs.aksClusterName.value]" - }, - "PoolName": { - "value": "espoolz1" - }, - "agentVMSize": { - "value": "[variables('elasticPoolPresets')[parameters('clusterSize')].vmSize]" + "name": { + "value": "[format('id-{0}{1}', replace(variables('serviceLayerConfig').name, '-', ''), uniqueString(resourceGroup().id, variables('serviceLayerConfig').name))]" }, - "agentCount": { - "value": 2 + "location": { + "value": "[parameters('location')]" }, - "agentCountMax": { - "value": 4 + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" }, - "availabilityZones": { + "federatedIdentityCredentials": { "value": [ - "1" + { + "audiences": [ + "api://AzureADTokenExchange" + ], + "issuer": "[reference(resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name)), '2022-09-01').outputs.aksOidcIssuerUrl.value]", + "name": "[format('{0}-user-managed-identity-fed1', variables('serviceLayerConfig').name)]", + "subject": "system:serviceaccount:default:workload-identity-sa" + } ] }, - "subnetId": { - "value": "" - }, - "nodeTaints": { + "roleAssignments": { "value": [ - "app=elasticsearch:NoSchedule" + { + "roleDefinitionIdOrName": "Managed Identity Operator", + "principalId": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('commonLayerConfig').name)), '2022-09-01').outputs.principalId.value]", + "principalType": "ServicePrincipal" + } ] }, - "nodeLabels": { + "tags": { "value": { - "app": "elasticsearch" + "layer": "[variables('serviceLayerConfig').displayName]" } } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "2918991882660483195" - } - }, - "parameters": { - "AksName": { - "type": "string" + "version": "0.23.1.45101", + "templateHash": "17425686371279834860" }, - "PoolName": { - "type": "string" + "name": "User Assigned Identities", + "description": "This module deploys a User Assigned Identity.", + "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 }, - "availabilityZones": { + "roleAssignmentType": { "type": "array", - "defaultValue": [], - "metadata": { - "description": "The zones to use for a node pool" - } - }, - "osDiskType": { + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { "type": "string", - "defaultValue": "Ephemeral", "metadata": { - "description": "OS disk type" + "description": "Required. Name of the User Assigned Identity." } }, - "agentVMSize": { + "location": { "type": "string", - "defaultValue": "Standard_DS3_v2", - "metadata": { - "description": "VM SKU" - } - }, - "osDiskSizeGB": { - "type": "int", - "defaultValue": 0, - "metadata": { - "description": "Disk size in GB" - } - }, - "agentCount": { - "type": "int", - "defaultValue": 3, + "defaultValue": "[resourceGroup().location]", "metadata": { - "description": "The number of agents for the user node pool" + "description": "Optional. Location for all resources." } }, - "agentCountMax": { - "type": "int", - "defaultValue": 0, + "federatedIdentityCredentials": { + "type": "array", + "defaultValue": [], "metadata": { - "description": "The maximum number of nodes for the user node pool" + "description": "Optional. The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object." } }, - "maxPods": { - "type": "int", - "defaultValue": 30, + "lock": { + "$ref": "#/definitions/lockType", "metadata": { - "description": "The maximum number of pods per node." + "description": "Optional. The lock settings of the service." } }, - "nodeTaints": { - "type": "array", - "defaultValue": [], + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", "metadata": { - "description": "Any taints that should be applied to the node pool" + "description": "Optional. Array of role assignments to create." } }, - "nodeLabels": { + "tags": { "type": "object", - "defaultValue": {}, - "metadata": { - "description": "Any labels that should be applied to the node pool" - } - }, - "subnetId": { - "type": "string", + "nullable": true, "metadata": { - "description": "The subnet the node pool will use" + "description": "Optional. Tags of the resource." } }, - "osType": { - "type": "string", - "defaultValue": "Linux", - "allowedValues": [ - "Linux", - "Windows" - ], + "enableTelemetry": { + "type": "bool", + "defaultValue": true, "metadata": { - "description": "OS Type for the node pool" + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." } } }, "variables": { - "autoScale": "[greater(parameters('agentCountMax'), parameters('agentCount'))]" + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "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": [ - { - "type": "Microsoft.ContainerService/managedClusters/agentPools", - "apiVersion": "2023-10-02-preview", - "name": "[format('{0}/{1}', parameters('AksName'), parameters('PoolName'))]", + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.managedidentity-userassignedidentity.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { - "mode": "User", - "vmSize": "[parameters('agentVMSize')]", - "count": "[parameters('agentCount')]", - "minCount": "[if(variables('autoScale'), parameters('agentCount'), null())]", + "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" + } + } + } + } + }, + "userAssignedIdentity": { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2023-01-31", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + "userAssignedIdentity_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.ManagedIdentity/userAssignedIdentities/{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": [ + "userAssignedIdentity" + ] + }, + "userAssignedIdentity_roleAssignments": { + "copy": { + "name": "userAssignedIdentity_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "userAssignedIdentity" + ] + }, + "userAssignedIdentity_federatedIdentityCredentials": { + "copy": { + "name": "userAssignedIdentity_federatedIdentityCredentials", + "count": "[length(parameters('federatedIdentityCredentials'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-UserMSI-FederatedIdentityCredential-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('federatedIdentityCredentials')[copyIndex()].name]" + }, + "userAssignedIdentityName": { + "value": "[parameters('name')]" + }, + "audiences": { + "value": "[parameters('federatedIdentityCredentials')[copyIndex()].audiences]" + }, + "issuer": { + "value": "[parameters('federatedIdentityCredentials')[copyIndex()].issuer]" + }, + "subject": { + "value": "[parameters('federatedIdentityCredentials')[copyIndex()].subject]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "4906524580099045986" + }, + "name": "User Assigned Identity Federated Identity Credential", + "description": "This module deploys a User Assigned Identity Federated Identity Credential.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "userAssignedIdentityName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent user assigned identity. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret." + } + }, + "audiences": { + "type": "array", + "metadata": { + "description": "Required. The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token." + } + }, + "issuer": { + "type": "string", + "metadata": { + "description": "Required. The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged." + } + }, + "subject": { + "type": "string", + "metadata": { + "description": "Required. The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD." + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('userAssignedIdentityName'), parameters('name'))]", + "properties": { + "audiences": "[parameters('audiences')]", + "issuer": "[parameters('issuer')]", + "subject": "[parameters('subject')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the federated identity credential." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the federated identity credential." + }, + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials', parameters('userAssignedIdentityName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the federated identity credential was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "userAssignedIdentity" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the user assigned identity." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the user assigned identity." + }, + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + }, + "principalId": { + "type": "string", + "metadata": { + "description": "The principal ID (object ID) of the user assigned identity." + }, + "value": "[reference('userAssignedIdentity').principalId]" + }, + "clientId": { + "type": "string", + "metadata": { + "description": "The client ID (application ID) of the user assigned identity." + }, + "value": "[reference('userAssignedIdentity').clientId]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the user assigned identity was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('userAssignedIdentity', '2023-01-31', 'full').location]" + } + } + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('commonLayerConfig').name))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-user-managed-identity-operator', variables('serviceLayerConfig').name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "operatorIdentityName": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('commonLayerConfig').name)), '2022-09-01').outputs.name.value]" + }, + "identityclientId": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('serviceLayerConfig').name)), '2022-09-01').outputs.clientId.value]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "11058293506964573769" + } + }, + "parameters": { + "operatorIdentityName": { + "type": "string" + }, + "identityclientId": { + "type": "string" + } + }, + "variables": { + "managedIdentityOperator": "[resourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]" + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Authorization/roleAssignments/{0}', parameters('operatorIdentityName'))]", + "name": "[guid(resourceId('Microsoft.Authorization/roleAssignments', parameters('operatorIdentityName')), parameters('identityclientId'), variables('managedIdentityOperator'))]", + "properties": { + "roleDefinitionId": "[variables('managedIdentityOperator')]", + "principalType": "ServicePrincipal", + "principalId": "[parameters('identityclientId')]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('serviceLayerConfig').name))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('commonLayerConfig').name))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-espool1', variables('serviceLayerConfig').name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "AksName": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name)), '2022-09-01').outputs.aksClusterName.value]" + }, + "PoolName": { + "value": "espoolz1" + }, + "agentVMSize": { + "value": "[variables('elasticPoolPresets')[parameters('clusterSize')].vmSize]" + }, + "agentCount": { + "value": 2 + }, + "agentCountMax": { + "value": 4 + }, + "availabilityZones": { + "value": [ + "1" + ] + }, + "subnetId": { + "value": "" + }, + "nodeTaints": { + "value": [ + "app=elasticsearch:NoSchedule" + ] + }, + "nodeLabels": { + "value": { + "app": "elasticsearch" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "2918991882660483195" + } + }, + "parameters": { + "AksName": { + "type": "string" + }, + "PoolName": { + "type": "string" + }, + "availabilityZones": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "The zones to use for a node pool" + } + }, + "osDiskType": { + "type": "string", + "defaultValue": "Ephemeral", + "metadata": { + "description": "OS disk type" + } + }, + "agentVMSize": { + "type": "string", + "defaultValue": "Standard_DS3_v2", + "metadata": { + "description": "VM SKU" + } + }, + "osDiskSizeGB": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Disk size in GB" + } + }, + "agentCount": { + "type": "int", + "defaultValue": 3, + "metadata": { + "description": "The number of agents for the user node pool" + } + }, + "agentCountMax": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "The maximum number of nodes for the user node pool" + } + }, + "maxPods": { + "type": "int", + "defaultValue": 30, + "metadata": { + "description": "The maximum number of pods per node." + } + }, + "nodeTaints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Any taints that should be applied to the node pool" + } + }, + "nodeLabels": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Any labels that should be applied to the node pool" + } + }, + "subnetId": { + "type": "string", + "metadata": { + "description": "The subnet the node pool will use" + } + }, + "osType": { + "type": "string", + "defaultValue": "Linux", + "allowedValues": [ + "Linux", + "Windows" + ], + "metadata": { + "description": "OS Type for the node pool" + } + } + }, + "variables": { + "autoScale": "[greater(parameters('agentCountMax'), parameters('agentCount'))]" + }, + "resources": [ + { + "type": "Microsoft.ContainerService/managedClusters/agentPools", + "apiVersion": "2023-10-02-preview", + "name": "[format('{0}/{1}', parameters('AksName'), parameters('PoolName'))]", + "properties": { + "mode": "User", + "vmSize": "[parameters('agentVMSize')]", + "count": "[parameters('agentCount')]", + "minCount": "[if(variables('autoScale'), parameters('agentCount'), null())]", + "maxCount": "[if(variables('autoScale'), parameters('agentCountMax'), null())]", + "enableAutoScaling": "[variables('autoScale')]", + "availabilityZones": "[if(not(empty(parameters('availabilityZones'))), parameters('availabilityZones'), null())]", + "osDiskType": "[parameters('osDiskType')]", + "osDiskSizeGB": "[parameters('osDiskSizeGB')]", + "osType": "[parameters('osType')]", + "maxPods": "[parameters('maxPods')]", + "type": "VirtualMachineScaleSets", + "vnetSubnetID": "[if(not(empty(parameters('subnetId'))), parameters('subnetId'), null())]", + "upgradeSettings": { + "maxSurge": "33%" + }, + "nodeTaints": "[parameters('nodeTaints')]", + "nodeLabels": "[parameters('nodeLabels')]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-espool2', variables('serviceLayerConfig').name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "AksName": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name)), '2022-09-01').outputs.aksClusterName.value]" + }, + "PoolName": { + "value": "espoolz2" + }, + "agentVMSize": { + "value": "[variables('elasticPoolPresets')[parameters('clusterSize')].vmSize]" + }, + "agentCount": { + "value": 2 + }, + "agentCountMax": { + "value": 4 + }, + "availabilityZones": { + "value": [ + "2" + ] + }, + "subnetId": { + "value": "" + }, + "nodeTaints": { + "value": [ + "app=elasticsearch:NoSchedule" + ] + }, + "nodeLabels": { + "value": { + "app": "elasticsearch" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "2918991882660483195" + } + }, + "parameters": { + "AksName": { + "type": "string" + }, + "PoolName": { + "type": "string" + }, + "availabilityZones": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "The zones to use for a node pool" + } + }, + "osDiskType": { + "type": "string", + "defaultValue": "Ephemeral", + "metadata": { + "description": "OS disk type" + } + }, + "agentVMSize": { + "type": "string", + "defaultValue": "Standard_DS3_v2", + "metadata": { + "description": "VM SKU" + } + }, + "osDiskSizeGB": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Disk size in GB" + } + }, + "agentCount": { + "type": "int", + "defaultValue": 3, + "metadata": { + "description": "The number of agents for the user node pool" + } + }, + "agentCountMax": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "The maximum number of nodes for the user node pool" + } + }, + "maxPods": { + "type": "int", + "defaultValue": 30, + "metadata": { + "description": "The maximum number of pods per node." + } + }, + "nodeTaints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Any taints that should be applied to the node pool" + } + }, + "nodeLabels": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Any labels that should be applied to the node pool" + } + }, + "subnetId": { + "type": "string", + "metadata": { + "description": "The subnet the node pool will use" + } + }, + "osType": { + "type": "string", + "defaultValue": "Linux", + "allowedValues": [ + "Linux", + "Windows" + ], + "metadata": { + "description": "OS Type for the node pool" + } + } + }, + "variables": { + "autoScale": "[greater(parameters('agentCountMax'), parameters('agentCount'))]" + }, + "resources": [ + { + "type": "Microsoft.ContainerService/managedClusters/agentPools", + "apiVersion": "2023-10-02-preview", + "name": "[format('{0}/{1}', parameters('AksName'), parameters('PoolName'))]", + "properties": { + "mode": "User", + "vmSize": "[parameters('agentVMSize')]", + "count": "[parameters('agentCount')]", + "minCount": "[if(variables('autoScale'), parameters('agentCount'), null())]", + "maxCount": "[if(variables('autoScale'), parameters('agentCountMax'), null())]", + "enableAutoScaling": "[variables('autoScale')]", + "availabilityZones": "[if(not(empty(parameters('availabilityZones'))), parameters('availabilityZones'), null())]", + "osDiskType": "[parameters('osDiskType')]", + "osDiskSizeGB": "[parameters('osDiskSizeGB')]", + "osType": "[parameters('osType')]", + "maxPods": "[parameters('maxPods')]", + "type": "VirtualMachineScaleSets", + "vnetSubnetID": "[if(not(empty(parameters('subnetId'))), parameters('subnetId'), null())]", + "upgradeSettings": { + "maxSurge": "33%" + }, + "nodeTaints": "[parameters('nodeTaints')]", + "nodeLabels": "[parameters('nodeLabels')]" + } + } + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-espool3', variables('serviceLayerConfig').name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "AksName": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name)), '2022-09-01').outputs.aksClusterName.value]" + }, + "PoolName": { + "value": "espoolz3" + }, + "agentVMSize": { + "value": "[variables('elasticPoolPresets')[parameters('clusterSize')].vmSize]" + }, + "agentCount": { + "value": 2 + }, + "agentCountMax": { + "value": 4 + }, + "availabilityZones": { + "value": [ + "3" + ] + }, + "subnetId": { + "value": "" + }, + "nodeTaints": { + "value": [ + "app=elasticsearch:NoSchedule" + ] + }, + "nodeLabels": { + "value": { + "app": "elasticsearch" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "2918991882660483195" + } + }, + "parameters": { + "AksName": { + "type": "string" + }, + "PoolName": { + "type": "string" + }, + "availabilityZones": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "The zones to use for a node pool" + } + }, + "osDiskType": { + "type": "string", + "defaultValue": "Ephemeral", + "metadata": { + "description": "OS disk type" + } + }, + "agentVMSize": { + "type": "string", + "defaultValue": "Standard_DS3_v2", + "metadata": { + "description": "VM SKU" + } + }, + "osDiskSizeGB": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Disk size in GB" + } + }, + "agentCount": { + "type": "int", + "defaultValue": 3, + "metadata": { + "description": "The number of agents for the user node pool" + } + }, + "agentCountMax": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "The maximum number of nodes for the user node pool" + } + }, + "maxPods": { + "type": "int", + "defaultValue": 30, + "metadata": { + "description": "The maximum number of pods per node." + } + }, + "nodeTaints": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Any taints that should be applied to the node pool" + } + }, + "nodeLabels": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Any labels that should be applied to the node pool" + } + }, + "subnetId": { + "type": "string", + "metadata": { + "description": "The subnet the node pool will use" + } + }, + "osType": { + "type": "string", + "defaultValue": "Linux", + "allowedValues": [ + "Linux", + "Windows" + ], + "metadata": { + "description": "OS Type for the node pool" + } + } + }, + "variables": { + "autoScale": "[greater(parameters('agentCountMax'), parameters('agentCount'))]" + }, + "resources": [ + { + "type": "Microsoft.ContainerService/managedClusters/agentPools", + "apiVersion": "2023-10-02-preview", + "name": "[format('{0}/{1}', parameters('AksName'), parameters('PoolName'))]", + "properties": { + "mode": "User", + "vmSize": "[parameters('agentVMSize')]", + "count": "[parameters('agentCount')]", + "minCount": "[if(variables('autoScale'), parameters('agentCount'), null())]", "maxCount": "[if(variables('autoScale'), parameters('agentCountMax'), null())]", "enableAutoScaling": "[variables('autoScale')]", "availabilityZones": "[if(not(empty(parameters('availabilityZones'))), parameters('availabilityZones'), null())]", @@ -20866,55 +21742,291 @@ "nodeLabels": "[parameters('nodeLabels')]" } } - ] + ] + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "helmAppConfigProvider", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "aksName": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name)), '2022-09-01').outputs.aksClusterName.value]" + }, + "location": { + "value": "[parameters('location')]" + }, + "newOrExistingManagedIdentity": { + "value": "existing" + }, + "managedIdentityName": { + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('commonLayerConfig').name)), '2022-09-01').outputs.name.value]" + }, + "existingManagedIdentitySubId": { + "value": "[subscription().subscriptionId]" + }, + "existingManagedIdentityResourceGroupName": { + "value": "[resourceGroup().name]" + }, + "commands": { + "value": [ + "helm install azureappconfiguration.kubernetesprovider oci://mcr.microsoft.com/azure-app-configuration/helmchart/kubernetes-provider --namespace azappconfig-system --create-namespace" + ] + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "15573168867133922782" + }, + "name": "AKS Run Command Script", + "description": "An Azure CLI Deployment Script that allows you to run a command on a Kubernetes cluster.", + "owner": "Aks-Bicep-Accelerator-Maintainers" + }, + "parameters": { + "aksName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Kubernetes Service" + } + }, + "location": { + "type": "string", + "metadata": { + "description": "The location to deploy the resources to" + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "How the deployment script should be forced to execute" + } + }, + "rbacRolesNeeded": { + "type": "array", + "defaultValue": [ + "b24988ac-6180-42a0-ab88-20f7382dd24c", + "7f6c6a51-bcf8-42ba-9220-52d62157d7db" + ], + "metadata": { + "description": "An array of Azure RoleIds that are required for the DeploymentScript resource" + } + }, + "newOrExistingManagedIdentity": { + "type": "string", + "defaultValue": "new", + "allowedValues": [ + "new", + "existing" + ], + "metadata": { + "description": "Create \"new\" or use \"existing\" Managed Identity. Default: new" + } + }, + "managedIdentityName": { + "type": "string", + "defaultValue": "[format('id-AksRunCommandProxy-{0}', parameters('location'))]", + "metadata": { + "description": "Name of the Managed Identity resource" + } + }, + "existingManagedIdentitySubId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", + "metadata": { + "description": "For an existing Managed Identity, the Subscription Id it is located in" + } + }, + "existingManagedIdentityResourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "For an existing Managed Identity, the Resource Group it is located in" + } + }, + "commands": { + "type": "array", + "metadata": { + "description": "An array of commands to run" + } + }, + "initialScriptDelay": { + "type": "string", + "defaultValue": "120s", + "metadata": { + "description": "A delay before the script import operation starts. Primarily to allow Azure AAD Role Assignments to propagate" + } + }, + "cleanupPreference": { + "type": "string", + "defaultValue": "OnSuccess", + "allowedValues": [ + "OnSuccess", + "OnExpiration", + "Always" + ], + "metadata": { + "description": "When the script resource is cleaned up" + } + }, + "isCrossTenant": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Set to true when deploying template across tenants" + } + } + }, + "variables": { + "$fxv#0": "#!/bin/bash\n\nset -e +H\n# -e to exit on error\n# +H to prevent history expansion\n\nif [ \"$loopIndex\" == \"0\" ] && [ \"$initialDelay\" != \"0\" ]\nthen\n echo \"Waiting on RBAC replication ($initialDelay)\"\n sleep $initialDelay\n\n #Force RBAC refresh\n az logout\n az login --identity\nfi\n\necho \"Sending command $command to AKS Cluster $aksName in $RG\"\ncmdOut=$(az aks command invoke -g $RG -n $aksName -o json --command \"${command}\")\necho $cmdOut\n\njsonOutputString=$cmdOut\necho $jsonOutputString > $AZ_SCRIPTS_OUTPUT_PATH\n", + "useExistingManagedIdentity": "[equals(parameters('newOrExistingManagedIdentity'), 'existing')]", + "delegatedManagedIdentityResourceId": "[if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')))]" + }, + "resources": [ + { + "condition": "[not(variables('useExistingManagedIdentity'))]", + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2023-01-31", + "name": "[parameters('managedIdentityName')]", + "location": "[parameters('location')]" + }, + { + "copy": { + "name": "rbac", + "count": "[length(parameters('rbacRolesNeeded'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.ContainerService/managedClusters/{0}', parameters('aksName'))]", + "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('aksName')), parameters('rbacRolesNeeded')[copyIndex()], if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))))]", + "properties": { + "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('rbacRolesNeeded')[copyIndex()])]", + "principalId": "[if(variables('useExistingManagedIdentity'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), '2023-01-31').principalId, reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), '2023-01-31').principalId)]", + "principalType": "ServicePrincipal", + "delegatedManagedIdentityResourceId": "[if(parameters('isCrossTenant'), variables('delegatedManagedIdentityResourceId'), null())]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))]" + ] + }, + { + "copy": { + "name": "runAksCommand", + "count": "[length(parameters('commands'))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[format('script-{0}-{1}-{2}', parameters('aksName'), deployment().name, copyIndex())]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))))]": {} + } + }, + "kind": "AzureCLI", + "properties": { + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "azCliVersion": "2.35.0", + "timeout": "PT10M", + "retentionInterval": "P1D", + "environmentVariables": [ + { + "name": "RG", + "value": "[resourceGroup().name]" + }, + { + "name": "aksName", + "value": "[parameters('aksName')]" + }, + { + "name": "command", + "value": "[parameters('commands')[copyIndex()]]" + }, + { + "name": "initialDelay", + "value": "[parameters('initialScriptDelay')]" + }, + { + "name": "loopIndex", + "value": "[string(copyIndex())]" + } + ], + "scriptContent": "[variables('$fxv#0')]", + "cleanupPreference": "[parameters('cleanupPreference')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))]", + "rbac" + ] + } + ], + "outputs": { + "commandOutput": { + "type": "array", + "metadata": { + "description": "Array of command output from each Deployment Script AKS run command" + }, + "copy": { + "count": "[length(parameters('commands'))]", + "input": { + "Index": "[copyIndex()]", + "Name": "[format('script-{0}-{1}-{2}', parameters('aksName'), deployment().name, copyIndex())]", + "CommandOutput": "[reference(resourceId('Microsoft.Resources/deploymentScripts', format('script-{0}-{1}-{2}', parameters('aksName'), deployment().name, copyIndex())), '2020-10-01').outputs]" + } + } + } + } } }, "dependsOn": [ - "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]" + "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('commonLayerConfig').name))]" ] }, { + "condition": "[variables('enableConfigMap')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-espool2', variables('serviceLayerConfig').name)]", + "name": "[format('{0}-cluster-workloadidentitymap', variables('serviceLayerConfig').name)]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { - "AksName": { + "aksName": { "value": "[reference(resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name)), '2022-09-01').outputs.aksClusterName.value]" }, - "PoolName": { - "value": "espoolz2" - }, - "agentVMSize": { - "value": "[variables('elasticPoolPresets')[parameters('clusterSize')].vmSize]" - }, - "agentCount": { - "value": 2 - }, - "agentCountMax": { - "value": 4 + "location": { + "value": "[parameters('location')]" }, - "availabilityZones": { - "value": [ - "2" - ] + "name": { + "value": "workload-identity-values" }, - "subnetId": { - "value": "" + "namespace": { + "value": "default" }, - "nodeTaints": { + "fileData": { "value": [ - "app=elasticsearch:NoSchedule" + "[format(variables('configMaps').workloadIdentityTemplate, subscription().tenantId, reference(resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('serviceLayerConfig').name)), '2022-09-01').outputs.clientId.value)]" ] - }, - "nodeLabels": { - "value": { - "app": "elasticsearch" - } } }, "template": { @@ -20924,175 +22036,263 @@ "_generator": { "name": "bicep", "version": "0.24.24.22086", - "templateHash": "2918991882660483195" - } + "templateHash": "4801579897722142587" + }, + "name": "AKS Config Map", + "description": "An Azure CLI Deployment Script that allows you to create a helm char on a Kubernetes cluster.", + "owner": "Daniel Scholl" }, "parameters": { - "AksName": { - "type": "string" + "aksName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Kubernetes Service" + } }, - "PoolName": { - "type": "string" + "location": { + "type": "string", + "metadata": { + "description": "The location to deploy the resources to" + } }, - "availabilityZones": { + "forceUpdateTag": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "How the deployment script should be forced to execute" + } + }, + "rbacRolesNeeded": { "type": "array", - "defaultValue": [], + "defaultValue": [ + "b24988ac-6180-42a0-ab88-20f7382dd24c", + "7f6c6a51-bcf8-42ba-9220-52d62157d7db" + ], "metadata": { - "description": "The zones to use for a node pool" + "description": "An array of Azure RoleIds that are required for the DeploymentScript resource" } }, - "osDiskType": { + "newOrExistingManagedIdentity": { "type": "string", - "defaultValue": "Ephemeral", + "defaultValue": "new", + "allowedValues": [ + "new", + "existing" + ], "metadata": { - "description": "OS disk type" + "description": "Create \"new\" or use \"existing\" Managed Identity. Default: new" } }, - "agentVMSize": { + "managedIdentityName": { "type": "string", - "defaultValue": "Standard_DS3_v2", + "defaultValue": "[format('id-AksConfigMap-{0}', parameters('location'))]", "metadata": { - "description": "VM SKU" + "description": "Name of the Managed Identity resource" } }, - "osDiskSizeGB": { - "type": "int", - "defaultValue": 0, + "existingManagedIdentitySubId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", "metadata": { - "description": "Disk size in GB" + "description": "For an existing Managed Identity, the Subscription Id it is located in" } }, - "agentCount": { - "type": "int", - "defaultValue": 3, + "existingManagedIdentityResourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", "metadata": { - "description": "The number of agents for the user node pool" + "description": "For an existing Managed Identity, the Resource Group it is located in" } }, - "agentCountMax": { - "type": "int", - "defaultValue": 0, + "name": { + "type": "string", + "defaultValue": "configuration", "metadata": { - "description": "The maximum number of nodes for the user node pool" + "description": "Specify the config map name." } }, - "maxPods": { - "type": "int", - "defaultValue": 30, + "namespace": { + "type": "string", + "defaultValue": "default", "metadata": { - "description": "The maximum number of pods per node." + "description": "Specify the namespace for the config mapl" } }, - "nodeTaints": { + "propertyData": { "type": "array", "defaultValue": [], "metadata": { - "description": "Any taints that should be applied to the node pool" + "description": "Specify the config map single property data. (e.g. \"player_initial_lives=3\")" } }, - "nodeLabels": { - "type": "object", - "defaultValue": {}, + "fileData": { + "type": "array", + "defaultValue": [], "metadata": { - "description": "Any labels that should be applied to the node pool" + "description": "Specify the config map file data. (e.g. \"game.properties: |enemy.types=aliens,monsters\nplayer.maximum-lives=5\")" } }, - "subnetId": { + "initialScriptDelay": { "type": "string", + "defaultValue": "120s", "metadata": { - "description": "The subnet the node pool will use" + "description": "A delay before the script import operation starts. Primarily to allow Azure AAD Role Assignments to propagate" } }, - "osType": { + "cleanupPreference": { "type": "string", - "defaultValue": "Linux", + "defaultValue": "OnSuccess", "allowedValues": [ - "Linux", - "Windows" + "OnSuccess", + "OnExpiration", + "Always" ], "metadata": { - "description": "OS Type for the node pool" + "description": "When the script resource is cleaned up" + } + }, + "isCrossTenant": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Set to true when deploying template across tenants" } } }, "variables": { - "autoScale": "[greater(parameters('agentCountMax'), parameters('agentCount'))]" + "$fxv#0": "\nset -e +H\n# -e to exit on error\n# +H to prevent history expansion\n\n# This script is used to apply a ConfigMap to an AKS cluster using the az aks command invoke command.\n\nif [ \"$initialDelay\" != \"0\" ]\nthen\n echo \"Waiting on RBAC replication ($initialDelay)\"\n sleep $initialDelay\n\n #Force RBAC refresh\n az logout\n az login --identity\nfi\n\n# Function to convert semi-colon-separated key-value pairs in $dataPropertyLike to YAML format\nconvert_properties_to_yaml() {\n local IFS=\";\"\n for pair in $dataPropertyLike; do\n IFS='=' read -r key value <<< \"$pair\"\n echo \" $key: \\\"$value\\\"\"\n done\n echo \"\" # Add an empty line for separation\n}\n\n# Function to append file-like data in $dataFileLike to YAML format, converting \\t to spaces\nappend_files_to_yaml() {\n local IFS=\";\"\n for file in $dataFileLike; do\n local name=\"${file%%: *}\"\n local content=\"${file#*: |}\"\n # Process content to ensure correct new line handling and indentation\n content=$(echo \"$content\" | sed 's/\\\\n/\\n/g' | sed 's/^/ /') # Adjust for actual new lines and indent\n echo \" $name: |\"\n echo \"$content\"\n done\n}\n\n\necho \"Checking and updating configmap $configMap in AKS Cluster $aksName in $RG\"\n\n\n# Combining property-like and file-like data into the ConfigMap\ncombinedYaml=$(cat < $AZ_SCRIPTS_OUTPUT_PATH\n", + "useExistingManagedIdentity": "[equals(parameters('newOrExistingManagedIdentity'), 'existing')]", + "delegatedManagedIdentityResourceId": "[if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')))]" }, "resources": [ { - "type": "Microsoft.ContainerService/managedClusters/agentPools", - "apiVersion": "2023-10-02-preview", - "name": "[format('{0}/{1}', parameters('AksName'), parameters('PoolName'))]", + "condition": "[not(variables('useExistingManagedIdentity'))]", + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2023-01-31", + "name": "[parameters('managedIdentityName')]", + "location": "[parameters('location')]" + }, + { + "copy": { + "name": "rbac", + "count": "[length(parameters('rbacRolesNeeded'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.ContainerService/managedClusters/{0}', parameters('aksName'))]", + "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('aksName')), parameters('rbacRolesNeeded')[copyIndex()], if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))))]", "properties": { - "mode": "User", - "vmSize": "[parameters('agentVMSize')]", - "count": "[parameters('agentCount')]", - "minCount": "[if(variables('autoScale'), parameters('agentCount'), null())]", - "maxCount": "[if(variables('autoScale'), parameters('agentCountMax'), null())]", - "enableAutoScaling": "[variables('autoScale')]", - "availabilityZones": "[if(not(empty(parameters('availabilityZones'))), parameters('availabilityZones'), null())]", - "osDiskType": "[parameters('osDiskType')]", - "osDiskSizeGB": "[parameters('osDiskSizeGB')]", - "osType": "[parameters('osType')]", - "maxPods": "[parameters('maxPods')]", - "type": "VirtualMachineScaleSets", - "vnetSubnetID": "[if(not(empty(parameters('subnetId'))), parameters('subnetId'), null())]", - "upgradeSettings": { - "maxSurge": "33%" - }, - "nodeTaints": "[parameters('nodeTaints')]", - "nodeLabels": "[parameters('nodeLabels')]" + "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('rbacRolesNeeded')[copyIndex()])]", + "principalId": "[if(variables('useExistingManagedIdentity'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), '2023-01-31').principalId, reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), '2023-01-31').principalId)]", + "principalType": "ServicePrincipal", + "delegatedManagedIdentityResourceId": "[if(parameters('isCrossTenant'), variables('delegatedManagedIdentityResourceId'), null())]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))]" + ] + }, + { + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[format('script-{0}-{1}', parameters('aksName'), deployment().name)]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))))]": {} + } + }, + "kind": "AzureCLI", + "properties": { + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "azCliVersion": "2.54.0", + "timeout": "PT10M", + "retentionInterval": "P1D", + "environmentVariables": [ + { + "name": "RG", + "value": "[resourceGroup().name]" + }, + { + "name": "aksName", + "value": "[parameters('aksName')]" + }, + { + "name": "configMap", + "value": "[parameters('name')]" + }, + { + "name": "namespace", + "value": "[parameters('namespace')]" + }, + { + "name": "dataPropertyLike", + "value": "[join(parameters('propertyData'), ';')]" + }, + { + "name": "dataFileLike", + "value": "[join(parameters('fileData'), ';')]" + }, + { + "name": "initialDelay", + "value": "[parameters('initialScriptDelay')]" + } + ], + "scriptContent": "[variables('$fxv#0')]", + "cleanupPreference": "[parameters('cleanupPreference')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))]", + "rbac" + ] + } + ], + "outputs": { + "commandOutput": { + "type": "object", + "metadata": { + "description": "Array of command output from each Deployment Script AKS run command" + }, + "value": { + "Name": "[format('script-{0}-{1}', parameters('aksName'), deployment().name)]", + "CommandOutput": "[reference(resourceId('Microsoft.Resources/deploymentScripts', format('script-{0}-{1}', parameters('aksName'), deployment().name)), '2020-10-01').outputs]" } } - ] + } } }, "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('serviceLayerConfig').name))]", "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]" ] }, { + "condition": "[variables('enableConfigMap')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-espool3', variables('serviceLayerConfig').name)]", + "name": "[format('{0}-cluster-appconfigmap', variables('serviceLayerConfig').name)]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { - "AksName": { + "aksName": { "value": "[reference(resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name)), '2022-09-01').outputs.aksClusterName.value]" }, - "PoolName": { - "value": "espoolz3" - }, - "agentVMSize": { - "value": "[variables('elasticPoolPresets')[parameters('clusterSize')].vmSize]" - }, - "agentCount": { - "value": 2 - }, - "agentCountMax": { - "value": 4 + "location": { + "value": "[parameters('location')]" }, - "availabilityZones": { - "value": [ - "3" - ] + "name": { + "value": "app-config-values" }, - "subnetId": { - "value": "" + "namespace": { + "value": "default" }, - "nodeTaints": { + "fileData": { "value": [ - "app=elasticsearch:NoSchedule" + "[format(variables('configMaps').appConfigTemplate, reference(resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('serviceLayerConfig').name)), '2022-09-01').outputs.clientId.value, reference(resourceId('Microsoft.Resources/deployments', format('{0}-appconfig', variables('serviceLayerConfig').name)), '2022-09-01').outputs.endpoint.value)]" ] - }, - "nodeLabels": { - "value": { - "app": "elasticsearch" - } } }, "template": { @@ -21102,157 +22302,272 @@ "_generator": { "name": "bicep", "version": "0.24.24.22086", - "templateHash": "2918991882660483195" - } + "templateHash": "4801579897722142587" + }, + "name": "AKS Config Map", + "description": "An Azure CLI Deployment Script that allows you to create a helm char on a Kubernetes cluster.", + "owner": "Daniel Scholl" }, "parameters": { - "AksName": { - "type": "string" + "aksName": { + "type": "string", + "metadata": { + "description": "The name of the Azure Kubernetes Service" + } }, - "PoolName": { - "type": "string" + "location": { + "type": "string", + "metadata": { + "description": "The location to deploy the resources to" + } }, - "availabilityZones": { + "forceUpdateTag": { + "type": "string", + "defaultValue": "[utcNow()]", + "metadata": { + "description": "How the deployment script should be forced to execute" + } + }, + "rbacRolesNeeded": { "type": "array", - "defaultValue": [], + "defaultValue": [ + "b24988ac-6180-42a0-ab88-20f7382dd24c", + "7f6c6a51-bcf8-42ba-9220-52d62157d7db" + ], "metadata": { - "description": "The zones to use for a node pool" + "description": "An array of Azure RoleIds that are required for the DeploymentScript resource" } }, - "osDiskType": { + "newOrExistingManagedIdentity": { "type": "string", - "defaultValue": "Ephemeral", + "defaultValue": "new", + "allowedValues": [ + "new", + "existing" + ], "metadata": { - "description": "OS disk type" + "description": "Create \"new\" or use \"existing\" Managed Identity. Default: new" } }, - "agentVMSize": { + "managedIdentityName": { "type": "string", - "defaultValue": "Standard_DS3_v2", + "defaultValue": "[format('id-AksConfigMap-{0}', parameters('location'))]", "metadata": { - "description": "VM SKU" + "description": "Name of the Managed Identity resource" } }, - "osDiskSizeGB": { - "type": "int", - "defaultValue": 0, + "existingManagedIdentitySubId": { + "type": "string", + "defaultValue": "[subscription().subscriptionId]", "metadata": { - "description": "Disk size in GB" + "description": "For an existing Managed Identity, the Subscription Id it is located in" } }, - "agentCount": { - "type": "int", - "defaultValue": 3, + "existingManagedIdentityResourceGroupName": { + "type": "string", + "defaultValue": "[resourceGroup().name]", "metadata": { - "description": "The number of agents for the user node pool" + "description": "For an existing Managed Identity, the Resource Group it is located in" } }, - "agentCountMax": { - "type": "int", - "defaultValue": 0, + "name": { + "type": "string", + "defaultValue": "configuration", "metadata": { - "description": "The maximum number of nodes for the user node pool" + "description": "Specify the config map name." } }, - "maxPods": { - "type": "int", - "defaultValue": 30, + "namespace": { + "type": "string", + "defaultValue": "default", "metadata": { - "description": "The maximum number of pods per node." + "description": "Specify the namespace for the config mapl" } }, - "nodeTaints": { + "propertyData": { "type": "array", "defaultValue": [], "metadata": { - "description": "Any taints that should be applied to the node pool" + "description": "Specify the config map single property data. (e.g. \"player_initial_lives=3\")" } }, - "nodeLabels": { - "type": "object", - "defaultValue": {}, + "fileData": { + "type": "array", + "defaultValue": [], "metadata": { - "description": "Any labels that should be applied to the node pool" + "description": "Specify the config map file data. (e.g. \"game.properties: |enemy.types=aliens,monsters\nplayer.maximum-lives=5\")" } }, - "subnetId": { + "initialScriptDelay": { "type": "string", + "defaultValue": "120s", "metadata": { - "description": "The subnet the node pool will use" + "description": "A delay before the script import operation starts. Primarily to allow Azure AAD Role Assignments to propagate" } }, - "osType": { + "cleanupPreference": { "type": "string", - "defaultValue": "Linux", + "defaultValue": "OnSuccess", "allowedValues": [ - "Linux", - "Windows" + "OnSuccess", + "OnExpiration", + "Always" ], "metadata": { - "description": "OS Type for the node pool" + "description": "When the script resource is cleaned up" + } + }, + "isCrossTenant": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Set to true when deploying template across tenants" } } }, "variables": { - "autoScale": "[greater(parameters('agentCountMax'), parameters('agentCount'))]" + "$fxv#0": "\nset -e +H\n# -e to exit on error\n# +H to prevent history expansion\n\n# This script is used to apply a ConfigMap to an AKS cluster using the az aks command invoke command.\n\nif [ \"$initialDelay\" != \"0\" ]\nthen\n echo \"Waiting on RBAC replication ($initialDelay)\"\n sleep $initialDelay\n\n #Force RBAC refresh\n az logout\n az login --identity\nfi\n\n# Function to convert semi-colon-separated key-value pairs in $dataPropertyLike to YAML format\nconvert_properties_to_yaml() {\n local IFS=\";\"\n for pair in $dataPropertyLike; do\n IFS='=' read -r key value <<< \"$pair\"\n echo \" $key: \\\"$value\\\"\"\n done\n echo \"\" # Add an empty line for separation\n}\n\n# Function to append file-like data in $dataFileLike to YAML format, converting \\t to spaces\nappend_files_to_yaml() {\n local IFS=\";\"\n for file in $dataFileLike; do\n local name=\"${file%%: *}\"\n local content=\"${file#*: |}\"\n # Process content to ensure correct new line handling and indentation\n content=$(echo \"$content\" | sed 's/\\\\n/\\n/g' | sed 's/^/ /') # Adjust for actual new lines and indent\n echo \" $name: |\"\n echo \"$content\"\n done\n}\n\n\necho \"Checking and updating configmap $configMap in AKS Cluster $aksName in $RG\"\n\n\n# Combining property-like and file-like data into the ConfigMap\ncombinedYaml=$(cat < $AZ_SCRIPTS_OUTPUT_PATH\n", + "useExistingManagedIdentity": "[equals(parameters('newOrExistingManagedIdentity'), 'existing')]", + "delegatedManagedIdentityResourceId": "[if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')))]" }, "resources": [ { - "type": "Microsoft.ContainerService/managedClusters/agentPools", - "apiVersion": "2023-10-02-preview", - "name": "[format('{0}/{1}', parameters('AksName'), parameters('PoolName'))]", + "condition": "[not(variables('useExistingManagedIdentity'))]", + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2023-01-31", + "name": "[parameters('managedIdentityName')]", + "location": "[parameters('location')]" + }, + { + "copy": { + "name": "rbac", + "count": "[length(parameters('rbacRolesNeeded'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.ContainerService/managedClusters/{0}', parameters('aksName'))]", + "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('aksName')), parameters('rbacRolesNeeded')[copyIndex()], if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))))]", "properties": { - "mode": "User", - "vmSize": "[parameters('agentVMSize')]", - "count": "[parameters('agentCount')]", - "minCount": "[if(variables('autoScale'), parameters('agentCount'), null())]", - "maxCount": "[if(variables('autoScale'), parameters('agentCountMax'), null())]", - "enableAutoScaling": "[variables('autoScale')]", - "availabilityZones": "[if(not(empty(parameters('availabilityZones'))), parameters('availabilityZones'), null())]", - "osDiskType": "[parameters('osDiskType')]", - "osDiskSizeGB": "[parameters('osDiskSizeGB')]", - "osType": "[parameters('osType')]", - "maxPods": "[parameters('maxPods')]", - "type": "VirtualMachineScaleSets", - "vnetSubnetID": "[if(not(empty(parameters('subnetId'))), parameters('subnetId'), null())]", - "upgradeSettings": { - "maxSurge": "33%" - }, - "nodeTaints": "[parameters('nodeTaints')]", - "nodeLabels": "[parameters('nodeLabels')]" + "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('rbacRolesNeeded')[copyIndex()])]", + "principalId": "[if(variables('useExistingManagedIdentity'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), '2023-01-31').principalId, reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), '2023-01-31').principalId)]", + "principalType": "ServicePrincipal", + "delegatedManagedIdentityResourceId": "[if(parameters('isCrossTenant'), variables('delegatedManagedIdentityResourceId'), null())]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))]" + ] + }, + { + "type": "Microsoft.Resources/deploymentScripts", + "apiVersion": "2020-10-01", + "name": "[format('script-{0}-{1}', parameters('aksName'), deployment().name)]", + "location": "[parameters('location')]", + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[format('{0}', if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))))]": {} + } + }, + "kind": "AzureCLI", + "properties": { + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "azCliVersion": "2.54.0", + "timeout": "PT10M", + "retentionInterval": "P1D", + "environmentVariables": [ + { + "name": "RG", + "value": "[resourceGroup().name]" + }, + { + "name": "aksName", + "value": "[parameters('aksName')]" + }, + { + "name": "configMap", + "value": "[parameters('name')]" + }, + { + "name": "namespace", + "value": "[parameters('namespace')]" + }, + { + "name": "dataPropertyLike", + "value": "[join(parameters('propertyData'), ';')]" + }, + { + "name": "dataFileLike", + "value": "[join(parameters('fileData'), ';')]" + }, + { + "name": "initialDelay", + "value": "[parameters('initialScriptDelay')]" + } + ], + "scriptContent": "[variables('$fxv#0')]", + "cleanupPreference": "[parameters('cleanupPreference')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))]", + "rbac" + ] + } + ], + "outputs": { + "commandOutput": { + "type": "object", + "metadata": { + "description": "Array of command output from each Deployment Script AKS run command" + }, + "value": { + "Name": "[format('script-{0}-{1}', parameters('aksName'), deployment().name)]", + "CommandOutput": "[reference(resourceId('Microsoft.Resources/deploymentScripts', format('script-{0}-{1}', parameters('aksName'), deployment().name)), '2020-10-01').outputs]" } } - ] + } } }, "dependsOn": [ - "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]" + "[resourceId('Microsoft.Resources/deployments', format('{0}-appconfig', variables('serviceLayerConfig').name))]", + "[resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('serviceLayerConfig').name))]", + "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]", + "[resourceId('Microsoft.Resources/deployments', 'helmAppConfigProvider')]" ] }, { - "condition": "[variables('enableConfigMap')]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-cluster-configmap', variables('serviceLayerConfig').name)]", + "name": "[format('{0}-appconfig', variables('serviceLayerConfig').name)]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { - "aksName": { - "value": "[reference(resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name)), '2022-09-01').outputs.aksClusterName.value]" + "resourceName": { + "value": "[variables('serviceLayerConfig').name]" }, "location": { "value": "[parameters('location')]" }, - "commands": { + "tags": { + "value": { + "layer": "[variables('serviceLayerConfig').displayName]" + } + }, + "roleAssignments": { "value": [ - "[format('kubectl create configmap app-config --from-literal=keyvault={0} -n default --save-config', reference(resourceId('Microsoft.Resources/deployments', format('{0}-azure-keyvault', variables('commonLayerConfig').name)), '2022-09-01').outputs.name.value)]" + { + "roleDefinitionIdOrName": "App Configuration Data Reader", + "principalIds": [ + "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('serviceLayerConfig').name)), '2022-09-01').outputs.principalId.value]" + ], + "principalType": "ServicePrincipal" + } ] }, - "cleanupPreference": { - "value": "Always" + "keyValues": { + "value": "[concat(variables('appSettings'))]" } }, "template": { @@ -21262,214 +22577,646 @@ "_generator": { "name": "bicep", "version": "0.24.24.22086", - "templateHash": "15573168867133922782" + "templateHash": "14285664342099441982" }, - "name": "AKS Run Command Script", - "description": "An Azure CLI Deployment Script that allows you to run a command on a Kubernetes cluster.", - "owner": "Aks-Bicep-Accelerator-Maintainers" + "name": "App Configuration", + "description": "This module deploys an App Configuration.", + "owner": "Azure/azure-global-energy" }, "parameters": { - "aksName": { + "resourceName": { "type": "string", + "minLength": 3, + "maxLength": 48, "metadata": { - "description": "The name of the Azure Kubernetes Service" + "description": "Used to name all resources" } }, "location": { "type": "string", + "defaultValue": "[resourceGroup().location]", "metadata": { - "description": "The location to deploy the resources to" + "description": "Resource Location." } }, - "forceUpdateTag": { + "lock": { "type": "string", - "defaultValue": "[utcNow()]", + "defaultValue": "NotSpecified", + "allowedValues": [ + "CanNotDelete", + "NotSpecified", + "ReadOnly" + ], "metadata": { - "description": "How the deployment script should be forced to execute" + "description": "Optional. Specify the type of lock." } }, - "rbacRolesNeeded": { - "type": "array", - "defaultValue": [ - "b24988ac-6180-42a0-ab88-20f7382dd24c", - "7f6c6a51-bcf8-42ba-9220-52d62157d7db" + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Tags." + } + }, + "sku": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Free", + "Standard" + ], + "metadata": { + "description": "Optional. Pricing tier of App Configuration." + } + }, + "createMode": { + "type": "string", + "defaultValue": "Default", + "allowedValues": [ + "Default", + "Recover" ], "metadata": { - "description": "An array of Azure RoleIds that are required for the DeploymentScript resource" + "description": "Optional. Indicates whether the configuration store need to be recovered." + } + }, + "disableLocalAuth": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Disables all authentication methods other than AAD authentication." + } + }, + "systemAssignedIdentity": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedIdentities": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. The ID(s) to assign to the resource." + } + }, + "keyValues": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. All Key / Values to create." + } + }, + "roleAssignments": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of objects that describe RBAC permissions, format { roleDefinitionResourceId (string), principalId (string), principalType (enum), enabled (bool) }. Ref: https://docs.microsoft.com/en-us/azure/templates/microsoft.authorization/roleassignments?tabs=bicep" } }, - "newOrExistingManagedIdentity": { + "diagnosticWorkspaceId": { "type": "string", - "defaultValue": "new", - "allowedValues": [ - "new", - "existing" - ], + "defaultValue": "", "metadata": { - "description": "Create \"new\" or use \"existing\" Managed Identity. Default: new" + "description": "Optional. Resource ID of the diagnostic log analytics workspace." } }, - "managedIdentityName": { + "diagnosticStorageAccountId": { "type": "string", - "defaultValue": "[format('id-AksRunCommandProxy-{0}', parameters('location'))]", + "defaultValue": "", "metadata": { - "description": "Name of the Managed Identity resource" + "description": "Optional. Resource ID of the diagnostic storage account." } }, - "existingManagedIdentitySubId": { + "diagnosticEventHubAuthorizationRuleId": { "type": "string", - "defaultValue": "[subscription().subscriptionId]", + "defaultValue": "", "metadata": { - "description": "For an existing Managed Identity, the Subscription Id it is located in" + "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." } }, - "existingManagedIdentityResourceGroupName": { + "diagnosticEventHubName": { "type": "string", - "defaultValue": "[resourceGroup().name]", + "defaultValue": "", "metadata": { - "description": "For an existing Managed Identity, the Resource Group it is located in" + "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." } }, - "commands": { - "type": "array", + "diagnosticLogsRetentionInDays": { + "type": "int", + "defaultValue": 365, + "minValue": 0, + "maxValue": 365, "metadata": { - "description": "An array of commands to run" + "description": "Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely." } }, - "initialScriptDelay": { - "type": "string", - "defaultValue": "120s", + "logsToEnable": { + "type": "array", + "defaultValue": [ + "HttpRequest", + "Audit" + ], + "allowedValues": [ + "HttpRequest", + "Audit" + ], "metadata": { - "description": "A delay before the script import operation starts. Primarily to allow Azure AAD Role Assignments to propagate" + "description": "Optional. The name of logs that will be streamed." } }, - "cleanupPreference": { - "type": "string", - "defaultValue": "OnSuccess", + "metricsToEnable": { + "type": "array", + "defaultValue": [ + "AllMetrics" + ], "allowedValues": [ - "OnSuccess", - "OnExpiration", - "Always" + "AllMetrics" ], "metadata": { - "description": "When the script resource is cleaned up" + "description": "Optional. The name of metrics that will be streamed." } }, - "isCrossTenant": { - "type": "bool", - "defaultValue": false, + "cmekConfiguration": { + "type": "object", + "defaultValue": { + "kvUrl": "", + "keyName": "", + "identityId": "" + }, "metadata": { - "description": "Set to true when deploying template across tenants" + "description": "Optional. Customer Managed Encryption Key." + } + }, + "privateLinkSettings": { + "type": "object", + "defaultValue": { + "subnetId": "1", + "vnetId": "1" + }, + "metadata": { + "description": "Settings Required to Enable Private Link" } } }, "variables": { - "$fxv#0": "#!/bin/bash\n\nset -e +H\n# -e to exit on error\n# +H to prevent history expansion\n\nif [ \"$loopIndex\" == \"0\" ] && [ \"$initialDelay\" != \"0\" ]\nthen\n echo \"Waiting on RBAC replication ($initialDelay)\"\n sleep $initialDelay\n\n #Force RBAC refresh\n az logout\n az login --identity\nfi\n\necho \"Sending command $command to AKS Cluster $aksName in $RG\"\ncmdOut=$(az aks command invoke -g $RG -n $aksName -o json --command \"${command}\")\necho $cmdOut\n\njsonOutputString=$cmdOut\necho $jsonOutputString > $AZ_SCRIPTS_OUTPUT_PATH\n", - "useExistingManagedIdentity": "[equals(parameters('newOrExistingManagedIdentity'), 'existing')]", - "delegatedManagedIdentityResourceId": "[if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')))]" + "copy": [ + { + "name": "diagnosticsLogs", + "count": "[length(parameters('logsToEnable'))]", + "input": { + "category": "[parameters('logsToEnable')[copyIndex('diagnosticsLogs')]]", + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + }, + { + "name": "diagnosticsMetrics", + "count": "[length(parameters('metricsToEnable'))]", + "input": { + "category": "[parameters('metricsToEnable')[copyIndex('diagnosticsMetrics')]]", + "timeGrain": null, + "enabled": true, + "retentionPolicy": { + "enabled": true, + "days": "[parameters('diagnosticLogsRetentionInDays')]" + } + } + } + ], + "name": "[format('ac-{0}{1}', replace(parameters('resourceName'), '-', ''), uniqueString(resourceGroup().id, parameters('resourceName')))]", + "enableCMEK": "[if(and(and(not(empty(parameters('cmekConfiguration').kvUrl)), not(empty(parameters('cmekConfiguration').keyName))), not(empty(parameters('cmekConfiguration').identityId))), true(), false())]", + "identityType": "[if(parameters('systemAssignedIdentity'), 'SystemAssigned', if(not(empty(parameters('userAssignedIdentities'))), 'UserAssigned', 'None'))]", + "enablePrivateLink": "[and(not(equals(parameters('privateLinkSettings').vnetId, '1')), not(equals(parameters('privateLinkSettings').subnetId, '1')))]", + "privateEndpointName": "[format('{0}-PrivateEndpoint', variables('name'))]", + "publicDNSZoneForwarder": "azconfig.io", + "privateDnsZoneName": "[format('privatelink.{0}', variables('publicDNSZoneForwarder'))]" }, "resources": [ { - "condition": "[not(variables('useExistingManagedIdentity'))]", - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2023-01-31", - "name": "[parameters('managedIdentityName')]", - "location": "[parameters('location')]" + "type": "Microsoft.AppConfiguration/configurationStores", + "apiVersion": "2022-05-01", + "name": "[if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('sku')]" + }, + "identity": "[if(not(empty(parameters('userAssignedIdentities'))), createObject('type', variables('identityType'), 'userAssignedIdentities', parameters('userAssignedIdentities')), createObject('type', variables('identityType')))]", + "properties": { + "createMode": "[parameters('createMode')]", + "disableLocalAuth": "[parameters('disableLocalAuth')]", + "encryption": "[if(variables('enableCMEK'), createObject('keyVaultProperties', createObject('identityClientId', parameters('cmekConfiguration').identityId, 'keyIdentifier', format('{0}/keys/{1}', parameters('cmekConfiguration').kvUrl, parameters('cmekConfiguration').keyName))), null())]" + } + }, + { + "condition": "[not(equals(parameters('lock'), 'NotSpecified'))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2017-04-01", + "scope": "[format('Microsoft.AppConfiguration/configurationStores/{0}', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]", + "name": "[format('{0}-{1}-lock', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')), parameters('lock'))]", + "properties": { + "level": "[parameters('lock')]", + "notes": "[if(equals(parameters('lock'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot modify the resource or child resources.')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.AppConfiguration/configurationStores', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]" + ] + }, + { + "condition": "[or(or(or(not(empty(parameters('diagnosticStorageAccountId'))), not(empty(parameters('diagnosticWorkspaceId')))), not(empty(parameters('diagnosticEventHubAuthorizationRuleId')))), not(empty(parameters('diagnosticEventHubName'))))]", + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.AppConfiguration/configurationStores/{0}', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]", + "name": "appconfig-diagnostics", + "properties": { + "storageAccountId": "[if(not(empty(parameters('diagnosticStorageAccountId'))), parameters('diagnosticStorageAccountId'), null())]", + "workspaceId": "[if(not(empty(parameters('diagnosticWorkspaceId'))), parameters('diagnosticWorkspaceId'), null())]", + "eventHubAuthorizationRuleId": "[if(not(empty(parameters('diagnosticEventHubAuthorizationRuleId'))), parameters('diagnosticEventHubAuthorizationRuleId'), null())]", + "eventHubName": "[if(not(empty(parameters('diagnosticEventHubName'))), parameters('diagnosticEventHubName'), null())]", + "metrics": "[variables('diagnosticsMetrics')]", + "logs": "[variables('diagnosticsLogs')]" + }, + "dependsOn": [ + "[resourceId('Microsoft.AppConfiguration/configurationStores', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]" + ] + }, + { + "condition": "[variables('enablePrivateLink')]", + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2020-06-01", + "name": "[variables('privateDnsZoneName')]", + "location": "global", + "properties": {} + }, + { + "condition": "[variables('enablePrivateLink')]", + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2022-01-01", + "name": "[variables('privateEndpointName')]", + "location": "[parameters('location')]", + "properties": { + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpointName')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.AppConfiguration/configurationStores', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]", + "groupIds": [ + "configurationStores" + ] + } + } + ], + "subnet": { + "id": "[parameters('privateLinkSettings').subnetId]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.AppConfiguration/configurationStores', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]" + ] + }, + { + "condition": "[variables('enablePrivateLink')]", + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2022-01-01", + "name": "[format('{0}/{1}', variables('privateEndpointName'), 'dnsgroupname')]", + "properties": { + "privateDnsZoneConfigs": [ + { + "name": "dnsConfig", + "properties": { + "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]" + } + } + ] + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]", + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointName'))]" + ] + }, + { + "condition": "[variables('enablePrivateLink')]", + "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", + "apiVersion": "2020-06-01", + "name": "[format('{0}/{1}', variables('privateDnsZoneName'), 'link_to_vnet')]", + "location": "global", + "properties": { + "registrationEnabled": false, + "virtualNetwork": { + "id": "[parameters('privateLinkSettings').vnetId]" + } + }, + "dependsOn": [ + "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]" + ] }, { "copy": { - "name": "rbac", - "count": "[length(parameters('rbacRolesNeeded'))]" + "name": "configurationStore_keyValues", + "count": "[length(parameters('keyValues'))]" }, - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.ContainerService/managedClusters/{0}', parameters('aksName'))]", - "name": "[guid(resourceId('Microsoft.ContainerService/managedClusters', parameters('aksName')), parameters('rbacRolesNeeded')[copyIndex()], if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-keyvalues-{1}', deployment().name, copyIndex())]", "properties": { - "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('rbacRolesNeeded')[copyIndex()])]", - "principalId": "[if(variables('useExistingManagedIdentity'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), '2023-01-31').principalId, reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), '2023-01-31').principalId)]", - "principalType": "ServicePrincipal", - "delegatedManagedIdentityResourceId": "[if(parameters('isCrossTenant'), variables('delegatedManagedIdentityResourceId'), null())]" + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "appConfigurationName": { + "value": "[if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name'))]" + }, + "name": { + "value": "[parameters('keyValues')[copyIndex()].name]" + }, + "value": { + "value": "[parameters('keyValues')[copyIndex()].value]" + }, + "label": "[if(contains(parameters('keyValues')[copyIndex()], 'label'), createObject('value', parameters('keyValues')[copyIndex()].label), createObject('value', ''))]", + "contentType": "[if(contains(parameters('keyValues')[copyIndex()], 'contentType'), createObject('value', parameters('keyValues')[copyIndex()].contentType), createObject('value', ''))]", + "tags": "[if(contains(parameters('keyValues')[copyIndex()], 'tags'), createObject('value', parameters('keyValues')[copyIndex()].tags), createObject('value', createObject()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "3690091182964384757" + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the key." + } + }, + "value": { + "type": "string", + "metadata": { + "description": "Required. Name of the value." + } + }, + "label": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Name of the Label." + } + }, + "appConfigurationName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent app configuration store. Required if the template is used in a standalone deployment." + } + }, + "contentType": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The content type of the key-values value. Providing a proper content-type can enable transformations of values when they are retrieved by applications." + } + }, + "tags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "variables": { + "keyValueName": "[if(empty(parameters('label')), parameters('name'), format('{0}${1}', parameters('name'), parameters('label')))]" + }, + "resources": [ + { + "type": "Microsoft.AppConfiguration/configurationStores/keyValues", + "apiVersion": "2022-05-01", + "name": "[format('{0}/{1}', parameters('appConfigurationName'), variables('keyValueName'))]", + "properties": { + "contentType": "[parameters('contentType')]", + "tags": "[parameters('tags')]", + "value": "[parameters('value')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the key values." + }, + "value": "[variables('keyValueName')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the key values." + }, + "value": "[resourceId('Microsoft.AppConfiguration/configurationStores/keyValues', parameters('appConfigurationName'), variables('keyValueName'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the batch account was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } }, "dependsOn": [ - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))]" + "[resourceId('Microsoft.AppConfiguration/configurationStores', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]" ] }, { "copy": { - "name": "runAksCommand", - "count": "[length(parameters('commands'))]", - "mode": "serial", - "batchSize": 1 - }, - "type": "Microsoft.Resources/deploymentScripts", - "apiVersion": "2020-10-01", - "name": "[format('script-{0}-{1}-{2}', parameters('aksName'), deployment().name, copyIndex())]", - "location": "[parameters('location')]", - "identity": { - "type": "UserAssigned", - "userAssignedIdentities": { - "[format('{0}', if(variables('useExistingManagedIdentity'), extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('existingManagedIdentitySubId'), parameters('existingManagedIdentityResourceGroupName')), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName')), resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))))]": {} - } + "name": "configStore_rbac", + "count": "[length(parameters('roleAssignments'))]" }, - "kind": "AzureCLI", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-rbac-{1}', deployment().name, copyIndex())]", "properties": { - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "azCliVersion": "2.35.0", - "timeout": "PT10M", - "retentionInterval": "P1D", - "environmentVariables": [ - { - "name": "RG", - "value": "[resourceGroup().name]" + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "description": "[if(contains(parameters('roleAssignments')[copyIndex()], 'description'), createObject('value', parameters('roleAssignments')[copyIndex()].description), createObject('value', ''))]", + "principalIds": { + "value": "[parameters('roleAssignments')[copyIndex()].principalIds]" }, - { - "name": "aksName", - "value": "[parameters('aksName')]" + "roleDefinitionIdOrName": { + "value": "[parameters('roleAssignments')[copyIndex()].roleDefinitionIdOrName]" }, - { - "name": "command", - "value": "[parameters('commands')[copyIndex()]]" + "principalType": "[if(contains(parameters('roleAssignments')[copyIndex()], 'principalType'), createObject('value', parameters('roleAssignments')[copyIndex()].principalType), createObject('value', ''))]", + "resourceId": { + "value": "[resourceId('Microsoft.AppConfiguration/configurationStores', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13612500138265831088" + } }, - { - "name": "initialDelay", - "value": "[parameters('initialScriptDelay')]" + "parameters": { + "principalIds": { + "type": "array", + "metadata": { + "description": "Required. The IDs of the principals to assign the role to." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of the resource to apply the role assignment to." + } + }, + "principalType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "ServicePrincipal", + "Group", + "User", + "ForeignGroup", + "Device", + "" + ], + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "defaultValue": "", + "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", + "defaultValue": "2.0", + "allowedValues": [ + "2.0" + ], + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Id of the delegated managed identity resource." + } + } }, - { - "name": "loopIndex", - "value": "[string(copyIndex())]" - } - ], - "scriptContent": "[variables('$fxv#0')]", - "cleanupPreference": "[parameters('cleanupPreference')]" + "variables": { + "builtInRoleNames": { + "App Compliance Automation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f37683f-2463-46b6-9ce7-9b788b988ba2')]", + "App Compliance Automation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ffc6bbe0-e443-4c3b-bf54-26581bb2f78e')]", + "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", + "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Managed Application Contributor Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e')]", + "Managed Application Operator Role": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae')]", + "Managed Applications Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": [ + { + "copy": { + "name": "roleAssignment", + "count": "[length(parameters('principalIds'))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.AppConfiguration/configurationStores/{0}', last(split(parameters('resourceId'), '/')))]", + "name": "[guid(resourceId('Microsoft.AppConfiguration/configurationStores', last(split(parameters('resourceId'), '/'))), parameters('principalIds')[copyIndex()], parameters('roleDefinitionIdOrName'))]", + "properties": { + "description": "[parameters('description')]", + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]", + "principalId": "[parameters('principalIds')[copyIndex()]]", + "principalType": "[if(not(empty(parameters('principalType'))), parameters('principalType'), null())]", + "condition": "[if(not(empty(parameters('condition'))), parameters('condition'), null())]", + "conditionVersion": "[if(and(not(empty(parameters('conditionVersion'))), not(empty(parameters('condition')))), parameters('conditionVersion'), null())]", + "delegatedManagedIdentityResourceId": "[if(not(empty(parameters('delegatedManagedIdentityResourceId'))), parameters('delegatedManagedIdentityResourceId'), null())]" + } + } + ] + } }, "dependsOn": [ - "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdentityName'))]", - "rbac" + "[resourceId('Microsoft.AppConfiguration/configurationStores', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]" ] } ], "outputs": { - "commandOutput": { - "type": "array", + "name": { + "type": "string", "metadata": { - "description": "Array of command output from each Deployment Script AKS run command" + "description": "The name of the azure app configuration service." }, - "copy": { - "count": "[length(parameters('commands'))]", - "input": { - "Index": "[copyIndex()]", - "Name": "[format('script-{0}-{1}-{2}', parameters('aksName'), deployment().name, copyIndex())]", - "CommandOutput": "[reference(resourceId('Microsoft.Resources/deploymentScripts', format('script-{0}-{1}-{2}', parameters('aksName'), deployment().name, copyIndex())), '2020-10-01').outputs]" - } - } + "value": "[if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name'))]" + }, + "id": { + "type": "string", + "metadata": { + "description": "The resourceId of the azure app configuration service." + }, + "value": "[resourceId('Microsoft.AppConfiguration/configurationStores', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name')))]" + }, + "endpoint": { + "type": "string", + "metadata": { + "description": "The endpoint of the azure app configuration service." + }, + "value": "[reference(resourceId('Microsoft.AppConfiguration/configurationStores', if(greater(length(variables('name')), 50), substring(variables('name'), 0, 50), variables('name'))), '2022-05-01').endpoint]" } } } }, "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', format('{0}-user-managed-identity', variables('serviceLayerConfig').name))]", "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]", - "[resourceId('Microsoft.Resources/deployments', format('{0}-azure-keyvault', variables('commonLayerConfig').name))]" + "[resourceId('Microsoft.Resources/deployments', 'helmAppConfigProvider')]" ] }, { @@ -21708,12 +23455,18 @@ } }, "dependsOn": [ - "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]", - "[resourceId('Microsoft.Resources/deployments', format('{0}-cluster-configmap', variables('serviceLayerConfig').name))]", - "[resourceId('Microsoft.Resources/deployments', format('{0}-espool1', variables('serviceLayerConfig').name))]", - "[resourceId('Microsoft.Resources/deployments', format('{0}-espool2', variables('serviceLayerConfig').name))]", - "[resourceId('Microsoft.Resources/deployments', format('{0}-espool3', variables('serviceLayerConfig').name))]" + "[resourceId('Microsoft.Resources/deployments', format('{0}-appconfig', variables('serviceLayerConfig').name))]", + "[resourceId('Microsoft.Resources/deployments', format('aks-{0}', variables('serviceLayerConfig').name))]" ] } - ] + ], + "outputs": { + "ENV_CONFIG_ENDPOINT": { + "type": "string", + "metadata": { + "description": "The name of the azure keyvault." + }, + "value": "[reference(resourceId('Microsoft.Resources/deployments', format('{0}-appconfig', variables('serviceLayerConfig').name)), '2022-09-01').outputs.endpoint.value]" + } + } } \ No newline at end of file