Skip to main content

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

TokenDefault LifetimeNotes
NetActuate OIDC tokenVaries by configurationSet in Account → Settings → OIDC
STS federated token1 hourCannot be refreshed; request a new one
Service account token1 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.workloadIdentityUser binding 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.