Fetch signedJwt token for google service account

Viewed 504

I am trying to generate signedJWT token for google service account

now = int(time.time())
expires = now + 900  # 15 mins in seconds, can't be longer.
payload = {
     'iat': now,
     'exp': expires,
     'sub': 'somekey@someproject.iam.gserviceaccount.com',
     'aud': 'aud'
}
body = {'payload': json.dumps(payload)}
name = 'projects/someproject/serviceAccounts/somekey@someproject.iam.gserviceaccount.com'

iam = googleapiclient.discovery.build('iam', 'v1', credentials=credentials)
request = iam.projects().serviceAccounts().signJwt(name=name, body=body)
resp = request.execute()
jwt = resp['signedJwt']

The problem I am facing is regarding credentials If I use

credentials = service_account.Credentials.from_service_account_info(gcp_json_credentials_dict)

works fine.

But I am trying to use default service account

credentials, your_project_id = google.auth.default(scopes=["https://www.googleapis.com/auth/cloud-platform"])

Getting following error -

googleapiclient.errors.HttpError: <HttpError 403 when requesting https://iam.googleapis.com/v1/projects/someproject/serviceAccounts/somekey@someproject.iam.gserviceaccount.com:signJwt?alt=json returned "Permission iam.serviceAccounts.signJwt is required to perform this operation on service account
1 Answers

First, I will try to explain why you are getting the error:

permission iam.serviceAccounts.signJwt is required to perform this operation on service account.

A) Your code is running on a compute service using the default service account. I will call this Identity-1.

B) Your code is impersonating the identity somekey@someproject.iam.gserviceaccount.com. I will call this Identity-2.

Your code needs permissions to use the credentials of Identity-1 and the rights to impersonate Identity-2.

Part 1:

When you use the default service account for a compute service or assign a service account to a compute service, two forms of permission control are in effect. The master control is the IAM roles assigned to the service account. The limiter is the ** OAuth scopes** set for the compute service.

The OAuth scopes do not grant permissions, the OAuth scopes limit permissions already granted to the service account via IAM roles. This is an important point that I see so many configure incorrectly. I recommend using the compute engine Access scopes set to Allow full access to all Cloud APIs. Then modify/manage the IAM roles assigned to the service account assigned to Compute Engine.

Part 2:

In order to impersonate another identity, in your case Identity-1 is impersonating Identity-2, your code must have the right to do so. There are two types of identities that can be impersonated: a) service accounts; b) user identities. In your case, you are impersonating another service account.

If you are impersonating a service account, that requires granting the correct IAM permission via an IAM role on Identity-2 with the member set to Identity-1. Think of it this way: Identity-2 must grant permission to Identity-1.

If you are impersonating a user identity, that requires setting up Google Workspace Domain-Wide Delegation of Authority. The account that you are impersonating must be managed by Google Workspace. Refer to Google Workspace Domain-Wide Delegation of Authority is set up user account impersonation which is not required in your case.

Now you might wonder, which identity needs the right to impersonate? The identity that the JWT represents. That identity is declared by the JWT claim iss. Your JWT does not include an iss claim. For more details an example see this link. The identity that you are impersonating is specified by the claim sub. In OAuth speak iss is impersonating sub.

Part 3:

You must also configure your Google Cloud Project to support your objective. This requires enabling two APIs:

  • iamcredentials.googleapis.com
  • cloudresourcemanager.googleapis.com

Solution:

  1. Enable the required APIs:

gcloud services enable iamcredentials.googleapis.com

gcloud services enable cloudresourcemanager.googleapis.com

  1. Set the Compute Engine Access Scopes to Allow full access to all Cloud APIs. This requires shutting down the VM and editing the VM configuration.

  2. Add the iss claim to the JWT that you are creating with the value Identity-1.

  3. Grant an IAM Role containing the permission iam.serviceAccounts.signJwt. A good role to use is Service Account Token Creator to Identity-2. See this link for more details.

Example command:

gcloud iam service-accounts add-iam-policy-binding [Identity-2] \
--member serviceAccount:[Identity-1\ \
--role roles/iam.serviceAccountTokenCreator
Related