GCP STS Integration
This guide covers using the Google Cloud Security Token Service (STS) to exchange NetActuate OIDC tokens for GCP access tokens. This is a focused walkthrough of the token exchange process, complementing the broader GCP OIDC Federation guide.
Overview
The GCP Security Token Service (STS) enables you to exchange third-party tokens for short-lived GCP access tokens. When combined with NetActuate OIDC, this allows your applications to authenticate with NetActuate and then access GCP resources without storing GCP service account keys.
Prerequisites
- A configured Workload Identity Pool and OIDC provider in GCP (see GCP OIDC Federation steps 1-2)
- A GCP service account with workload identity user binding
- A valid NetActuate OIDC token
Step 1: Obtain a NetActuate OIDC Token
Use the client credentials grant to obtain an OIDC token programmatically:
curl -X POST "https://portal.netactuate.com/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=openid"
Save the id_token from the response for use in the next step.
Step 2: Exchange the Token via STS
Call the GCP STS endpoint to exchange your NetActuate token for a federated access token:
curl -X POST "https://sts.googleapis.com/v1/token" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"audience": "//iam.googleapis.com/projects/YOUR_PROJECT_NUMBER/locations/global/workloadIdentityPools/netactuate-pool/providers/netactuate-oidc",
"scope": "https://www.googleapis.com/auth/cloud-platform",
"requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
"subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
"subject_token": "YOUR_NETACTUATE_ID_TOKEN"
}'
The response includes an access_token that represents a federated identity.
Step 3: Generate a Service Account Access Token
Use the federated token to impersonate a GCP service account:
curl -X POST "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/YOUR_SERVICE_ACCOUNT@YOUR_PROJECT_ID.iam.gserviceaccount.com:generateAccessToken" \
-H "Authorization: Bearer FEDERATED_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"scope": ["https://www.googleapis.com/auth/cloud-platform"],
"lifetime": "3600s"
}'
The lifetime parameter controls the token validity period (maximum 3600 seconds / 1 hour).
Step 4: Use the GCP Access Token
The service account access token can now be used to call GCP APIs. For example, to list Compute Engine instances:
curl -H "Authorization: Bearer SERVICE_ACCOUNT_ACCESS_TOKEN" \
"https://compute.googleapis.com/compute/v1/projects/YOUR_PROJECT_ID/zones/us-central1-a/instances"
Automating the Flow
You can script the full token exchange chain. Here is a Bash example:
#!/bin/bash
set -euo pipefail
PROJECT_NUMBER="YOUR_PROJECT_NUMBER"
PROJECT_ID="YOUR_PROJECT_ID"
SERVICE_ACCOUNT="YOUR_SERVICE_ACCOUNT@${PROJECT_ID}.iam.gserviceaccount.com"
POOL_PROVIDER="//iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/netactuate-pool/providers/netactuate-oidc"
# Step 1: Get NetActuate OIDC token
NA_TOKEN=$(curl -s -X POST "https://portal.netactuate.com/oauth/token" \
-d "grant_type=client_credentials" \
-d "client_id=${OIDC_CLIENT_ID}" \
-d "client_secret=${OIDC_CLIENT_SECRET}" \
-d "scope=openid" | jq -r '.id_token')
# Step 2: Exchange for federated token
FED_TOKEN=$(curl -s -X POST "https://sts.googleapis.com/v1/token" \
-H "Content-Type: application/json" \
-d "{
\"grant_type\": \"urn:ietf:params:oauth:grant-type:token-exchange\",
\"audience\": \"${POOL_PROVIDER}\",
\"scope\": \"https://www.googleapis.com/auth/cloud-platform\",
\"requested_token_type\": \"urn:ietf:params:oauth:token-type:access_token\",
\"subject_token_type\": \"urn:ietf:params:oauth:token-type:jwt\",
\"subject_token\": \"${NA_TOKEN}\"
}" | jq -r '.access_token')
# Step 3: Get service account token
GCP_TOKEN=$(curl -s -X POST \
"https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${SERVICE_ACCOUNT}:generateAccessToken" \
-H "Authorization: Bearer ${FED_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"scope": ["https://www.googleapis.com/auth/cloud-platform"]}' | jq -r '.accessToken')
echo "GCP Access Token: ${GCP_TOKEN}"
Token Lifetimes
| Token | Default Lifetime | Notes |
|---|---|---|
| NetActuate OIDC token | Varies by configuration | Set in Account → Settings → OIDC |
| STS federated token | 1 hour | Cannot be refreshed; request a new one |
| Service account token | 1 hour (max) | Configurable via lifetime parameter |
Troubleshooting
- "INVALID_ARGUMENT" from STS: Verify the audience string matches your pool/provider path exactly, including the project number (not project ID).
- "PERMISSION_DENIED" on generateAccessToken: Ensure the workload identity pool has the
roles/iam.workloadIdentityUserbinding on the service account. - Expired tokens: NetActuate OIDC tokens and GCP tokens both expire. Implement token refresh logic in your automation scripts.
Need Help?
If you run into issues, contact NetActuate Support.