Rediger

Configure external identity providers with AKS structured authentication (preview)

This article shows you how to configure GitHub and Google Identity external identity providers for Azure Kubernetes Service (AKS) control plane authentication using structured authentication. You learn how to create JSON Web Token (JWT) authenticators, configure claim validation and mapping, and test the authentication flow.

Important

AKS preview features are available on a self-service, opt-in basis. Previews are provided "as is" and "as available," and they're excluded from the service-level agreements and limited warranty. AKS previews are partially covered by customer support on a best-effort basis. As such, these features aren't meant for production use. For more information, see the following support articles:

Prerequisites

  • This article requires version 2.77.0 or later of the Azure CLI. If you're using Azure Cloud Shell, the latest version is already installed there. To install or update the Azure CLI on your local machine, see Install the Azure CLI.

  • You need to install the aks-preview Azure CLI extension version 18.0.0b41 or later to use structured authentication features.

    • If you don't already have the aks-preview extension, install it using the az extension add command.

      az extension add --name aks-preview
      
    • If you already have the aks-preview extension, update it to make sure you have the latest version using the az extension update command.

      az extension update --name aks-preview
      
    • Verify you have the required version of the aks-preview extension using the az extension show command.

      az extension show --name aks-preview --query version
      
  • An AKS cluster running Kubernetes version 1.30 or later. To create an AKS cluster, see Deploy an Azure Kubernetes Service (AKS) cluster using Azure CLI.

  • kubectl command-line tool to interact with your Kubernetes cluster. kubectl is already installed if you use Azure Cloud Shell. You can install kubectl locally using the az aks install-cli command.

    az aks install-cli
    
  • An external identity provider that supports OpenID Connect (OIDC).

  • Network connectivity from cluster nodes to your identity provider.

  • If you plan to use the kubelogin plugin, install it by following the instructions in the kubelogin setup guide.

Set environment variables

  • Set the following environment variables for your resource group and cluster name:

    export RESOURCE_GROUP="<your-resource-group-name>"
    export CLUSTER_NAME="<your-cluster-name>"
    

Register the JWTAuthenticatorPreview feature

  1. Register the JWTAuthenticatorPreview feature using the az feature register command.

    az feature register --name JWTAuthenticatorPreview --namespace Microsoft.ContainerService
    
  2. Check the registration status of the feature using the az feature show command.

    az feature show --name JWTAuthenticatorPreview --namespace Microsoft.ContainerService
    
  3. When the status shows Registered, refresh the resource provider registration for Microsoft.ContainerService using the az provider register command.

    az provider register --namespace Microsoft.ContainerService
    

Set up GitHub Actions OIDC authentication

  1. Ensure your GitHub Actions workflows have the necessary permissions.

  2. Configure the id-token: write permission in your workflow files. For example:

    permissions:
      id-token: write
      contents: read
    
  3. Set up appropriate repository and organization settings for OIDC token access. Configure repository OIDC settings and organization security policies for token usage.

Set up Google Identity OAuth 2.0 authentication

  1. Navigate to the Google Cloud Console.
  2. Create or select a project.
  3. Create OAuth 2.0 credentials.
  4. Note your client ID and client secret for later use.

Create JWT authenticator configuration for GitHub Actions OIDC

  • Create a file named jwt-config.json with the following configuration:

    {
      "issuer": {
          "url": "https://token.actions.githubusercontent.com",
          "audiences": [
              "my-api"
          ]
      },
      "claimValidationRules": [
          {
              "expression": "has(claims.sub)",
              "message": "must have sub claim"
          }
      ],
      "claimMappings": {
          "username": {
              "expression": "'aks:jwt:github:' + claims.sub"
          }
      },
      "userValidationRules": [
          {
              "expression": "has(user.username)",
              "message": "must have username"
          },
          {
              "expression": "!user.username.startsWith('aks:jwt:github:system')",
              "message": "username must not start with 'aks:jwt:github:system'"
          }
      ]
    }
    

Create JWT authenticator configuration for Google Identity

  • Create a file named jwt-config.json with the following configuration:

    {
        "issuer": {
            "url": "https://accounts.google.com",
            "audiences": [
                "your-client-id.apps.googleusercontent.com"
            ]
        },
        "claimValidationRules": [
            {
                "expression": "has(claims.sub)",
                "message": "must have sub claim"
            }
        ],
        "claimMappings": {
            "username": {
                "expression": "'aks:jwt:google:' + claims.sub"
            },
            "groups": {
                "expression": "has(claims.groups) ? claims.groups.split(',').map(g, 'aks:jwt:' + g) : []"
            }
        },
        "userValidationRules": [
            {
                "expression": "has(user.username)",
                "message": "must have username"
            },
            {
                "expression": "!user.username.startsWith('aks:jwt:google:system')",
                "message": "username must not start with 'aks:jwt:google:system'"
            }
        ]
    }
    

JWT authenticator configuration elements

The JWT authenticator configuration includes the following key elements: issuer, claimValidationRules, claimMappings, and userValidationRules. Each element serves a specific purpose in defining how AKS validates and processes JWT tokens from the external identity provider.

Issuer configuration

The following table describes the key elements of the issuer configuration:

Issuer configuration element Description
url The OIDC issuer URL that must match the iss claim in JWTs.
audiences List of audiences that JWTs must be issued for (checked against aud claim).

Claim validation rules configuration

The following table describes the key elements of the claimValidationRules configuration:

Claim validation rule element Description
expression CEL expression that defines the validation logic to apply to JWT claims. The expression must evaluate to true for the token to be accepted.
message Error message returned when the validation rule fails.

Claim mappings configuration

The following table describes the key elements of the claimMappings configuration:

Claim mappings element Description
username CEL expression that defines how to construct the Kubernetes username from JWT claims. Must include the aks:jwt: prefix to prevent conflicts with other authentication methods.
groups CEL expression that defines how to construct Kubernetes group memberships from JWT claims. Must include the aks:jwt: prefix to prevent conflicts with other authentication methods.
uid Optional CEL expression that defines a unique identifier for the user.
extra Optional map of additional user attributes defined by CEL expressions.

User validation rules configuration

The following table describes the key elements of the userValidationRules configuration:

User validation rule element Description
expression CEL expression that defines additional validation logic to apply to the final mapped user information. The expression must evaluate to true for the user to be accepted.
message Error message returned when the user validation rule fails.

Create the JWT authenticator

  • Add the JWT authenticator to your AKS cluster using the az aks jwtauthenticator add command.

    az aks jwtauthenticator add \
        --resource-group $RESOURCE_GROUP \
        --cluster-name $CLUSTER_NAME \
        --name external-auth \
        --config-file jwt-config.json
    

Manage JWT authenticators

List all JWT authenticators

  • List all JWT authenticators on your cluster using the az aks jwtauthenticator list command.

    az aks jwtauthenticator list \
        --resource-group $RESOURCE_GROUP \
        --cluster-name $CLUSTER_NAME
    

Get details for a specific JWT authenticator

  • Get details for a specific JWT authenticator using the az aks jwtauthenticator show command.

    az aks jwtauthenticator show \
        --resource-group $RESOURCE_GROUP \
        --cluster-name $CLUSTER_NAME \
        --name external-auth
    

Set up GitHub Actions OIDC for authentication

  1. Create environment variables for and set the following required repository secrets in your GitHub repository:

    • AKS_SERVER_URL: Your AKS cluster's API server URL.
    • AKS_CA_DATA: Base64-encoded certificate authority data for your AKS cluster.
  2. Create a workflow that obtains an OIDC token and uses it to authenticate with your AKS cluster. The following example workflow gets all pods running on the cluster:

    Note

    The audience value my-api should match the audience configured in your JWT authenticator configuration.

    name: AKS Access with GitHub OIDC
    on:
      workflow_dispatch:
      push:
        branches: [main]
    
    permissions:
      id-token: write
      contents: read
    
    jobs:
      aks-access:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout code
            uses: actions/checkout@v4
    
          - name: Install kubectl
            uses: azure/setup-kubectl@v3
            with:
              version: 'latest'
    
          - name: Get GitHub OIDC token
            id: get_token
            run: |
              TOKEN=$(curl -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
                "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=my-api" | \
                jq -r '.value')
              echo "::add-mask::$TOKEN"
              echo "oidc_token=$TOKEN" >> $GITHUB_OUTPUT
    
          - name: Create kubeconfig with OIDC token
            run: |
              cat <<EOF > kubeconfig
              apiVersion: v1
              kind: Config
              clusters:
              - cluster:
                  certificate-authority-data: ${{ secrets.AKS_CA_DATA }}
                  server: ${{ secrets.AKS_SERVER_URL }}
                name: aks-cluster
              contexts:
              - context:
                  cluster: aks-cluster
                  user: github-oidc-user
                name: aks-context
              current-context: aks-context
              users:
              - name: github-oidc-user
                user:
                  token: ${{ steps.get_token.outputs.oidc_token }}
              EOF
    
          - name: List all pods in the cluster
            run: |
              export KUBECONFIG=./kubeconfig
              kubectl get pods --all-namespaces
    

Get cluster information for JWT authenticator configuration

  1. Get the API server URL for your cluster using the az aks show command.

    az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query "fqdn" -o tsv | \
      awk '{print "https://" $0 ":443"}'
    
  2. Get the base64-encoded certificate authority data for your cluster using the az aks get-credentials command.

    # Get CA data (base64 encoded)
    az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --file - --format exec | \
      grep certificate-authority-data | awk '{print $2}'
    

Set up Google Identity OAuth 2.0 for authentication

You can set up Google Identity authentication using either the kubelogin plugin or by directly using a static token.

  • Add a new user context to your kubeconfig file. For example:

    users:
    - name: external-user
      user:
        exec:
          apiVersion: client.authentication.k8s.io/v1beta1
          command: kubectl
          args:
          - oidc-login
          - get-token
          - --oidc-issuer-url=https://accounts.google.com
          - --oidc-client-id=your-client-id.apps.googleusercontent.com
          - --oidc-client-secret=your-client-secret
    

Test authentication

  1. Trigger the workflow either by pushing to the main branch or manually triggering it from the Actions tab in your repository.

  2. Monitor the workflow execution in the Actions tab to verify authentication is working.

    Expected output for first-time setup before Role-Based Access Control (RBAC) configuration:

    Error from server (Forbidden): nodes is forbidden: User "aks:jwt:github:your-sub" cannot list resource "nodes" in API group "" at the cluster scope
    

    This error indicates successful authentication but lack of authorization.

  • Test the authentication using the kubectl get nodes command with the --user flag to specify the user context you created for Google Identity authentication. For example:

    kubectl get nodes --user external-user
    

    Expected output for first-time setup before Role-Based Access Control (RBAC) configuration:

    Error from server (Forbidden): nodes is forbidden: User "aks:jwt:google:your-subject" cannot list resource "nodes" in API group "" at the cluster scope
    

    This error indicates successful authentication but lack of authorization.

Configure Kubernetes Role-Based Access Control (RBAC)

Create appropriate RBAC bindings for your external users, and use the cluster admin credentials to apply these configurations.

  1. Create a file named rbac-config.yaml to configure RBAC bindings for external users. For example:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: external-user-role
    rules:
    - apiGroups: [""]
      resources: ["pods", "services", "nodes"]
      verbs: ["get", "list"]
    - apiGroups: ["apps"]
      resources: ["deployments", "replicasets"]
      verbs: ["get", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: external-user-binding
    subjects:
    - kind: User
      # This matches the username expression in claim mappings for GitHub; example of GitHub subject is "repo:<organization-name>/<repository-name>:ref:refs/heads/main"
      name: aks:jwt:github:your-github-sub
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: external-user-role
      apiGroup: rbac.authorization.k8s.io
    
  2. Apply the RBAC configuration using the kubectl apply command:

    kubectl apply -f rbac-config.yaml
    
  1. Create a file named rbac-config.yaml to configure RBAC bindings for external users. For example:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: external-user-role
    rules:
    - apiGroups: [""]
      resources: ["pods", "services", "nodes"]
      verbs: ["get", "list"]
    - apiGroups: ["apps"]
      resources: ["deployments", "replicasets"]
      verbs: ["get", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: external-user-binding
    subjects:
    - kind: User
      # This matches the username expression in claim mappings for Google
      name: aks:jwt:google:your-subject-claim
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: external-user-role
      apiGroup: rbac.authorization.k8s.io
    
  2. Apply the RBAC configuration using the kubectl apply command:

    kubectl apply -f rbac-config.yaml
    

Verify access with RBAC

  • Verify the external user can now access resources according to the RBAC permissions you configured using the kubectl get nodes and kubectl get pods commands with the --user flag. For example:

    kubectl get nodes --user external-user
    kubectl get pods --user external-user
    

Remove JWT authenticator

  • When you no longer need the JWT authenticator, remove it from your AKS cluster using the az aks jwtauthenticator delete command.

    az aks jwtauthenticator delete \
        --resource-group $RESOURCE_GROUP \
        --cluster-name $CLUSTER_NAME \
        --name external-auth