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, useanthos-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.
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
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.
Run a shell within the Pod.
env HTTPS_PROXY=http://localhost:8118 \ kubectl exec -it sample-pod -- bash
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
- Fleet Workload Identity
- Workload identity federation
- Access resources from an OIDC identity provider (Kubernetes clusters are OIDC identity providers)
- Using workload identity with AWS