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​
- Remediation
Remediation​
Manual Steps
-
Identify which clusters to review
On any machine withgcloudaccess, list clusters and pick the ones in scope:gcloud container clusters list --project <PROJECT_ID> -
Gather current Control Plane Authorized Networks configuration
For each cluster, run: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).
-
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. -
Enable Master Authorized Networks and set CIDRs (or adjust them)
Once the required CIDRs are agreed, enable and configure them: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/32Replace the example CIDRs with your approved list (up to 20 CIDRs). Be aware this immediately restricts API access to those ranges.
-
Re-verify configuration after the change
Confirm that the setting is enabled and that the CIDRs match your decision:gcloud container clusters describe <CLUSTER_NAME> \--location <LOCATION> \--project <PROJECT_ID> \--format json | jq '.masterAuthorizedNetworksConfig'Ensure
enabledistrueandcidrBlockscontains only the intended networks. -
Validate operational access and document
- From an IP inside an authorized CIDR, confirm you can still run:
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.
- From an IP inside an authorized CIDR, confirm you can still run:
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.
Automation
#!/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
enabledis true but nocidrBlocksare set; review this cluster carefully, as the control plane may still be broadly reachable.
- Indicates
-
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.