Skip to main content

VM Instances Should Not Use Default Service Account

More Info:

It is recommended to configure your instance to not use the default Compute Engine service account because it has the Editor role on the project.

Risk Level

High

Address

Security

Compliance Standards

  • CIS GCP
  • CIS GCP 2.0.0
  • Cloudanix Best Practice
  • HITRUST CSF
  • NIST CSF
  • PCI
  • SOC2

Triage and Remediation

Remediation

Using Console

Sure, here are the step-by-step instructions to remediate the misconfiguration "VM Instances Should Not Use Default Service Account" for GCP using GCP console:

  1. Open the GCP console and navigate to the Compute Engine page.

  2. Select the VM instance that is using the default service account.

  3. Click on the "Edit" button at the top of the page.

  4. Scroll down to the "Cloud API access scopes" section.

  5. Click on the "Set access for each API" link.

  6. Uncheck the box next to "Allow default access to all Cloud APIs".

  7. Select the specific API access scopes that are required for the VM instance.

  8. Click on the "Save" button at the bottom of the page.

  9. Repeat steps 2-8 for all VM instances that are using the default service account.

By following these steps, you will remediate the misconfiguration "VM Instances Should Not Use Default Service Account" for GCP using GCP console.

Using CLI

To remediate the misconfiguration "VM Instances Should Not Use Default Service Account" in GCP using GCP CLI, you can follow the below steps:

Step 1: List all the instances that are using the default service account by running the following command:

gcloud compute instances list --filter="serviceAccounts.email:[PROJECT_NUMBER]-compute@developer.gserviceaccount.com"

Note: Replace [PROJECT_NUMBER] with your GCP project number.

Step 2: For each instance that is using the default service account, create a new service account and assign the required IAM roles to it by running the following commands:

gcloud iam service-accounts create [NEW_SERVICE_ACCOUNT_NAME] --display-name "[NEW_SERVICE_ACCOUNT_DISPLAY_NAME]"

gcloud projects add-iam-policy-binding [PROJECT_ID] --member="serviceAccount:[NEW_SERVICE_ACCOUNT_NAME]@[PROJECT_ID].iam.gserviceaccount.com" --role="[REQUIRED_IAM_ROLE]"

Note: Replace [NEW_SERVICE_ACCOUNT_NAME] and [NEW_SERVICE_ACCOUNT_DISPLAY_NAME] with the desired name and display name for the new service account, [PROJECT_ID] with your GCP project ID and [REQUIRED_IAM_ROLE] with the required IAM role for the instance.

Step 3: Update the instance to use the new service account by running the following command:

gcloud compute instances set-service-account [INSTANCE_NAME] --service-account [NEW_SERVICE_ACCOUNT_NAME]@[PROJECT_ID].iam.gserviceaccount.com

Note: Replace [INSTANCE_NAME] with the name of the instance that needs to be updated and [NEW_SERVICE_ACCOUNT_NAME]@[PROJECT_ID].iam.gserviceaccount.com with the name of the new service account created in Step 2.

Step 4: Verify that the instance is now using the new service account by running the following command:

gcloud compute instances describe [INSTANCE_NAME] --format="get(serviceAccounts.email)"

Note: Replace [INSTANCE_NAME] with the name of the instance that was updated in Step 3.

Repeat the above steps for all the instances that are using the default service account to remediate the misconfiguration.

Using Python

To remediate the issue "VM Instances Should Not Use Default Service Account" for GCP using Python, you can follow the below steps:

  1. First, we need to identify the list of all VM instances that are using the default service account. This can be achieved by using the Google Cloud Python SDK's googleapiclient library.
from googleapiclient import discovery
from google.oauth2 import service_account

credentials = service_account.Credentials.from_service_account_file('path/to/credentials.json')

compute = discovery.build('compute', 'v1', credentials=credentials)

project = 'project-id'

instances = compute.instances().list(project=project).execute()

for instance in instances['items']:
if instance['serviceAccounts'][0]['email'].endswith('gserviceaccount.com'):
print(f"Instance {instance['name']} is using the default service account.")
  1. Once we have identified the instances that are using the default service account, we need to update the service account for each instance. This can be done using the instances().setServiceAccount method.
for instance in instances['items']:
if instance['serviceAccounts'][0]['email'].endswith('gserviceaccount.com'):
print(f"Instance {instance['name']} is using the default service account.")
updated_instance = compute.instances().setServiceAccount(
project=project,
zone=instance['zone'].split('/')[-1],
instance=instance['name'],
body={
"serviceAccounts": [
{
"email": "new-service-account@project-id.iam.gserviceaccount.com",
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
}
]
}
).execute()
print(f"Updated service account for instance {instance['name']} to new-service-account@project-id.iam.gserviceaccount.com.")

In the above code, we are updating the service account for each instance to a new service account new-service-account@project-id.iam.gserviceaccount.com with cloud-platform scope. You can replace this with the appropriate service account and scopes as per your requirements.

  1. Finally, you can verify that the instances are no longer using the default service account by running the code in step 1 again.
Using Terraform
# Custom service account for the instance (non-default)
resource "google_service_account" "INSTANCE_SERVICE_ACCOUNT" {
account_id = "NON_DEFAULT_SA_ID" # e.g. "app-server-sa"
display_name = "NON_DEFAULT_SA_DISPLAY" # e.g. "App Server Service Account"
}

# (Optional but typical) grant only the roles actually needed by the VM
resource "google_project_iam_member" "INSTANCE_SERVICE_ACCOUNT_ROLE" {
project = "GCP_PROJECT_ID"
role = "roles/LOGICAL_ROLE_NEEDED" # e.g. "roles/logging.logWriter"
member = "serviceAccount:${google_service_account.INSTANCE_SERVICE_ACCOUNT.email}"
}

# Compute Engine instance explicitly using the non-default service account
resource "google_compute_instance" "VM_INSTANCE" {
name = "VM_INSTANCE_NAME"
machine_type = "MACHINE_TYPE" # e.g. "e2-medium"
zone = "GCP_ZONE" # e.g. "us-central1-a"

boot_disk {
initialize_params {
image = "BOOT_IMAGE" # e.g. "debian-cloud/debian-12"
}
}

network_interface {
network = "NETWORK_NAME" # e.g. "default" or a custom VPC
# subnetwork = "SUBNETWORK_NAME"
}

# Explicitly stop using the default Compute Engine service account
service_account {
email = google_service_account.INSTANCE_SERVICE_ACCOUNT.email
scopes = [
"https://www.googleapis.com/auth/CLOUD_PLATFORM_SCOPE" # or narrower scopes as needed
]
}

# ...other arguments...
}

Changing the service_account on an existing google_compute_instance forces replacement of the VM (destroy and recreate), which may cause downtime; plan accordingly.

To verify, terraform plan should show the google_compute_instance.VM_INSTANCE with a change in the service_account block from the project default service account to google_service_account.INSTANCE_SERVICE_ACCOUNT.email, and the creation of the new google_service_account (and optional IAM binding).