Creating and Managing Expiring Secrets

This topic discusses support for expiring secrets in Secret Manager.

Overview

By default, secrets stored in Secret Manager exist until a user deletes them. If a secret should only be stored for a known, limited amount of time, you can attach an expiration time to it. At a secret's configured expiration time, it is automatically deleted.

If you don't have requirements that the secret must be deleted, consider using IAM Conditions or the Disabled version state to revoke access in a safe way.

When inputting an expiration, it can be expressed as either a timestamp or a duration. When retrieving secret metadata, the expiration will always be returned as a timestamp, regardless of how it was given.

An expiration can be added, updated, or removed from a secret at any time.

Limitations

Secret expiration is only available only in the Secret Manager v1 API and gcloud command-line tool.

A secret's expiration cannot be less than 60 seconds away or more than 100 years away.

Safely Using Expiring Secrets

When a secret expires in Secret Manager, it is irreversibly deleted. The best way to detect soon-to-expire secrets is by using IAM Conditions to remove permissions from the accounts that use the secret prior to expiration.

To do this, when granting permissions on a secret, attach a time-based condition to the binding. The binding should expire after the secret is expected to no longer be used, but early enough that the removed permissions would be noticed before the secret expires. If workflows that were thought to no longer use the secret break after permissions are revoked, then permissions can be added back to quickly mitigate. If more time is required, the secret expiration can be updated or even removed.

For example, suppose a service account is expected to access a secret daily over a 30 day period. The secret expiration could then be set to 60 days from creation and a conditional IAM binding could be used to grant the service account the Secret Accessor role for 45 days. If the service account attempts to access the secret after 45 days, a Permission Denied error will be returned and workflows requiring the secret would break. An administrator could then grant the Secret Accessor role back to the service account to quickly mitigate while investigating, since the secret itself wouldn't be deleted for 15 more days.

Additionally, it is possible to create alerts based on logs warning of secrets that are expiring soon. See Expiration Logging for more information.

Creating an expiring secret

To create an expiring secret using a timestamp run:

gcloud

$ gcloud secrets create my-secret \
    --replication-policy "automatic" \
    --expire-time="2100-01-01T09:00:00-05:00"

API

 curl "https://secretmanager.googleapis.com/v1/projects/${PROJECT_ID}/secrets?secretId=my-secret" \
    --request "POST" \
    --header "Content-Type: application/json" \
    --header "Authorization: Bearer $(gcloud auth print-access-token)" \
    --data-binary @- <<EOF
{
  "replication":{
    "automatic":{}
  },
    "expire_time": "2100-01-01T09:00:00-05:00"
}
EOF

To create an expiring secret using a duration run:

gcloud

$ gcloud secrets create my-secret \
    --replication-policy "automatic" \
    --ttl "86400s"

API

 curl "https://secretmanager.googleapis.com/v1/projects/${PROJECT_ID}/secrets?secretId=my-secret" \
    --request "POST" \
    --header "Content-Type: application/json" \
    --header "Authorization: Bearer $(gcloud auth print-access-token)" \
    --data-binary @- <<EOF
{
  "replication":{
    "automatic":{}
  },
    "ttl": "86400s"
}
EOF

Updating a secret's expiration

Any secret can have a new expiration applied to it regardless of whether it already has one. Each secret can only have one configured expiration at a time. Updating the expiration of a secret that already has one will overwrite its existing expiration.

To update a secret's expiration using a timestamp run:

gcloud

$ gcloud secrets update my-secret \
    --expire-time "2100-01-01T09:00:00-05:00"

API

  $ curl "https://secretmanager.googleapis.com/v1/projects/${PROJECT_ID}/secrets/my-secret?updateMask=expire_time" \
      --request "PATCH" \
      --header "Authorization: Bearer $(gcloud auth print-access-token)" \
      --header "Content-Type: application/json" \
      --data-binary @- <<EOF
  {
    "expire_time": "2100-01-01T09:00:00-05:00"
  }
  EOF

To update a secret's expiration using a duration run:

gcloud

$ gcloud secrets update my-secret \
    --ttl "86400s"

API

  $ curl "https://secretmanager.googleapis.com/v1/projects/${PROJECT_ID}/secrets/my-secret?updateMask=expire_time" \
      --request "PATCH" \
      --header "Authorization: Bearer $(gcloud auth print-access-token)" \
      --header "Content-Type: application/json" \
      --data-binary @- <<EOF
  {
    "ttl": "86400s"
  }
  EOF

Removing a secret's expiration

To remove a secret's expiration run:

gcloud

$ gcloud secrets update my-secret \
    --remove-expiration

API

Including either expire_time or ttl in the updateMask while providing values for neither will remove the expiration.

  $ curl "https://secretmanager.googleapis.com/v1/projects/${PROJECT_ID}/secrets/my-secret?updateMask=expire_time" \
      --request "PATCH" \
      --header "Authorization: Bearer $(gcloud auth print-access-token)" \
      --header "Content-Type: application/json" \
      --data-binary @- <<EOF
  {}
  EOF

Expiration Logging

Cloud Audit Logs are not produced when a Secret automatically expires. Instead Secret Manager writes logs to the Secret Manager Secret resource at specific intervals leading up to a secret's expiration.

Log Timing Secret Event Type
30 days before expiration EXPIRES_IN_30_DAYS
7 days before expiration EXPIRES_IN_7_DAYS
1 day before expiration EXPIRES_IN_1_DAY
6 hours before expiration EXPIRES_IN_6_HOURS
1 hour before expiration EXPIRES_IN_1_HOUR
at expiration EXPIRED

See the Logging Quickstart guide for information about how to view these logs. You can create Log-based metrics and use them to create alerts for upcoming expirations.

What's next?