Using workload identity with Google Cloud

This guide describes how to configure workload identity on GKE on AWS to control workload access to GCP resources. It includes an example of how to access Google Cloud resources from your cluster using the identity.

For information about using workload identities with AWS IAM accounts to control access to AWS resources, see Using workload identity with AWS.

Overview

Workload identity uses Google Cloud IAM permissions to control access to Google Cloud resources. With workload identity, you can assign different IAM roles to each workload. This fine-grained control of permissions lets you follow the principle of least privilege. Without workload identity, you must assign Google Cloud IAM roles to your GKE on AWS nodes, giving all workloads on those nodes the same permissions as the node itself.

Prerequisites

  • Create a user cluster with Kubernetes version v1.20 or later.

  • If your AWS VPC uses a proxy or firewall, allowlist the following URLs:

    • securetoken.googleapis.com
    • iamcredentials.googleapis.com
    • sts.googleapis.com
  • From your anthos-aws directory, use anthos-gke to switch context to your user cluster.

    cd anthos-aws
    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials CLUSTER_NAME
    Replace CLUSTER_NAME with your user cluster name.

  • Enable the four new services required for this feature with the following commands:

    gcloud services enable securetoken.googleapis.com
    gcloud services enable iam.googleapis.com
    gcloud services enable iamcredentials.googleapis.com
    gcloud services enable sts.googleapis.com
    

Compose the WI pool and provider names

Each Google Cloud project automatically creates a managed workload identity pool with a name in the form of PROJECT_ID.svc.id.goog. Similarly, Google Cloud creates an identity provider whose name follows the pattern https://gkehub.googleapis.com/projects/PROJECT_ID/locations/global/memberships/MEMBERSHIP_ID. For more information on workload identity pools, see Fleet-enabled components. Compose these names from your project ID and membership ID as shown here:

export PROJECT_ID=USER_PROJECT_NAME
export CLUSTER_MEMBERSHIP_ID=PROJECT_MEMBERSHIP_NAME
export IDP="https://gkehub.googleapis.com/projects/${PROJECT_ID}/locations/global/memberships/${CLUSTER_MEMBERSHIP_ID}"
export WI_POOL="${PROJECT_ID}.svc.id.goog"

Replace the following:

  • USER_PROJECT_NAME with the user's chosen user project name
  • PROJECT_MEMBERSHIP_NAME with the cluster's membership name

Create an IAM policy binding

Create a policy binding to allow a Kubernetes service account (KSA) to impersonate a Google Cloud service account (GSA).

export K8S_NAMESPACE=KUBERNETES_NAMESPACE
export KSA_NAME=KUBERNETES_SA_NAME
export GCP_SA_EMAIL="WORKLOAD_IDENTITY_TEST@${PROJECT_ID}.iam.gserviceaccount.com"
gcloud iam service-accounts add-iam-policy-binding \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:$WI_POOL[$K8S_NAMESPACE/$KSA_NAME]" $GCP_SA_EMAIL

Replace the following:

  • KUBERNETES_NAMESPACE with the Kubernetes namespace where the Kubernetes service account is defined
  • WORKLOAD_IDENTITY_TEST with a workload name of your choice
  • KUBERNETES_SA_NAME with the name of the Kubernetes service account attached to the application

Create an SDK config map

Execute the shell script below to store the workload identity details in a ConfigMap. When a Pod mounts the ConfigMap, the Google Cloud CLI can read the workload identity details.

cat << EOF > cfmap.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  namespace: ${K8S_NAMESPACE}
  name: my-cloudsdk-config
data:
  config: |
    {
      "type": "external_account",
      "audience": "identitynamespace:${WI_POOL}:${IDP}",
      "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${GCP_SA_EMAIL}:generateAccessToken",
      "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
      "token_url": "https://sts.googleapis.com/v1/token",
      "credential_source": {
        "file": "/var/run/secrets/tokens/gcp-ksa/token"
      }
    }
EOF

env HTTPS_PROXY=http://localhost:8118 \
  kubectl apply -f cfmap.yaml

Create a Kubernetes service account

Create a KSA on your user cluster with same name and namespace as was used in the IAM binding.

cat << EOF > k8s-service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ${KSA_NAME}
  namespace: ${K8S_NAMESPACE}
EOF

env HTTPS_PROXY=http://localhost:8118 \
  kubectl apply -f k8s-service-account.yaml

Create a Pod

Next, create a Pod with the service account token projection and ConfigMap created above.

  1. Create the sample Pod yaml file.

    cat << EOF > sample-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: sample-pod
      namespace: ${K8S_NAMESPACE}
    spec:
      serviceAccountName: ${KSA_NAME}
      containers:
      - command:
        - /bin/bash
        - -c
        - while :; do echo '.'; sleep 500 ; done
        image: google/cloud-sdk
        name: cloud-sdk
        env:
          - name: GOOGLE_APPLICATION_CREDENTIALS
            value: /var/run/secrets/tokens/gcp-ksa/google-application-credentials.json
        volumeMounts:
        - name: gcp-ksa
          mountPath: /var/run/secrets/tokens/gcp-ksa
          readOnly: true
      volumes:
      - name: gcp-ksa
        projected:
          defaultMode: 420
          sources:
          - serviceAccountToken:
              path: token
              audience: ${WI_POOL}
              expirationSeconds: 172800
          - configMap:
              name: my-cloudsdk-config
              optional: false
              items:
               - key: "config"
                 path: "google-application-credentials.json"
    EOF
    
  2. Apply the Pod's YAML to your cluster.

    env HTTPS_PROXY=http://localhost:8118 \
     kubectl apply -f sample-pod.yaml
    

Using Google Cloud workload identity

Supported SDK versions

To use the Google Cloud workload identity feature, you must build your code with an SDK that supports it. For a list of SDK versions that support Google Cloud workload identity, see Fleet Workload Identity.

Sample code using workload identity

This section includes sample Python code that uses Google Cloud workload identity. The service account in this example uses an identity with "Cloud Storage Admin" privileges to list all of the Google Cloud project's Cloud Storage buckets.

  1. Run a shell within the Pod.

    env HTTPS_PROXY=http://localhost:8118 \
    kubectl exec -it sample-pod -- bash
    
  2. Run a script to list the project's storage buckets.

    # execute these commands inside the Pod
    pip install --upgrade google-cloud-storage
    
    cat << EOF > sample-list-bucket.py
    from google.cloud import storage
    storage_client = storage.Client()
    buckets = storage_client.list_buckets()
    
    for bucket in buckets:
      print(bucket.name)
    EOF
    
    env GOOGLE_CLOUD_PROJECT=USER_PROJECT_NAME \
     python3 sample-list-bucket.py
    

    Replace USER_PROJECT_NAME with your Google Cloud project.

For further information