Service Account Impersonation in Google Cloud
“A service account is a special kind of account typically used by an application or compute workload, such as a Compute Engine instance, rather than a person. A service account is identified by its email address, which is unique to the account.”
Even though there are numerous ways to use service accounts, the most common usage of a service account is to create a service account key and use it to obtain OAuth 2.0 access tokens. However generating and distributing service account keys makes you more vulnerable to attacks and threats.
In this post, I am going to explain how to use short lived keys and service account impersonation to avoid service account key generation for both CLI and Terraform usage.
What is Service Account Impersonation?
As written in Google’s official documentation, “When a principal, such as a user or another service account, uses short-lived credentials to authenticate as a service account, it’s called impersonating the service account.”
To use impersonation, we first need to complete the following steps:
- Create a Service Account: To better explain the importance of the service account, I am going to create a service account and assign a Compute Admin role to it. As you may know Compute Admin is a very powerful role which you can not risk losing the account key. You can see the permissions of Compute Admin role from here
2. Service Account Token Creator: Second important thing is to assigning Service Account Token Creator role to a user on the service account you are going to impersonate. This will allow your user to create an access token on behalf of the service account.
In our case;
Service account: dogus-sa@simplevpc.iam.gserviceaccount.com
User: dummy@adsver.info
As you can see below, Service Account Token Creator role granted to dummy@adsver.info on dogus-sa@simplevpc.iam.gserviceaccount.com
Those two are pretty much what we need to do to use impersonation. Now; by using our dummy user, we can impersonate a service account which has a Compute Admin permissions.
How to impersonate service accounts via gcloud CLI?
If you are going to use service account impersonation for all of you gcloud commands (during the terminal session) it is a better choice to set it globally as follows
gcloud config set auth/impersonate_service_account <your-service-account>
After setting this property, all gcloud commands you’ll run are going to be impersonating your service account as you can see below
But if you are going to use impersonation only in one command, just add — impersonate-service-account=your-service-account to your command as seen below
gcloud --impersonate-service-account=dogus-sa@simplevpc.iam.gserviceaccount.com
\ compute instances create dummy-instance-1
\ --project=simplevpc --zone=us-central1-a
\ --machine-type=f1-micro --network-interface=network-tier=PREMIUM,stack-type=IPV4_ONLY,subnet=dummy-subnet
How to impersonate service account in Terraform?
To run a Terraform code on GCP, you must have a service account to make the necessary API calls required by your code. General approach is to generate a JSON formatted key file and attach it to your code which makes your code vulnerable as I mentioned above.
Instead of using JSON key file, just adding following lines in your terraform code (preferably in providers.tf file) you can easily use impersonation in your code.
terraform {
required_providers {
google = {
source = "hashicorp/google"
}
}
}
locals {
terraform_service_account = "dogus-sa@simplevpc.iam.gserviceaccount.com"
}
data "google_service_account_access_token" "default" {
provider = google.impersonation
target_service_account = local.terraform_service_account
scopes = ["userinfo-email", "cloud-platform"]
lifetime = "300s"
}
provider "google" {
project = "500015880151"
access_token = data.google_service_account_access_token.default.access_token
}
provider "google" {
alias = "impersonation"
scopes = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/userinfo.email",
]
}
Now with our main.tf file we can create a new compute instance named dummy-instance-tf
resource "google_compute_instance" "dummy-instance-tf" {
boot_disk {
auto_delete = true
device_name = "dummy-instance-tf"
initialize_params {
image = "projects/debian-cloud/global/images/debian-11-bullseye-v20230411"
size = 10
type = "pd-balanced"
}
mode = "READ_WRITE"
}
machine_type = "f1-micro"
name = "dummy-instance-tf"
network_interface {
access_config {
network_tier = "PREMIUM"
}
subnetwork = "projects/simplevpc/regions/us-central1/subnetworks/dummy-subnet"
}
zone = "us-central1-a"
}
References
Author: Doğuş Bebek Devops & Platform Engineering Manager, Oredata
Oredata is a premier Google Cloud Partner specialized in
- Cloud Migration Services
- Data & Analytics Services
- Infrastructure Services
- Google Workspace
If you are interested joining us, feel free to apply our job openings: https://www.linkedin.com/company/oredata/jobs/