Skip to content

feat(auth): support bound access and ID tokens for GKE - #18594

Merged
nbayati merged 3 commits into
mainfrom
cr-bound-id-token
Oct 7, 2026
Merged

nbayati merged 3 commits into
mainfrom
cr-bound-id-token

Conversation

@nbayati

@nbayati nbayati commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

The feature branch contains code that has already been reviewed and approved in two previous RPs. This PR merges the changes to main for a release.

Note: the branch name says cr-bound-id-token because we're reusing a feature branch that was initially for CR, but now the change is going out for GKE first.

b/545779266

nbayati and others added 3 commits September 26, 2026 23:40
…Cloud Run (#17698)

This PR adds the following: 
* Switch the MDS token acquisition from a GET to a POST request when the
agentic cert is detected.

* Add `get_agent_identity_certificate_and_bytes()` utility to read the
raw certificate bytes alongside the parsed cert.

* Update `_metadata.get_service_account_token()` (for access tokens) and
`IDTokenCredentials.refresh()` (for ID tokens) to send a POST request
with the `certificate_chain` payload instead of a GET request when bound
tokens are supported.

* Update `_metadata.get()` helper to support `method` and `body` params.

* Add and update unit tests to verify the new POST request flows.

----
design: go/sdk-mds-bound-token

id token verification:
- test script: paste/4514812804595712
- log results: paste/6316867684794368

Note:
1. This PR relies on the existing pattern of locating the certificates
using the path provided by the config file available at
GOOGLE_API_CERTIFICATE_CONFIG. It does not currently fallback on
checking the well known location if the env var is not set, which would
limit the scope to CR, as GKE and GCE don't set this env var.

2. It uses the same condition to decide if a bound token should be
requested for both access token and id token. We might decide to add a
separate env var to opt out.

3. it still uses the existing
`GOOGLE_API_PREVENT_AGENT_TOKEN_SHARING_FOR_GCP_SERVICES` flag to opt
out. We might update it and add a new env var, but will keep the old one
for backward compatibility.
This PR enables bound access tokens, bound ID tokens, and default mTLS
certificate discovery for Agent Identity workloads on GKE, and adds
per-request control for ID token binding:

* Fall back to the well-known GKE workload credential bundle
(`/var/run/secrets/workload-spiffe-credentials/x509.credential-bundle.private-key.pem`)
in `_agent_identity_utils.get_agent_identity_certificate_path()`,
`_mtls_helper._get_workload_cert_and_key()`,
`_mtls_helper.check_use_client_cert()`, and
`mtls.has_default_client_cert_source()` when no explicit or default
certificate config file is present.

* Add an optional `bind_id_token` parameter (`True`, `False`, or `None`)
to `compute_engine.IDTokenCredentials`, `fetch_id_token_credentials()`,
and `fetch_id_token()` (sync and async) so callers can explicitly opt in
or out of binding metadata server ID tokens per request.

* Scope default bound ID tokens to GKE by keeping ID tokens unbound when
`GOOGLE_API_CERTIFICATE_CONFIG` is set (unless `bind_id_token=True`),
while continuing to bind access tokens by default on both Cloud Run and
GKE.

* Add and update unit tests for GKE credential bundle fallback,
`bind_id_token` options, and the `GOOGLE_API_CERTIFICATE_CONFIG` default
gate.

----

Note:
1. GKE mounts a single combined PEM file
(`x509.credential-bundle.private-key.pem`) at
`/var/run/secrets/workload-spiffe-credentials/` without setting
`GOOGLE_API_CERTIFICATE_CONFIG`. With this fallback, GKE Agent Identity
workloads automatically use bound access tokens and bound ID tokens by
default when the file is present.

2. On Cloud Run (where `GOOGLE_API_CERTIFICATE_CONFIG` is set), default
ID token requests (`bind_id_token=None`) temporarily remain unbound so
existing callers do not receive bound ID tokens. Callers on Cloud Run
can pass `bind_id_token=True` to request bound ID tokens now, and a
follow-up PR will remove this temporary gate to enable bound ID tokens
by default on Cloud Run as well.

design: go/sdk-mds-bound-token
@nbayati
nbayati requested review from a team as code owners October 7, 2026 18:41
@nbayati nbayati changed the title Release bound access token and bound id token features for GKE feat(auth): support bound access and ID tokens for Cloud Run and GKE Oct 7, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for certificate-bound tokens using GKE workload credential bundles and Cloud Run mTLS endpoints, transitioning to the new GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN environment variable. It refactors certificate parsing to handle chains and combined bundles, and adds options to control ID token binding. The review feedback suggests minor code improvements, such as passing the already-cleaned cert_bytes instead of raw_bytes to parse_certificate to avoid redundant parsing, and explicitly importing _mtls_helper in sessions.py to avoid relying on implicit package attribute binding.


cert_bytes = b"\n".join(block.strip() for block in cert_blocks) + b"\n"
try:
return parse_certificate(raw_bytes), cert_bytes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Pass cert_bytes instead of raw_bytes to parse_certificate. Since cert_bytes has already been cleaned of non-certificate blocks (like private keys or bag attributes) and validated, parsing it directly is safer and avoids redundant regex parsing inside parse_certificate.

Suggested change
return parse_certificate(raw_bytes), cert_bytes
return parse_certificate(cert_bytes), cert_bytes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rejecting the suggestion. Keeping raw_bytes here is intentional: cert_bytes is built from regex matches of complete PEM blocks and strips out any trailing block missing an END marker, so passing raw_bytes is required for parse_certificate to detect truncated certificate chains.

import time
import urllib.parse
import warnings
from contextlib import asynccontextmanager

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Explicitly import _mtls_helper from google.auth.transport instead of relying on implicit package attribute binding via google.auth.transport._mtls_helper.

Suggested change
from contextlib import asynccontextmanager
from google.auth.transport import _mtls_helper
from contextlib import asynccontextmanager

@nbayati nbayati Oct 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

False positive: google.auth.transport._mtls_helper is already explicitly imported on line 27, so this does not rely on implicit package attribute binding.

Comment on lines +479 to +481
is_mtls_endpoint = (
google.auth.transport._mtls_helper.is_mtls_endpoint(url)
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use the explicitly imported _mtls_helper module.

Suggested change
is_mtls_endpoint = (
google.auth.transport._mtls_helper.is_mtls_endpoint(url)
)
is_mtls_endpoint = (
_mtls_helper.is_mtls_endpoint(url)
)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rejecting the suggestion: Keeping google.auth.transport._mtls_helper to match the existing import on line 27 and usage on line 304.

@nbayati nbayati changed the title feat(auth): support bound access and ID tokens for Cloud Run and GKE feat(auth): support bound access and ID tokens for GKE Oct 7, 2026
@nbayati
nbayati enabled auto-merge (squash) October 7, 2026 18:51
@nbayati
nbayati merged commit 9f5fd7b into main Oct 7, 2026
116 checks passed
@nbayati
nbayati deleted the cr-bound-id-token branch October 7, 2026 18:57
nbayati pushed a commit that referenced this pull request Oct 7, 2026
🤖 I have created a release *beep* *boop*
---


##
[2.61.0](google-auth-v2.60.0...google-auth-v2.61.0)
(2026-10-07)


### Features

* **auth:** support bound access and ID tokens for GKE
([#18594](#18594))
([9f5fd7b](9f5fd7b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants