Skip to content

Instantly share code, notes, and snippets.

@mikesparr
Last active January 5, 2026 15:08
Show Gist options
  • Select an option

  • Save mikesparr/6ffe13079505b598d98d55a2088411c3 to your computer and use it in GitHub Desktop.

Select an option

Save mikesparr/6ffe13079505b598d98d55a2088411c3 to your computer and use it in GitHub Desktop.
Example of granting access to select compute engine instance and enabling audit logs on Google Cloud Platform (GCP)
#!/usr/bin/env bash
#####################################################################
# REFERENCES
# - https://cloud.google.com/compute/docs/oslogin/manage-oslogin-in-an-org
# - https://cloud.google.com/compute/docs/instances/managing-instance-access#configure_users
# - https://cloud.google.com/iam/docs/configuring-resource-based-access
# - https://cloud.google.com/iap/docs/using-tcp-forwarding#grant-permission
# - https://cloud.google.com/iap/docs/audit-log-howto
# - https://cloud.google.com/compute/docs/oslogin/view-audit-logs#view-logs
#####################################################################
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 # workload 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 \
iap.googleapis.com
# configure gcloud sdk
gcloud config set compute/region $GCP_REGION
gcloud config set compute/zone $GCP_ZONE
# ideally require OS Login at org level but did at instance for demo
# gcloud beta resource-manager org-policies enable-enforce compute.requireOsLogin \
# --organization=$ORGANIZATION
# create two compute instances
export INSTANCE_1_NAME="accessible"
export INSTANCE_2_NAME="inaccessible"
gcloud compute instances create $INSTANCE_1_NAME \
--project=$PROJECT_ID \
--zone=$GCP_ZONE \
--machine-type=e2-micro \
--network-interface=subnet=default,no-address \
--scopes=https://www.googleapis.com/auth/cloud-platform \
--metadata enable-oslogin=TRUE
gcloud compute instances create $INSTANCE_2_NAME \
--project=$PROJECT_ID \
--zone=$GCP_ZONE \
--machine-type=e2-micro \
--network-interface=subnet=default,no-address \
--scopes=https://www.googleapis.com/auth/cloud-platform \
--metadata enable-oslogin=TRUE
# grant SSH access
gcloud compute firewall-rules create allow-ssh-ingress-from-iap \
--direction=INGRESS \
--action=allow \
--rules=tcp:22 \
--source-ranges=35.235.240.0/20
# enable IAP audit logs
gcloud projects get-iam-policy $PROJECT_ID > policy.yaml
cat >> policy.yaml << EOF
auditConfigs:
- auditLogConfigs:
- logType: ADMIN_READ
- logType: DATA_READ
- logType: DATA_WRITE
service: iap.googleapis.com
EOF
gcloud projects set-iam-policy $PROJECT_ID policy.yaml
# test access with non-owner user (realistic)
export TEST_EMAIL="you@youremail.com" # CHANGEME
# org scope (optional: since I used external user in demo)
gcloud organizations add-iam-policy-binding $ORGANIZATION \
--member user:$TEST_EMAIL \
--role roles/compute.osLoginExternalUser \
--condition=None
# project scope
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member user:$TEST_EMAIL \
--role roles/iap.tunnelResourceAccessor \
--condition \
'title=allow-ssh-only,expression=destination.port==22'
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member user:$TEST_EMAIL \
--role roles/browser \
--condition=None
# service account scope
export DEFAULT_SA="$PROJECT_NUMBER-compute@developer.gserviceaccount.com"
gcloud iam service-accounts add-iam-policy-binding $DEFAULT_SA \
--member user:$TEST_EMAIL \
--role roles/iam.serviceAccountUser \
--condition=None
# instance scope (instance-level roles for least privilege)
gcloud compute instances add-iam-policy-binding $INSTANCE_1_NAME \
--member user:$TEST_EMAIL \
--role roles/compute.instanceAdmin \
--condition=None
gcloud compute instances add-iam-policy-binding $INSTANCE_1_NAME \
--member user:$TEST_EMAIL \
--role roles/compute.osLogin \
--condition=None
# change to test user
gcloud config set account $TEST_EMAIL
# test login on accessible instance
gcloud compute ssh $INSTANCE_1_NAME # success
# test login on inaccessible instance
gcloud compute ssh $INSTANCE_2_NAME # failed
# switch back to original user
gcloud config set account $PROJECT_USER
# view logs
gcloud logging read --freshness=1h 'protoPayload.serviceName="oslogin.googleapis.com"'
@mikesparr
Copy link
Author

Clean up

Don't forget to clean up to avoid unexpected cloud costs. The easiest way is to delete the GCP project, but you can also perform the following:

gcloud compute instances delete $INSTANCE_1_NAME --zone $GCP_ZONE
gcloud compute instances delete $INSTANCE_2_NAME --zone $GCP_ZONE

And optionally reverse the IAM permissions, and audit logging config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment