gcp-auth
$
npx mdskill add TerminalSkills/skills/gcp-authConfigure Google Cloud authentication and authorization for different environments
- Solve authentication needs for local development and deployed services
- Uses gcloud CLI, ADC, service account impersonation, and Workload Identity Federation
- Analyzes deployment context and access requirements to recommend auth methods
- Provides configuration steps for secure access to Google Cloud APIs and resources
SKILL.md
.github/skills/gcp-authView on GitHub ↗
---
name: gcp-auth
description: |
Configure authentication and authorization for Google Cloud — Application
Default Credentials (ADC), service account impersonation, Workload Identity
Federation for GKE and external clouds, and OIDC ID tokens for service-to-
service auth. Use when setting up local dev access, deploying to Cloud Run /
Cloud Functions / GKE, or calling private Google Cloud APIs.
license: Apache-2.0
compatibility: 'gcloud-cli, google-cloud-sdk client libraries'
metadata:
author: google-cloud
version: 1.0.0
category: devops
tags:
- gcp
- iam
- authentication
- service-accounts
- workload-identity
---
# GCP Authentication & Authorization
## Overview
Authentication answers "who are you?" — authorization (IAM) answers "what can you do?" Google Cloud uses three concepts together: **Principals** (user accounts, service accounts, federated identities), short-lived **tokens** issued by metadata servers or the Service Account Credentials API, and **IAM Allow Policies** that bind principals to predefined or custom roles on resources.
The right pattern depends on where the code runs and who is calling.
## Instructions
### Decision Matrix
| Scenario | Use |
|---|---|
| Local development, calling Google APIs | `gcloud auth application-default login` (ADC) |
| Local dev, but you need to act as a service account | Service account impersonation (NOT keys) |
| Code on Compute Engine / Cloud Run / Cloud Functions | Attached service account + metadata server |
| Code on GKE | Workload Identity Federation for GKE |
| Code on AWS / Azure / on-prem | Workload Identity Federation (with external IdP) |
| Calling a private Cloud Run / Cloud Functions service | OIDC ID token in `Authorization: Bearer` |
| Public / quota-limited APIs (Maps, Vertex AI Express) | API key with restrictions |
If a downloadable service account key (JSON) appears in the answer for any of these, the answer is wrong.
### Local Development with Application Default Credentials
```bash
# One-time setup: log in as your human account
gcloud auth login
# Create local ADC (this is what client libraries use)
gcloud auth application-default login
# Set the project for downstream commands
gcloud config set project my-project
gcloud auth application-default set-quota-project my-project
```
```python
# No credentials in code — ADC is picked up automatically
from google.cloud import storage
client = storage.Client() # uses ~/.config/gcloud/application_default_credentials.json
for blob in client.list_blobs("my-bucket"):
print(blob.name)
```
ADC search order:
1. `GOOGLE_APPLICATION_CREDENTIALS` env var (path to JSON)
2. `gcloud auth application-default login` file
3. Attached service account on the runtime (GCE, Cloud Run, GKE, etc.)
### Service Account Impersonation (Local Dev, Production-Like)
Never download service account keys for local testing. Impersonate instead.
```bash
# Grant your user the Token Creator role on the target service account
gcloud iam service-accounts add-iam-policy-binding \
prod-deploy@my-project.iam.gserviceaccount.com \
--member="user:alice@example.com" \
--role="roles/iam.serviceAccountTokenCreator"
# Use impersonation for one command
gcloud storage buckets list \
--impersonate-service-account=prod-deploy@my-project.iam.gserviceaccount.com
# Or set ADC to use impersonation persistently
gcloud auth application-default login \
--impersonate-service-account=prod-deploy@my-project.iam.gserviceaccount.com
```
### Production: Attached Service Accounts
```bash
# Cloud Run
gcloud run deploy api \
--image=us-central1-docker.pkg.dev/my-project/repo/api:v1 \
--region=us-central1 \
--service-account=api-runtime@my-project.iam.gserviceaccount.com
# Compute Engine
gcloud compute instances create web-1 \
--zone=us-central1-a \
--service-account=web-runtime@my-project.iam.gserviceaccount.com \
--scopes=cloud-platform
# Cloud Functions (2nd gen)
gcloud functions deploy process-events \
--gen2 --region=us-central1 \
--runtime=python311 \
--trigger-topic=events \
--service-account=events-runtime@my-project.iam.gserviceaccount.com
```
The runtime fetches a short-lived OAuth token from the local metadata server — application code calls `google.auth.default()` and just works.
### Workload Identity Federation for GKE
```bash
# Enable on the cluster
gcloud container clusters update prod-cluster \
--region=us-central1 \
--workload-pool=my-project.svc.id.goog
# Bind a Kubernetes ServiceAccount to a Google Service Account
gcloud iam service-accounts add-iam-policy-binding \
orders-api@my-project.iam.gserviceaccount.com \
--role="roles/iam.workloadIdentityUser" \
--member="serviceAccount:my-project.svc.id.goog[default/orders-api]"
```
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: orders-api
namespace: default
annotations:
iam.gke.io/gcp-service-account: orders-api@my-project.iam.gserviceaccount.com
```
### Workload Identity Federation for AWS / Azure / On-Prem
```bash
# Create a workload identity pool
gcloud iam workload-identity-pools create aws-pool \
--location=global --display-name="AWS Pool"
# Add an AWS provider
gcloud iam workload-identity-pools providers create-aws aws \
--location=global \
--workload-identity-pool=aws-pool \
--account-id=123456789012
# Bind an AWS IAM role to a GSA
gcloud iam service-accounts add-iam-policy-binding \
cross-cloud-reader@my-project.iam.gserviceaccount.com \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/aws-pool/attribute.aws_role/arn:aws:sts::123456789012:assumed-role/AppRole"
```
### OIDC ID Tokens for Service-to-Service Calls
```python
# Service A (Cloud Run) calling Service B (private Cloud Run)
import google.auth.transport.requests
import google.oauth2.id_token
import requests
audience = "https://orders-api-xyz-uc.a.run.app"
auth_req = google.auth.transport.requests.Request()
id_token = google.oauth2.id_token.fetch_id_token(auth_req, audience)
response = requests.get(
f"{audience}/orders/123",
headers={"Authorization": f"Bearer {id_token}"},
)
print(response.json())
```
```bash
# Grant Cloud Run invoker on Service B to Service A's service account
gcloud run services add-iam-policy-binding orders-api \
--region=us-central1 \
--member="serviceAccount:caller-runtime@my-project.iam.gserviceaccount.com" \
--role="roles/run.invoker"
```
### API Keys (Limited Use Cases)
```bash
# Create an API key restricted to a specific API and HTTP referrer
gcloud alpha services api-keys create \
--display-name="maps-frontend" \
--api-target=service=maps-backend.googleapis.com \
--allowed-referrers="https://app.example.com/*"
```
Store the key in Secret Manager, never commit to git, and always restrict it.
## Examples
### Example 1 — Get a developer set up to call BigQuery
User clones the repo and needs to run integration tests locally. Walk them through `gcloud auth application-default login`, `gcloud config set project my-project`, and `gcloud auth application-default set-quota-project my-project`. Confirm the Python BigQuery client picks up ADC with no code changes. If they need to act as a service account, set up impersonation rather than handing them a JSON key.
### Example 2 — Migrate a GKE workload off a JSON key Secret
User's deployment mounts a service account JSON key as a Kubernetes Secret. Enable Workload Identity on the cluster, create a Kubernetes ServiceAccount with the `iam.gke.io/gcp-service-account` annotation, bind it to the existing GSA via `roles/iam.workloadIdentityUser`, redeploy without the Secret mount, then delete both the Secret and the underlying GSA key.
## Guidelines
- **Never download service account keys** — use impersonation, attached SAs, or Workload Identity Federation
- **Never use the Compute Engine default service account** in production — create a dedicated, least-privilege SA per workload
- For local dev, **ADC + impersonation** is the only acceptable pattern
- Use **Workload Identity for GKE** — JSON keys mounted as Secrets are a security anti-pattern
- For service-to-service calls, use **OIDC ID tokens**, not API keys or shared secrets
- **Restrict API keys** by API, IP, and HTTP referrer; store them in Secret Manager
- Compute Engine VMs and GKE node pools have **OAuth access scopes** that override IAM — check these first if attached SA calls fail unexpectedly
- Prefer **predefined roles** over custom roles; use custom only when predefined are too broad
- Audit service account usage via Cloud Audit Logs and the Recommender's "unused service accounts" insight