Creating and Using Service Accounts and Custom Roles in GCP
Disclaimer: this is not comprehensive, more of a scratch pad for me to make notes on my process of:
- creating a custom role
- creating a service account
- assigning the new custom role to the new service account
The code snippets here are hardcoded versions of snippets from a script I wrote that creates or updates custom roles, and keeps the spec files updated with the new etags as the role is updated. It’s just faster here for me to leave all that logic out of this doc. If you want help writing your own script for this, drop me a line.
Also, you can create roles at the org level (if you have high enough permissions), but for this doc we’re just doing it at the project level.
Requirements:
- gcloud executable
- yq
- IAM admin permissions within your project
Create a custom role
Define a custom role in a yaml spec file:
$ cat mynewrole.yaml
title: EngDeploybotTest
etag:
description: "Service Account to run deployments"
stage: "ALPHA"
includedPermissions:
- container.clusters.get
- container.clusters.getCredentials
- container.configMaps.create
- deploymentmanager.deployments.get
Create the custom role in your project:
$ role_id=$(yq r mynewrole.yaml title)
$ gcloud iam roles create ${role_id} --project=my-fancy-project --file=mynewrole.yaml
Create a service account
$ gcloud --project=my-fancy-project iam service-accounts create \
my-svc-acct@my-fancy-project.iam.gserviceaccount.com \
--description="Service Account used for deploying things" \
--display-name="my-svc-acct"
Generate and store its keys
Create and store the key that you’ll need to activate this account. GCP recommends using JSON format intead of P12. In this example I’m just gonna save these locally; additionally, you may want to save this JSON file in a secrets store like Google Secrets Manager or LastPass, in case you need to give somebody else access to use this service account.
Anyway, here’s me generating the service account keys. Of note here is that I’m using the $HOME variable to point to my homedir, instead of my usual “~” shorthand. This is because later on in the service account activation command, the key-file attribute isn’t able to expand the tilde, but it does recognize the $HOME environment variable.
$gcloud --project=my-fancy-project iam service-accounts keys create \
$HOME/.config/gcloud/gcp-service-acct-keys/my-svc-acct.json \
--iam-account my-svc-acct@my-fancy-project.iam.gserviceaccount.com
Give the service account your new custom role
$ gcloud projects add-iam-policy-binding my-fancy-project \
--member=serviceAccount:my-svc-acct@my-fancy-project.iam.gserviceaccount.com --role=roles/EngDeploybotTest
Activate the service account
$ gcloud --project=my-fancy-project auth activate-service-account \
my-svc-acct@my-fancy-project.iam.gserviceaccount.com \
--key-file=$HOME/.config/gcloud/gcp-service-acct-keys/my-svc-acct.json
Activating this account for the very first time will automatically set it as the active account in your auth list. You can confirm this:
$ gcloud auth list
Credentialed Accounts
ACTIVE ACCOUNT
* my-svc-acct@my-fancy-project.iam.gserviceaccount.com
inger.klekacz@dayjob.com
ingernet@personal-account.com
another-svc-acct@my-other-project.iam.gserviceaccount.com
To set the active account, run:
$ gcloud config set account `ACCOUNT`
Run Something as your service account
Once you’ve activated the service account, everything you do, you’re doing as that account - so if you’re accustomed to running as Project Owner, just get ready for the occasional odd IAM error.
# don't have this permission as this service account, so it won't work
$ gcloud --project=my-fancy-project deployment-manager deployments list
ERROR: (gcloud.deployment-manager.deployments.list) ResponseError: code=403, message=Required 'deploymentmanager.deployments.list' permission for 'projects/my-fancy-project'
# but this one should
$ gcloud --project=my-fancy-project deployment-manager deployments describe my-fancy-deployment
---
fingerprint: YI7lnJL964cKTMGWIMfYEg==
id: '5625931904623267331'
insertTime: '2020-08-14T13:15:40.454-07:00'
labels:
- key: owner
value: deployingCoworkerName
- key: project
value: fanciness
- key: gcp_env
value: sandbox
manifest: manifest-1597436566734
name: my-fancy-cluster-deployment
operation:
endTime: '2020-08-14T13:25:51.102-07:00'
name: operation-1597436566660-5acdc2f1b6461-9c0dd1dc-83cd6fdf
operationType: update
progress: 100
startTime: '2020-08-14T13:22:46.767-07:00'
status: DONE
user: deploying-coworker@my-fancy-project.iam.gserviceaccount.com
NAME TYPE STATE INTENT
my-fancy-cluster container.v1.cluster COMPLETED
my-fancy-cluster-type deploymentmanager.v2beta.typeProvider COMPLETED