How do you control who can reach and use the Kubernetes API?

You control access to the Kubernetes API in four layers: limit which networks can reach the API server endpoint, authenticate every caller with short-lived credentials from your identity provider, authorize each request with least-privilege RBAC, and record what happened in audit logs stored outside the cluster. The API server is the single entry point to a cluster, so anyone who can reach it with a valid credential and enough permissions controls every workload. Each layer covers a failure in the one before it.

Every request passes the same stages

The controlling access guide describes the path of a request: it reaches the API server over TLS, an authenticator establishes who the caller is, an authorizer (usually RBAC) decides whether that caller may perform the action, admission controllers can modify or reject it, and the audit subsystem records it. Network controls sit in front of all of this. Authorization has its own article, Kubernetes RBAC. This one covers the other layers.

Network exposure of the API endpoint

OptionHow it worksTrade-off
Public endpoint, openReachable from the internet; protection relies on authenticationExposed to scanning and to any future authentication bug
Public endpoint with an IP allow listOnly listed source ranges can connectBreaks for remote staff and CI runners with changing addresses
Private endpointReachable only from a VPC, VPN or peered networkEvery client, including CI, needs a network path into it
Identity-aware access proxyClients connect through a proxy that checks the user’s identity and device before forwardingOne more component to run, but works from anywhere without a VPN

Managed services offer the first three under their own names, such as authorized networks or authorized IP ranges and private clusters. A private endpoint shrinks the attack surface but does not replace authentication: anything inside the network, including a compromised Pod, can still reach it.

Authentication of callers

Kubernetes has no user objects. A user is whatever name and groups an authenticator reports. The methods differ in how long a credential lives and whether you can revoke it.

MethodCredential lifetimeRevocationUse for
Client certificatesUntil expiry, often a year or moreNo revocation check, so a leaked certificate works until it expiresBootstrap and break-glass only
Static token fileIndefinite; changes need an API server restartRestart onlyNothing in production
Bound service account tokensTied to an expiry time and to the Pod that requested themDeleting the Pod or service account invalidates themWorkloads inside the cluster
OIDC tokens from your identity providerSet by the identity provider, usually an hour or lessDisable the user in the identity providerAll human users, and CI through OIDC federation

The CIS Kubernetes Benchmark recommends against client certificates for users because of the missing revocation. For people, use single sign-on: kubectl gets an OIDC token through a credential plugin, and the API server validates it against your identity provider. Your identity provider then enforces multi-factor authentication and offboarding, and the groups claim feeds RBAC.

Kubernetes configures OIDC through structured authentication configuration, a file passed with --authentication-config. It has been stable since Kubernetes 1.34. It accepts up to 64 JWT authenticators with different issuers, validates and maps claims with CEL expressions, and reloads when the file changes, with no API server restart. That makes it possible to trust your corporate identity provider for people and your CI provider for pipelines at the same time. The article on workload identity explains the same token exchange for CI jobs and cloud APIs.

Hardening defaults

  • Anonymous requests. The API server accepts anonymous requests by default when an authorization mode other than AlwaysAllow is set. Since Kubernetes 1.34 you can limit anonymous access to /healthz, /livez and /readyz in the authentication configuration, or turn it off with --anonymous-auth=false. Never bind roles to system:anonymous or system:unauthenticated.
  • Long-lived tokens. Request bound tokens through the TokenRequest API, for example with kubectl create token, instead of creating Secrets of type kubernetes.io/service-account-token, which never expire.
  • Superuser credentials. Members of the system:masters group bypass RBAC entirely. Keep that group out of everyday kubeconfigs.
  • Break-glass access. Keep one or two emergency credentials that do not depend on the identity provider, store them in separate vaults, and alert on every use through the audit log.

The kubelet API is a second front door

Every node runs the kubelet, which serves its own HTTPS API, by default on port 10250. It can list Pods, read logs and run commands in containers. The kubelet’s own defaults are permissive: unauthenticated requests are treated as anonymous, and the default authorization mode is AlwaysAllow, according to the kubelet authentication guide. Run kubelets with --anonymous-auth=false and --authorization-mode=Webhook, so the kubelet asks the API server to authorize each request. Block port 10250 from anything except the control plane and monitoring, and treat RBAC access to nodes/proxy as equivalent to running commands on the node.

Audit logs

The API server writes audit events only when you pass a policy with --audit-policy-file. Each rule sets a level:

  • None: do not log.
  • Metadata: who, when, which verb and which resource, without bodies.
  • Request: metadata plus the request body.
  • RequestResponse: metadata plus request and response bodies.

Log Secrets, ConfigMaps and token requests at Metadata only, so values never end up in the log. Log writes to RBAC objects, Pods with exec or attach, and authentication failures at a level detailed enough to investigate. Send events through the log or webhook backend to storage that cluster administrators cannot modify, because an attacker with cluster-admin will try to erase their tracks. Then alert on the events that matter: new ClusterRoleBindings, pods/exec in production namespaces, reads of many Secrets and any use of break-glass credentials.

A short checklist

  1. Make the API endpoint private or allow-listed, or put an identity-aware proxy in front of it.
  2. Authenticate people through OIDC single sign-on with MFA. Keep client certificates for break-glass only.
  3. Authenticate CI through OIDC federation, not stored kubeconfigs.
  4. Restrict anonymous access to health endpoints.
  5. Lock down the kubelet API.
  6. Apply least-privilege RBAC bound to identity provider groups.
  7. Ship audit logs to storage outside the cluster and alert on high-risk events.

The same controls are the base layer for sharing a cluster between teams, covered in Kubernetes multi-tenancy.

API access on Cloudfleet

On Cloudfleet Kubernetes Engine (CFKE), people reach clusters through their Cloudfleet account with single sign-on from your identity provider, and GitHub Actions and GitLab CI authenticate with short-lived OIDC tokens instead of stored kubeconfigs. On Enterprise clusters, control plane endpoints can be restricted to private networks and the Kubernetes audit logs are delivered to your own infrastructure, as described on the security page.

On this page