Introduction

A common practice in Google Cloud is to create one or more service accounts to authorize the Google Cloud CLI. Using service accounts is recommended by Google instead of user accounts. However, a service account JSON or P12 file contains sensitive information, the private key, used to authorize requests in Google Cloud.

How do you manage and control access to this sensitive information? A common method is to create a service account and email it to the users. Email may or may not be a secure method of delivering a service account to users. If the service account file is leaked, you must revoke the service account. If multiple users or services depend on this service account, you might have a problem reconfiguring and recovering quickly.

In this article, we will discuss and use service account impersonation. This means that users do not need access to the service account key material. The contents of the service account remain in Google Cloud. Instead of providing users with a service account file, we provide the user authorization to use the service account (impersonation). This reduces the permissions required for that user account. Provided the user is not accessing the Google Cloud Console, the user account only requires permission to access the service account and no other Google Cloud services. The user’s authorization will be controlled by the permissions assigned to the service account. If a user no longer requires access to the service account, all that is required is to remove his identity from the service account resource in Google Cloud IAM. The service account itself is not impacted and remains protected.

I wrote a companion article on how to impersonate a service account in PowerShell:

Benefits

  • User accounts have limited permissions. The only permission requires is the ability to create OAuth Access Tokens.
  • Improved resource security. The user account is granted permission to a service account instead of all service accounts.
  • Improved access management. To stop access to a service account, remove the IAM member from the service account resource.
  • Improved access security. User credentials are not used to grant Google Cloud service authorization.

Drawbacks

  • Complexity. Permissions are granted to a service account and not directly to the user account. This requires two-step authorization.
  • Misunderstanding. Service account impersonation is not well understood in the Google Cloud community. Education may be required.

Summary

The improved security offered by impersonation outweighs the increased complexity of user and service account management. Far too often service accounts are created without strong management in place, which increases security risks. By reducing the permissions granted to a user account, security is improved. By impersonating service accounts, user credentials are not used to grant Google Cloud service authorization.

Service Accounts

A Google Cloud Service Account is an identity (who) that access (permission/role) to resources. The identity of a service account is the same format as an email address.

As an example, the Compute Engine default service account has this format:

PROJECTNUMBER-compute@developer.gserviceaccount.com

A service account is also a resource. As a resource, you can grant IAM permissions to other identities to access the service account. For example, you can grant the role of Service Account Admin to a user to manage service accounts. In this article, we will treat the service account as a resource and assign permissions to users to impersonate the service account by granting the ability to create OAuth Access Tokens.

IAM Permissions

The IAM permission required is: iam.serviceAccounts.getAccessToken.

The permission required to create Identity Tokens is: iam.serviceAccounts.getOpenIdToken.

Identity Tokens are used for authentication with cloud services protected by Identity Aware Proxy (IAP) and for service to service authentication, for example Cloud Scheduler calling Cloud Functions.

These permissions are in the role: Service Account Token Creator.

Service Account Token Creator

roles/iam.serviceAccountTokenCreator

This role grants an identity the permission to impersonate a service account (create OAuth2 access tokens, sign blobs or JWTs, etc).

This role has the following permissions:

  • iam.serviceAccounts.get
  • iam.serviceAccounts.getAccessToken
  • iam.serviceAccounts.getOpenIdToken
  • iam.serviceAccounts.implicitDelegation
  • iam.serviceAccounts.list
  • iam.serviceAccounts.signBlob
  • iam.serviceAccounts.signJwt
  • resourcemanager.projects.get
  • resourcemanager.projects.list

Setup

In this phase we will use the CLI with an identity that has the role Project Editor. This role or similar is required so that we have the permissions to manage Google Cloud IAM.

Get the current IAM account

This will list the current account and active configuration.

gcloud config get-value account

If the account returned is not the correct account, authenticate with:

gcloud auth login

Get the current project

gcloud config get-value core/project

If the project returned is not the correct project, change the project with:

gcloud config set core/project [PROJECT-ID]

Verify account permissions

Display the permissions that your account has. Replace ACCOUNT with your account email address.

gcloud projects get-iam-policy [PROJECT-ID] \
--flatten="bindings[].members" \
--format='table(bindings.role)' \
--filter="bindings.members:[ACCOUNT]"

Verify that the returned roles have Project Owner, Project Editor or required permissions to create and manage IAM members, roles and service accounts.

Enable APIs

This step is very important. For new accounts, you probably do not have the correct APIs enabled. Impersonation requires two APIs:

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

To list the enabled APIs:

gcloud services list --enabled

To enable the required APIs:

gcloud services enable iamcredentials.googleapis.com
gcloud services enable cloudresourcemanager.googleapis.com

Wait a few minutes for the APIs to be enabled.

Add user account to IAM

Add the user account to IAM granting permission to inspect service states and operations, and consume quota and billing for a consumer project.

Replace [ACCOUNT] with the email address used for the user account that looks like username@gmail.com.

gcloud projects add-iam-policy-binding [PROECT_ID] \
--member "[ACCOUNT]" \
--role "roles/serviceusage.serviceUsageConsumer"

Create a service account

Create a new service account for testing. You will need the Project ID (see above), a service account name, and the email address of the user account (G Suite or Google Accounts) to authorize.

The service account name is a simple string, in this example test100.

gcloud iam service-accounts create test100

This command creates a new service account. The new service account email address will be like:

test100@[PROEJECT_ID].iam.gserviceaccount.com

Grant permissions to the service account

This step grants permissions to the service account to access Google Cloud resources. In this example, grant the Project Viewer role.

Replace [SA_FULL_EMAIL] with the service account email address that looks like test100@[PROEJECT_ID].iam.gserviceaccount.com.

Replace [ACCOUNT] with the email address used for the user account that looks like username@gmail.com.

gcloud projects add-iam-policy-binding [PROECT_ID] \
--member "[SA_FULL_EMAIL]" \
--role "roles/viewer"

 

Grant permissions to the user on the service account

This step grants permission on the service account to the user. This step grants permission to the resource and not to the project.

Replace [SA_FULL_EMAIL] with the service account email address that looks like test100@[PROEJECT_ID].iam.gserviceaccount.com.

Replace [ACCOUNT] with the email address used for the user account that looks like username@gmail.com.

gcloud iam service-accounts add-iam-policy-binding [SA_FULL_EMAIL] \
--member user:[ACCOUNT] \
--role roles/iam.serviceAccountTokenCreator

Using impersonation

The CLI supports the command-line option –impersonate-service-account.

gcloud projects list --impersonate-service-account=[SA_FULL_EMAIL]

Configure the CLI for impersonation

Specifying the service account on the command line will get old quickly.

This step will configure the CLI to use impersonation by default.

gcloud config set auth/impersonate_service_account [SA_FULL_EMAIL]

To reset (clear) using impersonation by default:

gcloud config unset auth/impersonate_service_account

GSUTIL

The CLI gsutil also supports impersonation. If service account impersonation is setup by default, gsutil uses that configuration. Gsutil also supports the command-line option -i service-acount to specify the service account to impersonate.

gsutil -i [SA_FULL_EMAIL] ls

OAuth Access Token

The CLI supports generating Access Tokens from the impersonated service account.

gcloud auth print-access-token --impersonate-service-account [SA_FULL_EMAIL]

OIDC Identity Tokens

The CLI supports generating Identity Tokens from the impersonated service account.

gcloud auth print-identity-token --impersonate-service-account [SA_FULL_EMAIL] --include-email

 

Summary

Notice that we did not download the service account JSON key file. The only IAM permission we granted the user is to consume APIs to impersonate. We granted the user account the necessary permissions to impersonate the service account. The user account has no other permissions in Google Cloud for this project.

The improved security that service account impersonation provides is worth the effort. Once you understand the process, everything is easy as most of the steps only need to be completed once.

More Information

Photography Credits

I write free articles about technology. Recently, I learned about Pexels.com which provides free images. The image in this article is courtesy of Flickr at Pexels.