Skip to main content

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

Manual Steps
  1. Identify clusters and check current shielded node status
    Run on any machine with gcloud configured:

    PROJECT_ID="<your-project-id>"
    gcloud container clusters list --project "$PROJECT_ID" \
    --format="table(name,location,shieldedNodes.enabled)"

    For any cluster where shieldedNodes.enabled is not true, 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'
  2. 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)"
  3. 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.priorityClassName
    kubectl --context "gke_${PROJECT_ID}_${LOCATION}_${CLUSTER_NAME}" get pdb -A
  4. 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).
  5. Enable Shielded GKE Nodes on approved clusters
    For each approved cluster, run on any machine with gcloud configured:

    gcloud container clusters update "$CLUSTER_NAME" \
    --location "$LOCATION" \
    --project "$PROJECT_ID" \
    --enable-shielded-nodes

    If the command reports constraints (e.g., incompatible node pools), plan and perform node pool recreation or upgrade per GKE guidance, then rerun the command.

  6. 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_enabled is true.

  • Problematic clusters (need review and likely remediation):

    • shielded_nodes_enabled is false
    • or shielded_nodes_enabled is 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

Additional Reading: