Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impersonated credentials should implement IdTokenProvider interface #1318

Closed
salrashid123 opened this issue Nov 16, 2021 · 5 comments · Fixed by #1439
Closed

Impersonated credentials should implement IdTokenProvider interface #1318

salrashid123 opened this issue Nov 16, 2021 · 5 comments · Fixed by #1439
Assignees
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.

Comments

@salrashid123
Copy link
Contributor

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 = '[email protected]'
    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:

@SurferJeffAtGoogle SurferJeffAtGoogle added priority: p2 Moderately-important priority. Fix may not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. labels Nov 16, 2021
@bcoe
Copy link
Contributor

bcoe commented Nov 17, 2021

@salrashid123 do you have a testing project where you're experimenting with this functionality, I'd be happy to help add this functionality, but it would be nice to have a real world environment to test against.

@salrashid123
Copy link
Contributor Author

certaiinly. i've added your corp user cred access to impersonate the service account below so you could directly impersonate an SA and get its id_token like the gcloud command below

export ID_TOKEN=`gcloud auth print-identity-token --audiences="https://myapp-jyosxg6puq-uc.a.run.app" --impersonate-service-account=target-serviceaccount@fabled-ray-104117.iam.gserviceaccount.com  --format="value(id_token)"`

curl -v -H "Authorization: Bearer $ID_TOKEN" https://myapp-jyosxg6puq-uc.a.run.app/

the curl command uses that id token to access a Cloud Run instance which will only allow that svc account's idtoken through.

If you would rather,i can grant project access or create a test user within the cloud org i own. LMK

@bcoe
Copy link
Contributor

bcoe commented Nov 19, 2021

@bcoe I'll make an effort to prod at this next week during the slow week, feel free to message me if you feel like wokring on this patch together.

@m0ar
Copy link

m0ar commented Jun 23, 2022

@bcoe This is a blocker for us, is there an update?

@danielbankhead
Copy link
Contributor

Hey @m0ar, @salrashid123, & @FrodoTheTrue: found some time to work on this today. Here's the PR:

It should be merged shortly after review 👌🏽

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p2 Moderately-important priority. Fix may not be included in next release. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants