From 53c8b5cdda7964077c6b6293148937d59e86deeb Mon Sep 17 00:00:00 2001 From: Jorge Gomez Date: Sat, 23 May 2026 23:26:01 -0700 Subject: [PATCH] feat(google): accept pre-minted access tokens for service-account impersonation / OIDC --- helpers/google/index.js | 15 ++++++++++++++- index.js | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/helpers/google/index.js b/helpers/google/index.js index f8e2837e8d..c1578c3f76 100644 --- a/helpers/google/index.js +++ b/helpers/google/index.js @@ -2,7 +2,7 @@ var shared = require(__dirname + '/../shared.js'); var functions = require('./functions.js'); var regRegions = require('./regions.js'); -const {JWT} = require('google-auth-library'); +const {JWT, OAuth2Client} = require('google-auth-library'); var async = require('async'); @@ -11,6 +11,19 @@ var regions = function() { }; var authenticate = async function(GoogleConfig) { + // Pre-minted access-token shortcut. Allows callers that already hold a + // valid Google Cloud access token (for example service-account + // impersonation, workload-identity federation, or OIDC flows where no + // service-account JSON key is available) to bypass the JWT exchange + // and inject the token directly. The returned OAuth2Client exposes + // the same .request() surface that plugins consume, so no plugin + // changes are required. + if (GoogleConfig.access_token) { + const client = new OAuth2Client(); + client.setCredentials({ access_token: GoogleConfig.access_token }); + return client; + } + const client = new JWT({ email: GoogleConfig.client_email, key: GoogleConfig.private_key, diff --git a/index.js b/index.js index 3835435550..64c2fe02e3 100644 --- a/index.js +++ b/index.js @@ -172,6 +172,21 @@ if (config.credentials.aws.credential_file && (!settings.cloud || (settings.clou settings.cloud = 'google'; cloudConfig = loadHelperFile(config.credentials.google.credential_file); cloudConfig.project = cloudConfig.project_id; +} else if (config.credentials.google.access_token && (!settings.cloud || (settings.cloud == 'google'))) { + // Pre-minted access-token path. Pairs with the shortcut in + // helpers/google/index.js authenticate() — callers that already hold + // a valid Google Cloud access token (for example service-account + // impersonation, workload-identity federation, or OIDC flows where + // no service-account JSON key is available) supply access_token + // directly instead of client_email / private_key. Project is still + // required so plugins can address the correct GCP project. + settings.cloud = 'google'; + checkRequiredKeys(config.credentials.google, ['project']); + cloudConfig = { + type: 'service_account', + project: config.credentials.google.project, + access_token: config.credentials.google.access_token, + }; } else if (config.credentials.google.project && (!settings.cloud || (settings.cloud == 'google'))) { settings.cloud = 'google'; checkRequiredKeys(config.credentials.google, ['client_email', 'private_key']);