One of the things I like about GCP is that every workload always has an identity (GCP service account) attached, and the GCP client libraries can just magically pick up the identity and make authenticated calls.
For Google managed kubernetes (GKE), there's a layer of indirection,
as you (typically) don't want everything in your cluster running on the same identity.
This is Workload Identity:
your Kubernetes service accounts are annotated
with iam.gke.io/gcp-service-account=GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com
and a GKE metadata agent running as a daemonset on your nodes serves the GCP metadata endpoint
with the appropriate info.
The GCP service account needs to grant permissions to GSA_PROJECT.svc.id.goog[NAMESPACE/KSA_NAME]
,
but otherwise, the workload itself doesn't need to change.
For Kubernetes running anywhere else,
there's Workload Identity Federation
to trust AWS, Azure, or any OIDC provider,
including the one built into Kubernetes (Service Account Issuer Discovery).
Your K8s api endpoint doesn't even need to be exposed to the world.
Setup is slightly more involved (workload identity pool + provider),
and the workload definitions need to change:
you'll need to pass GOOGLE_APPLICATION_CREDENTIALS
,
and mount both a token and the generated config.
The client libraries start with the env,
read the file,
then read the token.
One hiccup was that depending on the library,
you may need to explicitly pass the google project.
generated config:
1{
2 "type": "external_account",
3 "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
4 "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
5 "token_url": "https://sts.googleapis.com/v1/token",
6 "credential_source": {
7 "file": "/var/run/service-account/token",
8 "format": {
9 "type": "text"
10 }
11 },
12 "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com:generateAccessToken"
13}
application spec:
1spec:
2 template:
3 spec:
4 containers:
5 - env:
6 - name: GOOGLE_APPLICATION_CREDENTIALS
7 value: /var/run/service-account/gcp-workload-identity.json
8 volumeMounts:
9 - name: token
10 mountPath: "/var/run/service-account"
11 readOnly: true
12 serviceAccountName: my-app
13 volumes:
14 - name: token
15 projected:
16 sources:
17 - serviceAccountToken:
18 audience: https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
19 expirationSeconds: 3600
20 path: token
21 - configMap:
22 name: gcp-workload-identity