Skip to main content

Integrity Monitoring For Shielded GKE Nodes Is Enabled

More Info:

Enable integrity monitoring on Shielded GKE nodes so their boot integrity is continuously verified against a trusted baseline. This detects rootkits and boot-level tampering.

Risk Level

Medium

Address

Security

Compliance Standards

  • CIS GKE

Triage and Remediation

Remediation

Manual Steps
  1. Identify node pools and current integrity monitoring settings
    Run on: any machine with gcloud access

    PROJECT_ID="<PROJECT_ID>"
    CLUSTER_NAME="<CLUSTER_NAME>"
    LOCATION="<REGION_OR_ZONE>"

    gcloud container node-pools list \
    --cluster "$CLUSTER_NAME" \
    --location "$LOCATION" \
    --project "$PROJECT_ID"

    For each node pool name returned:

    POOL_NAME="<POOL_NAME>"

    gcloud container node-pools describe "$POOL_NAME" \
    --cluster "$CLUSTER_NAME" \
    --location "$LOCATION" \
    --project "$PROJECT_ID" \
    --format json | jq .config.shieldedInstanceConfig
  2. Determine compliance for each node pool

    • Mark a node pool as compliant if:
      • enabled is true and integrityMonitoring (or equivalent flag) is true, or
      • The shieldedInstanceConfig block clearly shows integrity monitoring enabled.
    • Mark a node pool as non-compliant if integrity monitoring is not enabled or the field is absent.
  3. Plan new compliant node pools for non-compliant workloads
    For each non-compliant node pool, decide:

    • Desired machine type, disk size/type, labels, taints, autoscaling, and node count.
    • A new node pool name that indicates shielded + integrity monitoring (for traceability).
      Then create the new node pool with integrity monitoring enabled:
    NEW_POOL_NAME="<NEW_SHIELDED_POOL_NAME>"

    gcloud container node-pools create "$NEW_POOL_NAME" \
    --cluster "$CLUSTER_NAME" \
    --location "$LOCATION" \
    --project "$PROJECT_ID" \
    --shielded-integrity-monitoring

    Add any other flags (e.g. --machine-type, --num-nodes, --enable-autoscaling, --node-taints, --node-labels) to match your current non-compliant pool.

  4. Migrate workloads from non-compliant to compliant node pools
    Run on: any machine with kubectl access

    • If node pools are distinguished by labels/taints, adjust pod nodeSelector, affinity, or tolerations so workloads can schedule on the new pool.
    • Cordon and drain each non-compliant node pool’s nodes one at a time:
      kubectl get nodes -o wide
      # For each node belonging to a non-compliant pool:
      NODE_NAME="<NODE_NAME>"

      kubectl cordon "$NODE_NAME"
      kubectl drain "$NODE_NAME" --ignore-daemonsets --delete-emptydir-data
    • Verify pods reschedule onto the new, compliant node pool:
      kubectl get pods -A -o wide
  5. Delete non-compliant node pools after successful migration
    Once you confirm workloads are healthy on the new node pool(s):

    POOL_NAME="<NON_COMPLIANT_POOL_NAME>"

    gcloud container node-pools delete "$POOL_NAME" \
    --cluster "$CLUSTER_NAME" \
    --location "$LOCATION" \
    --project "$PROJECT_ID"
  6. Verify remediation
    Re-run the audit for each remaining node pool:

    gcloud container node-pools list \
    --cluster "$CLUSTER_NAME" \
    --location "$LOCATION" \
    --project "$PROJECT_ID"

    # For each listed pool:
    POOL_NAME="<POOL_NAME>"

    gcloud container node-pools describe "$POOL_NAME" \
    --cluster "$CLUSTER_NAME" \
    --location "$LOCATION" \
    --project "$PROJECT_ID" \
    --format json | jq .config.shieldedInstanceConfig

    Confirm all node pools in use show integrity monitoring enabled.

Using kubectl

kubectl cannot enable Shielded GKE node integrity monitoring because this setting is defined on the managed node pool in GKE (cloud provider control plane / IaC), not on Kubernetes API objects. Use the cloud console, gcloud, or your IaC pipeline to configure integrity monitoring as described in the Manual Steps section.

Automation
#!/usr/bin/env bash
#
# Report Shielded GKE node pool integrity monitoring status for all clusters
# in a given project. Requires:
# - gcloud CLI authenticated and configured
# - jq installed
#
# Usage:
# PROJECT_ID="my-project" LOCATION="us-central1" ./check_shielded_integrity.sh
#
# LOCATION can be:
# - a specific region/zone (e.g. "us-central1", "us-central1-a"), or
# - "-" to search all locations in the project.

set -euo pipefail

PROJECT_ID="${PROJECT_ID:-}"
LOCATION="${LOCATION:-"-"}"

if [[ -z "$PROJECT_ID" ]]; then
echo "ERROR: Set PROJECT_ID environment variable." >&2
exit 1
fi

echo "Checking Shielded GKE node pool integrity monitoring in project: $PROJECT_ID (location: $LOCATION)"
echo

# List all clusters in the project/location
clusters_json="$(gcloud container clusters list \
--project "$PROJECT_ID" \
--location "$LOCATION" \
--format json)"

if [[ "$(echo "$clusters_json" | jq 'length')" -eq 0 ]]; then
echo "No GKE clusters found."
exit 0
fi

echo "$clusters_json" | jq -r '.[] | @tsv "\(.name)\t\(.location)"' | \
while IFS=$'\t' read -r CLUSTER_NAME CLUSTER_LOCATION; do
echo "Cluster: $CLUSTER_NAME (location: $CLUSTER_LOCATION)"

node_pools_json="$(gcloud container node-pools list \
--cluster "$CLUSTER_NAME" \
--location "$CLUSTER_LOCATION" \
--project "$PROJECT_ID" \
--format json)"

if [[ "$(echo "$node_pools_json" | jq 'length')" -eq 0 ]]; then
echo " (no node pools)"
echo
continue
fi

echo "$node_pools_json" | jq -r '.[] | @tsv "\(.name)\t\(.config.shieldedInstanceConfig.enableIntegrityMonitoring)"' | \
while IFS=$'\t' read -r POOL_NAME INTEGRITY; do
# INTEGRITY may be "true", "false", or "null" (if not set)
case "$INTEGRITY" in
true)
echo " Node pool: $POOL_NAME -> integrity monitoring: ENABLED"
;;
false|null|"")
echo " Node pool: $POOL_NAME -> integrity monitoring: DISABLED <-- REVIEW / NON-COMPLIANT"
;;
*)
echo " Node pool: $POOL_NAME -> integrity monitoring: UNKNOWN ($INTEGRITY) <-- REVIEW"
;;
esac
done

echo
done

How to run (any machine with gcloud and kubectl access):

  1. Authenticate and set project:
    gcloud auth login
    gcloud config set project YOUR_PROJECT_ID
  2. Run the script:
    PROJECT_ID="YOUR_PROJECT_ID" LOCATION="-" ./check_shielded_integrity.sh

What output indicates a problem

Any node pool line showing:

  • integrity monitoring: DISABLED <-- REVIEW / NON-COMPLIANT, or
  • integrity monitoring: UNKNOWN (...) <-- REVIEW

indicates a node pool where Shielded GKE node integrity monitoring is not confirmed as enabled and must be reviewed and, if appropriate, remediated manually by creating a compliant node pool and migrating workloads.