Google workload identity federation to call directory API

165 Views Asked by At

I'm trying to set up Google Identity Federation with AWS to make admin.directory API calls from aws lambda function. It is written in Java.

{"code": 403,
 "errors": [{"domain": "global",
             "message": "Not Authorized to access this resource/api",
             "reason": "forbidden"}],
 "message": "Not Authorized to access this resource/api"}

I'm sure to have set the right scopes when calling the API. Because service account with keyfile works perfectly with the same code.

My questions are

  1. I'm suspicious that I have not properly configured service account permissions? ("https://www.googleapis.com/auth/admin.directory.user.readonly") how do you enable this scope for the service account? I can't seem to find the proper role, and I've set the role to be just 'owner' for testing, but it is still not working.

  2. The directory API requires super admin impersonation, but AwsCredential class or IdentityPoolCredential does not have createDelegated method. How am I going to query APIs that require super admin impersonation?

1

There are 1 best solutions below

0
Sanghyun Kim On

For those who stumbled upon this question, I finally got the answer.

Long story short, refer to this link (https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys#domain-wide-delegation), as this is the general guide to how I solved the problem.

First of all, I get the impression that the google federation is not meant for calling workspace APIs. If you look into the library codes for building credentials, there is no delegation method found for credentials like 'AWS' or other federated credentials; and because many functionalities in workspace require super admin impersonation, this is really not an easy job to do. Here are the steps to acquire the access token valid for calling workspace API with proper delegation.

  1. Configure your workload and external IDPs as guided.
  2. Create a credential based on the client library config json file.
  3. Call signJWT API with the access token from the credential. Here, make sure that sub and iss both exist, with sub being super admin user (or whomever you wish to impersonate), and iss being service account.
  4. After acquiring the signed JWT, call token API("https://oauth2.googleapis.com/token") for new token. The grant type has to be "urn:ietf:params:oauth:grant-type:jwt-bearer".
  5. Using the token, build the service of your choice. If you are using Java, make sure you replace the HttpRequestInitializer with your custom initializer, as the access token you are about to use cannot be auto-refreshed.
  6. Done!

There are some caveats.

  • Make sure that your service account HAS the proper role, namely, the Service Account Token generator. You can set this from IAM. I realized that giving a role to a principal and service account are two different things. Fix me if I'm wrong.
  • When you get errors from signing JWT, make sure to include iat key in the JWT. exp is not necessary, and is set automatically when not included. But iat is necessary.

Hope this helps!