From 2e1ab11ed67ec9ccae66b5d05d87656e06debed5 Mon Sep 17 00:00:00 2001 From: RebeccaCalixte <262454636+Rebecca-Calixte@users.noreply.github.com> Date: Thu, 13 Aug 2026 17:50:12 -0400 Subject: [PATCH 1/8] Simplify AKS Entra Kubernetes RBAC quickstart --- quickstart/101-aks-entra-k8s-rbac/README.md | 119 ++++++++++++++++ quickstart/101-aks-entra-k8s-rbac/main.tf | 150 ++++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 quickstart/101-aks-entra-k8s-rbac/README.md create mode 100644 quickstart/101-aks-entra-k8s-rbac/main.tf diff --git a/quickstart/101-aks-entra-k8s-rbac/README.md b/quickstart/101-aks-entra-k8s-rbac/README.md new file mode 100644 index 000000000..ff01f3bc5 --- /dev/null +++ b/quickstart/101-aks-entra-k8s-rbac/README.md @@ -0,0 +1,119 @@ +# Use Microsoft Entra ID Groups with Kubernetes RBAC in AKS + +This template uses Microsoft Entra ID groups with Kubernetes role-based access control (Kubernetes RBAC) in an existing Azure Kubernetes Service (AKS) cluster. + +The example scopes two existing Microsoft Entra groups to namespaces: + +- The `appdev` group can manage resources in the `dev` namespace. +- The `opssre` group can manage resources in the `sre` namespace. + +The AKS cluster must already have Microsoft Entra integration and Kubernetes RBAC enabled. Azure RBAC for Kubernetes Authorization must be disabled for this example. + +## Prerequisites + +- An Azure subscription +- An existing AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled +- Azure RBAC for Kubernetes Authorization disabled on the cluster +- Terraform `>= 1.6.0` installed +- Azure CLI and `kubectl` installed +- Permission to assign Azure roles at the AKS cluster scope +- Permission to manage Kubernetes resources on the AKS cluster +- Two existing Microsoft Entra security groups +- Test users already assigned to those groups + +Sign in to Azure and select the subscription to use: + +```console +az login +az account set --subscription +``` + +## Terraform providers and variables + +This sample uses the AzureRM provider to reference the existing AKS cluster and assign Azure permissions, and the Kubernetes provider to create namespaces, Roles, and RoleBindings. + +The Terraform variables require values for the existing cluster and the object IDs of existing groups: + +```hcl +resource_group_name = "" +aks_cluster_name = "" +appdev_group_object_id = "" +opssre_group_object_id = "" +``` + +## Example + +Create a `terraform.tfvars` file with values for the existing cluster and group object IDs, then initialize, format, and validate the configuration: + +```console +terraform init +terraform fmt +terraform validate +``` + +Review and apply the configuration: + +```console +terraform plan +terraform apply +``` + +The configuration creates the following Azure and Kubernetes resources: + +- Cluster User Role assignments for both groups +- `dev` and `sre` Kubernetes namespaces +- Namespace-scoped Kubernetes Roles and RoleBindings + +## Verify namespace access + +Get credentials for the AKS cluster: + +```console +az aks get-credentials \ + --resource-group \ + --name +``` + +Verify that both namespaces exist: + +```console +kubectl get namespaces +``` + +The output should include `dev` and `sre`. + +## Test appdev access + +Authenticate as a user that is already a member of the appdev group and create a pod in the `dev` namespace: + +```console +kubectl run nginx-dev \ + --image=nginx \ + --restart=Never \ + --namespace dev +kubectl get pods --namespace dev +``` + +Listing pods across all namespaces or creating a pod in the `sre` namespace should return a `Forbidden` error because the appdev group is scoped to `dev`. + +## Test opssre access + +Authenticate as a user that is already a member of the opssre group and create a pod in the `sre` namespace: + +```console +kubectl run nginx-sre \ + --image=nginx \ + --restart=Never \ + --namespace sre +kubectl get pods --namespace sre +``` + +Creating a pod in the `dev` namespace should return a `Forbidden` error because the opssre group is scoped to `sre`. + +## Clean up + +Remove the namespaces, RoleBindings, Roles, and role assignments created by this configuration: + +```console +terraform destroy +``` diff --git a/quickstart/101-aks-entra-k8s-rbac/main.tf b/quickstart/101-aks-entra-k8s-rbac/main.tf new file mode 100644 index 000000000..6425ba3e3 --- /dev/null +++ b/quickstart/101-aks-entra-k8s-rbac/main.tf @@ -0,0 +1,150 @@ +terraform { + required_version = ">= 1.6.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.30" + } + } +} + +provider "azurerm" { + features {} +} + +variable "resource_group_name" { + type = string + description = "Name of the resource group that contains the existing AKS cluster." +} + +variable "aks_cluster_name" { + type = string + description = "Name of the existing AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled." +} + +variable "appdev_group_object_id" { + type = string + description = "Object ID of an existing Microsoft Entra group used for developer access to the dev namespace." +} + +variable "opssre_group_object_id" { + type = string + description = "Object ID of an existing Microsoft Entra group used for SRE access to the sre namespace." +} + +data "azurerm_kubernetes_cluster" "aks" { + name = var.aks_cluster_name + resource_group_name = var.resource_group_name +} + +provider "kubernetes" { + host = data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].host + client_certificate = base64decode(data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_certificate) + client_key = base64decode(data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_key) + cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].cluster_ca_certificate) +} + +resource "azurerm_role_assignment" "appdev_cluster_user" { + scope = data.azurerm_kubernetes_cluster.aks.id + role_definition_name = "Azure Kubernetes Service Cluster User Role" + principal_id = var.appdev_group_object_id +} + +resource "azurerm_role_assignment" "opssre_cluster_user" { + scope = data.azurerm_kubernetes_cluster.aks.id + role_definition_name = "Azure Kubernetes Service Cluster User Role" + principal_id = var.opssre_group_object_id +} + +resource "kubernetes_namespace" "dev" { + metadata { + name = "dev" + } +} + +resource "kubernetes_namespace" "sre" { + metadata { + name = "sre" + } +} + +resource "kubernetes_role" "dev_full_access" { + metadata { + name = "dev-user-full-access" + namespace = kubernetes_namespace.dev.metadata[0].name + } + + rule { + api_groups = ["", "extensions", "apps"] + resources = ["*"] + verbs = ["*"] + } + + rule { + api_groups = ["batch"] + resources = ["jobs", "cronjobs"] + verbs = ["*"] + } +} + +resource "kubernetes_role" "sre_full_access" { + metadata { + name = "sre-user-full-access" + namespace = kubernetes_namespace.sre.metadata[0].name + } + + rule { + api_groups = ["", "extensions", "apps"] + resources = ["*"] + verbs = ["*"] + } + + rule { + api_groups = ["batch"] + resources = ["jobs", "cronjobs"] + verbs = ["*"] + } +} + +resource "kubernetes_role_binding" "dev_user_access" { + metadata { + name = "dev-user-access" + namespace = kubernetes_namespace.dev.metadata[0].name + } + + role_ref { + api_group = "rbac.authorization.k8s.io" + kind = "Role" + name = kubernetes_role.dev_full_access.metadata[0].name + } + + subject { + kind = "Group" + name = var.appdev_group_object_id + api_group = "rbac.authorization.k8s.io" + } +} + +resource "kubernetes_role_binding" "sre_user_access" { + metadata { + name = "sre-user-access" + namespace = kubernetes_namespace.sre.metadata[0].name + } + + role_ref { + api_group = "rbac.authorization.k8s.io" + kind = "Role" + name = kubernetes_role.sre_full_access.metadata[0].name + } + + subject { + kind = "Group" + name = var.opssre_group_object_id + api_group = "rbac.authorization.k8s.io" + } +} From dafef3a81d19f10b6fae64808d88d852c632cd72 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 23 Aug 2026 19:20:41 +0000 Subject: [PATCH 2/8] Make AKS Entra Kubernetes RBAC quickstart self-contained so e2e apply succeeds Co-authored-by: Rebecca-Calixte <262454636+Rebecca-Calixte@users.noreply.github.com> --- quickstart/101-aks-entra-k8s-rbac/README.md | 47 +++++---- quickstart/101-aks-entra-k8s-rbac/main.tf | 95 +++++++++++-------- quickstart/101-aks-entra-k8s-rbac/outputs.tf | 15 +++ .../101-aks-entra-k8s-rbac/providers.tf | 35 +++++++ .../101-aks-entra-k8s-rbac/variables.tf | 35 +++++++ 5 files changed, 166 insertions(+), 61 deletions(-) create mode 100644 quickstart/101-aks-entra-k8s-rbac/outputs.tf create mode 100644 quickstart/101-aks-entra-k8s-rbac/providers.tf create mode 100644 quickstart/101-aks-entra-k8s-rbac/variables.tf diff --git a/quickstart/101-aks-entra-k8s-rbac/README.md b/quickstart/101-aks-entra-k8s-rbac/README.md index ff01f3bc5..cdee7363a 100644 --- a/quickstart/101-aks-entra-k8s-rbac/README.md +++ b/quickstart/101-aks-entra-k8s-rbac/README.md @@ -1,25 +1,21 @@ # Use Microsoft Entra ID Groups with Kubernetes RBAC in AKS -This template uses Microsoft Entra ID groups with Kubernetes role-based access control (Kubernetes RBAC) in an existing Azure Kubernetes Service (AKS) cluster. +This template uses Microsoft Entra ID groups with Kubernetes role-based access control (Kubernetes RBAC) in Azure Kubernetes Service (AKS). -The example scopes two existing Microsoft Entra groups to namespaces: +The example creates an AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled, two Microsoft Entra groups, and scopes each group to a namespace: - The `appdev` group can manage resources in the `dev` namespace. - The `opssre` group can manage resources in the `sre` namespace. -The AKS cluster must already have Microsoft Entra integration and Kubernetes RBAC enabled. Azure RBAC for Kubernetes Authorization must be disabled for this example. +Azure RBAC for Kubernetes Authorization stays disabled so that Kubernetes Roles and RoleBindings control namespace access. ## Prerequisites - An Azure subscription -- An existing AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled -- Azure RBAC for Kubernetes Authorization disabled on the cluster - Terraform `>= 1.6.0` installed - Azure CLI and `kubectl` installed +- Permission to create Microsoft Entra groups in your tenant - Permission to assign Azure roles at the AKS cluster scope -- Permission to manage Kubernetes resources on the AKS cluster -- Two existing Microsoft Entra security groups -- Test users already assigned to those groups Sign in to Azure and select the subscription to use: @@ -30,20 +26,22 @@ az account set --subscription ## Terraform providers and variables -This sample uses the AzureRM provider to reference the existing AKS cluster and assign Azure permissions, and the Kubernetes provider to create namespaces, Roles, and RoleBindings. +This sample uses the AzureRM provider to create the AKS cluster and assign Azure permissions, the AzureAD provider to create the Microsoft Entra groups, and the Kubernetes provider to create namespaces, Roles, and RoleBindings. -The Terraform variables require values for the existing cluster and the object IDs of existing groups: +All variables have defaults, so no values are required. Override them to change the location, the resource group name prefix, the cluster name prefix, the node count, or the group name prefixes: ```hcl -resource_group_name = "" -aks_cluster_name = "" -appdev_group_object_id = "" -opssre_group_object_id = "" +resource_group_location = "eastus" +resource_group_name_prefix = "rg" +cluster_name_prefix = "aks-entra" +node_count = 2 +appdev_group_name_prefix = "appdev" +opssre_group_name_prefix = "opssre" ``` ## Example -Create a `terraform.tfvars` file with values for the existing cluster and group object IDs, then initialize, format, and validate the configuration: +Initialize, format, and validate the configuration: ```console terraform init @@ -60,18 +58,27 @@ terraform apply The configuration creates the following Azure and Kubernetes resources: +- A resource group and an AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled +- `appdev` and `opssre` Microsoft Entra groups - Cluster User Role assignments for both groups - `dev` and `sre` Kubernetes namespaces - Namespace-scoped Kubernetes Roles and RoleBindings +Add your test users to the groups created by this configuration. Use the group object IDs from the Terraform outputs: + +```console +terraform output appdev_group_object_id +terraform output opssre_group_object_id +``` + ## Verify namespace access Get credentials for the AKS cluster: ```console az aks get-credentials \ - --resource-group \ - --name + --resource-group $(terraform output -raw resource_group_name) \ + --name $(terraform output -raw kubernetes_cluster_name) ``` Verify that both namespaces exist: @@ -84,7 +91,7 @@ The output should include `dev` and `sre`. ## Test appdev access -Authenticate as a user that is already a member of the appdev group and create a pod in the `dev` namespace: +Authenticate as a user that is a member of the appdev group and create a pod in the `dev` namespace: ```console kubectl run nginx-dev \ @@ -98,7 +105,7 @@ Listing pods across all namespaces or creating a pod in the `sre` namespace shou ## Test opssre access -Authenticate as a user that is already a member of the opssre group and create a pod in the `sre` namespace: +Authenticate as a user that is a member of the opssre group and create a pod in the `sre` namespace: ```console kubectl run nginx-sre \ @@ -112,7 +119,7 @@ Creating a pod in the `dev` namespace should return a `Forbidden` error because ## Clean up -Remove the namespaces, RoleBindings, Roles, and role assignments created by this configuration: +Remove the resource group, cluster, Microsoft Entra groups, and Kubernetes resources created by this configuration: ```console terraform destroy diff --git a/quickstart/101-aks-entra-k8s-rbac/main.tf b/quickstart/101-aks-entra-k8s-rbac/main.tf index 6425ba3e3..fae6b3b07 100644 --- a/quickstart/101-aks-entra-k8s-rbac/main.tf +++ b/quickstart/101-aks-entra-k8s-rbac/main.tf @@ -1,64 +1,77 @@ -terraform { - required_version = ">= 1.6.0" - - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 4.0" - } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 2.30" - } - } +# Generate a random name for the resource group +resource "random_pet" "rg_name" { + prefix = var.resource_group_name_prefix } -provider "azurerm" { - features {} +resource "azurerm_resource_group" "rg" { + location = var.resource_group_location + name = random_pet.rg_name.id } -variable "resource_group_name" { - type = string - description = "Name of the resource group that contains the existing AKS cluster." +# Generate random names so the cluster and the Microsoft Entra groups are unique +resource "random_pet" "cluster_name" { + prefix = var.cluster_name_prefix } -variable "aks_cluster_name" { - type = string - description = "Name of the existing AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled." +resource "random_pet" "appdev_group_name" { + prefix = var.appdev_group_name_prefix } -variable "appdev_group_object_id" { - type = string - description = "Object ID of an existing Microsoft Entra group used for developer access to the dev namespace." +resource "random_pet" "opssre_group_name" { + prefix = var.opssre_group_name_prefix } -variable "opssre_group_object_id" { - type = string - description = "Object ID of an existing Microsoft Entra group used for SRE access to the sre namespace." +data "azurerm_client_config" "current" {} + +# Microsoft Entra group whose members can manage the dev namespace +resource "azuread_group" "appdev" { + display_name = random_pet.appdev_group_name.id + security_enabled = true } -data "azurerm_kubernetes_cluster" "aks" { - name = var.aks_cluster_name - resource_group_name = var.resource_group_name +# Microsoft Entra group whose members can manage the sre namespace +resource "azuread_group" "opssre" { + display_name = random_pet.opssre_group_name.id + security_enabled = true } -provider "kubernetes" { - host = data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].host - client_certificate = base64decode(data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_certificate) - client_key = base64decode(data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_key) - cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].cluster_ca_certificate) +# AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled +resource "azurerm_kubernetes_cluster" "aks" { + name = random_pet.cluster_name.id + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + dns_prefix = random_pet.cluster_name.id + role_based_access_control_enabled = true + + identity { + type = "SystemAssigned" + } + + default_node_pool { + name = "agentpool" + vm_size = "Standard_D2_v2" + node_count = var.node_count + } + + # Azure RBAC for Kubernetes Authorization stays disabled so that Kubernetes + # Roles and RoleBindings control namespace access + azure_active_directory_role_based_access_control { + tenant_id = data.azurerm_client_config.current.tenant_id + azure_rbac_enabled = false + } } +# Allow both groups to download the cluster user credentials resource "azurerm_role_assignment" "appdev_cluster_user" { - scope = data.azurerm_kubernetes_cluster.aks.id + scope = azurerm_kubernetes_cluster.aks.id role_definition_name = "Azure Kubernetes Service Cluster User Role" - principal_id = var.appdev_group_object_id + principal_id = azuread_group.appdev.object_id } resource "azurerm_role_assignment" "opssre_cluster_user" { - scope = data.azurerm_kubernetes_cluster.aks.id + scope = azurerm_kubernetes_cluster.aks.id role_definition_name = "Azure Kubernetes Service Cluster User Role" - principal_id = var.opssre_group_object_id + principal_id = azuread_group.opssre.object_id } resource "kubernetes_namespace" "dev" { @@ -125,7 +138,7 @@ resource "kubernetes_role_binding" "dev_user_access" { subject { kind = "Group" - name = var.appdev_group_object_id + name = azuread_group.appdev.object_id api_group = "rbac.authorization.k8s.io" } } @@ -144,7 +157,7 @@ resource "kubernetes_role_binding" "sre_user_access" { subject { kind = "Group" - name = var.opssre_group_object_id + name = azuread_group.opssre.object_id api_group = "rbac.authorization.k8s.io" } } diff --git a/quickstart/101-aks-entra-k8s-rbac/outputs.tf b/quickstart/101-aks-entra-k8s-rbac/outputs.tf new file mode 100644 index 000000000..310c78252 --- /dev/null +++ b/quickstart/101-aks-entra-k8s-rbac/outputs.tf @@ -0,0 +1,15 @@ +output "resource_group_name" { + value = azurerm_resource_group.rg.name +} + +output "kubernetes_cluster_name" { + value = azurerm_kubernetes_cluster.aks.name +} + +output "appdev_group_object_id" { + value = azuread_group.appdev.object_id +} + +output "opssre_group_object_id" { + value = azuread_group.opssre.object_id +} diff --git a/quickstart/101-aks-entra-k8s-rbac/providers.tf b/quickstart/101-aks-entra-k8s-rbac/providers.tf new file mode 100644 index 000000000..2b678a935 --- /dev/null +++ b/quickstart/101-aks-entra-k8s-rbac/providers.tf @@ -0,0 +1,35 @@ +terraform { + required_version = ">= 1.6.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.0" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 3.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.30" + } + random = { + source = "hashicorp/random" + version = "~> 3.0" + } + } +} + +provider "azurerm" { + features {} +} + +provider "azuread" {} + +provider "kubernetes" { + host = azurerm_kubernetes_cluster.aks.kube_admin_config[0].host + client_certificate = base64decode(azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_certificate) + client_key = base64decode(azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_key) + cluster_ca_certificate = base64decode(azurerm_kubernetes_cluster.aks.kube_admin_config[0].cluster_ca_certificate) +} diff --git a/quickstart/101-aks-entra-k8s-rbac/variables.tf b/quickstart/101-aks-entra-k8s-rbac/variables.tf new file mode 100644 index 000000000..50eb2ec13 --- /dev/null +++ b/quickstart/101-aks-entra-k8s-rbac/variables.tf @@ -0,0 +1,35 @@ +variable "resource_group_location" { + type = string + default = "eastus" + description = "Location of the resource group." +} + +variable "resource_group_name_prefix" { + type = string + default = "rg" + description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." +} + +variable "cluster_name_prefix" { + type = string + default = "aks-entra" + description = "Prefix of the AKS cluster name that's combined with a random ID so the name is unique in your Azure subscription." +} + +variable "node_count" { + type = number + default = 2 + description = "The initial quantity of nodes for the node pool." +} + +variable "appdev_group_name_prefix" { + type = string + default = "appdev" + description = "Prefix of the Microsoft Entra group used for developer access to the dev namespace." +} + +variable "opssre_group_name_prefix" { + type = string + default = "opssre" + description = "Prefix of the Microsoft Entra group used for SRE access to the sre namespace." +} From 952467c22975e2b7922b31768c13628672c866b1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 23 Aug 2026 19:24:29 +0000 Subject: [PATCH 3/8] Revert self-contained rewrite, restore original AKS Entra RBAC quickstart Co-authored-by: Rebecca-Calixte <262454636+Rebecca-Calixte@users.noreply.github.com> --- quickstart/101-aks-entra-k8s-rbac/README.md | 47 ++++----- quickstart/101-aks-entra-k8s-rbac/main.tf | 95 ++++++++----------- quickstart/101-aks-entra-k8s-rbac/outputs.tf | 15 --- .../101-aks-entra-k8s-rbac/providers.tf | 35 ------- .../101-aks-entra-k8s-rbac/variables.tf | 35 ------- 5 files changed, 61 insertions(+), 166 deletions(-) delete mode 100644 quickstart/101-aks-entra-k8s-rbac/outputs.tf delete mode 100644 quickstart/101-aks-entra-k8s-rbac/providers.tf delete mode 100644 quickstart/101-aks-entra-k8s-rbac/variables.tf diff --git a/quickstart/101-aks-entra-k8s-rbac/README.md b/quickstart/101-aks-entra-k8s-rbac/README.md index cdee7363a..ff01f3bc5 100644 --- a/quickstart/101-aks-entra-k8s-rbac/README.md +++ b/quickstart/101-aks-entra-k8s-rbac/README.md @@ -1,21 +1,25 @@ # Use Microsoft Entra ID Groups with Kubernetes RBAC in AKS -This template uses Microsoft Entra ID groups with Kubernetes role-based access control (Kubernetes RBAC) in Azure Kubernetes Service (AKS). +This template uses Microsoft Entra ID groups with Kubernetes role-based access control (Kubernetes RBAC) in an existing Azure Kubernetes Service (AKS) cluster. -The example creates an AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled, two Microsoft Entra groups, and scopes each group to a namespace: +The example scopes two existing Microsoft Entra groups to namespaces: - The `appdev` group can manage resources in the `dev` namespace. - The `opssre` group can manage resources in the `sre` namespace. -Azure RBAC for Kubernetes Authorization stays disabled so that Kubernetes Roles and RoleBindings control namespace access. +The AKS cluster must already have Microsoft Entra integration and Kubernetes RBAC enabled. Azure RBAC for Kubernetes Authorization must be disabled for this example. ## Prerequisites - An Azure subscription +- An existing AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled +- Azure RBAC for Kubernetes Authorization disabled on the cluster - Terraform `>= 1.6.0` installed - Azure CLI and `kubectl` installed -- Permission to create Microsoft Entra groups in your tenant - Permission to assign Azure roles at the AKS cluster scope +- Permission to manage Kubernetes resources on the AKS cluster +- Two existing Microsoft Entra security groups +- Test users already assigned to those groups Sign in to Azure and select the subscription to use: @@ -26,22 +30,20 @@ az account set --subscription ## Terraform providers and variables -This sample uses the AzureRM provider to create the AKS cluster and assign Azure permissions, the AzureAD provider to create the Microsoft Entra groups, and the Kubernetes provider to create namespaces, Roles, and RoleBindings. +This sample uses the AzureRM provider to reference the existing AKS cluster and assign Azure permissions, and the Kubernetes provider to create namespaces, Roles, and RoleBindings. -All variables have defaults, so no values are required. Override them to change the location, the resource group name prefix, the cluster name prefix, the node count, or the group name prefixes: +The Terraform variables require values for the existing cluster and the object IDs of existing groups: ```hcl -resource_group_location = "eastus" -resource_group_name_prefix = "rg" -cluster_name_prefix = "aks-entra" -node_count = 2 -appdev_group_name_prefix = "appdev" -opssre_group_name_prefix = "opssre" +resource_group_name = "" +aks_cluster_name = "" +appdev_group_object_id = "" +opssre_group_object_id = "" ``` ## Example -Initialize, format, and validate the configuration: +Create a `terraform.tfvars` file with values for the existing cluster and group object IDs, then initialize, format, and validate the configuration: ```console terraform init @@ -58,27 +60,18 @@ terraform apply The configuration creates the following Azure and Kubernetes resources: -- A resource group and an AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled -- `appdev` and `opssre` Microsoft Entra groups - Cluster User Role assignments for both groups - `dev` and `sre` Kubernetes namespaces - Namespace-scoped Kubernetes Roles and RoleBindings -Add your test users to the groups created by this configuration. Use the group object IDs from the Terraform outputs: - -```console -terraform output appdev_group_object_id -terraform output opssre_group_object_id -``` - ## Verify namespace access Get credentials for the AKS cluster: ```console az aks get-credentials \ - --resource-group $(terraform output -raw resource_group_name) \ - --name $(terraform output -raw kubernetes_cluster_name) + --resource-group \ + --name ``` Verify that both namespaces exist: @@ -91,7 +84,7 @@ The output should include `dev` and `sre`. ## Test appdev access -Authenticate as a user that is a member of the appdev group and create a pod in the `dev` namespace: +Authenticate as a user that is already a member of the appdev group and create a pod in the `dev` namespace: ```console kubectl run nginx-dev \ @@ -105,7 +98,7 @@ Listing pods across all namespaces or creating a pod in the `sre` namespace shou ## Test opssre access -Authenticate as a user that is a member of the opssre group and create a pod in the `sre` namespace: +Authenticate as a user that is already a member of the opssre group and create a pod in the `sre` namespace: ```console kubectl run nginx-sre \ @@ -119,7 +112,7 @@ Creating a pod in the `dev` namespace should return a `Forbidden` error because ## Clean up -Remove the resource group, cluster, Microsoft Entra groups, and Kubernetes resources created by this configuration: +Remove the namespaces, RoleBindings, Roles, and role assignments created by this configuration: ```console terraform destroy diff --git a/quickstart/101-aks-entra-k8s-rbac/main.tf b/quickstart/101-aks-entra-k8s-rbac/main.tf index fae6b3b07..6425ba3e3 100644 --- a/quickstart/101-aks-entra-k8s-rbac/main.tf +++ b/quickstart/101-aks-entra-k8s-rbac/main.tf @@ -1,77 +1,64 @@ -# Generate a random name for the resource group -resource "random_pet" "rg_name" { - prefix = var.resource_group_name_prefix -} +terraform { + required_version = ">= 1.6.0" -resource "azurerm_resource_group" "rg" { - location = var.resource_group_location - name = random_pet.rg_name.id + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.30" + } + } } -# Generate random names so the cluster and the Microsoft Entra groups are unique -resource "random_pet" "cluster_name" { - prefix = var.cluster_name_prefix +provider "azurerm" { + features {} } -resource "random_pet" "appdev_group_name" { - prefix = var.appdev_group_name_prefix +variable "resource_group_name" { + type = string + description = "Name of the resource group that contains the existing AKS cluster." } -resource "random_pet" "opssre_group_name" { - prefix = var.opssre_group_name_prefix +variable "aks_cluster_name" { + type = string + description = "Name of the existing AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled." } -data "azurerm_client_config" "current" {} - -# Microsoft Entra group whose members can manage the dev namespace -resource "azuread_group" "appdev" { - display_name = random_pet.appdev_group_name.id - security_enabled = true +variable "appdev_group_object_id" { + type = string + description = "Object ID of an existing Microsoft Entra group used for developer access to the dev namespace." } -# Microsoft Entra group whose members can manage the sre namespace -resource "azuread_group" "opssre" { - display_name = random_pet.opssre_group_name.id - security_enabled = true +variable "opssre_group_object_id" { + type = string + description = "Object ID of an existing Microsoft Entra group used for SRE access to the sre namespace." } -# AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled -resource "azurerm_kubernetes_cluster" "aks" { - name = random_pet.cluster_name.id - location = azurerm_resource_group.rg.location - resource_group_name = azurerm_resource_group.rg.name - dns_prefix = random_pet.cluster_name.id - role_based_access_control_enabled = true - - identity { - type = "SystemAssigned" - } - - default_node_pool { - name = "agentpool" - vm_size = "Standard_D2_v2" - node_count = var.node_count - } +data "azurerm_kubernetes_cluster" "aks" { + name = var.aks_cluster_name + resource_group_name = var.resource_group_name +} - # Azure RBAC for Kubernetes Authorization stays disabled so that Kubernetes - # Roles and RoleBindings control namespace access - azure_active_directory_role_based_access_control { - tenant_id = data.azurerm_client_config.current.tenant_id - azure_rbac_enabled = false - } +provider "kubernetes" { + host = data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].host + client_certificate = base64decode(data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_certificate) + client_key = base64decode(data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_key) + cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.aks.kube_admin_config[0].cluster_ca_certificate) } -# Allow both groups to download the cluster user credentials resource "azurerm_role_assignment" "appdev_cluster_user" { - scope = azurerm_kubernetes_cluster.aks.id + scope = data.azurerm_kubernetes_cluster.aks.id role_definition_name = "Azure Kubernetes Service Cluster User Role" - principal_id = azuread_group.appdev.object_id + principal_id = var.appdev_group_object_id } resource "azurerm_role_assignment" "opssre_cluster_user" { - scope = azurerm_kubernetes_cluster.aks.id + scope = data.azurerm_kubernetes_cluster.aks.id role_definition_name = "Azure Kubernetes Service Cluster User Role" - principal_id = azuread_group.opssre.object_id + principal_id = var.opssre_group_object_id } resource "kubernetes_namespace" "dev" { @@ -138,7 +125,7 @@ resource "kubernetes_role_binding" "dev_user_access" { subject { kind = "Group" - name = azuread_group.appdev.object_id + name = var.appdev_group_object_id api_group = "rbac.authorization.k8s.io" } } @@ -157,7 +144,7 @@ resource "kubernetes_role_binding" "sre_user_access" { subject { kind = "Group" - name = azuread_group.opssre.object_id + name = var.opssre_group_object_id api_group = "rbac.authorization.k8s.io" } } diff --git a/quickstart/101-aks-entra-k8s-rbac/outputs.tf b/quickstart/101-aks-entra-k8s-rbac/outputs.tf deleted file mode 100644 index 310c78252..000000000 --- a/quickstart/101-aks-entra-k8s-rbac/outputs.tf +++ /dev/null @@ -1,15 +0,0 @@ -output "resource_group_name" { - value = azurerm_resource_group.rg.name -} - -output "kubernetes_cluster_name" { - value = azurerm_kubernetes_cluster.aks.name -} - -output "appdev_group_object_id" { - value = azuread_group.appdev.object_id -} - -output "opssre_group_object_id" { - value = azuread_group.opssre.object_id -} diff --git a/quickstart/101-aks-entra-k8s-rbac/providers.tf b/quickstart/101-aks-entra-k8s-rbac/providers.tf deleted file mode 100644 index 2b678a935..000000000 --- a/quickstart/101-aks-entra-k8s-rbac/providers.tf +++ /dev/null @@ -1,35 +0,0 @@ -terraform { - required_version = ">= 1.6.0" - - required_providers { - azurerm = { - source = "hashicorp/azurerm" - version = "~> 4.0" - } - azuread = { - source = "hashicorp/azuread" - version = "~> 3.0" - } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 2.30" - } - random = { - source = "hashicorp/random" - version = "~> 3.0" - } - } -} - -provider "azurerm" { - features {} -} - -provider "azuread" {} - -provider "kubernetes" { - host = azurerm_kubernetes_cluster.aks.kube_admin_config[0].host - client_certificate = base64decode(azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_certificate) - client_key = base64decode(azurerm_kubernetes_cluster.aks.kube_admin_config[0].client_key) - cluster_ca_certificate = base64decode(azurerm_kubernetes_cluster.aks.kube_admin_config[0].cluster_ca_certificate) -} diff --git a/quickstart/101-aks-entra-k8s-rbac/variables.tf b/quickstart/101-aks-entra-k8s-rbac/variables.tf deleted file mode 100644 index 50eb2ec13..000000000 --- a/quickstart/101-aks-entra-k8s-rbac/variables.tf +++ /dev/null @@ -1,35 +0,0 @@ -variable "resource_group_location" { - type = string - default = "eastus" - description = "Location of the resource group." -} - -variable "resource_group_name_prefix" { - type = string - default = "rg" - description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription." -} - -variable "cluster_name_prefix" { - type = string - default = "aks-entra" - description = "Prefix of the AKS cluster name that's combined with a random ID so the name is unique in your Azure subscription." -} - -variable "node_count" { - type = number - default = 2 - description = "The initial quantity of nodes for the node pool." -} - -variable "appdev_group_name_prefix" { - type = string - default = "appdev" - description = "Prefix of the Microsoft Entra group used for developer access to the dev namespace." -} - -variable "opssre_group_name_prefix" { - type = string - default = "opssre" - description = "Prefix of the Microsoft Entra group used for SRE access to the sre namespace." -} From a913fdada8e46327c7006e7b4b5b30ec8da0dbc4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Aug 2026 15:05:05 +0000 Subject: [PATCH 4/8] Add e2e prerequisite config and special test for AKS Entra k8s RBAC quickstart Co-authored-by: vranade-microsoft <269690592+vranade-microsoft@users.noreply.github.com> --- quickstart/101-aks-entra-k8s-rbac/README.md | 2 + .../101-aks-entra-k8s-rbac/prequisite/main.tf | 47 +++++++++++++++++++ .../prequisite/outputs.tf | 19 ++++++++ .../prequisite/variables.tf | 11 +++++ .../prequisite/versions.tf | 26 ++++++++++ test/e2e/quickstart_test.go | 18 +++++++ 6 files changed, 123 insertions(+) create mode 100644 quickstart/101-aks-entra-k8s-rbac/prequisite/main.tf create mode 100644 quickstart/101-aks-entra-k8s-rbac/prequisite/outputs.tf create mode 100644 quickstart/101-aks-entra-k8s-rbac/prequisite/variables.tf create mode 100644 quickstart/101-aks-entra-k8s-rbac/prequisite/versions.tf diff --git a/quickstart/101-aks-entra-k8s-rbac/README.md b/quickstart/101-aks-entra-k8s-rbac/README.md index ff01f3bc5..058931082 100644 --- a/quickstart/101-aks-entra-k8s-rbac/README.md +++ b/quickstart/101-aks-entra-k8s-rbac/README.md @@ -21,6 +21,8 @@ The AKS cluster must already have Microsoft Entra integration and Kubernetes RBA - Two existing Microsoft Entra security groups - Test users already assigned to those groups +> **Note**: The `prequisite` folder contains a Terraform configuration that creates these prerequisites (resource group, AKS cluster with Microsoft Entra integration and Kubernetes RBAC, and the two Microsoft Entra groups). It is used by the end to end test of this repository and can also be applied first if you do not have an existing environment. + Sign in to Azure and select the subscription to use: ```console diff --git a/quickstart/101-aks-entra-k8s-rbac/prequisite/main.tf b/quickstart/101-aks-entra-k8s-rbac/prequisite/main.tf new file mode 100644 index 000000000..0ffc122a7 --- /dev/null +++ b/quickstart/101-aks-entra-k8s-rbac/prequisite/main.tf @@ -0,0 +1,47 @@ +data "azurerm_client_config" "current" {} + +resource "random_string" "suffix" { + length = 6 + special = false + upper = false +} + +resource "azurerm_resource_group" "rg" { + location = var.location + name = "rg-101-aks-entra-k8s-rbac-${random_string.suffix.result}" +} + +resource "azuread_group" "appdev" { + display_name = "appdev-${random_string.suffix.result}" + security_enabled = true +} + +resource "azuread_group" "opssre" { + display_name = "opssre-${random_string.suffix.result}" + security_enabled = true +} + +resource "azurerm_kubernetes_cluster" "aks" { + location = azurerm_resource_group.rg.location + name = "aks-101-entra-k8s-rbac-${random_string.suffix.result}" + resource_group_name = azurerm_resource_group.rg.name + dns_prefix = "aks-${random_string.suffix.result}" + # Kubernetes RBAC is required by the example, Azure RBAC for Kubernetes + # Authorization must stay disabled. + role_based_access_control_enabled = true + + default_node_pool { + name = "agentpool" + node_count = var.node_count + vm_size = "Standard_D2s_v3" + } + + identity { + type = "SystemAssigned" + } + + azure_active_directory_role_based_access_control { + azure_rbac_enabled = false + tenant_id = data.azurerm_client_config.current.tenant_id + } +} diff --git a/quickstart/101-aks-entra-k8s-rbac/prequisite/outputs.tf b/quickstart/101-aks-entra-k8s-rbac/prequisite/outputs.tf new file mode 100644 index 000000000..027d1a630 --- /dev/null +++ b/quickstart/101-aks-entra-k8s-rbac/prequisite/outputs.tf @@ -0,0 +1,19 @@ +output "resource_group_name" { + description = "Name of the resource group that contains the AKS cluster." + value = azurerm_resource_group.rg.name +} + +output "aks_cluster_name" { + description = "Name of the AKS cluster with Microsoft Entra integration and Kubernetes RBAC enabled." + value = azurerm_kubernetes_cluster.aks.name +} + +output "appdev_group_object_id" { + description = "Object ID of the Microsoft Entra group used for developer access." + value = azuread_group.appdev.object_id +} + +output "opssre_group_object_id" { + description = "Object ID of the Microsoft Entra group used for SRE access." + value = azuread_group.opssre.object_id +} diff --git a/quickstart/101-aks-entra-k8s-rbac/prequisite/variables.tf b/quickstart/101-aks-entra-k8s-rbac/prequisite/variables.tf new file mode 100644 index 000000000..267eb51b2 --- /dev/null +++ b/quickstart/101-aks-entra-k8s-rbac/prequisite/variables.tf @@ -0,0 +1,11 @@ +variable "location" { + type = string + default = "eastus" + description = "Location of the resources." +} + +variable "node_count" { + type = number + default = 1 + description = "Number of nodes in the default node pool of the AKS cluster." +} diff --git a/quickstart/101-aks-entra-k8s-rbac/prequisite/versions.tf b/quickstart/101-aks-entra-k8s-rbac/prequisite/versions.tf new file mode 100644 index 000000000..528c71ee3 --- /dev/null +++ b/quickstart/101-aks-entra-k8s-rbac/prequisite/versions.tf @@ -0,0 +1,26 @@ +terraform { + required_version = ">= 1.6.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 4.0" + } + azuread = { + source = "hashicorp/azuread" + version = "~> 3.0" + } + random = { + source = "hashicorp/random" + version = "~> 3.6" + } + } +} + +provider "azurerm" { + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + } +} diff --git a/test/e2e/quickstart_test.go b/test/e2e/quickstart_test.go index 696b3ec2c..8f9189756 100644 --- a/test/e2e/quickstart_test.go +++ b/test/e2e/quickstart_test.go @@ -25,6 +25,7 @@ var speicalTests = map[string]func(*testing.T){ "quickstart/202-machine-learning-moderately-secure-existing-VNet": test202machineLearningModeratelySecureExistingVnet, "quickstart/101-azure-netapp-files": test101AzureNetappFiles, "quickstart/101-azure-storage-actions-create-storage-task": test101AzureStorageActionsCreateStorageTask, + "quickstart/101-aks-entra-k8s-rbac": test101AksEntraK8sRbac, } func Test_Quickstarts(t *testing.T) { @@ -236,6 +237,23 @@ func test101AzureStorageActionsCreateStorageTask(t *testing.T) { }, nil) } +func test101AksEntraK8sRbac(t *testing.T) { + rootPath := filepath.Join("..", "..") + examplePath := filepath.Join("quickstart", "101-aks-entra-k8s-rbac") + prequistePath := filepath.Join(examplePath, "prequisite") + helper.RunE2ETest(t, rootPath, prequistePath, terraform.Options{}, func(t *testing.T, output helper.TerraformOutput) { + helper.RunE2ETest(t, rootPath, examplePath, terraform.Options{ + Upgrade: true, + Vars: map[string]interface{}{ + "resource_group_name": output["resource_group_name"], + "aks_cluster_name": output["aks_cluster_name"], + "appdev_group_object_id": output["appdev_group_object_id"], + "opssre_group_object_id": output["opssre_group_object_id"], + }, + }, nil) + }) +} + func removeDuplicates(s []string) []string { m := make(map[string]struct{}) result := []string{} From 9e15b9aa5309901a8a16f2fb7dc94de255c149aa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Aug 2026 12:09:50 +0000 Subject: [PATCH 5/8] Fix AKS e2e test syntax Co-authored-by: vranade-microsoft <269690592+vranade-microsoft@users.noreply.github.com> --- test/e2e/quickstart_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/e2e/quickstart_test.go b/test/e2e/quickstart_test.go index a6494027c..1e9e4263e 100644 --- a/test/e2e/quickstart_test.go +++ b/test/e2e/quickstart_test.go @@ -269,6 +269,11 @@ func test101AksEntraK8sRbac(t *testing.T) { "aks_cluster_name": output["aks_cluster_name"], "appdev_group_object_id": output["appdev_group_object_id"], "opssre_group_object_id": output["opssre_group_object_id"], + }, + }, nil) + }) +} + func test201AksFleetManagedNamespaces(t *testing.T) { rootPath := filepath.Join("..", "..") examplePath := filepath.Join("quickstart", "201-aks-fleet-managed-namespaces") From 9ed70984ef842955ad875f9dcd0893d2cf664970 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Aug 2026 12:31:23 +0000 Subject: [PATCH 6/8] Avoid Entra group creation in AKS e2e fixture Co-authored-by: vranade-microsoft <269690592+vranade-microsoft@users.noreply.github.com> --- quickstart/101-aks-entra-k8s-rbac/prequisite/main.tf | 10 ---------- .../101-aks-entra-k8s-rbac/prequisite/outputs.tf | 8 ++++---- .../101-aks-entra-k8s-rbac/prequisite/versions.tf | 4 ---- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/quickstart/101-aks-entra-k8s-rbac/prequisite/main.tf b/quickstart/101-aks-entra-k8s-rbac/prequisite/main.tf index 0ffc122a7..f8ea968b3 100644 --- a/quickstart/101-aks-entra-k8s-rbac/prequisite/main.tf +++ b/quickstart/101-aks-entra-k8s-rbac/prequisite/main.tf @@ -11,16 +11,6 @@ resource "azurerm_resource_group" "rg" { name = "rg-101-aks-entra-k8s-rbac-${random_string.suffix.result}" } -resource "azuread_group" "appdev" { - display_name = "appdev-${random_string.suffix.result}" - security_enabled = true -} - -resource "azuread_group" "opssre" { - display_name = "opssre-${random_string.suffix.result}" - security_enabled = true -} - resource "azurerm_kubernetes_cluster" "aks" { location = azurerm_resource_group.rg.location name = "aks-101-entra-k8s-rbac-${random_string.suffix.result}" diff --git a/quickstart/101-aks-entra-k8s-rbac/prequisite/outputs.tf b/quickstart/101-aks-entra-k8s-rbac/prequisite/outputs.tf index 027d1a630..ee77e1927 100644 --- a/quickstart/101-aks-entra-k8s-rbac/prequisite/outputs.tf +++ b/quickstart/101-aks-entra-k8s-rbac/prequisite/outputs.tf @@ -9,11 +9,11 @@ output "aks_cluster_name" { } output "appdev_group_object_id" { - description = "Object ID of the Microsoft Entra group used for developer access." - value = azuread_group.appdev.object_id + description = "Object ID of the existing test principal used for developer access." + value = data.azurerm_client_config.current.object_id } output "opssre_group_object_id" { - description = "Object ID of the Microsoft Entra group used for SRE access." - value = azuread_group.opssre.object_id + description = "Object ID of the existing test principal used for SRE access." + value = azurerm_kubernetes_cluster.aks.identity[0].principal_id } diff --git a/quickstart/101-aks-entra-k8s-rbac/prequisite/versions.tf b/quickstart/101-aks-entra-k8s-rbac/prequisite/versions.tf index 528c71ee3..9a0ced2f0 100644 --- a/quickstart/101-aks-entra-k8s-rbac/prequisite/versions.tf +++ b/quickstart/101-aks-entra-k8s-rbac/prequisite/versions.tf @@ -6,10 +6,6 @@ terraform { source = "hashicorp/azurerm" version = "~> 4.0" } - azuread = { - source = "hashicorp/azuread" - version = "~> 3.0" - } random = { source = "hashicorp/random" version = "~> 3.6" From 7fb829bdbc409988e473a441f928da39f04852a3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Aug 2026 12:32:05 +0000 Subject: [PATCH 7/8] Clarify AKS e2e fixture documentation Co-authored-by: vranade-microsoft <269690592+vranade-microsoft@users.noreply.github.com> --- quickstart/101-aks-entra-k8s-rbac/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart/101-aks-entra-k8s-rbac/README.md b/quickstart/101-aks-entra-k8s-rbac/README.md index 058931082..a6da2a12d 100644 --- a/quickstart/101-aks-entra-k8s-rbac/README.md +++ b/quickstart/101-aks-entra-k8s-rbac/README.md @@ -21,7 +21,7 @@ The AKS cluster must already have Microsoft Entra integration and Kubernetes RBA - Two existing Microsoft Entra security groups - Test users already assigned to those groups -> **Note**: The `prequisite` folder contains a Terraform configuration that creates these prerequisites (resource group, AKS cluster with Microsoft Entra integration and Kubernetes RBAC, and the two Microsoft Entra groups). It is used by the end to end test of this repository and can also be applied first if you do not have an existing environment. +> **Note**: The `prequisite` folder contains the Terraform configuration used by this repository's end-to-end test. It creates a resource group and an AKS cluster with Microsoft Entra integration and Kubernetes RBAC, then supplies existing test principal IDs to the example. Sign in to Azure and select the subscription to use: From a03b1879bccc327df147478b0978c2ae67f0bb7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 28 Aug 2026 14:45:47 +0000 Subject: [PATCH 8/8] Skip idempotency for AKS prerequisite fixture Co-authored-by: vranade-microsoft <269690592+vranade-microsoft@users.noreply.github.com> --- test/e2e/quickstart_test.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/test/e2e/quickstart_test.go b/test/e2e/quickstart_test.go index 1e9e4263e..92d5dd9c5 100644 --- a/test/e2e/quickstart_test.go +++ b/test/e2e/quickstart_test.go @@ -261,16 +261,19 @@ func test101AksEntraK8sRbac(t *testing.T) { rootPath := filepath.Join("..", "..") examplePath := filepath.Join("quickstart", "101-aks-entra-k8s-rbac") prequistePath := filepath.Join(examplePath, "prequisite") - helper.RunE2ETest(t, rootPath, prequistePath, terraform.Options{}, func(t *testing.T, output helper.TerraformOutput) { - helper.RunE2ETest(t, rootPath, examplePath, terraform.Options{ - Upgrade: true, - Vars: map[string]interface{}{ - "resource_group_name": output["resource_group_name"], - "aks_cluster_name": output["aks_cluster_name"], - "appdev_group_object_id": output["appdev_group_object_id"], - "opssre_group_object_id": output["opssre_group_object_id"], - }, - }, nil) + helper.RunE2ETestWithOption(t, rootPath, prequistePath, helper.TestOptions{ + SkipIdempotentCheck: true, + Assertion: func(t *testing.T, output helper.TerraformOutput) { + helper.RunE2ETest(t, rootPath, examplePath, terraform.Options{ + Upgrade: true, + Vars: map[string]interface{}{ + "resource_group_name": output["resource_group_name"], + "aks_cluster_name": output["aks_cluster_name"], + "appdev_group_object_id": output["appdev_group_object_id"], + "opssre_group_object_id": output["opssre_group_object_id"], + }, + }, nil) + }, }) }