Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save marcinantkiewicz/b3646829a758cf6d46972223d885b820 to your computer and use it in GitHub Desktop.

Select an option

Save marcinantkiewicz/b3646829a758cf6d46972223d885b820 to your computer and use it in GitHub Desktop.
k8s
# Players
# KSA - k8s service account
# GSA - GCP service account
# metadata server - runs on cluster nodes where pods with Workload Identity are dispatched, will respond to requests directed to 169.254.169.254.
# workload identity - modifies behavior of the metadata server. Transparently to the SA, it will return GCP STS tokens issued to the impersonated GCP role.
# Note: - when WI is enabled but not configured properly, the metadata server will fail (silently?) when it does not find annotation etc.
#
# request flow
# 1. pod requests credentials from the metadata server
# 2. metadata server checks if the pod is using workload identity, and identifies the KSA
# 3. metadata server looks up GCP account to impersonate in the KSA object's iam.gke.io/gcp-service-account annotation
# 4. if there is no annotation the process halts, no credentials are returned (naked request is issued? what error)
# 4. metadata server requests kublet to fetch a short lived JWT from the k8s API server. The JWT is audience bound to STS and bound to the pods that requested it. Kublet is trusted, but isolated to the node it runs on - it can only request tokens for pods on it's node. The token is audience and pod bound, shortlived.
# https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
# 5. and sends it to STS in an impersonation request for the GSA. If successful, STS will send back the GSA JWT
# 6. STS verifies signature on the JWT, based on OIDC metdata publised by cluster enrolled in WI, and verifies KSA is authorized to impersonate GSA - policy binding with roles/iam.workloadIdentityUser
# 7. STS returns GSA token to metadata server, which returns it to the pod
#
# in short there must be
# WI enabled
# KSA and GSA exist
# in k8s, KSA object must have annotation with the GSA
# In GCP IAM, KSA must have policy binding allowing it to impersonate GSA
# in GCP IAM, GSA must have rights to do whatever the pod will request KSA to do
#
#
# workload identity
# - without workload identity, the pods use identity of the cluster node. Usually it is ${PROJECT_NUMBER}[email protected], usually it is the `editor`
# - enabling workload identity turns on metadata server on 169.254.169.254 that can be asked for GCP STS tokens on pods configured to use workload identity
# - k8s is not GCP aware, in order to allow pods to connect to GCP service SA credentials would have to be provided to SDK/services in the pod
# - telling GCP to map GKE account to GCP identity handles authentication, including rotation, out of the user/customer accessible pod
# - it is a trust relationship between k8s cluster and GCP IAM
# - creation of workload identity pool gives the cluster IAM identity and allows pods to use service account bindings
# - k8s service account will impersonate the GCP IAM identity for any requests to the GCP, that GCP identity must have apropriate permissions
# -
## -- create namespace and service account used in it kubectl create namespace ${NAMESPACE}
kubectl create serviceaccount ${KSA} --namespace ${NAMESPACE}
## -- create GCP user and allow it to admin containers in the project
gcloud iam service-accounts create ${GSA} --project ${PROJECT_ID}
gcloud projects add-iam-policy-bindging ${PROJECT_ID} \
--member "serviceAccount:${GSA}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role roles/container.admin
## -- allow namespace/SA to impersonate GCP SA
# - ${PROJECT_ID}.svc.id.goog identifies the workload identity pool used in the cluster
# - in GCP, the k8s SA are have identity: `serviceAccount:${PROJECT_ID}.svc.id.goog[${NAMESPACE}/${KSA}]` and must be allowed to impersonate ${KSA}
gcloud iam service-accounts add-iam-policy-binding ${PROJECT_ID}\
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:${PROJECT_ID}.svc.id.goog[${NAMESPACE}/${KSA}]" \
${GSA}@$PROJECT_ID.iam.gserviceaccount.com
## -- allow role in GCP project to accesss containers
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member=serviceAccount:${GSA}.iam.gserviceaccount.com \
--role=roles/container.admin
## -- link k8s service account to GCP service account to allow pod to impersonate GCP identity
# - adds metadata, annotation to ${KSA} k8s object existing in the ${NAMESPACE}
# - that metadata is in the ServiceAccount object, metadata.annotations.iam.gke.io/gcp-service-account
# - and it is set to the IAM user existing in GCP
kubectl annotate serviceaccount ${KSA} \
--namespace ${NAMESPACE} \
iam.gke.io/gcp-service-account=${GSA}@${PROJECT_ID}.iam.gserviceaccount.com
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment