GCP for DevOps — Configuration & Secrets Practice Exercises
Configuration & Secrets Practice Exercises
Exercise 1 — Create and Rotate a Secret
Create a database password secret, add multiple versions, and simulate a rotation workflow.
Steps:
- Create a secret with an initial value
- Add a new version (rotate)
- Disable the old version
- Verify only the latest version is accessible
Show Answer
# Create the secret
$ echo -n "OldP@ss123" | gcloud secrets create db-password \
--replication-policy=automatic --data-file=-
# Add a new version (rotation)
$ echo -n "NewP@ss456!" | gcloud secrets versions add db-password --data-file=-
# List versions
$ gcloud secrets versions list db-password
# NAME STATE CREATED
# 2 enabled 2026-03-30T07:05:00Z
# 1 enabled 2026-03-30T07:00:00Z
# Disable the old version
$ gcloud secrets versions disable 1 --secret=db-password
# Access latest (should return new password)
$ gcloud secrets versions access latest --secret=db-password
# NewP@ss456!
# Trying to access disabled version fails
$ gcloud secrets versions access 1 --secret=db-password
# ERROR: Version is disabled
Exercise 2 — Mount Secrets in Cloud Run
Deploy a Cloud Run service that reads database credentials from Secret Manager.
Steps:
- Create two secrets (username and password)
- Deploy a Cloud Run service with secrets as env vars
- Verify the service can read the secrets
Show Answer
# Create secrets
$ echo -n "admin" | gcloud secrets create db-user --replication-policy=automatic --data-file=-
$ echo -n "SecureP@ss!" | gcloud secrets create db-pass --replication-policy=automatic --data-file=-
# Grant Cloud Run service account access
$ PROJECT_NUM=$(gcloud projects describe my-project --format='value(projectNumber)')
$ gcloud secrets add-iam-policy-binding db-user \
--member="serviceAccount:${PROJECT_NUM}-compute@developer.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
$ gcloud secrets add-iam-policy-binding db-pass \
--member="serviceAccount:${PROJECT_NUM}-compute@developer.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
# Deploy with secrets
$ gcloud run deploy secret-demo \
--image=us-docker.pkg.dev/cloudrun/container/hello \
--region=us-central1 \
--set-secrets=DB_USER=db-user:latest,DB_PASS=db-pass:latest \
--allow-unauthenticated
# Verify in application logs
$ gcloud logging read 'resource.type="cloud_run_revision" AND resource.labels.service_name="secret-demo"' --limit=5
Exercise 3 — Audit Resource Inventory
Use Cloud Asset Inventory to find all storage buckets and VMs in your project.
Steps:
- Search for all Cloud Storage buckets
- Search for all Compute Engine instances
- Export the full resource inventory to a GCS bucket
Show Answer
# Search for storage buckets
$ gcloud asset search-all-resources \
--scope=projects/my-project \
--asset-types=storage.googleapis.com/Bucket \
--format="table(name, location, createTime)"
# Search for compute instances
$ gcloud asset search-all-resources \
--scope=projects/my-project \
--asset-types=compute.googleapis.com/Instance \
--format="table(name, location, state)"
# Search for resources with specific labels
$ gcloud asset search-all-resources \
--scope=projects/my-project \
--query="labels.env:production"
# Export full inventory
$ gcloud asset export \
--project=my-project \
--output-path=gs://my-audit-bucket/inventory-$(date +%Y%m%d).json \
--content-type=resource
Exercise 4 — Analyze IAM Permissions
Find all members who have the ability to delete storage objects in your project.
Steps:
- Use Policy Analyzer to find members with
storage.objects.delete - Use Policy Troubleshooter to check a specific user’s access
- Identify over-permissioned service accounts
Show Answer
# Find who can delete storage objects
$ gcloud asset analyze-iam-policy \
--project=my-project \
--permissions="storage.objects.delete"
# Check if a specific user can delete objects
$ gcloud policy-troubleshoot iam \
//cloudresourcemanager.googleapis.com/projects/my-project \
--permission=storage.objects.delete \
--principal-email=alice@example.com
# Find all service accounts with owner role
$ gcloud asset search-all-iam-policies \
--scope=projects/my-project \
--query="policy:roles/owner AND policy:serviceAccount"
# Find all external members (non-organization)
$ gcloud asset search-all-iam-policies \
--scope=projects/my-project \
--query="policy:user" \
--format="table(resource, policy.bindings.role, policy.bindings.members)"
Exercise 5 — Scheduled Patch Management
Set up automated weekly patching for a fleet of production VMs.
Steps:
- Enable OS Config on your project
- Create VMs with appropriate labels
- Create a weekly patch deployment
- Verify patch job status
Show Answer
# Enable OS Config
$ gcloud services enable osconfig.googleapis.com
$ gcloud compute project-info add-metadata --metadata=enable-osconfig=TRUE
# Create test VMs with labels
$ gcloud compute instances create patch-test-1 \
--zone=us-central1-a \
--machine-type=e2-micro \
--labels=env=production,role=web
$ gcloud compute instances create patch-test-2 \
--zone=us-central1-a \
--machine-type=e2-micro \
--labels=env=production,role=web
# Create weekly patch deployment
$ gcloud compute os-config patch-deployments create weekly-prod-patch \
--instance-filter-group-labels="env=production" \
--apt-type=upgrade \
--reboot-config=DEFAULT \
--recurring-schedule-frequency=WEEKLY \
--recurring-schedule-weekly-day-of-week=SUNDAY \
--recurring-schedule-time-of-day="02:00" \
--recurring-schedule-time-zone="UTC"
# Verify deployment
$ gcloud compute os-config patch-deployments describe weekly-prod-patch
# Run a one-time test patch
$ gcloud compute os-config patch-jobs execute \
--instance-filter-group-labels="env=production" \
--apt-type=upgrade \
--reboot-config=NEVER \
--dry-run
# Check results
$ gcloud compute os-config patch-jobs list
Cleanup
$ gcloud secrets delete db-password --quiet
$ gcloud secrets delete db-user --quiet
$ gcloud secrets delete db-pass --quiet
$ gcloud run services delete secret-demo --region=us-central1 --quiet
$ gcloud compute os-config patch-deployments delete weekly-prod-patch --quiet
$ gcloud compute instances delete patch-test-1 patch-test-2 --zone=us-central1-a --quiet
Next Chapter → Advanced Networking