GCP Workload Identity Federation — SKILL.md
Raw skill file that agents receive when using this skill
---
name: "GCP Workload Identity Federation"
description: "Skill for GCP Workload Identity Federation — auto-generated from documentation"
version: "1.0.0"
author: "skynet"
category: "infrastructure"
agents: ["claude-code", "codex", "gemini"]
tags: ["gcp-workload-identity", "infrastructure", "auto-generated"]
---
# GCP Workload Identity Federation
---
name: GCP Workload Identity Federation
description: Configure secure authentication for external workloads (GitHub Actions, AWS, Azure) to access GCP resources without service account keys
metadata:
author: skynet
version: 1.0.0
category: infrastructure
---
# GCP Workload Identity Federation
## Overview
Workload Identity Federation allows external workloads to authenticate to GCP without storing service account keys, using OIDC tokens from trusted identity providers.
## Prerequisites
- GCP project with appropriate IAM permissions
- External identity provider (GitHub Actions, AWS, Azure AD, etc.)
- `gcloud` CLI installed and authenticated
## Core Commands
### Create Workload Identity Pool
```bash
# Create identity pool
gcloud iam workload-identity-pools create POOL_NAME \
--project=PROJECT_ID \
--location=global \
--display-name="Pool Display Name" \
--description="Pool for external workloads"
# Verify pool creation
gcloud iam workload-identity-pools describe POOL_NAME \
--project=PROJECT_ID \
--location=global
```
### Configure Identity Providers
#### GitHub Actions Provider
```bash
# Create GitHub provider
gcloud iam workload-identity-pools providers create-oidc PROVIDER_NAME \
--project=PROJECT_ID \
--location=global \
--workload-identity-pool=POOL_NAME \
--display-name="GitHub Actions" \
--attribute-mapping="google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository" \
--issuer-uri="https://token.actions.githubusercontent.com"
# Add attribute conditions for specific repository
gcloud iam workload-identity-pools providers update-oidc PROVIDER_NAME \
--project=PROJECT_ID \
--location=global \
--workload-identity-pool=POOL_NAME \
--attribute-condition="assertion.repository=='OWNER/REPO'"
```
#### AWS Provider
```bash
# Create AWS provider
gcloud iam workload-identity-pools providers create-aws PROVIDER_NAME \
--project=PROJECT_ID \
--location=global \
--workload-identity-pool=POOL_NAME \
--account-id=AWS_ACCOUNT_ID \
--display-name="AWS Provider"
# Add attribute mapping
gcloud iam workload-identity-pools providers update-aws PROVIDER_NAME \
--project=PROJECT_ID \
--location=global \
--workload-identity-pool=POOL_NAME \
--attribute-mapping="google.subject=assertion.arn,attribute.aws_role=assertion.arn.contains('assumed-role') ? assertion.arn.extract('{account}:assumed-role/{role_name}/') : assertion.arn"
```
### Bind Service Account
```bash
# Allow external identity to impersonate service account
gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
--project=PROJECT_ID \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME/attribute.repository/OWNER/REPO"
# For all repositories in an organization
gcloud iam service-accounts add-iam-policy-binding SERVICE_ACCOUNT_EMAIL \
--project=PROJECT_ID \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME/attribute.repository_owner/ORG_NAME"
```
## Common Workflows
### GitHub Actions Integration
```yaml
# .github/workflows/deploy.yml
name: Deploy
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v3
- id: 'auth'
uses: 'google-github-actions/auth@v1'
with:
workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME/providers/PROVIDER_NAME'
service_account: 'SERVICE_ACCOUNT_EMAIL'
- name: 'Set up Cloud SDK'
uses: 'google-github-actions/setup-gcloud@v1'
- name: 'Use gcloud CLI'
run: 'gcloud info'
```
### AWS Cross-Cloud Authentication
```bash
# Configure AWS CLI to use GCP credentials
aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::ACCOUNT:role/ROLE_NAME \
--role-session-name gcp-session \
--web-identity-token $(gcloud auth print-identity-token) \
--duration-seconds 3600
```
### Test Authentication
```bash
# Test token generation
gcloud iam workload-identity-pools create-cred-config \
projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME/providers/PROVIDER_NAME \
--service-account=SERVICE_ACCOUNT_EMAIL \
--output-file=credentials.json
# Test with generated credentials
export GOOGLE_APPLICATION_CREDENTIALS=credentials.json
gcloud auth list
```
## Decision Trees
### Provider Type Selection
```
External Identity Provider?
├── GitHub Actions → Use OIDC provider with token.actions.githubusercontent.com
├── GitLab CI → Use OIDC provider with gitlab.com
├── AWS → Use AWS provider with account ID
├── Azure → Use OIDC provider with Azure AD endpoint
└── Custom OIDC → Use OIDC provider with custom issuer
```
### Attribute Mapping Strategy
```
Scope of Access?
├── Single Repository → attribute.repository='owner/repo'
├── Organization → attribute.repository_owner='org'
├── Specific AWS Role → attribute.aws_role contains 'role-name'
└── Environment-based → attribute.environment='prod'
```
## Troubleshooting
### Common Errors and Solutions
**Error: `The caller does not have permission`**
```bash
# Check IAM permissions
gcloud projects get-iam-policy PROJECT_ID \
--flatten="bindings[].members" \
--format="table(bindings.role)" \
--filter="bindings.members:YOUR_EMAIL"
# Add required role
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="user:YOUR_EMAIL" \
--role="roles/iam.workloadIdentityPoolAdmin"
```
**Error: `Invalid token or token not found`**
```bash
# Verify provider configuration
gcloud iam workload-identity-pools providers describe PROVIDER_NAME \
--project=PROJECT_ID \
--location=global \
--workload-identity-pool=POOL_NAME
# Check issuer URI and attribute mapping
gcloud iam workload-identity-pools providers describe PROVIDER_NAME \
--project=PROJECT_ID \
--location=global \
--workload-identity-pool=POOL_NAME \
--format="value(oidc.issuerUri,attributeMapping)"
```
**Error: `Workload identity pool does not exist`**
```bash
# List available pools
gcloud iam workload-identity-pools list \
--project=PROJECT_ID \
--location=global
# Check project number vs ID usage
gcloud projects list \
--filter="projectId:PROJECT_ID" \
--format="value(projectNumber)"
```
**Error: `Principal not found in policy binding`**
```bash
# Verify service account binding
gcloud iam service-accounts get-iam-policy SERVICE_ACCOUNT_EMAIL \
--project=PROJECT_ID
# Check principal format
echo "principalSet://iam.googleapis.com/projects/$(gcloud projects list --filter="projectId:PROJECT_ID" --format="value(projectNumber)")/locations/global/workloadIdentityPools/POOL_NAME/attribute.repository/OWNER/REPO"
```
### Debugging Authentication Flow
```bash
# Enable audit logs for debugging
gcloud logging read "protoPayload.serviceName=iam.googleapis.com AND protoPayload.methodName=google.iam.credentials.v1.IAMCredentials.GenerateIdToken" \
--limit=10 \
--format=json
# Test token exchange manually
curl -X POST https://sts.googleapis.com/v1/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "audience=//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_NAME/providers/PROVIDER_NAME&grant_type=urn:ietf:params:oauth:grant-type:token-exchange&requested_token_type=urn:ietf:params:oauth:token-type:access_token&scope=https://www.googleapis.com/auth/cloud-platform&subject_token_type=urn:ietf:params:oauth:token-type:id_token&subject_token=EXTERNAL_TOKEN"
```
curl -s https://skills.skynet.ceo/api/skills/gcp-workload-identity/skill.md