From cff2fba676b6a1d98fff6f8c985a145a4b690f95 Mon Sep 17 00:00:00 2001 From: Hangyu Xu Date: Mon, 17 Feb 2025 14:42:24 +0800 Subject: [PATCH 1/4] init connected clusters --- .github/CODEOWNERS | 1 + .github/ISSUE_TEMPLATE/avm_module_issue.yml | 1 + .../avm-validateModuleDeployment/action.yml | 1 + .../avm.res.kubernetes.connected-clusters.yml | 88 +++++ .../kubernetes/connected-clusters/README.md | 303 ++++++++++++++++++ .../kubernetes/connected-clusters/main.bicep | 120 +++++++ .../kubernetes/connected-clusters/main.json | 188 +++++++++++ .../tests/e2e/defaults/main.test.bicep | 31 ++ .../tests/e2e/waf-aligned/main.test.bicep | 33 ++ .../connected-clusters/version.json | 7 + 10 files changed, 773 insertions(+) create mode 100644 .github/workflows/avm.res.kubernetes.connected-clusters.yml create mode 100644 avm/res/kubernetes/connected-clusters/README.md create mode 100644 avm/res/kubernetes/connected-clusters/main.bicep create mode 100644 avm/res/kubernetes/connected-clusters/main.json create mode 100644 avm/res/kubernetes/connected-clusters/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/kubernetes/connected-clusters/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/kubernetes/connected-clusters/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e2ab1172d0..cd51e2b545 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -105,6 +105,7 @@ /avm/res/key-vault/vault/ @Azure/avm-res-keyvault-vault-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/kubernetes-configuration/extension/ @Azure/avm-res-kubernetesconfiguration-extension-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/kubernetes-configuration/flux-configuration/ @Azure/avm-res-kubernetesconfiguration-fluxconfiguration-module-owners-bicep @Azure/avm-module-reviewers-bicep +/avm/res/kubernetes/connected-clusters/ @Azure/avm-res-kubernetes-connectedclusters-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/kusto/cluster/ @Azure/avm-res-kusto-cluster-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/load-test-service/load-test/ @Azure/avm-res-loadtestservice-loadtest-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/logic/workflow/ @Azure/avm-res-logic-workflow-module-owners-bicep @Azure/avm-module-reviewers-bicep diff --git a/.github/ISSUE_TEMPLATE/avm_module_issue.yml b/.github/ISSUE_TEMPLATE/avm_module_issue.yml index 871a9782a5..76b5c19415 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -140,6 +140,7 @@ body: - "avm/res/key-vault/vault" - "avm/res/kubernetes-configuration/extension" - "avm/res/kubernetes-configuration/flux-configuration" + - "avm/res/kubernetes/connected-clusters" - "avm/res/kusto/cluster" - "avm/res/load-test-service/load-test" - "avm/res/logic/workflow" diff --git a/.github/actions/templates/avm-validateModuleDeployment/action.yml b/.github/actions/templates/avm-validateModuleDeployment/action.yml index f127041711..3a3175855d 100644 --- a/.github/actions/templates/avm-validateModuleDeployment/action.yml +++ b/.github/actions/templates/avm-validateModuleDeployment/action.yml @@ -77,6 +77,7 @@ runs: 'avm/res/azure-stack-hci/cluster' # Failing on resource deletion when trying to delete RBAC at subscription level 'avm/res/compute/image' # Failing on resource deletion when trying to delete RBAC at subscription level 'avm/res/compute/disk' # Failing on resource deletion when trying to delete RBAC at subscription level + 'avm/res/kubernetes/connected-clusters' # Failing on resource deletion when trying to delete RBAC at subscription level 'avm/ptn/virtual-machine-images/azure-image-builder' # Failing on resource deletion when trying to delete RBAC at subscription level ) if ($exceptionModulePaths.Contains($modulePath)) { diff --git a/.github/workflows/avm.res.kubernetes.connected-clusters.yml b/.github/workflows/avm.res.kubernetes.connected-clusters.yml new file mode 100644 index 0000000000..fddd8b6536 --- /dev/null +++ b/.github/workflows/avm.res.kubernetes.connected-clusters.yml @@ -0,0 +1,88 @@ +name: "avm.res.kubernetes.connected-clusters" + +on: + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + customLocation: + type: string + description: "Default location overwrite (e.g., eastus)" + required: false + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.kubernetes.connected-clusters.yml" + - "avm/res/kubernetes/connected-clusters/**" + - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/kubernetes/connected-clusters" + workflowPath: ".github/workflows/avm.res.kubernetes.connected-clusters.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/kubernetes/connected-clusters/README.md b/avm/res/kubernetes/connected-clusters/README.md new file mode 100644 index 0000000000..76d9bd98ac --- /dev/null +++ b/avm/res/kubernetes/connected-clusters/README.md @@ -0,0 +1,303 @@ +# Kubernetes Connected Clusters `[Microsoft.Kubernetes/connectedClusters]` + +Deploy an Azure Arc connected cluster. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Kubernetes/connectedClusters` | [2024-07-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Kubernetes/2024-07-15-preview/connectedClusters) | + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/kubernetes/connected-clusters:`. + +- [Deploy connected clusters in default configuration](#example-1-deploy-connected-clusters-in-default-configuration) +- [Deploy connected clusters in WAF aligned configuration](#example-2-deploy-connected-clusters-in-waf-aligned-configuration) + +### Example 1: _Deploy connected clusters in default configuration_ + +This test deploys a connected clusters. + + +
+ +via Bicep module + +```bicep +module connectedClusters 'br/public:avm/res/kubernetes/connected-clusters:' = { + name: 'connectedClustersDeployment' + params: { + // Required parameters + name: 'kccmin001' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

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

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/kubernetes/connected-clusters:' + +// Required parameters +param name = 'kccmin001' +// Non-required parameters +param location = '' +``` + +
+

+ +### Example 2: _Deploy connected clusters in WAF aligned configuration_ + +This test deploys a connected clusters. + + +

+ +via Bicep module + +```bicep +module connectedClusters 'br/public:avm/res/kubernetes/connected-clusters:' = { + name: 'connectedClustersDeployment' + params: { + // Required parameters + name: 'kccwaf001' + // Non-required parameters + location: '' + oidcIssuerEnabled: true + workloadIdentityEnabled: true + } +} +``` + +
+

+ +

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

+ +

+ +via Bicep parameters file + +```bicep-params +using 'br/public:avm/res/kubernetes/connected-clusters:' + +// Required parameters +param name = 'kccwaf001' +// Non-required parameters +param location = '' +param oidcIssuerEnabled = true +param workloadIdentityEnabled = true +``` + +
+

+ +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the Azure Arc connected cluster. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`aadAdminGroupObjectIds`](#parameter-aadadmingroupobjectids) | array | The Azure AD admin group object IDs. | +| [`aadTenantId`](#parameter-aadtenantid) | string | Optional. The Azure AD tenant ID. | +| [`agentAutoUpgrade`](#parameter-agentautoupgrade) | string | Enable automatic agent upgrades. | +| [`enableAzureRBAC`](#parameter-enableazurerbac) | bool | Enable Azure RBAC. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`identityType`](#parameter-identitytype) | string | The identity type for the cluster. Allowed values: "SystemAssigned", "None". | +| [`location`](#parameter-location) | string | Location for all Resources. | +| [`oidcIssuerEnabled`](#parameter-oidcissuerenabled) | bool | Enable OIDC issuer. | +| [`tags`](#parameter-tags) | object | Tags for the cluster resource. | +| [`workloadIdentityEnabled`](#parameter-workloadidentityenabled) | bool | Enable workload identity. | + +### Parameter: `name` + +The name of the Azure Arc connected cluster. + +- Required: Yes +- Type: string + +### Parameter: `aadAdminGroupObjectIds` + +The Azure AD admin group object IDs. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `aadTenantId` + +Optional. The Azure AD tenant ID. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `agentAutoUpgrade` + +Enable automatic agent upgrades. + +- Required: No +- Type: string +- Default: `'Enabled'` +- Allowed: + ```Bicep + [ + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `enableAzureRBAC` + +Enable Azure RBAC. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `identityType` + +The identity type for the cluster. Allowed values: "SystemAssigned", "None". + +- Required: No +- Type: string +- Default: `'SystemAssigned'` +- Allowed: + ```Bicep + [ + 'None' + 'SystemAssigned' + ] + ``` + +### Parameter: `location` + +Location for all Resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `oidcIssuerEnabled` + +Enable OIDC issuer. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `tags` + +Tags for the cluster resource. + +- Required: No +- Type: object + +### Parameter: `workloadIdentityEnabled` + +Enable workload identity. + +- Required: No +- Type: bool +- Default: `False` + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `connectedClusterId` | string | The resource ID of the connected cluster. | +| `location` | string | The location of the connected cluster. | +| `name` | string | The name of the connected cluster. | +| `resourceGroupName` | string | The resource group of the connected cluster. | +| `resourceId` | string | The ID of the connected cluster. | + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/kubernetes/connected-clusters/main.bicep b/avm/res/kubernetes/connected-clusters/main.bicep new file mode 100644 index 0000000000..1d86f9f076 --- /dev/null +++ b/avm/res/kubernetes/connected-clusters/main.bicep @@ -0,0 +1,120 @@ +metadata name = 'Kubernetes Connected Clusters' +metadata description = 'Deploy an Azure Arc connected cluster.' + +// ============== // +// Parameters // +// ============== // + +@description('Required. The name of the Azure Arc connected cluster.') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +@description('Optional. The identity type for the cluster. Allowed values: "SystemAssigned", "None".') +@allowed([ + 'SystemAssigned' + 'None' +]) +param identityType string = 'SystemAssigned' + +@description('Optional. Tags for the cluster resource.') +param tags object? + +@description('Optional. Optional. The Azure AD tenant ID.') +param aadTenantId string = '' + +@description('Optional. The Azure AD admin group object IDs.') +param aadAdminGroupObjectIds array = [] + +@description('Optional. Enable Azure RBAC.') +param enableAzureRBAC bool = false + +@description('Optional. Enable automatic agent upgrades.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param agentAutoUpgrade string = 'Enabled' + +@description('Optional. Enable OIDC issuer.') +param oidcIssuerEnabled bool = false + +@description('Optional. Enable workload identity.') +param workloadIdentityEnabled bool = false + +// ============= // +// Resources // +// ============= // + +#disable-next-line no-deployments-resources +resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableTelemetry) { + name: '46d3xbcp.res.kubernetes-connectedcluster.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +// Resource definition +resource connectedCluster 'Microsoft.Kubernetes/connectedClusters@2024-07-15-preview' = { + name: name + kind: 'ProvisionedCluster' + location: location + identity: { + type: identityType + } + tags: tags + properties: { + aadProfile: !empty(aadTenantId) + ? { + tenantID: aadTenantId + adminGroupObjectIDs: aadAdminGroupObjectIds + enableAzureRBAC: enableAzureRBAC + } + : null + agentPublicKeyCertificate: '' + arcAgentProfile: { + agentAutoUpgrade: agentAutoUpgrade + } + distribution: null + infrastructure: null + oidcIssuerProfile: { + enabled: oidcIssuerEnabled + } + securityProfile: { + workloadIdentity: { + enabled: workloadIdentityEnabled + } + } + azureHybridBenefit: null + } +} + +@description('The name of the connected cluster.') +output name string = connectedCluster.name + +@description('The ID of the connected cluster.') +output resourceId string = connectedCluster.id + +@description('The resource group of the connected cluster.') +output resourceGroupName string = resourceGroup().name + +@description('The location of the connected cluster.') +output location string = connectedCluster.location + +@description('The resource ID of the connected cluster.') +output connectedClusterId string = connectedCluster.id diff --git a/avm/res/kubernetes/connected-clusters/main.json b/avm/res/kubernetes/connected-clusters/main.json new file mode 100644 index 0000000000..1e1a8b0795 --- /dev/null +++ b/avm/res/kubernetes/connected-clusters/main.json @@ -0,0 +1,188 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.32.4.45862", + "templateHash": "15406540205079791461" + }, + "name": "Kubernetes Connected Clusters", + "description": "Deploy an Azure Arc connected cluster." + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Azure Arc connected cluster." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "identityType": { + "type": "string", + "defaultValue": "SystemAssigned", + "allowedValues": [ + "SystemAssigned", + "None" + ], + "metadata": { + "description": "Optional. The identity type for the cluster. Allowed values: \"SystemAssigned\", \"None\"." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for the cluster resource." + } + }, + "aadTenantId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Optional. The Azure AD tenant ID." + } + }, + "aadAdminGroupObjectIds": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The Azure AD admin group object IDs." + } + }, + "enableAzureRBAC": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enable Azure RBAC." + } + }, + "agentAutoUpgrade": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Enable automatic agent upgrades." + } + }, + "oidcIssuerEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enable OIDC issuer." + } + }, + "workloadIdentityEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Enable workload identity." + } + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.kubernetes-connectedcluster.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "connectedCluster": { + "type": "Microsoft.Kubernetes/connectedClusters", + "apiVersion": "2024-07-15-preview", + "name": "[parameters('name')]", + "kind": "ProvisionedCluster", + "location": "[parameters('location')]", + "identity": { + "type": "[parameters('identityType')]" + }, + "tags": "[parameters('tags')]", + "properties": { + "aadProfile": "[if(not(empty(parameters('aadTenantId'))), createObject('tenantID', parameters('aadTenantId'), 'adminGroupObjectIDs', parameters('aadAdminGroupObjectIds'), 'enableAzureRBAC', parameters('enableAzureRBAC')), null())]", + "agentPublicKeyCertificate": "", + "arcAgentProfile": { + "agentAutoUpgrade": "[parameters('agentAutoUpgrade')]" + }, + "distribution": null, + "infrastructure": null, + "oidcIssuerProfile": { + "enabled": "[parameters('oidcIssuerEnabled')]" + }, + "securityProfile": { + "workloadIdentity": { + "enabled": "[parameters('workloadIdentityEnabled')]" + } + }, + "azureHybridBenefit": null + } + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the connected cluster." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The ID of the connected cluster." + }, + "value": "[resourceId('Microsoft.Kubernetes/connectedClusters', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the connected cluster." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location of the connected cluster." + }, + "value": "[reference('connectedCluster', '2024-07-15-preview', 'full').location]" + }, + "connectedClusterId": { + "type": "string", + "metadata": { + "description": "The resource ID of the connected cluster." + }, + "value": "[resourceId('Microsoft.Kubernetes/connectedClusters', parameters('name'))]" + } + } +} \ No newline at end of file diff --git a/avm/res/kubernetes/connected-clusters/tests/e2e/defaults/main.test.bicep b/avm/res/kubernetes/connected-clusters/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..83e94fb239 --- /dev/null +++ b/avm/res/kubernetes/connected-clusters/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,31 @@ +targetScope = 'subscription' + +metadata name = 'Deploy connected clusters in default configuration' +metadata description = 'This test deploys a connected clusters.' + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-kubernets-connectedcluster-${serviceShort}-rg' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'kccmin' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +#disable-next-line no-hardcoded-location // Due to quotas and capacity challenges, this region must be used in the AVM testing subscription +var enforcedLocation = 'southeastasia' + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + name: '${namePrefix}${serviceShort}001' + location: enforcedLocation + } +} diff --git a/avm/res/kubernetes/connected-clusters/tests/e2e/waf-aligned/main.test.bicep b/avm/res/kubernetes/connected-clusters/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..d11d57645e --- /dev/null +++ b/avm/res/kubernetes/connected-clusters/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,33 @@ +targetScope = 'subscription' + +metadata name = 'Deploy connected clusters in WAF aligned configuration' +metadata description = 'This test deploys a connected clusters.' + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-kubernets-connectedcluster-${serviceShort}-rg' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'kccwaf' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +#disable-next-line no-hardcoded-location // Due to quotas and capacity challenges, this region must be used in the AVM testing subscription +var enforcedLocation = 'southeastasia' + +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: enforcedLocation +} + +module testDeployment '../../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, enforcedLocation)}-test-${serviceShort}' + params: { + name: '${namePrefix}${serviceShort}001' + location: enforcedLocation + oidcIssuerEnabled: true + workloadIdentityEnabled: true + } +} diff --git a/avm/res/kubernetes/connected-clusters/version.json b/avm/res/kubernetes/connected-clusters/version.json new file mode 100644 index 0000000000..8def869ede --- /dev/null +++ b/avm/res/kubernetes/connected-clusters/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} From 33f0b3f3f78c07b079cdc01c2c6d10e6577aa05f Mon Sep 17 00:00:00 2001 From: Hangyu Xu Date: Tue, 18 Feb 2025 12:40:30 +0800 Subject: [PATCH 2/4] rename --- .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/avm_module_issue.yml | 2 +- .../avm-validateModuleDeployment/action.yml | 1 - ... avm.res.kubernetes.connected-cluster.yml} | 10 +++---- .../README.md | 27 +++++++++---------- .../main.bicep | 7 ++--- .../main.json | 15 +++-------- .../tests/e2e/defaults/main.test.bicep | 4 +-- .../tests/e2e/waf-aligned/main.test.bicep | 2 +- .../version.json | 0 10 files changed, 29 insertions(+), 41 deletions(-) rename .github/workflows/{avm.res.kubernetes.connected-clusters.yml => avm.res.kubernetes.connected-cluster.yml} (92%) rename avm/res/kubernetes/{connected-clusters => connected-cluster}/README.md (88%) rename avm/res/kubernetes/{connected-clusters => connected-cluster}/main.bicep (93%) rename avm/res/kubernetes/{connected-clusters => connected-cluster}/main.json (92%) rename avm/res/kubernetes/{connected-clusters => connected-cluster}/tests/e2e/defaults/main.test.bicep (87%) rename avm/res/kubernetes/{connected-clusters => connected-cluster}/tests/e2e/waf-aligned/main.test.bicep (95%) rename avm/res/kubernetes/{connected-clusters => connected-cluster}/version.json (100%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cd51e2b545..40c8b77871 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -105,7 +105,7 @@ /avm/res/key-vault/vault/ @Azure/avm-res-keyvault-vault-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/kubernetes-configuration/extension/ @Azure/avm-res-kubernetesconfiguration-extension-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/kubernetes-configuration/flux-configuration/ @Azure/avm-res-kubernetesconfiguration-fluxconfiguration-module-owners-bicep @Azure/avm-module-reviewers-bicep -/avm/res/kubernetes/connected-clusters/ @Azure/avm-res-kubernetes-connectedclusters-module-owners-bicep @Azure/avm-module-reviewers-bicep +/avm/res/kubernetes/connected-cluster/ @Azure/avm-res-kubernetes-connectedcluster-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/kusto/cluster/ @Azure/avm-res-kusto-cluster-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/load-test-service/load-test/ @Azure/avm-res-loadtestservice-loadtest-module-owners-bicep @Azure/avm-module-reviewers-bicep /avm/res/logic/workflow/ @Azure/avm-res-logic-workflow-module-owners-bicep @Azure/avm-module-reviewers-bicep diff --git a/.github/ISSUE_TEMPLATE/avm_module_issue.yml b/.github/ISSUE_TEMPLATE/avm_module_issue.yml index 76b5c19415..501510025f 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -140,7 +140,7 @@ body: - "avm/res/key-vault/vault" - "avm/res/kubernetes-configuration/extension" - "avm/res/kubernetes-configuration/flux-configuration" - - "avm/res/kubernetes/connected-clusters" + - "avm/res/kubernetes/connected-cluster" - "avm/res/kusto/cluster" - "avm/res/load-test-service/load-test" - "avm/res/logic/workflow" diff --git a/.github/actions/templates/avm-validateModuleDeployment/action.yml b/.github/actions/templates/avm-validateModuleDeployment/action.yml index 3a3175855d..f127041711 100644 --- a/.github/actions/templates/avm-validateModuleDeployment/action.yml +++ b/.github/actions/templates/avm-validateModuleDeployment/action.yml @@ -77,7 +77,6 @@ runs: 'avm/res/azure-stack-hci/cluster' # Failing on resource deletion when trying to delete RBAC at subscription level 'avm/res/compute/image' # Failing on resource deletion when trying to delete RBAC at subscription level 'avm/res/compute/disk' # Failing on resource deletion when trying to delete RBAC at subscription level - 'avm/res/kubernetes/connected-clusters' # Failing on resource deletion when trying to delete RBAC at subscription level 'avm/ptn/virtual-machine-images/azure-image-builder' # Failing on resource deletion when trying to delete RBAC at subscription level ) if ($exceptionModulePaths.Contains($modulePath)) { diff --git a/.github/workflows/avm.res.kubernetes.connected-clusters.yml b/.github/workflows/avm.res.kubernetes.connected-cluster.yml similarity index 92% rename from .github/workflows/avm.res.kubernetes.connected-clusters.yml rename to .github/workflows/avm.res.kubernetes.connected-cluster.yml index fddd8b6536..c0342a00ae 100644 --- a/.github/workflows/avm.res.kubernetes.connected-clusters.yml +++ b/.github/workflows/avm.res.kubernetes.connected-cluster.yml @@ -1,4 +1,4 @@ -name: "avm.res.kubernetes.connected-clusters" +name: "avm.res.kubernetes.connected-cluster" on: workflow_dispatch: @@ -28,15 +28,15 @@ on: paths: - ".github/actions/templates/avm-**" - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.kubernetes.connected-clusters.yml" - - "avm/res/kubernetes/connected-clusters/**" + - ".github/workflows/avm.res.kubernetes.connected-cluster.yml" + - "avm/res/kubernetes/connected-cluster/**" - "avm/utilities/pipelines/**" - "!avm/utilities/pipelines/platform/**" - "!*/**/README.md" env: - modulePath: "avm/res/kubernetes/connected-clusters" - workflowPath: ".github/workflows/avm.res.kubernetes.connected-clusters.yml" + modulePath: "avm/res/kubernetes/connected-cluster" + workflowPath: ".github/workflows/avm.res.kubernetes.connected-cluster.yml" concurrency: group: ${{ github.workflow }} diff --git a/avm/res/kubernetes/connected-clusters/README.md b/avm/res/kubernetes/connected-cluster/README.md similarity index 88% rename from avm/res/kubernetes/connected-clusters/README.md rename to avm/res/kubernetes/connected-cluster/README.md index 76d9bd98ac..921f20cd8e 100644 --- a/avm/res/kubernetes/connected-clusters/README.md +++ b/avm/res/kubernetes/connected-cluster/README.md @@ -1,6 +1,6 @@ -# Kubernetes Connected Clusters `[Microsoft.Kubernetes/connectedClusters]` +# Kubernetes Connected Cluster `[Microsoft.Kubernetes/connectedClusters]` -Deploy an Azure Arc connected cluster. +This module deploys an Azure Arc connected cluster. ## Navigation @@ -22,14 +22,14 @@ The following section provides usage examples for the module, which were used to >**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. ->**Note**: To reference the module, please use the following syntax `br/public:avm/res/kubernetes/connected-clusters:`. +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/kubernetes/connected-cluster:`. -- [Deploy connected clusters in default configuration](#example-1-deploy-connected-clusters-in-default-configuration) +- [WAF-aligned](#example-1-waf-aligned) - [Deploy connected clusters in WAF aligned configuration](#example-2-deploy-connected-clusters-in-waf-aligned-configuration) -### Example 1: _Deploy connected clusters in default configuration_ +### Example 1: _WAF-aligned_ -This test deploys a connected clusters. +This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.

@@ -37,8 +37,8 @@ This test deploys a connected clusters. via Bicep module ```bicep -module connectedClusters 'br/public:avm/res/kubernetes/connected-clusters:' = { - name: 'connectedClustersDeployment' +module connectedCluster 'br/public:avm/res/kubernetes/connected-cluster:' = { + name: 'connectedClusterDeployment' params: { // Required parameters name: 'kccmin001' @@ -80,7 +80,7 @@ module connectedClusters 'br/public:avm/res/kubernetes/connected-clusters:via Bicep parameters file ```bicep-params -using 'br/public:avm/res/kubernetes/connected-clusters:' +using 'br/public:avm/res/kubernetes/connected-cluster:' // Required parameters param name = 'kccmin001' @@ -93,7 +93,7 @@ param location = '' ### Example 2: _Deploy connected clusters in WAF aligned configuration_ -This test deploys a connected clusters. +This test deploys a connected cluster.
@@ -101,8 +101,8 @@ This test deploys a connected clusters. via Bicep module ```bicep -module connectedClusters 'br/public:avm/res/kubernetes/connected-clusters:' = { - name: 'connectedClustersDeployment' +module connectedCluster 'br/public:avm/res/kubernetes/connected-cluster:' = { + name: 'connectedClusterDeployment' params: { // Required parameters name: 'kccwaf001' @@ -152,7 +152,7 @@ module connectedClusters 'br/public:avm/res/kubernetes/connected-clusters:via Bicep parameters file ```bicep-params -using 'br/public:avm/res/kubernetes/connected-clusters:' +using 'br/public:avm/res/kubernetes/connected-cluster:' // Required parameters param name = 'kccwaf001' @@ -292,7 +292,6 @@ Enable workload identity. | Output | Type | Description | | :-- | :-- | :-- | -| `connectedClusterId` | string | The resource ID of the connected cluster. | | `location` | string | The location of the connected cluster. | | `name` | string | The name of the connected cluster. | | `resourceGroupName` | string | The resource group of the connected cluster. | diff --git a/avm/res/kubernetes/connected-clusters/main.bicep b/avm/res/kubernetes/connected-cluster/main.bicep similarity index 93% rename from avm/res/kubernetes/connected-clusters/main.bicep rename to avm/res/kubernetes/connected-cluster/main.bicep index 1d86f9f076..2b3e687990 100644 --- a/avm/res/kubernetes/connected-clusters/main.bicep +++ b/avm/res/kubernetes/connected-cluster/main.bicep @@ -1,5 +1,5 @@ -metadata name = 'Kubernetes Connected Clusters' -metadata description = 'Deploy an Azure Arc connected cluster.' +metadata name = 'Kubernetes Connected Cluster' +metadata description = 'This module deploys an Azure Arc connected cluster.' // ============== // // Parameters // @@ -115,6 +115,3 @@ output resourceGroupName string = resourceGroup().name @description('The location of the connected cluster.') output location string = connectedCluster.location - -@description('The resource ID of the connected cluster.') -output connectedClusterId string = connectedCluster.id diff --git a/avm/res/kubernetes/connected-clusters/main.json b/avm/res/kubernetes/connected-cluster/main.json similarity index 92% rename from avm/res/kubernetes/connected-clusters/main.json rename to avm/res/kubernetes/connected-cluster/main.json index 1e1a8b0795..ac15650b63 100644 --- a/avm/res/kubernetes/connected-clusters/main.json +++ b/avm/res/kubernetes/connected-cluster/main.json @@ -5,11 +5,11 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.32.4.45862", - "templateHash": "15406540205079791461" + "version": "0.33.93.31351", + "templateHash": "2038960427044767471" }, - "name": "Kubernetes Connected Clusters", - "description": "Deploy an Azure Arc connected cluster." + "name": "Kubernetes Connected Cluster", + "description": "This module deploys an Azure Arc connected cluster." }, "parameters": { "name": { @@ -176,13 +176,6 @@ "description": "The location of the connected cluster." }, "value": "[reference('connectedCluster', '2024-07-15-preview', 'full').location]" - }, - "connectedClusterId": { - "type": "string", - "metadata": { - "description": "The resource ID of the connected cluster." - }, - "value": "[resourceId('Microsoft.Kubernetes/connectedClusters', parameters('name'))]" } } } \ No newline at end of file diff --git a/avm/res/kubernetes/connected-clusters/tests/e2e/defaults/main.test.bicep b/avm/res/kubernetes/connected-cluster/tests/e2e/defaults/main.test.bicep similarity index 87% rename from avm/res/kubernetes/connected-clusters/tests/e2e/defaults/main.test.bicep rename to avm/res/kubernetes/connected-cluster/tests/e2e/defaults/main.test.bicep index 83e94fb239..ceb6e77efd 100644 --- a/avm/res/kubernetes/connected-clusters/tests/e2e/defaults/main.test.bicep +++ b/avm/res/kubernetes/connected-cluster/tests/e2e/defaults/main.test.bicep @@ -1,7 +1,7 @@ targetScope = 'subscription' -metadata name = 'Deploy connected clusters in default configuration' -metadata description = 'This test deploys a connected clusters.' +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.' @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) diff --git a/avm/res/kubernetes/connected-clusters/tests/e2e/waf-aligned/main.test.bicep b/avm/res/kubernetes/connected-cluster/tests/e2e/waf-aligned/main.test.bicep similarity index 95% rename from avm/res/kubernetes/connected-clusters/tests/e2e/waf-aligned/main.test.bicep rename to avm/res/kubernetes/connected-cluster/tests/e2e/waf-aligned/main.test.bicep index d11d57645e..5f751822d6 100644 --- a/avm/res/kubernetes/connected-clusters/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/kubernetes/connected-cluster/tests/e2e/waf-aligned/main.test.bicep @@ -1,7 +1,7 @@ targetScope = 'subscription' metadata name = 'Deploy connected clusters in WAF aligned configuration' -metadata description = 'This test deploys a connected clusters.' +metadata description = 'This test deploys a connected cluster.' @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) diff --git a/avm/res/kubernetes/connected-clusters/version.json b/avm/res/kubernetes/connected-cluster/version.json similarity index 100% rename from avm/res/kubernetes/connected-clusters/version.json rename to avm/res/kubernetes/connected-cluster/version.json From 108ad88092182ca900b0106ce2bb7cee569598d0 Mon Sep 17 00:00:00 2001 From: Hangyu Xu Date: Tue, 18 Feb 2025 15:09:05 +0800 Subject: [PATCH 3/4] update --- avm/res/kubernetes/connected-cluster/README.md | 14 +++++++------- avm/res/kubernetes/connected-cluster/main.bicep | 2 +- avm/res/kubernetes/connected-cluster/main.json | 4 ++-- .../tests/e2e/defaults/main.test.bicep | 4 ++-- .../tests/e2e/waf-aligned/main.test.bicep | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/avm/res/kubernetes/connected-cluster/README.md b/avm/res/kubernetes/connected-cluster/README.md index 921f20cd8e..8f99d65e6c 100644 --- a/avm/res/kubernetes/connected-cluster/README.md +++ b/avm/res/kubernetes/connected-cluster/README.md @@ -24,12 +24,12 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br/public:avm/res/kubernetes/connected-cluster:`. -- [WAF-aligned](#example-1-waf-aligned) -- [Deploy connected clusters in WAF aligned configuration](#example-2-deploy-connected-clusters-in-waf-aligned-configuration) +- [Using only defaults](#example-1-using-only-defaults) +- [WAF-aligned](#example-2-waf-aligned) -### Example 1: _WAF-aligned_ +### Example 1: _Using only defaults_ -This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. +This instance deploys the module with the minimum set of required parameters.
@@ -91,9 +91,9 @@ param location = ''

-### Example 2: _Deploy connected clusters in WAF aligned configuration_ +### Example 2: _WAF-aligned_ -This test deploys a connected cluster. +This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.

@@ -295,7 +295,7 @@ Enable workload identity. | `location` | string | The location of the connected cluster. | | `name` | string | The name of the connected cluster. | | `resourceGroupName` | string | The resource group of the connected cluster. | -| `resourceId` | string | The ID of the connected cluster. | +| `resourceId` | string | The resource ID of the connected cluster. | ## Data Collection diff --git a/avm/res/kubernetes/connected-cluster/main.bicep b/avm/res/kubernetes/connected-cluster/main.bicep index 2b3e687990..bb4f38b6ae 100644 --- a/avm/res/kubernetes/connected-cluster/main.bicep +++ b/avm/res/kubernetes/connected-cluster/main.bicep @@ -107,7 +107,7 @@ resource connectedCluster 'Microsoft.Kubernetes/connectedClusters@2024-07-15-pre @description('The name of the connected cluster.') output name string = connectedCluster.name -@description('The ID of the connected cluster.') +@description('The resource ID of the connected cluster.') output resourceId string = connectedCluster.id @description('The resource group of the connected cluster.') diff --git a/avm/res/kubernetes/connected-cluster/main.json b/avm/res/kubernetes/connected-cluster/main.json index ac15650b63..9ae286953b 100644 --- a/avm/res/kubernetes/connected-cluster/main.json +++ b/avm/res/kubernetes/connected-cluster/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.33.93.31351", - "templateHash": "2038960427044767471" + "templateHash": "1046029270487723622" }, "name": "Kubernetes Connected Cluster", "description": "This module deploys an Azure Arc connected cluster." @@ -159,7 +159,7 @@ "resourceId": { "type": "string", "metadata": { - "description": "The ID of the connected cluster." + "description": "The resource ID of the connected cluster." }, "value": "[resourceId('Microsoft.Kubernetes/connectedClusters', parameters('name'))]" }, diff --git a/avm/res/kubernetes/connected-cluster/tests/e2e/defaults/main.test.bicep b/avm/res/kubernetes/connected-cluster/tests/e2e/defaults/main.test.bicep index ceb6e77efd..d519e81970 100644 --- a/avm/res/kubernetes/connected-cluster/tests/e2e/defaults/main.test.bicep +++ b/avm/res/kubernetes/connected-cluster/tests/e2e/defaults/main.test.bicep @@ -1,7 +1,7 @@ targetScope = 'subscription' -metadata name = 'WAF-aligned' -metadata description = 'This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.' +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) diff --git a/avm/res/kubernetes/connected-cluster/tests/e2e/waf-aligned/main.test.bicep b/avm/res/kubernetes/connected-cluster/tests/e2e/waf-aligned/main.test.bicep index 5f751822d6..0f17d77ebe 100644 --- a/avm/res/kubernetes/connected-cluster/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/kubernetes/connected-cluster/tests/e2e/waf-aligned/main.test.bicep @@ -1,7 +1,7 @@ targetScope = 'subscription' -metadata name = 'Deploy connected clusters in WAF aligned configuration' -metadata description = 'This test deploys a connected cluster.' +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.' @description('Optional. The name of the resource group to deploy for testing purposes.') @maxLength(90) From e6402d196e4878c08101af420e42a97670b511d7 Mon Sep 17 00:00:00 2001 From: Hangyu Xu Date: Tue, 18 Feb 2025 18:17:29 +0800 Subject: [PATCH 4/4] add rbac --- .../kubernetes/connected-cluster/README.md | 114 ++++++++++++++++ .../kubernetes/connected-cluster/main.bicep | 46 +++++++ .../kubernetes/connected-cluster/main.json | 127 +++++++++++++++++- 3 files changed, 286 insertions(+), 1 deletion(-) diff --git a/avm/res/kubernetes/connected-cluster/README.md b/avm/res/kubernetes/connected-cluster/README.md index 8f99d65e6c..e85c47df05 100644 --- a/avm/res/kubernetes/connected-cluster/README.md +++ b/avm/res/kubernetes/connected-cluster/README.md @@ -8,12 +8,14 @@ This module deploys an Azure Arc connected cluster. - [Usage examples](#Usage-examples) - [Parameters](#Parameters) - [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) - [Data Collection](#Data-Collection) ## Resource Types | Resource Type | API Version | | :-- | :-- | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Kubernetes/connectedClusters` | [2024-07-15-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Kubernetes/2024-07-15-preview/connectedClusters) | ## Usage examples @@ -185,6 +187,7 @@ param workloadIdentityEnabled = true | [`identityType`](#parameter-identitytype) | string | The identity type for the cluster. Allowed values: "SystemAssigned", "None". | | [`location`](#parameter-location) | string | Location for all Resources. | | [`oidcIssuerEnabled`](#parameter-oidcissuerenabled) | bool | Enable OIDC issuer. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | | [`tags`](#parameter-tags) | object | Tags for the cluster resource. | | [`workloadIdentityEnabled`](#parameter-workloadidentityenabled) | bool | Enable workload identity. | @@ -273,6 +276,109 @@ Enable OIDC issuer. - Type: bool - Default: `False` +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array +- Roles configurable by name: + - `'Contributor'` + - `'Owner'` + - `'Reader'` + - `'User Access Administrator'` + - `'Role Based Access Control Administrator (Preview)'` + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`name`](#parameter-roleassignmentsname) | string | The name (as GUID) of the role assignment. If not provided, a GUID will be generated. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.name` + +The name (as GUID) of the role assignment. If not provided, a GUID will be generated. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + ### Parameter: `tags` Tags for the cluster resource. @@ -297,6 +403,14 @@ Enable workload identity. | `resourceGroupName` | string | The resource group of the connected cluster. | | `resourceId` | string | The resource ID of the connected cluster. | +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/utl/types/avm-common-types:0.5.1` | Remote reference | + ## Data Collection The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/kubernetes/connected-cluster/main.bicep b/avm/res/kubernetes/connected-cluster/main.bicep index bb4f38b6ae..7d067ca103 100644 --- a/avm/res/kubernetes/connected-cluster/main.bicep +++ b/avm/res/kubernetes/connected-cluster/main.bicep @@ -46,6 +46,36 @@ param oidcIssuerEnabled bool = false @description('Optional. Enable workload identity.') param workloadIdentityEnabled bool = false +import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1' +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType[]? + +var builtInRoleNames = { + // Add other relevant built-in roles here for your resource as per BCPNFR5 + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) +} + +var formattedRoleAssignments = [ + for (roleAssignment, index) in (roleAssignments ?? []): union(roleAssignment, { + roleDefinitionId: builtInRoleNames[?roleAssignment.roleDefinitionIdOrName] ?? (contains( + roleAssignment.roleDefinitionIdOrName, + '/providers/Microsoft.Authorization/roleDefinitions/' + ) + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName)) + }) +] + // ============= // // Resources // // ============= // @@ -104,6 +134,22 @@ resource connectedCluster 'Microsoft.Kubernetes/connectedClusters@2024-07-15-pre } } +resource connectedCluster_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (formattedRoleAssignments ?? []): { + name: roleAssignment.?name ?? guid(connectedCluster.id, roleAssignment.principalId, roleAssignment.roleDefinitionId) + properties: { + roleDefinitionId: roleAssignment.roleDefinitionId + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: connectedCluster + } +] + @description('The name of the connected cluster.') output name string = connectedCluster.name diff --git a/avm/res/kubernetes/connected-cluster/main.json b/avm/res/kubernetes/connected-cluster/main.json index 9ae286953b..9013f2052c 100644 --- a/avm/res/kubernetes/connected-cluster/main.json +++ b/avm/res/kubernetes/connected-cluster/main.json @@ -6,11 +6,88 @@ "_generator": { "name": "bicep", "version": "0.33.93.31351", - "templateHash": "1046029270487723622" + "templateHash": "7551101804629042655" }, "name": "Kubernetes Connected Cluster", "description": "This module deploys an Azure Arc connected cluster." }, + "definitions": { + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1" + } + } + } + }, "parameters": { "name": { "type": "string", @@ -95,6 +172,32 @@ "metadata": { "description": "Optional. Enable workload identity." } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" } }, "resources": { @@ -146,6 +249,28 @@ }, "azureHybridBenefit": null } + }, + "connectedCluster_roleAssignments": { + "copy": { + "name": "connectedCluster_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Kubernetes/connectedClusters/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Kubernetes/connectedClusters', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "connectedCluster" + ] } }, "outputs": {