GCP for DevOps — Secret Manager

2 minute read

Secret Manager

Secret Manager is a secure, centralized service for managing API keys, passwords, certificates, and other sensitive data. It provides versioning, automatic rotation, IAM-based access control, and audit logging.

How Secret Manager Works

Secret Manager:
┌──────────────┐    ┌──────────────────┐    ┌──────────────┐
│ DevOps Team   │───▶│ Secret Manager    │◀───│ Cloud Run     │
│ (create)      │    │                   │    │ (access)      │
│               │    │ my-db-password    │    ├──────────────┤
│               │    │ ├── v1 (disabled) │    │ GKE           │
│               │    │ ├── v2 (enabled)  │    │ (access)      │
│               │    │ └── v3 (latest)   │    ├──────────────┤
│               │    │                   │    │ Cloud          │
│               │    │ Encrypted at rest │    │ Functions     │
│               │    │ IAM-controlled    │    │ (access)      │
└──────────────┘    └──────────────────┘    └──────────────┘

Create and Manage Secrets

# Create a secret
$ gcloud secrets create my-db-password \
    --replication-policy="automatic"

# Add a secret version (the actual value)
$ echo -n "SuperS3cret!" | gcloud secrets versions add my-db-password --data-file=-

# Create secret with value in one step
$ printf "my-api-key-value" | gcloud secrets create my-api-key \
    --replication-policy="automatic" \
    --data-file=-

# List secrets
$ gcloud secrets list

# Output:
# NAME              CREATED              REPLICATION_POLICY
# my-db-password    2026-03-30T07:00:00  automatic
# my-api-key        2026-03-30T07:01:00  automatic

Secret Versions

# Add a new version (rotates the secret)
$ echo -n "NewP@ssw0rd!" | gcloud secrets versions add my-db-password --data-file=-

# List versions
$ gcloud secrets versions list my-db-password

# Output:
# NAME  STATE    CREATED
# 2     enabled  2026-03-30T07:05:00Z
# 1     enabled  2026-03-30T07:00:00Z

# Access the latest version
$ gcloud secrets versions access latest --secret=my-db-password
# NewP@ssw0rd!

# Access a specific version
$ gcloud secrets versions access 1 --secret=my-db-password
# SuperS3cret!

# Disable an old version
$ gcloud secrets versions disable 1 --secret=my-db-password

# Destroy a version (permanent)
$ gcloud secrets versions destroy 1 --secret=my-db-password

Regional Replication

# Automatic replication (Google manages)
$ gcloud secrets create auto-secret \
    --replication-policy="automatic"

# User-managed replication (specific regions)
$ gcloud secrets create regional-secret \
    --replication-policy="user-managed" \
    --locations="us-central1,us-east1"

IAM Access Control

# Grant a service account access to a secret
$ gcloud secrets add-iam-policy-binding my-db-password \
    --member="serviceAccount:my-app@my-project.iam.gserviceaccount.com" \
    --role="roles/secretmanager.secretAccessor"

# View who has access
$ gcloud secrets get-iam-policy my-db-password
Role Permissions
roles/secretmanager.secretAccessor Access secret versions
roles/secretmanager.viewer View secret metadata (not values)
roles/secretmanager.admin Full management
roles/secretmanager.secretVersionManager Add/disable/destroy versions

Secret Rotation

# Set a rotation schedule
$ gcloud secrets update my-db-password \
    --next-rotation-time="2026-04-30T00:00:00Z" \
    --rotation-period="2592000s"

# Rotation sends a Pub/Sub notification
# Create a topic for rotation events
$ gcloud pubsub topics create secret-rotation

# Configure the secret to notify on rotation
$ gcloud secrets update my-db-password \
    --topics="projects/my-project/topics/secret-rotation"

Labels and Organization

# Add labels
$ gcloud secrets update my-db-password \
    --update-labels=env=production,team=backend

# Filter secrets by label
$ gcloud secrets list --filter="labels.env=production"

Access Secrets from Code

from google.cloud import secretmanager

client = secretmanager.SecretManagerServiceClient()

# Access the latest version
name = "projects/my-project/secrets/my-db-password/versions/latest"
response = client.access_secret_version(request={"name": name})
secret_value = response.payload.data.decode("UTF-8")

print(f"Secret: {secret_value}")

Common Mistakes

Mistake Why It’s Wrong Fix
Secrets in env vars / code Exposed in logs, repos Use Secret Manager
Too broad IAM roles Over-permissioned access Grant secretAccessor only
No version rotation Stale credentials Set rotation schedule
Not disabling old versions Old creds remain valid Disable after rotation
No audit logging Can’t track access Enable Data Access audit logs

Quick Reference

Command Description
gcloud secrets create NAME Create a secret
gcloud secrets versions add NAME Add a version
gcloud secrets versions access latest Read latest value
gcloud secrets versions disable VERSION Disable a version
gcloud secrets add-iam-policy-binding Grant access
gcloud secrets list List secrets

Next → Accessing Secrets

Updated: