gcp.md
Workload Federation with GCP
Namespace relies on Workload Identity Federation to allow Namespace to interact with different systems, instead of relying on pre-shared keys which can be more easily compromised.
Accessing GCP resources from Namespace
Identity Federation with GCP allows your Namespace workloads to identify themselves to GCP using short-lived secure credentials.
To enable this federation, create a Workload Identity Pool and Provider for Namespace federation in GCP and configure service account impersonation.
1. Create a Workload Identity Pool and Provider
- Ensure IAM is enabled for your GCP project.
- Create a Workload Identity Pool using
gcloudCLI:
d export POOL_ID=namespace-workload-pool
gcloud iam workload-identity-pools create ${POOL_ID} \
--location="global"
- Create an Identity Provider:
export PROVIDER_ID=namespace-id-provider
gcloud iam workload-identity-pools providers create-oidc \
${PROVIDER_ID} \
--location="global" \
--workload-identity-pool=${POOL_ID} \
--issuer-uri="https://federation.namespaceapis.com" \
--attribute-mapping="google.subject=assertion.tenant_id"
2. Configure service account impersonation
- Discover your GCP Project number. Note, this is different from the GCP Project ID:
export PROJECT_NUMBER=$(gcloud projects list \
--filter="$(gcloud config get-value project)" \
--format="value(PROJECT_NUMBER)")
echo ${PROJECT_NUMBER}
- Open the Dashboard and copy your Workspace ID.
- Allow external workloads to impersonate the service account by granting the Workload Identity User role
roles/iam.workloadIdentityUseron the service account:
export SERVICE_ACCOUNT=<NAME>@${PROJECT_ID}.iam.gserviceaccount.com
gcloud iam service-accounts add-iam-policy-binding \
${SERVICE_ACCOUNT} \
--project="${PROJECT_ID}" \
--role="roles/iam.workloadIdentityUser" \
--member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_ID}/subject/<your-workspace-id>"
3. Access GCP resources from a Namespace workload
- Obtain GCP credentials:
nsc gcp impersonate --service_account $SERVICE_ACCOUNT \
--workload_identity_provider /projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_ID}/providers/${PROVIDER_ID} \\
--write_creds=gcp-creds.json
- Apply the obtained credentials:
export GOOGLE_APPLICATION_CREDENTIALS=gcp-creds.json
- Access GCP resources:
gcloud storage cp test.txt gs://your-bucket-name/test2.txt
Pulling private Artifact Registry images on instances
When creating an instance through the Compute API, you can pull private images from Google Artifact Registry by having Namespace federate with GCP Workload Identity Federation to obtain a short-lived access token automatically.
The resolved token is used both to pull the instance's own container images and is written into the guest's Docker/nerdctl configuration (/root/.docker/config.json), so subsequent docker pull and nerdctl pull commands from inside the instance authenticate to the same registry.
1. Grant read access to Artifact Registry
Namespace maps each workspace to the federated subject assertion.tenant_id. Grant that principal the roles/artifactregistry.reader role on the repository, using your Workspace ID as <your-workspace-id>:
gcloud artifacts repositories add-iam-policy-binding <REPOSITORY> \
--project=${PROJECT_ID} \
--location=<region> \
--role="roles/artifactregistry.reader" \
--member="principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_ID}/subject/<your-workspace-id>"
2. Reference the registry when creating an instance
Set additional_registries on the CreateInstance request, keyed by your Artifact Registry host (<region>-docker.pkg.dev). Namespace performs the STS token-exchange against the provider audience and uses the resulting token to pull the image:
{
"containers": [
{
"name": "app",
"image_ref": "<region>-docker.pkg.dev/<project-id>/<repository>/my-image:latest"
}
],
"additional_registries": {
"<region>-docker.pkg.dev": {
"authentication": {
"gcp_workload_identity_federation": {
"audience": "/iam.googleapis.com/projects/<project-number>/locations/global/workloadIdentityPools/<pool-id>/providers/<provider-id>",
"username": "oauth2accesstoken"
}
}
}
}
}
Accessing Namespace resources from GCP
Identity Federation with GCP allows your GCP-based workloads (e.g. running in GKE) to identify themselves to Namespace using short-lived secure credentials. To enable this federation, we rely on GCP's ability to generate OIDC tokens that can be exchanged for Namespace credentials.
- Issuer:
https://accounts.google.com - Subject Format: The full resource path of the Google Service Account your workload runs as (format:
projects/PROJECT_NUMBER/serviceAccounts/EMAIL)
1. Ensure your workload has a Google Service Account
Your GCP workload needs a Google Service Account (GSA) that can mint OIDC tokens. If you're running in GKE with Workload Identity, bind your Kubernetes Service Account (KSA) to a GSA:
- Create a GSA (if you don't already have one):
gcloud iam service-accounts create my-nsc-sa --project=${PROJECT_ID}
- Bind the KSA to the GSA:
gcloud iam service-accounts add-iam-policy-binding \
my-nsc-sa@${PROJECT_ID}.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:${PROJECT_ID}.svc.id.goog[${K8S_NAMESPACE}/${KSA_NAME}]"
- Annotate the KSA:
kubectl annotate serviceaccount ${KSA_NAME} -n ${K8S_NAMESPACE} \
iam.gke.io/gcp-service-account=my-nsc-sa@${PROJECT_ID}.iam.gserviceaccount.com
2. Configure Trust Relationship
Use the Namespace CLI to establish a trust relationship with your GCP service account:
For a specific service account:
nsc auth trust-relationships add \
--issuer "https://accounts.google.com" \
--subject-match "projects/${PROJECT_NUMBER}/serviceAccounts/my-nsc-sa@${PROJECT_ID}.iam.gserviceaccount.com"
For all service accounts in a GCP project:
nsc auth trust-relationships add \
--issuer "https://accounts.google.com" \
--subject-match "projects/${PROJECT_NUMBER}/serviceAccounts/*"
3. Verify Trust Relationship
List your configured trust relationships to confirm the setup:
nsc auth trust-relationships list
4. Obtain Namespace credentials from your GCP workload
From your GCP workload (e.g. a GKE pod), obtain and exchange an OIDC token for Namespace credentials:
- Generate a GCP OIDC token targeting Namespace:
export OIDC_TOKEN=$(gcloud auth print-identity-token --audiences=federation.namespaceapis.com)
- Exchange the OIDC token for Namespace credentials:
nsc auth exchange-oidc-token --token $OIDC_TOKEN --tenant_id <your-workspace-id>
This command should succeed with the name of workspace you've signed in to.
It stores a short-lived token that will be used automatically in subsequent nsc calls.