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

### More Info:

Enable Master Authorized Networks To Restrict Access To The ClusterS Control Plane (Master Endpoint) To Only An Allowlist (Whitelist) Of Authorized Ips

### 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. **Gather current configuration (on any machine with gcloud access)**
           ```bash theme={null}
           gcloud container clusters describe CLUSTER_NAME \
             --zone CLUSTER_ZONE \
             --format=json | jq '.masterAuthorizedNetworksConfig'
           ```
           * If this returns `{}` or `null`, Master Authorized Networks (MAN) is effectively disabled.
           * If `"enabled": true` is present, review the `cidrBlocks` to ensure they match your intended allowlist.

        2. **Inventory legitimate control‑plane access sources (off-cluster / documentation review)**
           * Collect the public IPs or CIDR ranges for:
             * Corporate offices / VPN egress gateways.
             * CI/CD systems that run `kubectl` or use Kubernetes APIs.
             * Bastion/jump hosts used by administrators.
           * Decide whether direct access from arbitrary developer laptops or the public internet is required; in most cases it should not be.

        3. **Decide on the desired allowlist and approve with stakeholders**
           * Define explicit IPv4 CIDR ranges (e.g. `203.0.113.10/32`, `198.51.100.0/24`) that should have API access.
           * Remove any broad ranges such as `0.0.0.0/0` or consumer ISP ranges unless there is a strong, documented justification and compensating controls (e.g. strong VPN, short-lived clusters).
           * Ensure there is at least one path (VPN, bastion, or CI/CD) that operations can use for break‑glass access if needed.

        4. **Configure Master Authorized Networks (change via gcloud; IaC users mirror in Terraform/other)**
           * If MAN is currently disabled or misconfigured, enable/update it (run on any machine with gcloud access):
             ```bash theme={null}
             gcloud container clusters update CLUSTER_NAME \
               --zone CLUSTER_ZONE \
               --enable-master-authorized-networks \
               --master-authorized-networks <CIDR_1>,<CIDR_2>,<CIDR_3>
             ```
           * Replace `<CIDR_1>,<CIDR_2>,<CIDR_3>` with the approved list, e.g.:
             ```bash theme={null}
             gcloud container clusters update CLUSTER_NAME \
               --zone CLUSTER_ZONE \
               --enable-master-authorized-networks \
               --master-authorized-networks 203.0.113.10/32,198.51.100.0/24
             ```
           * If using Terraform or another IaC tool, make equivalent changes there (for Terraform `google_container_cluster`, set `master_authorized_networks_config` with the same CIDRs) and apply, ensuring it matches the gcloud change to avoid drift.

        5. **Verify configuration and effective access (on any machine with gcloud and from test clients)**
           * Re-check the cluster configuration:
             ```bash theme={null}
             gcloud container clusters describe CLUSTER_NAME \
               --zone CLUSTER_ZONE \
               --format=json | jq '.masterAuthorizedNetworksConfig'
             ```
             Confirm:
             * `"enabled": true`
             * The `cidrBlocks` list matches the approved IP ranges.
           * From a machine whose IP is *not* in the allowlist, attempt:
             ```bash theme={null}
             kubectl get ns
             ```
             It should fail with an API access/connection error.
           * From an allowed IP, the same command should succeed.

        6. **Document and monitor**
           * Record the approved CIDR list, justification, and date in your security/change management system.
           * Set up periodic review (e.g., quarterly) and update the allowlist as office/VPN/CI IPs change, repeating steps 1–5 for each review.
      </Accordion>

      <Accordion title="Using kubectl">
        kubectl cannot enable or configure Master Authorized Networks because this setting is part of the managed control plane configuration in your cloud provider (GKE) rather than a Kubernetes API object. To remediate this finding, use the cloud provider console/CLI/IaC as described in the Manual Steps section.
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        #
        # Report GKE Master Authorized Networks status for all clusters in the project.
        # REQUIREMENTS:
        #   - gcloud CLI installed and authenticated
        #   - jq installed
        #
        # RUN ON: any machine with gcloud access to the GCP project.

        set -euo pipefail

        PROJECT_ID="$(gcloud config get-value project 2>/dev/null || true)"
        if [[ -z "${PROJECT_ID}" ]]; then
          echo "ERROR: No default project set in gcloud config."
          echo "Run: gcloud config set project PROJECT_ID"
          exit 1
        fi

        echo "Using project: ${PROJECT_ID}"
        echo

        # List all zones that have GKE clusters in this project
        ZONES="$(gcloud container clusters list \
          --project "${PROJECT_ID}" \
          --format='value(location)' 2>/dev/null | sort -u)"

        if [[ -z "${ZONES}" ]]; then
          echo "No GKE clusters found in project ${PROJECT_ID}."
          exit 0
        fi

        printf "Cluster,Location,MAN_Enabled,Has_Authorized_Networks,Authorized_CIDRs\n"

        # For each cluster, describe and extract masterAuthorizedNetworksConfig
        while read -r LOCATION; do
          [[ -z "${LOCATION}" ]] && continue

          # The same list command will work for both zonal and regional clusters
          CLUSTERS_IN_LOC="$(gcloud container clusters list \
            --project "${PROJECT_ID}" \
            --region "${LOCATION}" \
            --format='value(name)' 2>/dev/null || true)"

          if [[ -z "${CLUSTERS_IN_LOC}" ]]; then
            # Try as zone if region listing failed / empty
            CLUSTERS_IN_LOC="$(gcloud container clusters list \
              --project "${PROJECT_ID}" \
              --zone "${LOCATION}" \
              --format='value(name)' 2>/dev/null || true)"
          fi

          while read -r CLUSTER; do
            [[ -z "${CLUSTER}" ]] && continue

            # Describe cluster; location can be region or zone, gcloud will handle it
            DESC_JSON="$(gcloud container clusters describe "${CLUSTER}" \
              --project "${PROJECT_ID}" \
              --location "${LOCATION}" \
              --format=json 2>/dev/null || true)"

            if [[ -z "${DESC_JSON}" ]]; then
              printf "%s,%s,ERROR,ERROR,ERROR (failed to describe cluster)\n" \
                "${CLUSTER}" "${LOCATION}"
              continue
            fi

            # Extract masterAuthorizedNetworksConfig block
            MAN_CFG="$(printf '%s\n' "${DESC_JSON}" | jq -c '.masterAuthorizedNetworksConfig')"

            if [[ "${MAN_CFG}" == "null" || "${MAN_CFG}" == "{}" ]]; then
              # MAN not configured at all
              printf "%s,%s,DISABLED,NO,\n" "${CLUSTER}" "${LOCATION}"
              continue
            fi

            ENABLED="$(printf '%s\n' "${MAN_CFG}" | jq -r '.enabled // "false"')"
            # Extract all CIDRs if present
            CIDRS="$(printf '%s\n' "${MAN_CFG}" \
              | jq -r '.cidrBlocks[]? | .displayName + "=" + .cidrBlock' 2>/dev/null \
              | paste -sd'|' -)"

            if [[ "${ENABLED}" != "true" ]]; then
              printf "%s,%s,DISABLED,YES,%s\n" "${CLUSTER}" "${LOCATION}" "${CIDRS}"
            else
              if [[ -z "${CIDRS}" ]]; then
                # Enabled but no specific networks configured (effectively open)
                printf "%s,%s,ENABLED,BUT_NO_CIDRS,\n" "${CLUSTER}" "${LOCATION}"
              else
                printf "%s,%s,ENABLED,YES,%s\n" "${CLUSTER}" "${LOCATION}" "${CIDRS}"
              fi
            fi

          done <<< "${CLUSTERS_IN_LOC}"

        done <<< "${ZONES}"
        ```

        Interpretation of the output (problem indicators):

        * `MAN_Enabled = DISABLED` (with `Has_Authorized_Networks = NO` or `YES`):\
          Master Authorized Networks is not effectively protecting the control plane; this **fails** the intent of CIS GKE 5.6.3.

        * `MAN_Enabled = ENABLED` and `Has_Authorized_Networks = BUT_NO_CIDRS`:\
          The feature is enabled but no CIDR blocks are configured; this is **functionally insecure** and should be reviewed as non-compliant.

        Only rows with `MAN_Enabled = ENABLED` and `Has_Authorized_Networks = YES` and a tightly scoped `Authorized_CIDRs` list meet the control; the exact networks should be manually reviewed for appropriateness.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

### Additional Reading:

* [https://cloud.google.com/kubernetes-engine/docs/how-to/authorized-networks](https://cloud.google.com/kubernetes-engine/docs/how-to/authorized-networks)
