Authenticate to Cloudsmith with your Google Cloud identity

Long-lived API keys are a liability. They sit in secret managers, leak into logs, and eventually someone has to remember to rotate them. If you run workloads on Google Cloud, you can skip that whole problem: every VM, container, and function already carries a service account identity, and you can use it to authenticate to Cloudsmith directly.

Google's workload identity tokens and Cloudsmith's OIDC support work together to handle authentication. Your workload swaps its service account identity for a short-lived Cloudsmith token at runtime. Nothing long-lived gets written to an environment variable or a key file on disk.

What's happening under the hood?

Google's metadata server can issue signed JSON Web Tokens (JWTs), and Cloudsmith verifies them against Google's public keys. The flow:

  1. Your workload asks the Google metadata server for an ID token, naming Cloudsmith as the intended audience
  2. Google returns a signed JWT carrying your service account's identity (its email and your chosen aud)
  3. You pass this token to Cloudsmith's OIDC endpoint
  4. Cloudsmith fetches Google's public verification keys and validates the signature
  5. If the claims you pinned all match, Cloudsmith hands back a short-lived token for API calls
  6. You're authenticated

Setting things up

Setting this up has two parts. Your workload needs a way to get a Google token, and Cloudsmith needs to know when to trust that Google token.

Mint a token from your service account

On a server you want the token to carry a meaningful audience and a dedicated identity. Service account identity tokens give you both: a custom aud and an explicit email.

The simplest source is the metadata server, available on GCE, Cloud Run, GKE, App Engine, and Cloud Build:

export AUDIENCE="cloudsmith"

export OIDC_TOKEN=$(curl -s -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=${AUDIENCE}&format=full")

format=full includes the email and email_verified claims you'll pin against in Cloudsmith.

You can also impersonate the service account from another identity, such as your own user. However, the calling identity needs roles/iam.serviceAccountTokenCreator on the target service account first:

gcloud iam service-accounts add-iam-policy-binding \
  deployer@my-project.iam.gserviceaccount.com \
  --member="user:you@example.com" \
  --role="roles/iam.serviceAccountTokenCreator" \
  --project=my-project

Then mint the token:

gcloud auth print-identity-token \
  --impersonate-service-account="deployer@my-project.iam.gserviceaccount.com" \
  --audiences="cloudsmith" \
  --include-email

Either way, the token's email is the service account and aud is the value you chose. Decode it at jwt.io and the payload looks roughly like this:

{
  "iss": "https://accounts.google.com",
  "aud": "cloudsmith",
  "azp": "112233445566778899001",
  "sub": "112233445566778899001",
  "email": "deployer@my-project.iam.gserviceaccount.com",
  "email_verified": true,
  "iat": 1780523590,
  "exp": 1780527190
}

Trying it locally first

Before wiring up a workload, you can prove the whole flow with your own Google login:

gcloud auth login
export OIDC_TOKEN=$(gcloud auth print-identity-token)

One thing to know: a user login token's aud doesn’t give you any isolation because it is hard-wired to the gcloud SDK's shared OAuth client ID, which is the same value every gcloud user carries. For a local proof of concept, pin the hd (hosted domain) claim, e.g., your Google Workspace domain, which ties the token back to your organization.

Configure OIDC in Cloudsmith

Now tell Cloudsmith to trust tokens from your service account. You'll need the Manager or Owner role, at least one Cloudsmith service account, and the robot identity that holds your repository entitlements must already exist. Go to Settings > Authentication > OpenID Connect and create a provider:

FieldValue
Provider namegoogle-workload-identity
Provider URLhttps://accounts.google.com
Service accountsThe Cloudsmith service account(s) this provider may authenticate as
Required claimsemail = your service account's full address, aud = cloudsmith

accounts.google.com is a planet-wide issuer used by every Google account, so the issuer alone proves nothing. The isolation comes from the email claim. Only something that can act as that exact service account can mint a token carrying its address, and that is gated by IAM. The aud value just binds the token to Cloudsmith so it can't be replayed elsewhere.

Exchange it for a Cloudsmith token

Swap the Google token for Cloudsmith credentials:

export SERVICE_SLUG="your-service-account-slug"
export ORG_SLUG="your-cloudsmith-org"

export CLOUDSMITH_JWT=$(curl -s -X POST \
  "https://api.cloudsmith.io/openid/${ORG_SLUG}/" \
  -H "Content-Type: application/json" \
  -d "{\"oidc_token\": \"${OIDC_TOKEN}\", \"service_slug\": \"${SERVICE_SLUG}\"}" \
  | jq -r '.token')

Replace your-service-account-slug with your Cloudsmith service account slug, and your-cloudsmith-org with your Cloudsmith organization identifier.

Verify it works

Test your credentials:

curl -s -H "Authorization: Bearer ${CLOUDSMITH_JWT}" \
  "https://api.cloudsmith.io/v1/user/self/" | jq

If everything's configured correctly, you'll see something like:

{
  "authenticated": true,
  "name": "gcp-pipeline",
  "slug": "gcp-pipeline",
  "slug_perm": "Ne67GhNtJOe7",
  "self_url": "https://api.cloudsmith.io/v1/user/self/"
}

The returned token is a normal Cloudsmith API key, valid for 2 hours. Pass it on any Cloudsmith API request, as the verify call above shows.

Using it on a real workload

This works anywhere you have a Google Cloud service account identity. Both tokens are short-lived, so there's nothing long-lived to store, and you're reusing an identity you already manage.

  • Compute Engine instances use their attached service account to request a token from the metadata server, then exchange it for Cloudsmith access whenever they need it.
  • Cloud Run and GKE work the same way through their workload identities, fetching a fresh token for each job or when the current one nears expiry.
  • Cloud Functions and App Engine can request a token on demand within the handler.
  • Cloud Build pipelines with a service account attached can do the token exchange to gain Cloudsmith access.

Wrapping up

You're reusing an identity you already manage, and the token it gets back expires in two hours. Nothing long-lived sits in an environment variable, and there's no rotation schedule for anyone to own.

If you want to try it, spin up a free Cloudsmith trial and point an existing Google Cloud workload at it. For the details, see Google's guide to getting an ID token, Workload Identity Federation on GKE, and Cloudsmith's OIDC documentation.