3

I am creating new google service account and want to use newly created service account for authentication

def create_service_account(project_id, name, display_name):
"""Creates a service account."""

credentials = service_account.Credentials.from_service_account_file(
    filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'],
    scopes=['https://www.googleapis.com/auth/cloud-platform'])

service = googleapiclient.discovery.build(
    'iam', 'v1', credentials=credentials)

my_service_account = service.projects().serviceAccounts().create(
    name='projects/' + project_id,
    body={
        'accountId': name,
        'serviceAccount': {
            'displayName': display_name
        }
    }).execute()

print('Created service account: ' + my_service_account['email'])
return my_service_account

says my service account name is XXXX@com I am generating key for this service account using

def create_key(service_account_email):
    """Creates a key for a service account."""

    credentials = service_account.Credentials.from_service_account_file(
        filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'],
        scopes=['https://www.googleapis.com/auth/cloud-platform'])

    service = googleapiclient.discovery.build(
        'iam', 'v1', credentials=credentials)

    key = service.projects().serviceAccounts().keys().create(
        name='projects/-/serviceAccounts/' + service_account_email, body={}
        ).execute()

    print('Created key: ' + key['name'])

Above code is working fine.

I want to use newly created service account for other operations. How to authenticate new created service account ? Is there any other way of creating Credentials apart from this

credentials = service_account.Credentials.from_service_account_file(
    filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'],
    scopes=['https://www.googleapis.com/auth/cloud-platform'])

service = googleapiclient.discovery.build(
    'iam', 'v1', credentials=credentials)

1 Answer 1

3

I recommend you to use the default credential method, your code can be like this

import google.auth

credentials, project_id = google.auth.default()

You have the description here. The code

  1. Check first if the GOOGLE_APPLICATION_CREDENTIALS is defined.
  2. If not, check the gcloud application-default credential on your environment.
  3. If not, check if the code run on GCP environment (if the metadata servers exist)
  4. Error

Here, it's important to note the point 2 and 3.

  • On your local environment, you don't need a service account key file. You can use your own user credential with GCLOUD as default credentials
  • On GCP environment, you also don't need service account key file, because you can use the component identity (check your component documentation for specifying the service account email that yon want on it)

At the end, if your app in on not-GCP environment (on premise, on other cloud provider), you have to use the service account key files and define it in the environment variable. But you don't have to explicitly call it in your code. Here again, the default credential works!

NOTE

I strongly recommend you to avoid to generate service account security file. It's a nightmare for the security. It's simply a file that authenticate you. A file can be copied, sent by email and even committed on public git repo. In addition it's recommended to rotate these key files at least every 90 days (...). If you don't run your app outside GCP, avoid to use it, it will save you!

EDIT

If you have an error, it's because you use the answer of the create service account key file as key. It's a common mistake. You have to use only the field privateKeyData in the answer, and decoded it (it's in base 64).

Then you have a valid service account JSON key file.

If you want to use the key, you have to provide this key in the credential creation

# either you have save your json into a file
credentials = service_account.Credentials.from_service_account_file(
    filename=/path/to/file/key.json,
    scopes=['https://www.googleapis.com/auth/cloud-platform'])

# or if you have kept the json into memory and convert it into a dict
credentials = service_account.Credentials.from_service_account_info(dict_json_key,
    scopes=['https://www.googleapis.com/auth/cloud-platform'])
Sign up to request clarification or add additional context in comments.

4 Comments

My requirement is different. I want to create a new service account dynamically for short time and do some stuff. I have new generated key from rest call -{ "name": "projects/project-id/serviceAccounts/service-account-email/keys/key-id", "privateKeyType": "TYPE_GOOGLE_CREDENTIALS_FILE", "privateKeyData": "private-key", "validAfterTime": "date", "validBeforeTime": "date", "keyAlgorithm": "KEY_ALG_RSA_2048" }-----------------How do I use this file for my credentials. Getting ValueError: Service account info was not in the expected format, missing fields token_uri, ..
Later i am going to delete the keys file.
I updated my answer. Just because I'm curious, what is your use case that requires to create key file on the fly?
This! This was my issue. Thank you! >>> If you have an error, it's because you use the answer of the create service account key file as key. It's a common mistake. You have to use only the field privateKeyData in the answer, and decoded it (it's in base 64).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.