Kubernetes: Using GKE Workload Identity


For this example, I will be setting up access to Google Secrets Manager.

Setup Environment Variables

  • PROJECT_ID = Google Project ID
  • GSA_NAME = Google IAM Service Account
  • K8S_NAMESPACE = Kubernetes namespace
  • KSA_NAME = Kubernetes Service Account
export PROJECT_ID=[YOUR_PROJECT_ID]
export GSA_NAME=sonic-itsmetommy
export K8S_NAMESPACE=itsmetommy
export KSA_NAME=sonic

Create Kubernetes Service Account

kubectl create serviceaccount ${KSA_NAME} -n ${K8S_NAMESPACE}

Create Google Service Account

gcloud iam service-accounts create ${GSA_NAME}

Create the binding between the google service account and the Kubernetes service account

The following command grants the same access to any cluster in the project that uses the sonic service account and itsmetommy namespace, and have Workload Identity enabled on the cluster:

gcloud iam service-accounts add-iam-policy-binding \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:${PROJECT_ID}.svc.id.goog[${K8S_NAMESPACE}/${KSA_NAME}]" \
  ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com

Add role for Google Secret Manager access

gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --role roles/secretmanager.secretAccessor \
  --member serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com

Verify

gcloud iam service-accounts get-iam-policy \
  --flatten="bindings[].members" \
--format="table(bindings.role, bindings.members)" \ ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com gcloud projects get-iam-policy ${PROJECT_ID} \
--flatten="bindings[].members" \
--format='table(bindings.role)' \
--filter="bindings.members:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"

Add annotation to Kubernetes Service Account

Add the iam.gke.io/gcp-service-account=GSA_NAME@PROJECT_ID annotation to the Kubernetes service account, using the email address of the Google service account.

kubectl annotate serviceaccount \
--namespace ${K8S_NAMESPACE} \
${KSA_NAME} \
iam.gke.io/gcp-service-account=${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com

Verify

Create a secret using Google Secret Manager if you haven’t already.

echo -n "12345" | gcloud secrets create itsmetommy_db_password \
--replication-policy="automatic" \
--data-file=-

Create a pod using cloud-sdk and adding the correct serviceaccount.

kubectl run -it --rm \
--image google/cloud-sdk:slim \
--serviceaccount ${KSA_NAME} \
--namespace ${K8S_NAMESPACE} \
workload-identity-test

Run the following inside the pod.

# gcloud auth list
# gcloud secrets versions access latest --secret="[SECRET_NAME]"

Example

# gcloud auth list
                             Credentialed Accounts
ACTIVE  ACCOUNT
*       sonic-itsmetommy@${PROJECT_ID}.iam.gserviceaccount.com

# gcloud secrets versions access latest --secret="itsmetommy_db_password"
12345

Revoke access

Revoke access to the Google service account.

gcloud iam service-accounts remove-iam-policy-binding \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:${PROJECT_ID}.svc.id.goog[${K8S_NAMESPACE}/${KSA_NAME}]" \
  ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com

Remove the annotation from the Kubernetes service account. This step is optional because access has been revoked by IAM.

kubectl annotate serviceaccount \
--namespace ${K8S_NAMESPACE} \
${KSA_NAME} \
iam.gke.io/gcp-service-account=${KSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com

Clean up

# Delete KSA
kubectl delete sa ${KSA_NAME}

# Delete GSA
gcloud iam service-accounts delete ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
, ,