Workload Identity Federation (WIF) allows workloads running in Google Cloud (e.g., GKE pods) to securely access AWS resources (like S3) without storing static AWS credentials. Instead of using long-lived access keys, GCP workloads exchange Google identity tokens for temporary AWS credentials via AWS STS (Security Token Service)

  Without:

workload- identity- federation

Check if Workload Identity Federation is enabled:

$ gcloud container clusters describe CLUSTER_NAME \

    --project=YOUR_PROJECT_ID \

    --location=GKE_REGION \

    --format="value(workloadIdentityConfig.workloadPool)"

Example:

$ gcloud container clusters describe mgr-main-sbx \

    --project=mgr-product-sbx \

    --location=europe-west1 \

    --format="value(workloadIdentityConfig.workloadPool)"

Output:

mgr-product-sbx.svc.id.goog

If it is not enabled, run:

$ gcloud container clusters update CLUSTER_NAME \

    --workload-pool=YOUR_PROJECT_ID.svc.id.goog \

    --project=YOUR_PROJECT_ID \

    --location=GKE_REGION

To create the provider:

$ aws iam create-open-id-connect-provider \

    --url https://sts.googleapis.com \

    --client-id-list sts.amazonaws.com \

    --thumbprint-list 08745487ghdud7e7eh1f2a07e452f36f6

Verify the OIDC Provider is created:

$ aws iam list-open-id-connect-providers

Create GCP Service Account (poc-gcp-to-aws-sa@mgr-product-sbx.iam.gserviceaccount.com) and create a key for this SA:

$ gcloud iam service-accounts create poc-gcp-to-aws-sa --project=YOUR_PROJECT_ID  --display-name="GCP to AWS Service Account"

Example:

$ gcloud iam service-accounts create poc-gcp-to-aws-sa \     --project=mgr-product-sbx \     --display-name="GCP to AWS Service Account"     --role="roles/iam.serviceAccountTokenCreator"


Give SA permissions to get/create tokens!

$ gcloud auth activate-service-account --key-file=mgr-product-sbx-24aa6b13e9a7.json

$ TOKEN=$(gcloud auth print-identity-token --impersonate-service-account=poc-gcp-to-aws-sa@mgr-product-sbx.iam.gserviceaccount.com)

$ echo $TOKEN | jq -R 'split(".") | .[1] | @base64d | fromjson'

Create file poc-trust-policy.json

{

    "Version": "2012-10-17",

    "Statement": [

        {

            "Effect": "Allow",

            "Principal": {"Federated": "accounts.google.com"},

            "Action": "sts:AssumeRoleWithWebIdentity",

            "Condition": {

                "StringEquals": {

                    "accounts.google.com:aud": "<azp-value>",

                    "accounts.google.com:oaud": "<aud-value>",

                    "accounts.google.com:sub": "<sub-value>"

                }

            }

        }

    ]

}

For “aud“, “oaud“ and “sub“ use the output from SA TOKEN.

accounts.google.com:oaud condition key matches the aud (AUDIENCE) field on the Google ID token.

accounts.google.com:aud condition key matches the azp (AUTHORIZED_PARTY) field on the Google ID token.

accounts.google.com:sub condition key matches the sub (SUBJECT) field on the Google ID token.

Create the AWS role

$ aws iam create-role \

    --role-name GCPWorkloadIAMRole \

    --assume-role-policy-document file://poc-trust-policy.json

Assigning policy “AmazonS3ReadOnlyAccess“ to this role (for the test later).

Configure Workload Identity Federation

$ gcloud iam workload-identity-pools create "POOL_NAME" \

    --project=YOUR_PROJECT_ID \

    --location="global" \

    --display-name="AWS Workload Identity Pool"

Example:

$ gcloud iam workload-identity-pools create "poc-aws-pool" --project=mgr-product-sbx --location="global" --display-name="AWS Workload Identity Pool"

This connects the pool to AWS.

$ gcloud iam workload-identity-pools providers create-oidc "PROVIDER_NAME" \                      

--project=PROJECT_NAME \    

--location="global" \    

--workload-identity-pool="POOL_NAME" \          

--display-name="AWS OIDC Provider" \    

--issuer-uri="https://sts.amazonaws.com" \    

--allowed-audiences="sts.amazonaws.com" \    

--attribute-mapping="google.subject=assertion.sub,google.groups=assertion.groups"

Example:

$ gcloud iam workload-identity-pools providers create-oidc "aws-provider"

--project=mgr-product-sbx

--location="global"

--workload-identity-pool="poc-aws-pool"

--display-name="AWS OIDC Provider"

--issuer-uri="https://sts.amazonaws.com"

--allowed-audiences="sts.amazonaws.com"

--attribute-mapping="google.subject=assertion.sub,google.groups=assertion.groups"

The output will be:

projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/poc-aws-   pool/providers/aws-provider

Allow Workloads to Assume This Service Account

$ gcloud iam service-accounts add-iam-policy-binding \

    poc-gcp-to-aws-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com \

    --role roles/iam.workloadIdentityUser \

    --member "principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME/subject/arn:aws:iam::AWS_ACCOUNT_ID:role/ROLE_NAME"

Examaple:

$ gcloud iam service-accounts add-iam-policy-binding poc-gcp-to-aws-sa@mgr-product-sbx.iam.gserviceaccount.com

--role roles/iam.workloadIdentityUser

--member "principal://iam.googleapis.com/projects/960144414359/locations/global/workloadIdentityPools/poc-aws-pool/subject/arn:aws:iam::211125558983:role/GCPWorkloadIAMRole"
$ gcloud auth activate-service-account --key-file=mgr-product-sbx-e284c02e086c.json

TOKEN=$(gcloud auth print-identity-token --impersonate-service-account=poc-gcp-to-aws-sa@mgr-product-sbx.iam.gserviceaccount.com)

$ echo $TOKEN | jq -R 'split(".") | .[1] | @base64d | fromjson'

$ aws sts assume-role-with-web-identity --role-arn "arn:aws:iam::211125558983:role/GCPWorkloadIAMRole" --role-session-name "gcp-session" --web-identity-token "$TOKEN" --query 'Credentials'

Output should looks something like:

export AWS_ACCESS_KEY_ID=”YOUR_ACCESS_KEY_ID”
export AWS_SECRET_ACCESS_KEY=”YOUR_SECRET_ACCESS_KEY”
export AWS_SESSION_TOKEN=”YOUR_SESSION_TOKEN”

Test S3 Access

$ aws s3 ls

Output:

2024-11-09 07:19:45 baseline-tfstates-211125558983

2024-11-09 07:37:41 billing-export-211125558983

2024-11-20 13:12:19 gar-credential-provider-test

$ aws iam list-roles

Output:

An error occurred (AccessDenied) when calling the ListRoles operation: User: arn:aws:sts::211125558983:assumed-role/GCPWorkloadIAMRole/gcp-session is not authorized to perform: iam:ListRoles on resource: arn:aws:iam::211125558983:role/ because no identity-based policy allows the iam:ListRoles action

This setup lets GCP workloads like GKE pods access AWS securely, without ever managing or embedding long-lived secrets. With Workload Identity Federation, you ensure: