Ensure Kubernetes Web Ui Is Disabled
More Info:
The Kubernetes Web Ui (Dashboard) Has Been A Historical Source Of Vulnerability And Should Only Be Deployed When Necessary.
Risk Level
Medium
Address
Security
Compliance Standards
- CIS GKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify all GKE clusters and their locations
Run on: any machine withgcloudaccess.gcloud container clusters list --project PROJECT_ID \--format="table(name,location,endpoint,currentMasterVersion)"Replace
PROJECT_IDwith your GCP project ID and note each clusternameandlocation. -
Check dashboard add‑on status for each cluster
Run on: any machine withgcloudaccess. For each cluster:gcloud container clusters describe CLUSTER_NAME \--location LOCATION \--project PROJECT_ID \--format="json" | jq '.addonsConfig.kubernetesDashboard'- If the result is
nullor"disabled": true, the legacy add‑on is not enabled. - If
"disabled": falseor an object withenabled: trueis present, the dashboard add‑on is enabled.
- If the result is
-
Decide if the dashboard is strictly required
- If any cluster shows the dashboard enabled, review with application/operations teams:
- Is the dashboard actively used for operations, or could
kubectl, Cloud Console, or other tools replace it? - Are there compliance or security requirements that prohibit in-cluster dashboards?
- Is the dashboard actively used for operations, or could
- If not strictly required, plan to disable it. If required, ensure strong RBAC, restricted network access, and auditing.
- If any cluster shows the dashboard enabled, review with application/operations teams:
-
Disable the Kubernetes Dashboard add‑on where not needed
Run on: any machine withgcloudaccess. For each cluster where you decided to disable:gcloud container clusters update CLUSTER_NAME \--location LOCATION \--project PROJECT_ID \--update-addons=KubernetesDashboard=DISABLEDOperational impact: this removes the managed dashboard add‑on; any workflows depending on it will lose access and must use alternative tools.
-
Verify the dashboard add‑on is disabled
Run on: any machine withgcloudaccess. For each updated cluster:gcloud container clusters describe CLUSTER_NAME \--location LOCATION \--project PROJECT_ID \--format="json" | jq '.addonsConfig.kubernetesDashboard'Confirm the output is
nullor shows"disabled": true. -
(Optional) Search for any other dashboard deployments
This is not controlled by the add‑on setting but may indicate residual dashboards.
Run on: any machine withgcloudandkubectlaccess. For each cluster, get credentials then:gcloud container clusters get-credentials CLUSTER_NAME \--location LOCATION \--project PROJECT_IDkubectl get deploy,svc,pod -A | grep -i dashboard || echo "No dashboard resources found"If you find custom dashboard deployments, review and remove them if they’re not strictly required.
Using kubectl
kubectl cannot disable the managed Kubernetes Web UI (Dashboard) in GKE, because this setting is controlled at the GKE cluster add‑on level in the Google Cloud control plane. Use the cloud provider configuration (gcloud CLI/console/IaC) as described in the Manual Steps section to remediate this finding.
Automation
#!/usr/bin/env bash
#
# Check status of the Kubernetes Dashboard addon across multiple GKE clusters.
# Requirements:
# - gcloud and jq installed
# - You are authenticated (gcloud auth login / impersonation as needed)
# - You have access to the listed projects
#
# USAGE:
# ./check_gke_dashboard.sh project-1 project-2 ...
#
# OUTPUT:
# PROJECT,LOCATION,CLUSTER,ADDON_STATUS
#
# INTERPRETATION:
# - ADDON_STATUS=null or DISABLED => Dashboard is NOT enabled (no problem)
# - ADDON_STATUS=ENABLED => Dashboard is enabled (requires review)
# - ADDON_STATUS=UNKNOWN => Could not determine (investigate manually)
set -euo pipefail
if ! command -v gcloud >/dev/null 2>&1; then
echo "ERROR: gcloud not found in PATH" >&2
exit 1
fi
if ! command-v jq >/dev/null 2>&1; then
echo "ERROR: jq not found in PATH" >&2
exit 1
fi
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <PROJECT_ID_1> [PROJECT_ID_2 ...]" >&2
exit 1
fi
echo "PROJECT,LOCATION,CLUSTER,ADDON_STATUS"
for PROJECT in "$@"; do
CLUSTERS_JSON="$(gcloud container clusters list \
--project "$PROJECT" \
--format=json 2>/dev/null || echo "[]")"
echo "$CLUSTERS_JSON" | jq -r '.[] | @base64' | while read -r CLUSTER_B64; do
_jq() { echo "$CLUSTER_B64" | base64 --decode | jq -r "$1"; }
NAME=$(_jq '.name')
LOCATION=$(_jq '.location')
# Describe cluster to get addonsConfig
DESC_JSON="$(gcloud container clusters describe "$NAME" \
--location "$LOCATION" \
--project "$PROJECT" \
--format=json 2>/dev/null || echo "{}")"
# This field may be null, missing, or an object with enabled flag
RAW_FIELD="$(echo "$DESC_JSON" | jq '.addonsConfig.kubernetesDashboard')"
# Default to UNKNOWN if we cannot parse expected structure
STATUS="UNKNOWN"
# If field is null or missing, treat as not enabled
if [ "$RAW_FIELD" = "null" ] || [ "$RAW_FIELD" = "" ]; then
STATUS="null"
else
ENABLED_VAL="$(echo "$RAW_FIELD" | jq -r '.disabled // empty' 2>/dev/null || true)"
# In older API versions KubernetesDashboard may have `disabled: true|false`
# Interpret:
# disabled: true => effectively DISABLED
# disabled: false => effectively ENABLED
# If structure is different, leave as UNKNOWN for manual review
if [ "$ENABLED_VAL" = "true" ]; then
STATUS="DISABLED"
elif [ "$ENABLED_VAL" = "false" ]; then
STATUS="ENABLED"
fi
fi
echo "${PROJECT},${LOCATION},${NAME},${STATUS}"
done
done
How to run (any machine with gcloud access):
chmod +x check_gke_dashboard.sh
./check_gke_dashboard.sh my-project-1 my-project-2 > gke-dashboard-status.csv
column -t -s',' gke-dashboard-status.csv
What indicates a problem:
- Any row where
ADDON_STATUSisENABLEDindicates the Kubernetes Dashboard addon is active on that cluster and should be reviewed. - Rows with
ADDON_STATUS=UNKNOWNmean the script could not confidently determine the state; investigate those clusters manually with:
gcloud container clusters describe <cluster_name> \
--location <location> \
--project <project_id> \
--format json | jq '.addonsConfig.kubernetesDashboard'