SEANK.H.LIAO

GCP Workload Identity Federation

no more service accounts

Workload Identity Federation

Last year when I setup my local (off cloud) Kubernetes cluster, I found that you could use workload identity to trust the kubernetes identities and impersonate GCP service accounts. Ref: blog post

This year, I see they've upgraded it to not require impersonation at all, allowing you to use the workload identity directly. The upstream docs are still the same at Configure Workload Identity Federation with Kubernetes.

Compared to the previous config, this time we have two new keys: universe_domain and token_info_url, and no longer need service_account_impersonation_url

 1{
 2		"universe_domain":    "googleapis.com",
 3		"type":               "external_account",
 4		"audience":           "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
 5		"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
 6		"token_url":          "https://sts.googleapis.com/v1/token",
 7		"credential_source": {
 8			"file": "/var/run/service-account/token",
 9			"format": {
10				"type": "text"
11			}
12		},
13		"token_info_url": "https://sts.googleapis.com/v1/introspect"
14}

Mounting the config and pointing GCP SDKs to it is still the same, though I'm still confused by the audience not needing https: in the config but needing it in the GCP and token setup.

Also, I realized that if you used a projected serviceAccountToken volume, the default token isn't mounted, causing issues if the application talked to the Kubernetes API. Setting automountServiceAccountToken appears to be the easiest way to get it back.

 1spec:
 2  template:
 3    spec:
 4      automountServiceAccountToken: true
 5      containers:
 6        - env:
 7            - name: GOOGLE_APPLICATION_CREDENTIALS
 8              value: /etc/workload-identity/creds.json
 9          volumeMounts:
10            - name: token
11              mountPath: /var/run/service-account
12              readOnly: true
13            - name: gcp-creds
14              mountPath: /etc/workload-identity
15              readOnly: true
16      volumes:
17        - name: token
18          projected:
19            sources:
20              - serviceAccountToken:
21                  audience: https://iam.googleapis.com/projects/330311169810/locations/global/workloadIdentityPools/kubernetes/providers/justia-asami
22                  expirationSeconds: 3600
23                  path: token
24        - name: gcp-creds
25          configMap:
26            name: gcp

With this we can grant access to the new principal types such as:

# a specific service account
principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/system:serviceaccount:KSA_NAMESPACE:KSA_NAME

# service account with the same name in all namespaces
principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.service_account_name/KSA_NAME