Ensure GKE Clusters Are Not Using Default Service Account
More Info:
Create and use minimally privileged Service accounts to run GKE cluster nodes instead of using the Compute Engine default Service account. Unnecessary permissions could be abused in the case of a node compromise.
Risk Level
Critical
Address
Best Practice, Operational Excellence, Security
Compliance Standards
- HITRUST CSF
- NIST CSF
- PCI
- SOC2
Triage and Remediation
- Remediation
Remediation
Using Console
To remediate the misconfiguration "Ensure GKE Clusters Are Not Using Default Service Account" in GCP using GCP console, please follow the below steps:
Step 1: Login to GCP console (https://console.cloud.google.com/).
Step 2: Navigate to Kubernetes Engine and select the cluster that is using the default service account.
Step 3: Click on the "Edit" button at the top of the page.
Step 4: Scroll down to the "Node Pools" section and click on the "default-pool" node pool.
Step 5: Under the "Node pool details" section, click on the "Edit" button.
Step 6: Scroll down to the "Security" section and expand it.
Step 7: Under the "Service account" section, select "Create a new service account".
Step 8: In the "Service account name" field, enter a name for the new service account.
Step 9: In the "Service account ID" field, enter a unique ID for the new service account.
Step 10: Click on the "Save" button to save the changes.
Step 11: Repeat the above steps for all the node pools that are using the default service account.
Step 12: Once all the node pools have been updated, click on the "Save" button at the bottom of the page to save the changes to the cluster.
By following these steps, the misconfiguration "Ensure GKE Clusters Are Not Using Default Service Account" will be remediated for GCP using GCP console.
Using CLI
To remediate the misconfiguration "Ensure GKE Clusters Are Not Using Default Service Account" for GCP using GCP CLI, follow the below steps:
-
Open the Cloud Shell from the GCP console.
-
Run the following command to list all the GKE clusters in your project:
gcloud container clusters list -
Identify the GKE cluster that is using the default service account.
-
Run the following command to get the details of the GKE cluster:
gcloud container clusters describe [CLUSTER_NAME]Replace [CLUSTER_NAME] with the name of the GKE cluster that you identified in step 3.
-
Check the output for the field
serviceAccountundernodePools. If the value isdefault, then the GKE cluster is using the default service account. -
To remediate this misconfiguration, you need to create a new service account and then assign it to the GKE cluster. Run the following command to create a new service account:
gcloud iam service-accounts create [SA-NAME] --display-name [SA-DISPLAY-NAME]Replace [SA-NAME] with the name of the new service account and [SA-DISPLAY-NAME] with a display name for the service account.
-
Run the following command to assign the new service account to the GKE cluster:
gcloud container clusters update [CLUSTER_NAME] --zone [ZONE] --service-account [SA-EMAIL]Replace [CLUSTER_NAME] with the name of the GKE cluster, [ZONE] with the zone in which the cluster is located, and [SA-EMAIL] with the email address of the new service account.
-
Verify that the new service account is assigned to the GKE cluster by running the command in step 4 again and checking the value of the
serviceAccountfield.
By following these steps, you can remediate the misconfiguration "Ensure GKE Clusters Are Not Using Default Service Account" for GCP using GCP CLI.
Using Python
To remediate the misconfiguration "Ensure GKE Clusters Are Not Using Default Service Account" in GCP, you can follow these steps using Python:
-
Install the necessary Python packages:
google-authandgoogle-api-python-client. -
Authenticate with the GCP API using a service account that has the necessary permissions to manage GKE clusters. You can create a service account and download its credentials in JSON format from the GCP console.
from google.oauth2 import service_account
from googleapiclient.discovery import build
credentials = service_account.Credentials.from_service_account_file(
'path/to/credentials.json',
scopes=['https://www.googleapis.com/auth/cloud-platform']
)
gke_service = build('container', 'v1', credentials=credentials)
- List all GKE clusters in the project and check if any of them are using the default service account.
project_id = 'my-project-id'
clusters = gke_service.projects().locations().clusters().list(parent=f"projects/{project_id}/locations/-").execute()
for cluster in clusters.get('clusters', []):
if cluster.get('nodeConfig', {}).get('serviceAccount', '') == 'default':
# The cluster is using the default service account
# Remediation steps go here
- To remediate the misconfiguration, you can create a new service account and assign it to the GKE cluster.
from googleapiclient.errors import HttpError
new_service_account = 'my-new-service-account@my-project-id.iam.gserviceaccount.com'
cluster_name = 'my-cluster'
zone = 'us-central1-c'
try:
gke_service.projects().zones().clusters().update(
name=f"projects/{project_id}/locations/{zone}/clusters/{cluster_name}",
body={
'nodeConfig': {
'serviceAccount': new_service_account
}
}
).execute()
print(f"Updated service account for cluster {cluster_name}")
except HttpError as error:
print(f"Error updating service account for cluster {cluster_name}: {error}")
Note: You will need to have the necessary IAM permissions to create and assign service accounts to GKE clusters.
Using Terraform
# Least-privilege service account for GKE nodes
resource "google_service_account" "gke_nodes" {
account_id = "GKE_NODES_SA_ID" # Replace with a short ID, e.g. "gke-nodes"
display_name = "GKE Nodes Service Account for CLUSTER_NAME" # Replace CLUSTER_NAME
}
# Optionally bind only the roles the nodes really need (example: pull from Container Registry)
resource "google_project_iam_member" "gke_nodes_artifact_reader" {
project = "GCP_PROJECT_ID" # Replace with your project ID
role = "roles/artifactregistry.reader"
member = "serviceAccount:${google_service_account.gke_nodes.email}"
}
# GKE cluster using the custom node service account instead of the default
resource "google_container_cluster" "primary" {
name = "CLUSTER_NAME" # Replace with your cluster name
location = "GCP_REGION_OR_ZONE" # Replace with region/zone, e.g. "us-central1"
remove_default_node_pool = true
initial_node_count = 1
# Other cluster settings...
}
# Managed node pool with the non-default service account
resource "google_container_node_pool" "primary_nodes" {
name = "PRIMARY_NODE_POOL_NAME" # Replace with node pool name
cluster = google_container_cluster.primary.name
location = google_container_cluster.primary.location
node_count = 3
node_config {
service_account = google_service_account.gke_nodes.email
# Other node settings as needed, e.g.:
machine_type = "e2-medium"
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform",
]
}
}
Changing a node pool’s service_account forces recreation of that node pool (nodes are drained and replaced; plan will show -/+ for the node pool), so coordinate this to avoid disruption-sensitive workloads.
Verification with terraform plan should show that the current node pool (or node_config on an inline default pool) will be replaced or updated so that service_account changes from the Compute Engine default to google_service_account.gke_nodes.email, with no remaining reference to the default Compute Engine service account.