GCP for DevOps — Security Practice Exercises
Security Practice Exercises
Exercise 1 — Encrypt Data with Cloud KMS
Create a KMS key ring and key, then encrypt and decrypt a file.
Steps:
- Create a key ring and encryption key
- Encrypt a plaintext file
- Decrypt it back and verify
Show Answer
# Create key ring and key
$ gcloud kms keyrings create devops-keyring --location=us-central1
$ gcloud kms keys create data-key \
--keyring=devops-keyring \
--location=us-central1 \
--purpose=encryption \
--rotation-period=90d
# Create a test file
$ echo "This is sensitive data" > secret.txt
# Encrypt
$ gcloud kms encrypt \
--key=data-key \
--keyring=devops-keyring \
--location=us-central1 \
--plaintext-file=secret.txt \
--ciphertext-file=secret.enc
# Verify encrypted file is not readable
$ cat secret.enc
# (binary data)
# Decrypt
$ gcloud kms decrypt \
--key=data-key \
--keyring=devops-keyring \
--location=us-central1 \
--ciphertext-file=secret.enc \
--plaintext-file=secret-decrypted.txt
$ cat secret-decrypted.txt
# This is sensitive data
Exercise 2 — Cloud Storage with CMEK
Create a Cloud Storage bucket encrypted with a customer-managed key.
Steps:
- Create a KMS key for Cloud Storage
- Grant the Storage service account access to the key
- Create a bucket with CMEK
- Upload and download a file
Show Answer
# Create key
$ gcloud kms keys create storage-key \
--keyring=devops-keyring \
--location=us-central1 \
--purpose=encryption
# Grant Cloud Storage service account access
$ PROJECT_NUM=$(gcloud projects describe my-project --format='value(projectNumber)')
$ gcloud kms keys add-iam-policy-binding storage-key \
--keyring=devops-keyring \
--location=us-central1 \
--member="serviceAccount:service-${PROJECT_NUM}@gs-project-accounts.iam.gserviceaccount.com" \
--role="roles/cloudkms.cryptoKeyEncrypterDecrypter"
# Create bucket with CMEK
$ gsutil mb -l us-central1 \
-k projects/my-project/locations/us-central1/keyRings/devops-keyring/cryptoKeys/storage-key \
gs://cmek-demo-bucket-$(date +%s)
# Upload and download
$ echo "encrypted content" > test.txt
$ gsutil cp test.txt gs://cmek-demo-bucket-*/
$ gsutil cp gs://cmek-demo-bucket-*/test.txt downloaded.txt
$ cat downloaded.txt
# encrypted content
Exercise 3 — Enable Binary Authorization
Set up Binary Authorization on a GKE cluster and verify unsigned images are blocked.
Steps:
- Enable Binary Authorization on a cluster
- Set the policy to deny all unsigned images
- Try deploying an unsigned image
- Verify it is blocked
Show Answer
# Enable Binary Authorization
$ gcloud container clusters update my-cluster \
--region=us-central1 \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE
# Export and update policy
$ gcloud container binauthz policy export > policy.yaml
# Edit policy.yaml to set default rule to deny
# defaultAdmissionRule:
# evaluationMode: ALWAYS_DENY
# enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
$ gcloud container binauthz policy import policy.yaml
# Try deploying an unsigned image (should be blocked)
$ kubectl run test --image=nginx:latest
# Error: Denied by Binary Authorization
# Check audit logs for denial
$ gcloud logging read 'resource.type="k8s_cluster" AND protoPayload.status.message:"denied by"' --limit=5
# Reset policy to allow for cleanup
# defaultAdmissionRule:
# evaluationMode: ALWAYS_ALLOW
# enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
$ gcloud container binauthz policy import policy.yaml
Exercise 4 — Container Vulnerability Scanning
Push a container image and check for vulnerabilities.
Steps:
- Enable Container Scanning API
- Build and push an image to Artifact Registry
- Check the vulnerability report
- Identify critical and high vulnerabilities
Show Answer
# Enable scanning
$ gcloud services enable containerscanning.googleapis.com
# Create a simple Dockerfile with a known-vulnerable base
$ cat > Dockerfile << 'EOF'
FROM python:3.9-slim
COPY app.py /app.py
CMD ["python", "/app.py"]
EOF
$ echo 'print("Hello")' > app.py
# Build and push
$ gcloud builds submit --tag=us-central1-docker.pkg.dev/my-project/my-repo/vuln-test:v1
# Wait for scan to complete (usually 1-2 minutes)
$ sleep 120
# Check vulnerabilities
$ gcloud artifacts docker images describe \
us-central1-docker.pkg.dev/my-project/my-repo/vuln-test:v1 \
--show-all-metadata
# List vulnerabilities by severity
$ gcloud artifacts vulnerabilities list \
us-central1-docker.pkg.dev/my-project/my-repo/vuln-test:v1 \
--format="table(vulnerability.shortDescription, vulnerability.effectiveSeverity, vulnerability.fixAvailable)"
Exercise 5 — Security Command Center Findings
Review and manage Security Command Center findings for your project.
Steps:
- List all active findings in your project
- Filter for high-severity findings
- Mute a known false positive
- Set up a Pub/Sub notification for critical findings
Show Answer
# List all active findings
$ gcloud scc findings list projects/my-project \
--source=projects/my-project/sources/- \
--filter='state="ACTIVE"' \
--format="table(finding.category, finding.severity, finding.resourceName)"
# Filter high and critical
$ gcloud scc findings list projects/my-project \
--source=projects/my-project/sources/- \
--filter='state="ACTIVE" AND (severity="HIGH" OR severity="CRITICAL")'
# Mute a known false positive
$ gcloud scc findings set-mute FINDING_NAME \
--mute=MUTED
# Create notification topic
$ gcloud pubsub topics create scc-critical-alerts
# Create notification config
$ gcloud scc notifications create critical-notifier \
--project=my-project \
--pubsub-topic=projects/my-project/topics/scc-critical-alerts \
--filter='state="ACTIVE" AND severity="CRITICAL"'
# Verify
$ gcloud scc notifications list --project=my-project
Cleanup
$ gcloud kms keys versions destroy 1 --key=data-key --keyring=devops-keyring --location=us-central1 --quiet
$ gcloud kms keys versions destroy 1 --key=storage-key --keyring=devops-keyring --location=us-central1 --quiet
$ gcloud scc notifications delete critical-notifier --project=my-project --quiet
$ gcloud pubsub topics delete scc-critical-alerts --quiet
Next Chapter → Cost Optimization