This check flags GKE clusters that still accept a static username and password for authentication. Basic auth predates modern GKE identity controls and gives attackers a low-effort path to full cluster admin. Disable it by setting the master auth username and password to empty and migrate to IAM plus client certificates.
Basic authentication on a Kubernetes cluster is one of those settings that quietly survives migrations and copy-pasted Terraform modules long after Google deprecated it. If you provisioned a GKE cluster a few years ago, or cloned an older config, there's a real chance it still has a static admin username and password attached to the control plane. Lensix raises gke_basicauth when it finds a cluster with this legacy authentication mechanism enabled.
This post covers what the check looks at, why basic auth is a genuine risk and not just a compliance nag, and how to remove it without breaking your access to the cluster.
What this check detects
The gke_basicauth check inspects the masterAuth configuration of each GKE cluster. Specifically, it looks at whether a username and password are set. When both are populated, the cluster accepts HTTP basic authentication against the Kubernetes API server, where credentials are sent as a base64-encoded Authorization: Basic header.
You can confirm the state of a cluster yourself:
gcloud container clusters describe CLUSTER_NAME \
--zone ZONE \
--format="value(masterAuth.username, masterAuth.password)"
If that command returns a username (often admin) and a password string, basic auth is active. An empty result means it is already disabled.
Note: Google removed the ability to enable basic auth on new clusters running GKE 1.12 and later, and clusters created with version 1.19+ have it disabled by default. The check matters most for older clusters that were created before these defaults landed and have been upgraded in place, which keeps the original auth settings intact.
Why it matters
Basic auth gives an attacker a single, static credential pair that maps directly to cluster admin. Unlike short-lived tokens or IAM-brokered access, that username and password do not expire, do not rotate on their own, and are not tied to any individual identity. Anyone who holds them can authenticate as cluster-admin.
Here is what makes this dangerous in practice:
- The credentials are usually static and long-lived. They get baked into CI pipelines, kubeconfig files on laptops, and Terraform state. Each copy is a new place they can leak from.
- There is no MFA and no per-user attribution. If the password is used to make a destructive change, your audit logs show the action but cannot tell you which person or system was responsible.
- It bypasses your IAM controls. You might have tight RBAC and Cloud IAM bindings, but a valid basic auth credential routes around all of it.
- Credentials end up in plaintext. The password sits in
masterAuthand is visible to anyone withcontainer.clusters.getpermission. It is also retrievable through the API and stored in Terraform state files.
A realistic attack chain looks like this: a developer's laptop with a stale kubeconfig is compromised, or a public Git repo leaks a Terraform state file. The basic auth password is right there in cleartext. The attacker points kubectl at the public control plane endpoint and immediately has full admin, with no second factor to clear and no tie to a revocable identity.
Danger: If basic auth is enabled and your control plane has a public endpoint, the cluster is one leaked password away from full compromise. Treat any cluster flagged by this check as a priority, and rotate the credential as part of disabling it in case it has already been exposed.
How to fix it
The fix is to empty the username and password on the cluster's master auth and rely on the modern combination of Cloud IAM, RBAC, and client certificates instead. GKE has moved entirely to this model, so disabling basic auth aligns you with how the platform is meant to work.
Step 1: Confirm who currently relies on basic auth
Before you turn anything off, find out what is authenticating with the static credential. Check your CI/CD service connections, scheduled jobs, and any automation that runs kubectl. Look for kubeconfig entries that use a username and password rather than an auth provider or exec plugin.
Warning: If a pipeline or service still authenticates with basic auth, disabling it will break that access immediately. Migrate those consumers to a Google service account with the right IAM roles first, then disable basic auth.
Step 2: Disable basic auth with gcloud
Setting both the username and password to empty strings removes basic auth entirely:
gcloud container clusters update CLUSTER_NAME \
--zone ZONE \
--no-enable-basic-auth
On some older CLI and cluster versions, you disable it by clearing the username explicitly:
gcloud container clusters update CLUSTER_NAME \
--zone ZONE \
--username=""
While you are at it, disabling the legacy client certificate (another deprecated auth method) tightens things further:
gcloud container clusters update CLUSTER_NAME \
--zone ZONE \
--no-issue-client-certificate
Step 3: Re-authenticate with IAM-based credentials
Regenerate your kubeconfig so it uses the gcloud auth plugin instead of the static credential:
gcloud container clusters get-credentials CLUSTER_NAME \
--zone ZONE
This writes a kubeconfig that fetches short-lived tokens through your Google identity, so access is tied to IAM and respects your RBAC bindings.
Step 4: Fix it in Terraform
If you manage clusters with the google_container_cluster resource, the relevant block is master_auth. The correct modern configuration omits the username and password and disables the client certificate:
resource "google_container_cluster" "primary" {
name = "primary-cluster"
location = "us-central1-a"
# No username or password block at all.
master_auth {
client_certificate_config {
issue_client_certificate = false
}
}
}
If your existing config has a username or password attribute under master_auth, remove them entirely. Leaving them with empty strings can cause provider churn, so delete the lines.
Tip: After removing the attributes, run terraform plan and confirm the diff only touches master auth. If your state was created from an older module, you may also see the client certificate flip to false, which is the change you want.
How to prevent it from happening again
Disabling basic auth on one cluster is a point fix. Keeping it disabled across an entire fleet needs guardrails.
Block it in your IaC pipeline
Add a policy check to CI that fails any plan introducing basic auth. With Open Policy Agent and conftest against a Terraform plan, a rule looks like this:
package gke
deny[msg] {
resource := input.resource_changes[_]
resource.type == "google_container_cluster"
auth := resource.change.after.master_auth[_]
auth.username != ""
msg := sprintf("Cluster %q has basic auth enabled (master_auth.username set)", [resource.name])
}
Wire this into the same job that runs terraform plan so a pull request cannot merge a cluster with basic auth.
Enforce with Organization Policy
For new clusters, you do not need a custom rule, since GKE 1.19+ disables basic auth by default. Pin your cluster creation to a recent minimum version and use the regular release channel so you stay on supported defaults:
gcloud container clusters create CLUSTER_NAME \
--zone ZONE \
--release-channel regular
Catch drift continuously
IaC gates only cover resources that go through your pipeline. Clusters created by hand, or settings changed out-of-band, slip past them. This is where continuous scanning earns its keep: Lensix runs the gke_basicauth check across all your projects on a schedule, so a cluster that gets reconfigured manually still gets flagged.
Tip: Pair your CI policy gate with scheduled posture scanning. The gate stops bad config at the door; the scanner catches anything that was created before the gate existed or made outside of it.
Best practices
- Use IAM and RBAC as your only auth path. Map Google identities and service accounts to Kubernetes RBAC roles, and drop every static credential mechanism.
- Disable legacy client certificates too. Like basic auth, they are long-lived and hard to revoke cleanly. Set
issue_client_certificateto false. - Restrict the control plane endpoint. Enable authorized networks or use a private cluster so the API server is not reachable from the open internet even if a credential leaks.
- Use short-lived credentials for automation. Workload Identity Federation lets CI systems and external workloads authenticate without long-lived service account keys.
- Audit your kubeconfig files. Periodically check developer machines and pipeline secrets for kubeconfigs that still carry usernames and passwords, and rotate or replace them.
- Scan the whole estate, not just new builds. Continuous checks across every project keep the fleet clean as teams come and go.
Basic auth is a leftover from an earlier era of GKE, and there is no scenario where keeping it is the right call. Remove it, move your access to IAM, and put a gate in place so it cannot creep back in.

