One of the best practices for storing service account keys is to rotate them on a regular basis. You can do that manually but it would be much better to have a kind of mechanism that doesn’t let you miss the date of key renewal.
I will use some gcloud console commands here but it is not necessary as you can do the same in Google Cloud Platform (GCP) interface. You must replace everything rounded by {} with your own values.
First let’s get a list of all keys associated with the service account:
gcloud iam service-accounts keys list --iam-account={service-account-id}@{gcp-project-id}.iam.gserviceaccount.com
The result will be something like this:
KEY_ID | CREATED_AT | EXPIRES_AT |
---|---|---|
{key_1} | 2020-11-27T21:26:17Z | 9999-12-31T23:59:59Z |
{key_2} | 2021-09-01T15:27:45Z | 9999-12-31T23:59:59Z |
9999-12-31T23:59:59Z means here that the expiration date for this key was not set.
Next you create your self-made key with -days parameter that specifies the number of days until the expiration date of the key:
openssl req -x509 -nodes -newkey rsa:2048 -days 365 -keyout private_key.pem -out public_key.pem
It will ask you a few questions and as a result you will get private_key.pem and public_key.pem files in your working directory. Upload public_key.pem to your Google Cloud project:
gcloud iam service-accounts keys upload public_key.pem --iam-account={service-account-id}@{gcs-project-id}.iam.gserviceaccount.com
And check the list of keys again:
gcloud iam service-accounts keys list --iam-account={service-account-id}@{gcp-project-id}.iam.gserviceaccount.com
This time you should see your new key with the expiration date listed in the results:
KEY_ID | CREATED_AT | EXPIRES_AT |
---|---|---|
{key_1} | 2020-11-27T21:26:17Z | 9999-12-31T23:59:59Z |
{key_2} | 2021-09-01T15:27:45Z | 9999-12-31T23:59:59Z |
{key_3} | 2021-11-18T10:27:12Z | 2022-11-18T10:27:12Z |
Now you successfully associated the key with the GCP service account. The last step is to actually use this key. When you create keys using gcloud CLI, user interface or client libraries you immediately get JSON file with following structure:
{
"type": "service_account",
"project_id": "{gcp-project-id}",
"private_key_id": "{key-id}",
"private_key": "{private-key}",
"client_email": "{service-account-id}@{gcp-project-id}.iam.gserviceaccount.com",
"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-id}@{gcp-project-id}.iam.gserviceaccount.com"
}
You can manually create this JSON file and fill in all the required data. {key-id} is {key_3} here. {client-id} is the id of your service account. The easiest way is to grab it from the url of your service account details in GCP: https://console.cloud.google.com/iam-admin/serviceaccounts/details/{client-id}?project={gcp-project-id}
You can list all service account in you project and then list URIs of these account as they follow in the same order:
gcloud iam service-accounts list
gcloud iam service-accounts list --uri
{private-key} is the content of a previously created private_key.pem file. You must append all the lines in the private_key.pem file with \n separator and combine everything into a single line like this:
a
b
c
becomes
a\nb\nc\n
Use this JSON file with client libraries the same way as you do with files downloaded from Google Cloud Platform JSON.