Skip to content

Instantly share code, notes, and snippets.

@mikesparr
Created April 12, 2023 00:07
Show Gist options
  • Save mikesparr/ec815e82fae316059967cd80a8eb86e4 to your computer and use it in GitHub Desktop.
Save mikesparr/ec815e82fae316059967cd80a8eb86e4 to your computer and use it in GitHub Desktop.
Example fetching and using Google Cloud Platform Secret Manager secrets from Compute Engine VM startup script
#!/usr/bin/env bash
#####################################################################
# REFERENCES
# - https://cloud.google.com/secret-manager/docs/create-secret-quickstart
# - https://cloud.google.com/secret-manager/docs/manage-access-to-secrets
# - https://cloud.google.com/secret-manager/docs/creating-and-managing-expiring-secrets
# - https://cloud.google.com/secret-manager/docs/secret-rotation
# - https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances
# - https://cloud.google.com/iam/docs/best-practices-service-accounts#single-purpose
# - https://cloud.google.com/compute/docs/access/iam
# - https://cloud.google.com/compute/docs/instances/startup-scripts/linux#passing-storage
#####################################################################
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_USER=$(gcloud config get-value core/account) # set current user
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export IDNS=${PROJECT_ID}.svc.id.goog # workflow identity domain
export GCP_REGION="us-central1" # CHANGEME (OPT)
export GCP_ZONE="us-central1-a" # CHANGEME (OPT)
export NETWORK_NAME="default"
# enable apis
gcloud services enable compute.googleapis.com \
storage.googleapis.com \
secretmanager.googleapis.com
# configure gcloud sdk
gcloud config set compute/region $GCP_REGION
gcloud config set compute/zone $GCP_ZONE
#############################################################
# SERVICE ACCOUNT
#############################################################
export SA_NAME="vm-withsecrets-sa"
export SA_EMAIL="$SA_NAME@$PROJECT_ID.iam.gserviceaccount.com"
# create service account
gcloud iam service-accounts create $SA_NAME --project $PROJECT_ID
# grant service account roles
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member "serviceAccount:$SA_EMAIL" \
--role roles/monitoring.metricWriter
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member "serviceAccount:$SA_EMAIL" \
--role roles/logging.logWriter
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member "serviceAccount:$SA_EMAIL" \
--role roles/stackdriver.resourceMetadata.writer
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member "serviceAccount:$SA_EMAIL" \
--role roles/compute.networkUser
#############################################################
# SECRETS
#############################################################
export DB_PASS=$(openssl rand -base64 32)
export SECRET_DB_PASS="db-password"
# create secret
echo -n $DB_PASS | gcloud secrets create $SECRET_DB_PASS \
--replication-policy="automatic" \
--data-file=-
# grant service account access to secret
gcloud secrets add-iam-policy-binding $SECRET_DB_PASS \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/secretmanager.secretAccessor"
#############################################################
# STORAGE BUCKET / SCRIPT
#############################################################
export BUCKET_NAME="mike-test-secret-manager-utils"
export STARTUP_FILE="startup.sh"
# create storage bucket
gcloud storage buckets create gs://$BUCKET_NAME \
--location $GCP_REGION \
--uniform-bucket-level-access
# create startup script
cat > $STARTUP_FILE << EOF
#!/usr/bin/env bash
whoami
echo "Fetching secret db-password ..."
gcloud secrets versions access latest --secret=db-password > db.pass
echo
echo "db-password was: $(cat db.pass)"
EOF
chmod +x $STARTUP_FILE
# copy file to storage bucket
gcloud storage cp ./$STARTUP_FILE gs://$BUCKET_NAME/$STARTUP_FILE
# grant bucket permission to vm service account to read startup script
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_NAME \
--member="serviceAccount:$SA_EMAIL" \
--role=roles/storage.objectViewer
#############################################################
# COMPUTE INSTANCE
#############################################################
export INSTANCE_NAME="instance-1"
# network enable firewall for ssh
gcloud compute firewall-rules create fw-allow-ssh \
--network=$NETWORK_NAME \
--action=allow \
--direction=ingress \
--target-tags=allow-ssh \
--rules=tcp:22
# create compute instance to test (WARN: external IP for test only)
gcloud compute instances create $INSTANCE_NAME \
--machine-type e2-micro \
--zone $GCP_ZONE \
--service-account $SA_EMAIL \
--metadata=startup-script-url=gs://$BUCKET_NAME/$STARTUP_FILE \
--scopes cloud-platform \
--tags allow-ssh
# verify script ran
gcloud compute ssh $INSTANCE_NAME --zone $GCP_ZONE -- journalctl -u google-startup-scripts.service
# optionally rerun script
gcloud compute ssh $INSTANCE_NAME --zone $GCP_ZONE -- google_metadata_script_runner startup
# verify secret stored in file
gcloud compute ssh $INSTANCE_NAME --zone $GCP_ZONE -- cat db.pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment