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
Remediation
Manual Steps
-
Identify node pools and current integrity monitoring settings
Run on: any machine withgcloudaccessPROJECT_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 -
Determine compliance for each node pool
- Mark a node pool as compliant if:
enabledistrueandintegrityMonitoring(or equivalent flag) istrue, or- The
shieldedInstanceConfigblock clearly shows integrity monitoring enabled.
- Mark a node pool as non-compliant if integrity monitoring is not enabled or the field is absent.
- Mark a node pool as compliant if:
-
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-monitoringAdd any other flags (e.g.
--machine-type,--num-nodes,--enable-autoscaling,--node-taints,--node-labels) to match your current non-compliant pool. -
Migrate workloads from non-compliant to compliant node pools
Run on: any machine withkubectlaccess- 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
- If node pools are distinguished by labels/taints, adjust pod
-
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" -
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.shieldedInstanceConfigConfirm 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):
- Authenticate and set project:
gcloud auth logingcloud config set project YOUR_PROJECT_ID
- 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, orintegrity 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.