Ensure Authentication Using Client Certificates Is Disabled
More Info:
Disable Client Certificates, Which Require Certificate Rotation, For Authentication. Instead, Use Another Authentication Method Like Openid Connect.
Risk Level
Low
Address
Security
Compliance Standards
- CIS GKE
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
On any machine with
gcloudconfigured for the project, gather the current setting for client certificates:gcloud container clusters describe CLUSTER_NAME \--location LOCATION \--project PROJECT_ID \--format=json | jq '.masterAuth'Review:
.masterAuth.clientKey.masterAuth.clientCertificate.masterAuth.clusterCaCertificate
-
Decide on an alternative authentication mechanism if you will disable client certificates. For GKE, review and plan to use one or more of:
- GCP IAM‑based authentication (
gcloud auth,gke-gcloud-auth-plugin) - OpenID Connect (OIDC)–based authentication
- Other supported identity providers tied to IAM / RBAC
Ensure your admins and automation can authenticate without client certificates.
- GCP IAM‑based authentication (
-
If
.masterAuth.clientKeyisnulland.masterAuth.clientCertificateisnull:- Record that the cluster is already compliant; no further change is needed.
- Optionally re‑run:
to confirm both values aregcloud container clusters describe CLUSTER_NAME \--location LOCATION \--project PROJECT_ID \--format=json | jq '.masterAuth.clientKey, .masterAuth.clientCertificate'
null.
-
If
.masterAuth.clientKeyor.masterAuth.clientCertificateis non‑null, assess impact:- Identify any users, scripts, or tools currently using these client certs to access the API server.
- Locate their kubeconfig files (typically
~/.kube/config) and check for embedded client certs/keys for this cluster:grep -n "client-certificate-data" ~/.kube/config || truegrep -n "client-key-data" ~/.kube/config || true - Plan migration of these clients to IAM/OIDC authentication before you disable or stop relying on client certificates.
-
Because existing GKE clusters cannot be toggled to
--no-issue-client-certificate, plan a remediation approach:- Preferable: create a replacement cluster without client certificates:
gcloud container clusters create NEW_CLUSTER_NAME \--location LOCATION \--project PROJECT_ID \--no-issue-client-certificate \[OTHER_REQUIRED_FLAGS]
- Migrate workloads, users, and automation from the old cluster to the new one using IAM/OIDC auth only.
- Decommission the old cluster once all dependencies on client certificates are removed.
- Preferable: create a replacement cluster without client certificates:
-
After migration, verify the new cluster is compliant:
gcloud container clusters describe NEW_CLUSTER_NAME \--location LOCATION \--project PROJECT_ID \--format=json | jq '.masterAuth.clientKey, .masterAuth.clientCertificate'Confirm both values are
nulland that all administrative access works via the chosen alternative authentication method (e.g., IAM/OIDC).
Using kubectl
kubectl cannot disable client certificate authentication for the GKE control plane; this setting is managed only via GCP APIs/Console/CLI/IaC at the cluster configuration level. Refer to the Manual Steps section for how to review and change the cluster’s authentication settings.
Automation
#!/usr/bin/env bash
#
# Report GKE clusters that have client certificate authentication enabled.
# REQUIREMENTS:
# - gcloud
# - jq
#
# USAGE:
# PROJECTS="proj-1 proj-2" REGIONS="us-central1 us-east1" ZONES="us-central1-a us-east1-b" ./check_gke_client_certs.sh
#
# NOTES:
# - Runs from any machine with gcloud access.
# - Does NOT make any changes; it only reports.
set -euo pipefail
# Comma/space separated lists allowed
PROJECTS="${PROJECTS:-$(gcloud projects list --format='value(projectId)')}"
REGIONS="${REGIONS:-}"
ZONES="${ZONES:-}"
# Normalize to space-separated
to_space_list() {
echo "$1" | tr ',;' ' '
}
PROJECTS="$(to_space_list "$PROJECTS")"
REGIONS="$(to_space_list "$REGIONS")"
ZONES="$(to_space_list "$ZONES")"
echo "Checking client certificate authentication on GKE clusters..."
echo "Projects: $PROJECTS"
echo "Regions: ${REGIONS:-<all>}"
echo "Zones: ${ZONES:-<all>}"
echo
check_cluster() {
local project="$1"
local location="$2"
local name="$3"
# Describe cluster and extract masterAuth fields
local desc
if ! desc="$(gcloud container clusters describe "$name" \
--project="$project" \
--location="$location" \
--format=json 2>/dev/null)"; then
echo "ERROR: failed to describe cluster $project/$location/$name" >&2
return
fi
local client_key client_cert_cluster_ca
client_key="$(jq -r '.masterAuth.clientKey // empty' <<<"$desc")"
client_cert_cluster_ca="$(jq -r '.masterAuth.clientCertificate, .masterAuth.clusterCaCertificate | select(length>0)' <<<"$desc" | wc -l | tr -d ' ')"
# client_key non-empty means client cert auth is configured
if [[ -n "$client_key" ]]; then
echo "NON-COMPLIANT: project=$project location=$location cluster=$name"
echo " masterAuth.clientKey is present (client certificate authentication ENABLED)"
else
echo "COMPLIANT: project=$project location=$location cluster=$name"
echo " masterAuth.clientKey is empty (client certificate authentication DISABLED)"
fi
}
for project in $PROJECTS; do
echo "=== Project: $project ==="
# Zonal clusters
if [[ -n "$ZONES" ]]; then
for zone in $ZONES; do
mapfile -t clusters < <(gcloud container clusters list \
--project="$project" \
--zone="$zone" \
--format='value(name)' 2>/dev/null || true)
for c in "${clusters[@]}"; do
check_cluster "$project" "$zone" "$c"
done
done
else
mapfile -t clusters < <(gcloud container clusters list \
--project="$project" \
--format='value(name,location)' 2>/dev/null || true)
for line in "${clusters[@]}"; do
name="${line%% *}"
location="${line##* }"
check_cluster "$project" "$location" "$name"
done
fi
echo
done
cat <<'EOF'
INTERPRETING RESULTS
--------------------
- NON-COMPLIANT lines indicate clusters where client certificate authentication is ENABLED.
This violates CIS GKE 5.8.2 and should be reviewed.
- COMPLIANT lines indicate clusters where client certificate authentication is DISABLED.
Because this control is MANUAL, you must decide per cluster whether to:
- Keep the current configuration (with documented justification), or
- Plan a migration to a new cluster created with:
gcloud container clusters create CLUSTER_NAME --no-issue-client-certificate
EOF