Google Cloud Service Accounts Security Best Practices

Service Accounts in Google Cloud Platform (GCP) are the main vector to hack an account: it’s easy to use them wrong and end up with a compromised key and a lot of headaches.

What is a Google Cloud Service Account?

Service Account (SA) is the identity in Google Cloud that you use to authenticate and authorize application and services.

They come in two flavours: user and google managed.

User Managed Service Accounts

A user managed service account is, surprise, intended to be manually managed. What does this mean?

If you have an application that needs to connect to a cloud service, say a CloudSQL instance, you want to create a Service Account with a proper Role for it.

A good analogy is to see your application as a user: the Service Account is its own dedicated account for Google Cloud, and to authenticate you will then need a “password” that comes in the form of Service Account Key.

Service Account Keys are a json data structure like the following:

{
  "type": "service_account",
  "project_id": "project-id",
  "private_key_id": "key-id",
  "private_key": "-----BEGIN PRIVATE KEY-----\nprivate-key\n-----END PRIVATE KEY-----\n",
  "client_email": "service-account-email",
  "client_id": "client-id",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/service-account-email"
}

You can generate as many as you like to be used by your applications to authenticate.

So what’s the problem?

As you have already guessed: if you leak the service account key, the service account can be considered compromised.

And this is so common because secrets distribution usually introduce friction.

There is a non-zero chance that someone in your company is (silently) cutting corners by embedding the json key in their applications and pushing to a public GitHub repository.

Cyber-scoundrels continuously scan public repositories to harvest credentials, it takes on average 10 minutes from committing a key to have someone login with it.

Google Managed Service Account

Google Managed Service Accounts, are SAs for which you don’t need to generate keys and your applications can just assume their identity.

For example Compute Engine comes with a default service account that is associated to all virtual machines (VM) you will provision. Services running on those VMs can use the default service account to authenticate to other cloud services.

No keys are involved: the VM will continuously request short lived authorization tokens from the metadata service. Sweet.

1. Do not use Service Account Keys

The first recommendation is to not use Service Account keys as much as possible.

Using keys implies that you are in charge of their lifecycle and security, and it’s a lot to ask because:

  • you need a robust system for secrets distribution
  • you need to implement a key rotation policy
  • you need to implement safeguards to prevent key leaks

Unless you have a hybrid setup and half your workloads are on prem, it’s just so much easier to use google managed service accounts.

2. Use Google Managed Service Accounts

In fact, the second recommendation is to use google managed service accounts.

Your applications running con Compute Engine can automatically assume the default service account identity.

But, there is a caveat: the default compute engine service account is automatically assigned the role Editor, which is read and write access to everything.

3. Do not use the Default Compute Engine Service Account

Yep. Don’t use the default compute engine service account.

Instead, create a new Service Account and use it as the default account used by a VM. Even better: create one account for each VM.

This will allow you to fine tune the authorization grants (and greatly please the gods of least privilege).

For extra points you can as well disable it with an Organizational Policy:

Service Consumer Management 

Disable Automatic IAM Grants for Default Service Accounts 

This boolean constraint, when enforced, prevents the  [default](https://cloud.google.com/iam/help/service-accounts/default)  App Engine and Compute Engine service accounts that are created in your projects from being automatically granted any IAM role on the project when the accounts are created. 
By default, these service accounts automatically receive the Editor role when they are created. 

constraints/iam.automaticIamGrantsForDefaultServiceAccounts

4. Do not bind Service Account User and Token Creator on the Project IAM

Service Account can be impersonated by other identities, and there are two roles that regulate this behaviour:

Service account impersonation is a risky behaviour because multiplies the blast radius of a compromised identity.

For this reason bind Service Account User or Token Creator directly on the Service Account IAM policy and never on the Project’s (or Folder’s or - god forbid - the Organization’s)

5. Reduce the Authorization Scopes with IAM Recommender

Continuously enforcing least privilege is auspicable for every kind of identity but for Service Accounts in particular: since they are intended to be used programmatically the risk of compromising one is higher than for a normal account.

Google provides an extremely valuable service: the IAM Recommender. It continuously scan role bindings and suggest changes to reduce the authorization scope.

Use it.

Conclusion

If there is one insight I would like you to get from this post is that Service Account Keys are dangerous and their use should be minimized.

If you are looking for more high level recommendations on Identity and Access Management (IAM) governance in GCP, please refer to my previous article on the topic.