Securing GCS Bucket Access for GCP VMs: Best Practices Explained
Best Methods for Securing Connections Between GCS Buckets and GCP VMs

In this lab we will see how to access the GCS bucket data to GCP VM in most secure manner.
What we’ll cover
Cloud Storage FUSE
Service Account
Linux User
GCP VM
Cloud KMS
What you’ll need
Google Cloud Admin access
Access to VM and a Bucket
Cloud KMS access
Here is flowchart on this lab
Lets first create the Cloud KMS keyring and Cryptographic Key
Setup Cloud KMS
Cloud KMS help in building the data sovereignty between GCS bucekt and VM, It ensures that even if someone get access to physical disk in Google data’s center, they cannot read your files without your cryptographic keys.
We are using this Cloud KMS to setup most secure infra for our data, from virtual to physical data will be secure in this data transaction
gcloud kms keyrings create secure-bucket-keyring --location us-central1
This keyring will be use by the Cloud bucket and VM to decrypt the data
Create Service account to user to use this KMS key
export SA_NAME="secure-vm-sa"
gcloud iam service-accounts create $SA_NAME --display-name "Secure VM Access"
Grant permission to us Cloud KMS key
export REGION="us-central1"
export KEY_RING="secure-bucket-keyring"
export KEY_NAME="secure-vm-bucket-key"
export SA_EMAIL="\(SA_NAME@\)PROJECT_ID.iam.gserviceaccount.com"
gcloud kms keys add-iam-policy-binding $KEY_NAME \
--location $REGION \
--keyring $KEY_RING \
--member "serviceAccount:$SA_EMAIL" \
--role "roles/cloudkms.cryptoKeyEncrypterDecrypter"
Now will grant the bucket to access the Cloud KMS key
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=\((gcloud projects describe \)PROJECT_ID --format="value(projectNumber)")
export STORAGE_AGENT="service-$PROJECT_NUMBER@gs-project-accounts.iam.gserviceaccount.com"
gcloud kms keys add-iam-policy-binding $KEY_NAME \
--location $REGION \
--keyring $KEY_RING \
--member "serviceAccount:$STORAGE_AGENT" \
--role "roles/cloudkms.cryptoKeyEncrypterDecrypter"
Now we will create Bucket
Bucket setup
We will apply four security layers in a single command:
Enforce Public Access Prevention: Hard block on "allUsers" (internet).
Uniform Bucket-Level Access: Disables messy ACLs (Access Control Lists); forces strict IAM usage.
Default CMEK Encryption: Forces your KMS key on every file immediately.
Versioning: Protects against ransomware or accidental deletion (you can "undelete" files).
BUCKET_NAME="secure-bucket-lab-2025"
REGION="us-central1"
PROJECT_ID=$(gcloud config get-value project)
KMS_KEY="projects/\(PROJECT_ID/locations/\)REGION/keyRings/secure-bucket-keyring/cryptoKeys/secure-vm-bucket-key"
Note: Create a bucket with unique name please don’t use this name
Now let create secure bucket with Cloud KMS key, remove public access, and add uniform bucket level access and enable versioning
gcloud storage buckets create gs://$BUCKET_NAME \
--location=$REGION \
--project=$PROJECT_ID \
--public-access-prevention \
--uniform-bucket-level-access \
--default-encryption-key=$KMS_KEY
Enable versioning to bucket
gcloud storage buckets update gs://$BUCKET_NAME --versioning
Grant a service account access to bucket
gcloud storage buckets add-iam-policy-binding gs://$BUCKET_NAME \
--member "serviceAccount:$SA_EMAIL" \
--role "roles/storage.objectUser"
Now we will create the VM
VM_NAME="secure-vm"
ZONE="us-central1-a"
PROJECT_ID=$(gcloud config get-value project)
SA_EMAIL="secure-vm-sa@$PROJECT_ID.iam.gserviceaccount.com"
gcloud compute instances create $VM_NAME \
--zone=$ZONE \
--machine-type=e2-medium \
--image-family=ubuntu-2204-lts \
--image-project=ubuntu-os-cloud \
--service-account=$SA_EMAIL \
--scopes=cloud-platform \
--shielded-secure-boot \
--shielded-vtpm \
--shielded-integrity-monitoring \
--tags=secure-ssh
We added these thing to make it more secure
--shielded-secure-boot: Ensures the OS hasn't been tampered with before it loads.--service-account: It never uses the "Default" editor account, only your restricted one.--tags=secure-ssh: We will use this tag to create a specific firewall rule next.
Now secure the Firewall to allow access with only Cloud IAP
gcloud compute firewall-rules create allow-ssh-ingress-from-iap \
--direction=INGRESS \
--action=allow \
--rules=tcp:22 \
--source-ranges=35.235.240.0/20 \
--target-tags=secure-ssh
Use this ssh command to access the VM in Cloud IAM ssh tunnel
gcloud compute ssh \(VM_NAME --zone=\)ZONE --tunnel-through-iap
Install Dependencies on VM
Google Cloud Storage FUSE
export GCSFUSE_REPO=gcsfuse-`lsb_release -c -s`
echo "deb https://packages.cloud.google.com/apt $GCSFUSE_REPO main" | sudo tee /etc/apt/sources.list.d/gcsfuse.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install -y gcsfuse
Check your user id
id <username>
Create new users and group then
sudo groupadd -g 2000 app_group
sudo useradd -u 2000 -g 2000 -m -s /bin/bash app_user
create secure folder and give access to the particular user
sudo mkdir -p /home/app_user/secure_data
sudo chown app_user:app_group /home/app_user/secure_data
sudo chmod 700 /home/app_user/secure_data
User mount to fuse.conf file
sudo sed -i 's/#user_allow_other/user_allow_other/g' /etc/fuse.conf
Mount the bucket data to persistent volume
BUCKET_NAME="secure-bucket-lab-2025"
echo "$BUCKET_NAME /home/app_user/secure_data gcsfuse rw,_netdev,allow_other,implicit_dirs,uid=2000,gid=2000,file_mode=600,dir_mode=700,noexec,nosuid,nodev 0 0" | sudo tee -a /etc/fstab
sudo mount -a
Now switch to user and verify the folder
sudo su - app_user
ls -ld secure_data/
This will the folder secure_data with drwx------ 1 app_user app_group 0
Now verify the mount volume
df -h /home/app_user/secure_data
Here you can see the avail size 1.0P which is significant saying Google Storage bucket in petabyte of storage
Test data access
Push object into bucket
Now ls inside the secure_data folder
In this lab, we explore securing data access between Google Cloud Storage (GCS) buckets and Google Cloud Platform (GCP) virtual machines (VMs) using Cloud Key Management Service (KMS) and other security measures. Key steps include setting up a KMS keyring and cryptographic key, creating a service account for secure VM access, configuring a secure bucket with four layers of security (preventing public access, enforcing uniform bucket-level access, default CMEK encryption, and versioning), and setting up the VM with specific security configurations. We also cover using Cloud Storage FUSE for data access, creating secure user groups, and mounting the bucket data as a persistent volume. Finally, we verify data accessibility and security configurations on the VM.





