diff --git a/dev-infrastructure/modules/aks-cluster-base.bicep b/dev-infrastructure/modules/aks-cluster-base.bicep index 2ddfa0b93..ff72afe11 100644 --- a/dev-infrastructure/modules/aks-cluster-base.bicep +++ b/dev-infrastructure/modules/aks-cluster-base.bicep @@ -216,6 +216,16 @@ resource aksNetworkContributorRoleAssignment 'Microsoft.Authorization/roleAssign } } +resource aksClusterAdminRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + scope: aksCluster + name: guid(aksClusterUserDefinedManagedIdentity.id, aksClusterAdminRoleId, aksCluster.id) + properties: { + roleDefinitionId: aksClusterAdminRoleId + principalId: aksClusterUserDefinedManagedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + resource aksCluster 'Microsoft.ContainerService/managedClusters@2024-01-01' = { location: location name: aksClusterName @@ -375,6 +385,32 @@ resource uami_fedcred 'Microsoft.ManagedIdentity/userAssignedIdentities/federate } ] +module serviceAccounts './aks-manifest.bicep' = { + name: '${aksClusterName}-service-accounts' + params: { + name: '${aksClusterName}-service-accounts' + aksClusterName: aksClusterName + manifests: [ + for i in range(0, length(workloadIdentities)): { + apiVersion: 'v1' + kind: 'ServiceAccount' + metadata: { + name: workloadIdentities[i].value.uamiName + namespace: workloadIdentities[i].value.namespace + annotations: { + 'azure.workload.identity/client-id': uami[i].properties.clientId + } + } + } + ] + aksManagedIdentityId: aksClusterUserDefinedManagedIdentity.id + location: location + } + dependsOn: [ + aksClusterAdminRoleAssignment + ] +} + // Outputs output userAssignedIdentities array = [ for i in range(0, length(workloadIdentities)): { diff --git a/dev-infrastructure/modules/aks-manifest.bicep b/dev-infrastructure/modules/aks-manifest.bicep new file mode 100644 index 000000000..c1e9aae5a --- /dev/null +++ b/dev-infrastructure/modules/aks-manifest.bicep @@ -0,0 +1,77 @@ +param name string +param aksClusterName string +param location string +param aksManagedIdentityId string +param manifests array + +var namespaces = [for manifest in manifests: manifest.metadata.namespace] +var uniqueNamespaces = union(namespaces, []) +var namespaceManifests = [ + for i in range(0, length(uniqueNamespaces)): { + apiVersion: 'v1' + kind: 'Namespace' + metadata: { + name: uniqueNamespaces[i] + } + } +] +var namespaceManifestList = { + apiVersion: 'v1' + kind: 'List' + items: namespaceManifests +} + +var mainfestList = { + apiVersion: 'v1' + kind: 'List' + items: manifests +} + +resource deploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = { + name: name + location: location + kind: 'AzureCLI' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${aksManagedIdentityId}': {} + } + } + + properties: { + azCliVersion: '2.30.0' + cleanupPreference: 'OnSuccess' + retentionInterval: 'P1D' + scriptContent: ''' + az login --identity + az aks install-cli + az aks get-credentials --resource-group ${AKS_CLUSTER_RG} --name ${AKS_CLUSTER_NAME} --overwrite-existing -a + echo "${NAMESPACE_MANIFESTS}" | base64 -d | kubectl apply -f - + echo "${MANIFESTS}" | base64 -d | kubectl apply -f - + ''' + // todo figure out how to leverage az aks command invoke to + // * avoid installing kubectl + // * avoid the need for a network path to the cluster + // + // right now az aks command invoke fails with `MissingAADClusterToken` when run within a deploymentscript + environmentVariables: [ + { + name: 'AKS_CLUSTER_RG' + value: resourceGroup().name + } + { + name: 'AKS_CLUSTER_NAME' + value: aksClusterName + } + { + name: 'NAMESPACE_MANIFESTS' + value: base64(string(namespaceManifestList)) + } + { + name: 'MANIFESTS' + value: base64(string(mainfestList)) + } + ] + timeout: 'PT30M' + } +}