Ensure Shielded Gke Nodes Are Enabled
More Info:
Shielded Gke Nodes Provides Verifiable Integrity Via Secure Boot, Virtual Trusted Platform Module (Vtpm)-Enabled Measured Boot, And Integrity Monitoring.
Risk Level
High
Address
Security
Compliance Standards
- CIS GKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify clusters and check current shielded node status
Run on any machine withgcloudconfigured:PROJECT_ID="<your-project-id>"gcloud container clusters list --project "$PROJECT_ID" \--format="table(name,location,shieldedNodes.enabled)"For any cluster where
shieldedNodes.enabledis nottrue, gather full details:CLUSTER_NAME="<cluster-name>"LOCATION="<cluster-location>"gcloud container clusters describe "$CLUSTER_NAME" --location "$LOCATION" --project "$PROJECT_ID" \--format json | jq '.shieldedNodes' -
Review compatibility and feature requirements
For each non-shielded cluster, confirm:- Node OS image type and version (COS/Container-Optimized OS and most recent Ubuntu images are typically compatible).
- No organization or workload requirement explicitly forbids shielded nodes (for example, custom low-level boot tooling that conflicts with secure boot).
Gather node pool and image info:
gcloud container node-pools list --cluster "$CLUSTER_NAME" --location "$LOCATION" --project "$PROJECT_ID"gcloud container node-pools describe "<node-pool-name>" \--cluster "$CLUSTER_NAME" --location "$LOCATION" --project "$PROJECT_ID" \--format="value(config.imageType)" -
Assess operational impact and maintenance windows
Determine whether enabling shielded nodes will require recreating node pools or performing disruptive upgrades (cordon/drain, pod eviction, possible restarts).
For each cluster, export current workloads and disruption policies:kubectl --context "gke_${PROJECT_ID}_${LOCATION}_${CLUSTER_NAME}" get pods -A \-o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,PRIORITY:.spec.priorityClassName' \--sort-by=.spec.priorityClassNamekubectl --context "gke_${PROJECT_ID}_${LOCATION}_${CLUSTER_NAME}" get pdb -A -
Decide whether to enable Shielded GKE Nodes on each cluster
For every cluster where:- Shielded nodes are currently disabled,
- Node images are compatible, and
- A maintenance window and disruption approach are acceptable,
approve enabling Shielded GKE Nodes.
Document any cluster where you intentionally do not enable it, with a risk justification (e.g., legacy image dependency).
-
Enable Shielded GKE Nodes on approved clusters
For each approved cluster, run on any machine withgcloudconfigured:gcloud container clusters update "$CLUSTER_NAME" \--location "$LOCATION" \--project "$PROJECT_ID" \--enable-shielded-nodesIf the command reports constraints (e.g., incompatible node pools), plan and perform node pool recreation or upgrade per GKE guidance, then rerun the command.
-
Verify remediation and record evidence
After the update completes, verify shielded nodes are enabled:gcloud container clusters describe "$CLUSTER_NAME" --location "$LOCATION" --project "$PROJECT_ID" \--format json | jq '.shieldedNodes'Confirm the output shows:
{"enabled": true}Optionally, re-list all clusters for a summary view:
gcloud container clusters list --project "$PROJECT_ID" \--format="table(name,location,shieldedNodes.enabled)"
Using kubectl
kubectl cannot enable Shielded GKE Nodes because this setting is configured at the GKE cluster control-plane level through Google Cloud (gcloud/console/IaC), not via Kubernetes API objects. Refer to the Manual Steps section for guidance on updating the cluster configuration to enable Shielded Nodes.
Automation
#!/usr/bin/env bash
# Check Shielded GKE Nodes status for all clusters in a project (or all projects)
# REQUIREMENTS:
# - gcloud, jq installed
# - Authenticated to GCP
# - Optional: GOOGLE_CLOUD_PROJECT env var; otherwise all active projects are scanned
set -euo pipefail
PROJECTS=()
if [[ -n "${GOOGLE_CLOUD_PROJECT:-}" ]]; then
PROJECTS+=("${GOOGLE_CLOUD_PROJECT}")
else
# List all active projects you have access to
mapfile -t PROJECTS < <(gcloud projects list --format='value(projectId)')
fi
if [[ ${#PROJECTS[@]} -eq 0 ]]; then
echo "No projects found. Set GOOGLE_CLOUD_PROJECT or ensure you have project access." >&2
exit 1
fi
echo "project,location,cluster_name,shielded_nodes_enabled"
for PROJECT in "${PROJECTS[@]}"; do
# List all GKE clusters in the project across all locations
mapfile -t CLUSTERS < <(
gcloud container clusters list \
--project "${PROJECT}" \
--format='csv[no-heading](name,location)'
) || true
if [[ ${#CLUSTERS[@]} -eq 0 ]]; then
continue
fi
for ENTRY in "${CLUSTERS[@]}"; do
CLUSTER_NAME="$(cut -d',' -f1 <<< "${ENTRY}")"
LOCATION="$(cut -d',' -f2 <<< "${ENTRY}")"
# Describe cluster and extract shieldedNodes configuration
RAW_JSON="$(gcloud container clusters describe "${CLUSTER_NAME}" \
--location "${LOCATION}" \
--project "${PROJECT}" \
--format=json 2>/dev/null || echo '')"
if [[ -z "${RAW_JSON}" ]]; then
echo "${PROJECT},${LOCATION},${CLUSTER_NAME},ERROR-describe-failed"
continue
fi
# shieldedNodes.enabled is true when Shielded GKE Nodes is enabled
ENABLED="$(jq -r '.shieldedNodes.enabled // "false"' <<< "${RAW_JSON}")"
echo "${PROJECT},${LOCATION},${CLUSTER_NAME},${ENABLED}"
done
done
How to run (any machine with gcloud/jq access):
chmod +x check_shielded_gke_nodes.sh
./check_shielded_gke_nodes.sh
How to interpret output:
-
Output is CSV:
project,location,cluster_name,shielded_nodes_enabled -
Compliant clusters: rows where
shielded_nodes_enabledistrue. -
Problematic clusters (need review and likely remediation):
shielded_nodes_enabledisfalse- or
shielded_nodes_enabledis empty / missing - or value starts with
ERROR-(script could not reliably assess the cluster)
For any problematic cluster, review business/technical constraints and, if appropriate, enable Shielded GKE Nodes using:
gcloud container clusters update <cluster_name> \
--location <location> \
--enable-shielded-nodes