KCSA — API Server Security
The API Server — Gateway to Everything
The kube-apiserver is the front door to your Kubernetes cluster. Every interaction — whether it’s a user running kubectl, a CI/CD pipeline deploying workloads, or a kubelet reporting node status — goes through the API server.
If the API server is compromised, the attacker has full control of the cluster. Period.
This makes the API server the single most important component to secure in any Kubernetes deployment. Understanding how it handles requests is foundational to the KCSA exam.
The API Server Request Flow
Every request to the API server passes through three sequential gates before it’s allowed to execute. If the request fails at any gate, it’s rejected immediately.
┌─────────────────┐
Client Request → │ AUTHENTICATION │ → "Who are you?"
└────────┬────────┘
│ (identity established)
▼
┌─────────────────┐
│ AUTHORIZATION │ → "Are you allowed to do this?"
└────────┬────────┘
│ (permission verified)
▼
┌─────────────────┐
│ ADMISSION │ → "Should we modify or reject this?"
│ CONTROL │
└────────┬────────┘
│ (request validated/mutated)
▼
┌─────────────────┐
│ etcd / Action │ → Object persisted or action taken
└─────────────────┘
This three-stage pipeline is one of the most frequently tested concepts on the KCSA exam. Know it cold.
Stage 1 — Authentication
Authentication answers one question: “Who are you?”
Kubernetes does not have a built-in user database. Instead, it supports multiple authentication methods that can be used simultaneously. The API server evaluates each authenticator in order until one succeeds or all fail.
Authentication Methods
| Method | How It Works | Common Use Case |
|---|---|---|
| X.509 Client Certificates | Client presents a TLS certificate signed by the cluster CA. The Common Name (CN) becomes the username, Organization (O) becomes the group | Cluster administrators, kubeconfig-based access |
| Bearer Tokens | A token is sent in the Authorization: Bearer <token> header |
Service-to-service communication, bootstrap tokens |
| OpenID Connect (OIDC) | Integrates with external identity providers (Google, Azure AD, Okta). Uses JWT tokens | Enterprise SSO, federated identity |
| Service Account Tokens | Automatically mounted into Pod filesystems at /var/run/secrets/kubernetes.io/serviceaccount/token |
Pod-to-API-server communication |
| Bootstrap Tokens | Short-lived tokens used during cluster bootstrapping (kubeadm) | Node joins, cluster initialization |
| Webhook Token Authentication | API server calls an external webhook to validate the token | Custom authentication backends |
For the KCSA exam, focus on understanding when each method is used and which ones are appropriate for humans vs. machines.
What Happens After Authentication?
Once authenticated, the API server extracts three pieces of identity information:
- Username — the identity of the requester (e.g.,
admin,system:serviceaccount:default:my-app) - UID — a unique identifier for the user
- Groups — the groups the user belongs to (e.g.,
system:masters,system:authenticated)
This identity information is then passed to the authorization stage.
Stage 2 — Authorization
Authorization answers the question: “Is this identity allowed to perform this action on this resource?”
Kubernetes supports multiple authorization modes that can be chained together. The API server evaluates each mode in order — if any mode allows the request, it proceeds. If all modes deny, the request is rejected.
Authorization Modes
| Mode | How It Works | When to Use |
|---|---|---|
| RBAC (Role-Based Access Control) | Grants permissions through Roles and RoleBindings (namespaced) or ClusterRoles and ClusterRoleBindings (cluster-wide) | Default and recommended. Used in almost all production clusters |
| ABAC (Attribute-Based Access Control) | Grants permissions based on attributes defined in a static policy file on disk | Legacy. Requires API server restart to change policies. Avoid in production |
| Node | A special-purpose mode that authorizes kubelet requests based on the Pods scheduled to their node | Always enabled alongside RBAC. Restricts kubelet to only access resources for Pods on its node |
| Webhook | API server calls an external HTTP service to make authorization decisions | Custom authorization logic, integration with external policy engines (e.g., OPA) |
The recommended configuration for production clusters is --authorization-mode=Node,RBAC. This combines the Node authorizer (for kubelet security) with RBAC (for everything else).
RBAC Quick Recap
RBAC consists of four resource types:
| Resource | Scope | Purpose |
|---|---|---|
| Role | Namespace | Defines permissions within a specific namespace |
| ClusterRole | Cluster-wide | Defines permissions across the entire cluster |
| RoleBinding | Namespace | Grants a Role to a user/group/service account within a namespace |
| ClusterRoleBinding | Cluster-wide | Grants a ClusterRole to a user/group/service account cluster-wide |
Example: A ClusterRoleBinding that binds the cluster-admin ClusterRole to a group gives every member of that group full administrative access to the entire cluster — be very careful with this.
Stage 3 — Admission Control
Admission controllers are the final checkpoint before a request is persisted to etcd. They can modify (mutate) requests, reject them, or both.
This is where the cluster enforces policies, defaults, and guardrails beyond what RBAC can express.
Mutating vs. Validating Admission Controllers
| Type | When It Runs | What It Does | Example |
|---|---|---|---|
| Mutating | First (before validating) | Modifies the incoming request — adds defaults, injects sidecars, sets fields | Injecting a sidecar proxy, setting default resource limits |
| Validating | Second (after mutating) | Validates the final request — accepts or rejects, but cannot modify | Rejecting Pods that request privileged mode, enforcing label requirements |
The order matters: mutating controllers run first so that validating controllers see the final version of the object.
Important Admission Controllers for KCSA
| Controller | Type | Purpose |
|---|---|---|
| PodSecurity | Validating | Enforces Pod Security Standards (Privileged, Baseline, Restricted) at the namespace level. Replaces the deprecated PodSecurityPolicy |
| LimitRanger | Mutating + Validating | Sets default resource requests/limits for containers that don’t specify them, and rejects Pods that exceed namespace limits |
| ResourceQuota | Validating | Enforces resource quotas (CPU, memory, object count) at the namespace level |
| NodeRestriction | Validating | Restricts kubelet to only modify its own Node object and Pods bound to its node. Prevents a compromised node from affecting other nodes |
| AlwaysPullImages | Mutating | Forces imagePullPolicy: Always on every container. Ensures nodes always pull fresh images and must authenticate with the registry |
| ServiceAccount | Mutating | Automatically mounts service account tokens into Pods |
| NamespaceLifecycle | Validating | Prevents creation of objects in non-existent or terminating namespaces |
| MutatingAdmissionWebhook | Mutating | Calls external webhooks to mutate requests (used by Istio, OPA Gatekeeper, etc.) |
| ValidatingAdmissionWebhook | Validating | Calls external webhooks to validate requests |
For the KCSA exam, know what PodSecurity, NodeRestriction, and AlwaysPullImages do — these are frequently tested.
Anonymous Access
By default, the API server allows anonymous requests — if no authentication credentials are provided, the request is treated as the user system:anonymous in the group system:unauthenticated.
This is dangerous because:
- Discovery APIs (like
/apiand/version) may be accessible without credentials - Misconfigured RBAC could accidentally grant permissions to
system:unauthenticated - Attackers can probe the API server without any authentication
How to Disable Anonymous Access
Set the following flag on the API server:
--anonymous-auth=false
With this flag, any request without valid credentials will receive a 401 Unauthorized response.
In most production environments, anonymous access should be disabled. Some managed Kubernetes services do this by default.
Security-Relevant API Server Flags
The KCSA exam tests your understanding of what these flags do — you won’t need to configure them, but you need to know their purpose.
| Flag | Purpose | Recommended Value |
|---|---|---|
--anonymous-auth |
Enables or disables anonymous (unauthenticated) access | false |
--authorization-mode |
Specifies which authorization modes to enable | Node,RBAC |
--enable-admission-plugins |
Comma-separated list of admission controllers to enable | Include NodeRestriction,PodSecurity at minimum |
--disable-admission-plugins |
Comma-separated list of admission controllers to disable | Disable any you don’t need |
--insecure-port |
Serves API over HTTP (no auth, no authz). Deprecated and removed in 1.24+ | 0 (disabled) |
--tls-cert-file / --tls-private-key-file |
TLS certificate and key for the API server | Always configure — API server should serve HTTPS only |
--client-ca-file |
CA certificate used to verify client certificates | Required for X.509 authentication |
--audit-policy-file |
Path to the audit policy file | Always configure in production |
--encryption-provider-config |
Path to the encryption configuration for encrypting data at rest in etcd | Required for secret encryption |
The --insecure-port flag is a classic exam topic. It allowed unauthenticated, unencrypted access to the API server. It has been removed since Kubernetes 1.24, but you should know that it existed and why it was dangerous.
API Server Network Exposure
Beyond flags and configurations, how the API server is exposed on the network matters enormously:
- Restrict network access — the API server should not be accessible from the public internet unless absolutely necessary
- Use a load balancer with TLS termination — in HA setups, front the API server with a load balancer
- Firewall rules — only allow traffic from authorized networks (admin workstations, CI/CD, worker nodes)
- Private clusters — many cloud providers offer private cluster configurations where the API server has no public endpoint
Putting It All Together
Here’s how the three stages work together in a real scenario:
Scenario: A developer runs kubectl create deployment nginx --image=nginx against the cluster.
- Authentication — kubectl sends the developer’s client certificate. The API server verifies it against the cluster CA and extracts the username and groups
- Authorization — RBAC checks: does this user have
createpermission ondeploymentsin the target namespace? If yes, proceed - Admission Control —
LimitRangeradds default resource limits.AlwaysPullImagessets the pull policy.PodSecurityvalidates the resulting Pod spec against the namespace’s security standard. If all pass, the Deployment is persisted to etcd
If any stage rejects the request, it stops immediately and returns an error to the client.
Key Takeaways for the Exam
| Concept | What to Remember |
|---|---|
| Request flow | Authentication → Authorization → Admission Control (in that exact order) |
| Authentication | Kubernetes has no user store — it relies on external methods (certs, OIDC, tokens) |
| Authorization | RBAC is the standard. Know the difference between Role/ClusterRole and RoleBinding/ClusterRoleBinding |
| Admission controllers | Mutating runs before validating. Know PodSecurity, NodeRestriction, AlwaysPullImages |
| Anonymous access | Should be disabled (--anonymous-auth=false) in production |
| Insecure port | Deprecated and removed in K8s 1.24+. Never enable it |
| Node,RBAC | The recommended --authorization-mode for production clusters |
| Webhook authorization | Used to integrate external policy engines like OPA |
The API server is the gateway. Everything passes through it. Understand the three-stage pipeline, and you’ll be able to answer a large portion of this domain’s exam questions.