> ## 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 Control Plane Authorized Networks Is Enabled

### More Info:

Enable Control Plane (master) Authorized Networks to restrict which external CIDR ranges can reach the cluster control plane over HTTPS. Without it, the control plane endpoint is reachable from broader networks.

### Risk Level

Critical

### Address

Security

### Compliance Standards

* CIS GKE

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. **Identify which clusters to review**\
           On any machine with `gcloud` access, list clusters and pick the ones in scope:
           ```bash theme={null}
           gcloud container clusters list --project <PROJECT_ID>
           ```

        2. **Gather current Control Plane Authorized Networks configuration**\
           For each cluster, run:
           ```bash theme={null}
           gcloud container clusters describe <CLUSTER_NAME> \
             --location <LOCATION> \
             --project <PROJECT_ID> \
             --format json | jq '.masterAuthorizedNetworksConfig'
           ```
           Save the output for evidence (e.g., copy to your ticket or security review document).

        3. **Decide required authorized CIDR ranges**\
           With your networking/security team, determine the minimal external CIDR ranges that need control plane access (e.g., corporate VPN egress, bastion hosts, specific admin offices). Explicitly decide whether public access is needed at all for this cluster.

        4. **Enable Master Authorized Networks and set CIDRs (or adjust them)**\
           Once the required CIDRs are agreed, enable and configure them:
           ```bash theme={null}
           gcloud container clusters update <CLUSTER_NAME> \
             --location <LOCATION> \
             --project <PROJECT_ID> \
             --enable-master-authorized-networks \
             --master-authorized-networks \
               198.51.100.0/24,203.0.113.10/32
           ```
           Replace the example CIDRs with your approved list (up to 20 CIDRs). Be aware this immediately restricts API access to those ranges.

        5. **Re-verify configuration after the change**\
           Confirm that the setting is enabled and that the CIDRs match your decision:
           ```bash theme={null}
           gcloud container clusters describe <CLUSTER_NAME> \
             --location <LOCATION> \
             --project <PROJECT_ID> \
             --format json | jq '.masterAuthorizedNetworksConfig'
           ```
           Ensure `enabled` is `true` and `cidrBlocks` contains only the intended networks.

        6. **Validate operational access and document**
           * From an IP inside an authorized CIDR, confirm you can still run:
             ```bash theme={null}
             kubectl get nodes
             ```
           * From an IP outside all authorized CIDRs, confirm API access is blocked.
           * Record the chosen CIDRs, rationale, and the verification output as part of your security documentation.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot configure Control Plane Authorized Networks because this setting is managed at the GKE control-plane / cloud provider level, not via Kubernetes API objects. To remediate this finding, follow the guidance in the Manual Steps section and make the change using `gcloud`, the GCP console, or your IaC tooling.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Report GKE Control Plane Authorized Networks configuration
        # for all clusters in one or more projects.
        #
        # Requirements:
        #   - gcloud CLI authenticated and configured
        #   - jq installed
        #
        # Usage examples:
        #   ./report-master-authorized-networks.sh            # uses current gcloud project
        #   GCP_PROJECTS="proj-a proj-b" ./report-master-authorized-networks.sh

        set -euo pipefail

        # Space-separated list of projects. If not set, use current gcloud project.
        GCP_PROJECTS="${GCP_PROJECTS:-}"

        if [[ -z "${GCP_PROJECTS}" ]]; then
          CURRENT_PROJECT="$(gcloud config get-value project 2>/dev/null || true)"
          if [[ -z "${CURRENT_PROJECT}" ]]; then
            echo "ERROR: No project set. Either:"
            echo "  - run: gcloud config set project <PROJECT_ID>"
            echo "  - or set GCP_PROJECTS=\"proj-a proj-b\" before running this script."
            exit 1
          fi
          GCP_PROJECTS="${CURRENT_PROJECT}"
        fi

        echo "Reporting Control Plane Authorized Networks state"
        echo "Projects: ${GCP_PROJECTS}"
        echo "Timestamp: $(date -Iseconds)"
        echo

        for PROJECT in ${GCP_PROJECTS}; do
          echo "==== Project: ${PROJECT} ===="

          # List all clusters (both zonal and regional) in the project.
          # We use --format to get a simple JSON array for easier parsing.
          CLUSTERS_JSON="$(gcloud container clusters list \
            --project "${PROJECT}" \
            --format='json(name,location,endpoint)' 2>/dev/null || true)"

          if [[ -z "${CLUSTERS_JSON}" || "${CLUSTERS_JSON}" == "[]" ]]; then
            echo "  No GKE clusters found."
            echo
            continue
          fi

          echo "${CLUSTERS_JSON}" | jq -c '.[]' | while read -r CLUSTER; do
            NAME="$(echo "${CLUSTER}"     | jq -r '.name')"
            LOCATION="$(echo "${CLUSTER}" | jq -r '.location')"
            ENDPOINT="$(echo "${CLUSTER}" | jq -r '.endpoint')"

            # Describe cluster to get masterAuthorizedNetworksConfig
            DESC_JSON="$(gcloud container clusters describe "${NAME}" \
              --location "${LOCATION}" \
              --project "${PROJECT}" \
              --format=json 2>/dev/null || true)"

            if [[ -z "${DESC_JSON}" ]]; then
              echo "  [ERROR] Failed to describe cluster ${NAME} (${LOCATION})"
              continue
            fi

            MAN_CFG="$(echo "${DESC_JSON}" | jq '.masterAuthorizedNetworksConfig')"

            # Determine basic status:
            # - If null or {}: feature disabled => NON-COMPLIANT
            # - If enabled == false or missing: treat as disabled => NON-COMPLIANT
            # - If enabled == true but no cidrBlocks or an empty list: MISCONFIGURED
            # - If enabled == true with non-empty cidrBlocks: configured (needs review)
            ENABLED_RAW="$(echo "${DESC_JSON}" | jq '.masterAuthorizedNetworksConfig.enabled // false')"
            CIDR_COUNT="$(echo "${DESC_JSON}" \
              | jq '.masterAuthorizedNetworksConfig.cidrBlocks // [] | length')"

            STATUS="UNKNOWN"
            REASON=""

            if [[ "${MAN_CFG}" == "null" || "${MAN_CFG}" == "{}" ]]; then
              STATUS="NON-COMPLIANT"
              REASON="masterAuthorizedNetworksConfig is not set (feature disabled)."
            elif [[ "${ENABLED_RAW}" != "true" ]]; then
              STATUS="NON-COMPLIANT"
              REASON="masterAuthorizedNetworksConfig.enabled is false or missing (feature disabled)."
            elif [[ "${CIDR_COUNT}" -eq 0 ]]; then
              STATUS="MISCONFIGURED"
              REASON="Feature enabled but no cidrBlocks configured; review endpoint exposure."
            else
              STATUS="CONFIGURED"
              REASON="Feature enabled with ${CIDR_COUNT} configured CIDR block(s); review for least privilege."
            fi

            echo "  Cluster: ${NAME}"
            echo "    Location: ${LOCATION}"
            echo "    Endpoint: ${ENDPOINT}"
            echo "    Status:   ${STATUS}"
            echo "    Detail:   ${REASON}"
            echo "    masterAuthorizedNetworksConfig:"
            echo "${MAN_CFG}" | jq '."enabled", ."cidrBlocks"' | sed 's/^/      /'
            echo
          done

          echo
        done
        ```

        **How to interpret the output**

        * `Status: NON-COMPLIANT`
          * Indicates Control Plane Authorized Networks is effectively **disabled** for that cluster.
          * This matches the finding: the control plane endpoint is reachable from broader networks and does **not** meet CIS GKE 5.6.3.

        * `Status: MISCONFIGURED`
          * Indicates `enabled` is true but no `cidrBlocks` are set; review this cluster carefully, as the control plane may still be broadly reachable.

        * `Status: CONFIGURED`
          * Indicates the feature is enabled with one or more CIDR blocks; you must manually review those CIDRs to ensure they are tightly scoped to trusted admin networks only, per your security policy.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
