Skip to main content

VM Instances Should Not Use Default Service Accounts With

More Info:

Instances should not be configured to use the default service account with full access to all cloud APIs. The principle of least privilege should be used to prevent potential privilege escalation.

Risk Level

High

Address

Security

Compliance Standards

  • CIS GCP
  • CIS GCP 2.0.0
  • Cloudanix Best Practice

Triage and Remediation

Remediation

Using Console

To remediate the misconfiguration "VM Instances Should Not Use Default Service Accounts With Full Access To Cloud APIs" for GCP using GCP console, follow these steps:

  1. Go to the Google Cloud Console and select the project that contains the VM instances with default service accounts.

  2. Click on the "Compute Engine" option from the left-hand side menu.

  3. From the Compute Engine menu, select the "VM instances" option.

  4. Select the VM instance that is using the default service account with full access to Cloud APIs.

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

  6. Scroll down to the "Service account" section and click on the "Change" button.

  7. Select "Create a new service account" from the dropdown menu.

  8. Give the new service account a name and description.

  9. Under "Role", select the appropriate role for the service account based on the permissions required for the VM instance.

  10. Click on the "Save" button to create the new service account.

  11. Once the new service account is created, select it from the "Service account" dropdown menu.

  12. Click on the "Save" button to apply the changes.

  13. Repeat these steps for all VM instances that are using the default service account with full access to Cloud APIs.

By following these steps, you will remediate the misconfiguration "VM Instances Should Not Use Default Service Accounts With Full Access To Cloud APIs" for GCP using GCP console.

Using CLI

To remediate the misconfiguration "VM Instances Should Not Use Default Service Accounts With Full Access To Cloud APIs" for GCP using GCP CLI, please follow the steps below:

  1. List all the VM instances in your GCP project using the following command:
gcloud compute instances list
  1. For each VM instance that is using the default service account, create a new service account with limited access using the following command:
gcloud iam service-accounts create [SA-NAME] --description="[SA-DESCRIPTION]"

Replace [SA-NAME] with the name of your new service account and [SA-DESCRIPTION] with a brief description of the account.

  1. Grant the new service account the minimum required permissions using the following command:
gcloud projects add-iam-policy-binding [PROJECT-ID] --member="serviceAccount:[SA-EMAIL]" --role="[ROLE]"

Replace [PROJECT-ID] with your GCP project ID, [SA-EMAIL] with the email address of your new service account, and [ROLE] with the minimum required role for your VM instance.

  1. Update your VM instance to use the new service account using the following command:
gcloud compute instances set-service-account [INSTANCE-NAME] --service-account=[SA-EMAIL]

Replace [INSTANCE-NAME] with the name of your VM instance and [SA-EMAIL] with the email address of your new service account.

  1. Verify that your VM instance is now using the new service account by running the following command:
gcloud compute instances describe [INSTANCE-NAME] --format="get(serviceAccounts.email)"

Replace [INSTANCE-NAME] with the name of your VM instance.

Repeat steps 2-5 for each VM instance that is using the default service account. This will ensure that your VM instances are not using the default service account with full access to Cloud APIs.

Using Python

To remediate the misconfiguration "VM Instances Should Not Use Default Service Accounts With Full Access To Cloud APIs" for GCP using Python, follow the below steps:

  1. First, identify the VM instances that are using the default service accounts with full access to Cloud APIs. You can use the following command to get the list of VM instances:
from google.cloud import compute_v1

compute_client = compute_v1.InstancesClient()
project = "your-project-id"

instances = compute_client.list(project=project)
for instance in instances:
for access_config in instance.service_accounts:
if access_config.email.endswith('gserviceaccount.com') and 'Editor' in access_config.scopes:
print(f"Instance {instance.name} is using the default service account with full access to Cloud APIs.")
  1. Once you have identified the VM instances, create a new service account with the necessary permissions and grant it to the instances. You can use the following code to create a new service account:
from google.cloud import iam_v1

iam_client = iam_v1.IAMClient()
project_id = "your-project-id"
service_account_name = "your-service-account-name"
display_name = "your-display-name"

parent = f"projects/{project_id}"
service_account = iam_client.create_service_account(
request={
"name": f"{parent}/serviceAccounts/{service_account_name}",
"accountId": service_account_name,
"service_account": {
"display_name": display_name
}
}
)

print(f"Created service account with name: {service_account.name}")
  1. After creating the new service account, grant it the necessary permissions. You can use the following code to grant the necessary roles to the service account:
from google.cloud import iam_v1

iam_client = iam_v1.IAMClient()
project_id = "your-project-id"
service_account_email = "your-service-account-email"
roles = ["roles/logging.logWriter", "roles/monitoring.metricWriter"]

policy = iam_client.get_policy(request={"resource": f"projects/{project_id}"})
bindings = policy.bindings

for role in roles:
binding = next((b for b in bindings if b.role == role), None)
if binding is None:
binding = policy.bindings.add(role=role)
binding.members.append(f"serviceAccount:{service_account_email}")

iam_client.set_iam_policy(request={"resource": f"projects/{project_id}", "policy": policy})
print(f"Granted roles to service account {service_account_email}")
  1. Finally, update the VM instances to use the newly created service account. You can use the following code to update the VM instances:
from google.cloud import compute_v1

compute_client = compute_v1.InstancesClient()
project = "your-project-id"
zone = "your-zone"
instance_name = "your-instance-name"
service_account_email = "your-service-account-email"

instance = compute_client.get(project=project, zone=zone, instance=instance_name)
instance.service_accounts = [
{
"email": service_account_email,
"scopes": ["https://www.googleapis.com/auth/cloud-platform"]
}
]
update_mask = ["service_accounts"]

operation = compute_client.update(project=project, zone=zone, instance=instance_name, instance_resource=instance, update_mask=update_mask)
print(f"Updated instance {instance_name} with new service account.")

By following the above steps, you can remediate the misconfiguration "VM Instances Should Not Use Default Service Accounts With Full Access To Cloud APIs" for GCP using Python.

Using Terraform
# Least-privilege service account for the instance
resource "google_service_account" "app_sa" {
account_id = "APP_SA_ID" # TODO: replace with a unique ID, e.g. "web-server-sa"
display_name = "APP_SA_NAME" # TODO: replace with a human-friendly name
}

# Example IAM binding giving this SA only the roles it needs
resource "google_project_iam_member" "app_sa_role" {
project = "PROJECT_ID" # TODO: replace with your project ID
role = "roles/COMPUTE_ENGINE_ROLE" # TODO: replace with the minimum required role
member = "serviceAccount:${google_service_account.app_sa.email}"
}

# Compute Engine instance NOT using default SA with full API access
resource "google_compute_instance" "vm" {
name = "INSTANCE_NAME" # TODO: replace
machine_type = "MACHINE_TYPE" # TODO: e.g. "e2-medium"
zone = "ZONE" # TODO: e.g. "us-central1-a"

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

network_interface {
network = "NETWORK_NAME" # TODO: replace or use self_link
subnetwork = "SUBNETWORK_NAME" # TODO: replace or omit if using default
# access_config {} # Uncomment if you need an external IP
}

# Use a dedicated service account and avoid full "cloud-platform" scope
service_account {
email = google_service_account.app_sa.email
scopes = [
"https://www.googleapis.com/auth/LOGGING_SCOPE", # TODO: replace with specific scopes needed
"https://www.googleapis.com/auth/MONITORING_SCOPE"
# Do NOT use "https://www.googleapis.com/auth/cloud-platform"
]
}

# Other required arguments...
}

Changing an existing instance from the default service account with full access to a new least‑privilege service account will force replacement of the google_compute_instance (stop/delete and recreate), which is an outage for that VM.

After the change, terraform plan should show:

  • a new google_service_account (and any IAM bindings) to be created, and
  • the google_compute_instance to be replaced with the new service_account configuration and without the full cloud-platform scope.

Additional Reading: