Google Cloud Limiting the validity of service account keys

When you create a service account key, Google Cloud doesn’t let you specify an expiry date. The key stays valid until you either delete the key or delete the entire service account.

Things look different when you upload a service account key: uploading a service account key works by creating a self-signed X.509 certificate, and then uploading that certificate in PEM format. X.509 certificates have an expiry date, and you can use that to limit the validity of a service account key.

Let’s see how that works:

  1. Create a self-signed certificate that uses an RSA 2048- or 4096-bit key and is valid for 7 days:

    openssl req -newkey rsa:4096 -nodes -keyout 7-days-cert.key -x509 -days 7 -out 7-days-cert.cer
    

    If you’re using Windows, you can use New-SelfSignedCertificate and CryptoAPI or CNG-based keys instead.

  2. Create a service account:

    gcloud iam service-accounts create sa-with-7-days-cert
    
  3. Upload the certificate and associate it with the service account:

    gcloud iam service-accounts keys upload 7-days-cert.cer --iam-account  sa-with-7-days-cert@[PROJECT-ID].iam.gserviceaccount.com
    

    The output should look similar to this, indicating that the validAfterTime is 7 days from today:

    keyOrigin: USER_PROVIDED`
    keyType: USER_MANAGED
    name: ...
    validAfterTime: '2021-06-11T10:15:18Z'     <-- +7 days -+
    validBeforeTime: '2021-06-18T10:15:18Z'     ------------+
    

    The Cloud Console also shows the expiry date:

    Uploaded key

Once the expiry time passes, the service account key can’t be used for authentication anymore, but it’ll stay associated with the service account until you delete it. In Cloud Console, an expired key looks like this:

Expired key

The safest way to use service accounts is to not use service account keys at all – but if you do, limiting the lifetime of those keys can be one way to limit risks associated with potential service account key leaks.

Thanks to Marco Ferrari for reviewing this blog post.

Any opinions expressed on this blog are Johannes' own. Refer to the respective vendor’s product documentation for authoritative information.
« Back to home