> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Ensure Secure Boot For Shielded GKE Nodes Is Enabled

### More Info:

Enable Secure Boot on Shielded GKE nodes so only signed, trusted boot components are permitted to load. This blocks unsigned kernel modules and boot-level malware.

### Risk Level

Medium

### Address

Security

### Compliance Standards

* CIS GKE

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. On any machine with `gcloud` configured, list node pools and identify which are non‑compliant:
           ```bash theme={null}
           gcloud container node-pools list \
             --cluster CLUSTER_NAME \
             --location LOCATION \
             --project PROJECT_ID \
             --format="table(name,config.shieldedInstanceConfig)"
           ```
           Review the `shieldedInstanceConfig` field; node pools where `enableSecureBoot` is missing or `false` need remediation.

        2. For each node pool, gather full Shielded VM details to confirm status:
           ```bash theme={null}
           gcloud container node-pools describe POOL_NAME \
             --cluster CLUSTER_NAME \
             --location LOCATION \
             --project PROJECT_ID \
             --format=json | jq '.config.shieldedInstanceConfig'
           ```
           Document which workloads and namespaces currently run on each non‑compliant pool.

        3. Plan the remediation (per cluster / environment): decide which node pools will be replaced, the desired machine type, size, labels/taints, and maintenance window; validate that enabling Secure Boot is supported for the node image and machine type used in your organization.

        4. Create a new compliant node pool with Secure Boot enabled (repeat per replacement pool):
           ```bash theme={null}
           gcloud container node-pools create NEW_POOL_NAME \
             --cluster CLUSTER_NAME \
             --location LOCATION \
             --project PROJECT_ID \
             --shielded-secure-boot
           ```
           Add any required flags (e.g., `--machine-type`, `--num-nodes`, `--node-labels`, `--node-taints`) to match your existing pool’s configuration.

        5. Migrate workloads from each non‑compliant node pool to its new Secure Boot pool using your standard process (e.g., update node selectors/affinity, taints/tolerations, PodDisruptionBudgets, and scale settings), then drain the old nodes and delete the non‑compliant pool:
           ```bash theme={null}
           gcloud container node-pools delete OLD_POOL_NAME \
             --cluster CLUSTER_NAME \
             --location LOCATION \
             --project PROJECT_ID
           ```

        6. Verify remediation for all pools:
           ```bash theme={null}
           gcloud container node-pools list \
             --cluster CLUSTER_NAME \
             --location LOCATION \
             --project PROJECT_ID \
             --format="table(name,config.shieldedInstanceConfig)"
           ```
           Confirm every active node pool shows Secure Boot enabled in `shieldedInstanceConfig`.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot enable Secure Boot for Shielded GKE nodes, because this setting is only configurable on the node pool via GCP (Cloud Console, `gcloud`, or IaC such as Terraform). Use those cloud-provider tools instead and follow the guidance in the Manual Steps section to recreate node pools with `--shielded-secure-boot` and migrate workloads.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Report Secure Boot status for all node pools in all GKE clusters in a project.
        # REQUIREMENTS:
        #   - gcloud SDK installed and authenticated
        #   - jq installed
        # USAGE:
        #   PROJECT_ID=your-project-id ./check-gke-secure-boot.sh

        set -euo pipefail

        PROJECT_ID="${PROJECT_ID:-}"
        if [[ -z "$PROJECT_ID" ]]; then
          echo "ERROR: PROJECT_ID environment variable must be set." >&2
          exit 1
        fi

        echo "Checking Secure Boot status for all GKE node pools in project: $PROJECT_ID"
        echo

        # List all clusters (zonal and regional)
        clusters_json="$(gcloud container clusters list \
          --project "$PROJECT_ID" \
          --format=json)"

        if [[ "$clusters_json" == "[]" ]]; then
          echo "No GKE clusters found in project $PROJECT_ID"
          exit 0
        fi

        # Header
        printf "%-40s %-20s %-25s %-25s %-15s\n" \
          "CLUSTER" "LOCATION" "NODE_POOL" "SHIELDED_SECURE_BOOT" "ISSUE"
        printf "%0.s-" {1..130}; echo

        # Iterate over clusters and their node pools
        echo "$clusters_json" | jq -r '.[] | @base64' | while read -r cluster_b64; do
          _jq() { echo "$cluster_b64" | base64 --decode | jq -r "$1"; }

          CLUSTER_NAME=$(_jq '.name')
          LOCATION=$(_jq '.location')

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

          if [[ "$node_pools_json" == "[]" ]]; then
            printf "%-40s %-20s %-25s %-25s %-15s\n" \
              "$CLUSTER_NAME" "$LOCATION" "-" "-" "NO_NODE_POOLS"
            continue
          fi

          echo "$node_pools_json" | jq -r '.[] | @base64' | while read -r np_b64; do
            _npjq() { echo "$np_b64" | base64 --decode | jq -r "$1"; }

            NODE_POOL_NAME=$(_npjq '.name')

            # Describe node pool to get shieldedInstanceConfig
            np_desc="$(gcloud container node-pools describe "$NODE_POOL_NAME" \
              --cluster "$CLUSTER_NAME" \
              --location "$LOCATION" \
              --project "$PROJECT_ID" \
              --format=json)"

            # secureBoot is a boolean; may be null/absent
            SECURE_BOOT_VAL="$(echo "$np_desc" \
              | jq -r '.config.shieldedInstanceConfig.secureBoot // "false"')"

            ISSUE="OK"
            if [[ "$SECURE_BOOT_VAL" != "true" ]]; then
              ISSUE="MISSING_SECURE_BOOT"
            fi

            printf "%-40s %-20s %-25s %-25s %-15s\n" \
              "$CLUSTER_NAME" "$LOCATION" "$NODE_POOL_NAME" "$SECURE_BOOT_VAL" "$ISSUE"
          done
        done

        cat <<'EOF'

        INTERPRETING RESULTS
        --------------------
        - SHIELDED_SECURE_BOOT == "true" and ISSUE == "OK":
            The node pool is configured with Secure Boot enabled and conforms to CIS GKE 5.5.7.

        - SHIELDED_SECURE_BOOT == "false" (or blank/null) and ISSUE == "MISSING_SECURE_BOOT":
            This node pool does NOT have Secure Boot enabled. It should be reviewed.
            To remediate, create a new node pool with:
              gcloud container node-pools create <node_pool_name> \
                --cluster <cluster_name> \
                --location <location> \
                --shielded-secure-boot
            Then migrate workloads and delete the non-conforming node pool.

        NOTE: This script only reports state; it does NOT change any configuration.
        EOF
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
