Extend GCP ServiceAccount access_token upto 12 hours

2022-03-17

The constraints/iam.allowServiceAccountCredentialLifetimeExtension GCP Org Policy constraint is advertized as:

You can create an OAuth 2.0 access token that provides short-lived credentials for a service account. 

By default, the maximum lifetime of an access token is 1 hour (3,600 seconds). However, you can extend the maximum lifetime to 12 hours.

With this, you can run a token-broker which dishes out short-lived credentials that can be optionally downscoped (for Cloud Storage atleast).

These tokens can then be handed to a long running process that does not by itself have a refreshable token but is “given” one for a task that may run upto 12h.

Great..soo..how do i get one of these tokens?

Well, currently its only available by using the iamcredentials.generateAccessToken() API for an allow-listed serviceAccount and then within that api request by specifying the lifetime parameter.

This example here walk you through a simple scenario and demos the extended token lifetime


First setup a service account:

export GCLOUD_USER=`gcloud config get-value core/account`
export PROJECT_ID=`gcloud config get-value core/project`
export PROJECT_NUMBER=`gcloud projects describe $PROJECT_ID --format='value(projectNumber)'`
gcloud iam service-accounts create long-lived

gcloud iam service-accounts add-iam-policy-binding long-lived@$PROJECT_ID.iam.gserviceaccount.com  \
     --role roles/iam.serviceAccountTokenCreator \
     --member "user:$GCLOUD_USER"

then set the requisite Org policy:

Enable org policy for service accounts

Use the iam api to request a token of 3600s:

$ date -u
Thu Mar 17 11:04:06 AM EDT 2022

$ curl -s -H "Authorization: Bearer `gcloud auth print-access-token`"  \
    -X POST -H "Content-Type: application/json" \
     -d '{"scope": ["https://www.googleapis.com/auth/cloud-platform"], "lifetime": "3600s"}' \
      "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/long-lived@$PROJECT_ID.iam.gserviceaccount.com:generateAccessToken"  | jq -r '.expireTime'

2022-03-17T16:04:10Z

Now ask for much longer 43200s

$ curl -s -H "Authorization: Bearer `gcloud auth print-access-token`"  \
    -X POST -H "Content-Type: application/json" \
    -d '{"scope": ["https://www.googleapis.com/auth/cloud-platform"], "lifetime": "43200s"}'  \
    "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/long-lived@$PROJECT_ID.iam.gserviceaccount.com:generateAccessToken" \
       | jq -r '.expireTime'

2022-03-18T03:04:13Z

# if you extracted the actual accessToken from the request and used it against the oauth2 tokeinfo, you'll see the extended
# `expires_in` value
$ curl -s "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=$TOKEN"
{
  "issued_to": "103266848859123965085",
  "audience": "103266848859123965085",
  "scope": "https://www.googleapis.com/auth/cloud-platform",
  "expires_in": 43161,
  "access_type": "online"
}

done…now you have a long lived access_token

The iam.serviceAccountTokenCreator role includes concentric set of permission (see Concentric IAMCredentials Permissions: The secret life of signBlob. If you just need to generate an access_token or an id_token, consider generating a custom role with that specific capability.

Revoking Long-Lived Tokens

You can’t really revoke the long lived token but what you can do is go scorched-earth and disable the service account outright.

gcloud iam service-accounts disable long-lived@$PROJECT_ID.iam.gserviceaccount.com

# which will immediately invalidate the token too
$ curl -s "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=$TOKEN"
{
  "error": "invalid_token",
  "error_description": "Invalid Value"
}

note, this was also a requested feature in GCP Vault Secrets: Support 12h lifetime Access_Token but as of now, the vaultprovider

This site supports webmentions. Send me a mention via this form.