-
Notifications
You must be signed in to change notification settings - Fork 405
Impersonated credentials should implement IdTokenProvider interface #1318
Description
Currently there is no easy way to acquire an id_token for a service account that was impersonated.
For example, if you run an application as SA1 but you would like to get an id_token for SA2, you would have to first use Impersonated module to get a raw access_token for SA2 and then use that in iamcredentials.generateIdToken() api call manually.
in another example, if you run running workload identity federation (WIF) in AWS and need an id_token to access Cloud Run, you would need to acquire the access_token for the service account for WIF on aws and then use that same generateIDToken() api call.
This FR is to allow the Impersonated module to acquire its own id_token
the workaround i tried was to edit the following
- node_modules/google-auth-library/build/src/auth/impersonated.d.ts
export declare class Impersonated extends OAuth2Client implements IdTokenProvider {}
/**
* Fetches an ID token.
* @param targetAudience the audience for the fetched ID token.
*/
fetchIdToken(targetAudience: string): Promise<string>; - node_modules/google-auth-library/build/src/auth/impersonated.js
async fetchIdToken(targetAudience) {
try {
await this.sourceClient.getAccessToken();
const name = 'projects/-/serviceAccounts/' + this.targetPrincipal;
const u = `${this.endpoint}/v1/${name}:generateIdToken`;
const body = {
delegates: this.delegates,
audience: targetAudience,
includeEmail: true,
};
const res = await this.sourceClient.request({
url: u,
data: body,
method: 'POST',
});
const tokenResponse = res.data;
return tokenResponse.token
}
catch (error) {
...
}
} then the usage would be
const scopes = 'https://www.googleapis.com/auth/cloud-platform'
const auth = new GoogleAuth({
scopes: scopes
});
const client = await auth.getClient();
// First impersonate
let targetCredentials = 'target-serviceaccount@fabled-ray-104117.iam.gserviceaccount.com'
let targetClient = new Impersonated({
sourceClient: client,
targetPrincipal: targetCredentials,
lifetime: 30,
delegates: [],
targetScopes: [scopes]
});
// then get an ID Token
let idClient = new IdTokenClient({
targetAudience: 'https://foo.bar',
idTokenProvider: targetClient
})
const res = await idClient.request({
method: 'GET',
url: 'https://httpbin.org/get',
});
console.log(res.data);Finally, please note the following:
ref:
- https://github.com/googleapis/google-cloud-node-core/issues/532
- Allow setting authentication client for google-cloud libraries #1210
(The last issue describes the limits of using the impersonated module with google cloud client libraries)