Skip to main content

Command Palette

Search for a command to run...

Securing GCS Bucket Access for GCP VMs: Best Practices Explained

Best Methods for Securing Connections Between GCS Buckets and GCP VMs

Updated
5 min read
Securing GCS Bucket Access for GCP VMs: Best Practices Explained

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"
Service account

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" 
Cloud KMS Decrypter

Now we will create Bucket


Bucket setup

We will apply four security layers in a single command:

  1. Enforce Public Access Prevention: Hard block on "allUsers" (internet).

  2. Uniform Bucket-Level Access: Disables messy ACLs (Access Control Lists); forces strict IAM usage.

  3. Default CMEK Encryption: Forces your KMS key on every file immediately.

  4. 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"
Bucket access

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

Cloud Storage Bucket

Now ls inside the secure_data folder

GCP VM

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.