docs(auth): document certificate-bound tokens for agent identities [blocked on #13873] - #14557
macastelaz wants to merge 36 commits into
Conversation
1. POST request to MDS with cert-chain 2. Cert-key matching 3. Included logic to consider the user's choice by looking at GOOGLE_API_USE_CLIENT_CERTIFICATE env variable 4. Bound ID tokens. # Conflicts: # google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java # google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/MockMetadataServerTransport.java
…etry logic. Nit fixes. # Conflicts: # google-auth-library-java/oauth2_http/javatests/com/google/auth/oauth2/ComputeEngineCredentialsTest.java
# Conflicts: # google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java
…fill CI formatting rules
…n binding - Prevent 30-second polling delay and IOException on standard GCE/container environments when well-known credentials directory exists without certificate files unless mTLS is explicitly enabled. - Fail fast on malformed certificate config JSON without retrying. - Fix URI resource path decoding in AgentIdentityUtilsTest to prevent FileNotFoundException when workspace paths contain spaces. - Copy matching private key in well-known fallback test to verify full key pair loading. - Clean up static wellKnownDir state and temporary directories in ComputeEngineCredentialsTest. - Correct opt-out environment variable value in test setup from 'true' to 'false'.
…n binding - Replace placeholder Javadoc comments across AgentIdentityUtils and CertInfo with descriptive documentation. - Inline polling interval calculations via getSleepIntervalMs(), removing the static POLLING_INTERVALS list. - Support GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN as primary environment variable with fallback to GOOGLE_API_PREVENT_AGENT_TOKEN_SHARING_FOR_GCP_SERVICES. - Add early check for GOOGLE_API_USE_CLIENT_CERTIFICATE=false in getAgentIdentityCertInfo() to exit without polling. - Parse certificate and private key blocks separately using regex to strip private keys from HTTP payloads and enable cryptographic key-pair verification on combined bundle files. - Throw IOException on AccessDeniedException for explicit configs and gracefully return null for implicit well-known discovery. - Exit early without polling for non-workload configs (hasWorkloadConfig) and configs outside the well-known directory. - Add non-production SPIFFE trust domain patterns (agents-nonprod) matching Python. - Maintain IOException exception type on credential verification failures to preserve Credentials#refreshAccessToken interface contract. - Validate full certificate content in ComputeEngineCredentialsTest. - Use JUnit 5 @tempdir in AgentIdentityUtilsTest.
…d key validation - Check isPathInWellKnownDir(paths.getCertPath()) after parsing workload config so startup polling is enabled even when GOOGLE_API_CERTIFICATE_CONFIG resides outside the well-known directory. - Avoid throwing early on malformed config JSON when polling is active to handle non-atomic container startup writes. - Record startup polling timeout (startupPollTimedOut) so subsequent token refreshes fail fast or fall back immediately without repeating 30-second sleep loops. - Require a valid matching private key whenever loading Agent Identity credentials for token binding, removing the cert-only fallback branch. - Check shouldRequestBoundToken(cert) immediately after parsing certificate content before reading private keys or executing signature verification. - Cache verified CertInfo (and negative non-agent SPIFFE results) across token refreshes based on file metadata (mtime, size, fileKey), invalidating on file rotation. - Make static fields (wellKnownDir, envReader, timeService) volatile and restrict EnvReader and setEnvReader visibility to package-private. - Use JUnit 5 @tempdir parameter in AgentIdentityUtilsTest and add unit tests covering all new behaviors.
…tityUtils and ComputeEngineCredentials
…comments - Remove unrequested lastVerifiedCertInfo, hasValidBoundTokenCache helper, stat-reuse ternaries, and ECDSA KeyFactory normalization. - Restore original keyPath fail-fast, initialStartupCompleted name, and exact-case algorithm checks (accepting EC and ECDSA per review). - Make the internal loadAndVerifyCredentials overload private.
- Scope cached-credential fallbacks to their source: the config fallback requires a config-derived cache (and logs a warning), the well-known fallback requires a well-known cache. - getLatestOrInitialCache only prefers the latest cache when it is a verified bound-token credential; reuse it in the loadAndVerifyCredentials fallback. - tryUpdateCache: a config-only change mid-read returns the verified pair without caching it instead of forcing retries. - checkExistsOrAccessDenied treats existing but unreadable files as AccessDeniedException. - Stop polling when a workload config is missing cert_path or key_path. - Normalize ECDSA-labelled EC public keys before initVerify. - Reject unsupported key algorithms in readPrivateKey without retrying. - Skip re-reading the config once mTLS is evaluated as explicitly disabled, and check the cached cert type before shouldEnableMtls in the fast path. - Nits: message/comment wording, test split and sleep-count assertion.
…oogleapis#13873) Adds a README section and ComputeEngineCredentials class Javadoc covering: - bound tokens are the default when an agent identity workload certificate is present, and require mTLS with the same certificate - when a bound token is requested (cert discovery, agent SPIFFE trust domain) - opt-out env vars and precedence: GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN over the legacy GOOGLE_API_PREVENT_AGENT_TOKEN_SHARING_FOR_GCP_SERVICES, and GOOGLE_API_USE_CLIENT_CERTIFICATE=false also disabling binding - the process-wide scope of the opt-out - the ADK for Java known limitation and its workaround
There was a problem hiding this comment.
Code Review
This pull request introduces support for certificate-bound access and ID tokens for agent identities within ComputeEngineCredentials. It adds a new AgentIdentityUtils utility class to manage certificate discovery, SPIFFE trust domain validation, cryptographic key-pair verification, and credential caching. ComputeEngineCredentials is updated to request bound tokens via POST requests to the metadata server when a workload certificate is available. Feedback on the changes suggests improving code readability in the test suite by avoiding fully qualified class names when the class is already imported.
| Files.write(keyPath, mismatchedKeyPem.getBytes(StandardCharsets.UTF_8)); | ||
| Files.setLastModifiedTime( |
There was a problem hiding this comment.
Avoid using fully qualified class names (such as java.nio.file.attribute.FileTime) if there is no class name conflict in the file and the class is already imported, as it unnecessarily reduces code readability.
Files.setLastModifiedTime(
keyPath, FileTime.fromMillis(System.currentTimeMillis() + 10000));References
- Do not use fully qualified class names if there is no class name conflict in the file and the class is already imported, as it unnecessarily reduces code readability.
Important
Draft, blocked on #13873. This branch is based on #13873's head (
f17f773a75c), because #13873 also editsComputeEngineCredentials.java. Until #13873 merges, this PR also shows #13873's commits. Only the last commit (docs(auth): document certificate-bound tokens for agent identities) belongs to this PR. After #13873 merges I'll rebase ontoagentic-identities-bound-tokenso the diff is docs-only.Note
Open question: the team is considering shipping bound access tokens only and deferring bound ID tokens. If that happens, this PR will be updated to say "access tokens" only.
What this adds
Docs only; no code changes.
google-auth-library-java/README.md: new section "Certificate-bound tokens for agent identities":GOOGLE_API_CERTIFICATE_CONFIGor the default directory, and an agent identity SPIFFE trust domain.GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN=false, which takes precedence over the legacyGOOGLE_API_PREVENT_AGENT_TOKEN_SHARING_FOR_GCP_SERVICES.GOOGLE_API_USE_CLIENT_CERTIFICATE=falsealso turns binding off. Values are case-insensitive, the opt-out applies to the whole process, and it's strongly discouraged.401; the workaround is the opt-out.ComputeEngineCredentialsclass Javadoc: the same behavior in brief, plus the fail-fast cases. If the certificate config points to missing files, or the metadata server doesn't support bound tokens, requests throwIOExceptioninstead of silently falling back to unbound tokens.All statements were checked against
AgentIdentityUtils(isTokenBindingEnabled,shouldEnableMtls,shouldRequestBoundToken) andComputeEngineCredentialsin #13873.The Cloud Run public docs are being updated separately (internal CL), and the README links to https://cloud.google.com/run/docs/ai/authenticate-agents.
Release notes
google-auth-library-java/CHANGELOG.mdis generated, so release notes come from commit messages. Suggested text for theBEGIN_COMMIT_OVERRIDEblock of the feature-branch →mainmerge PR:Testing
fmt-maven-plugin:checkpasses.javadoc:javadoconoauth2_httpcompletes with no new warnings.