Featured
8 min read14 hours ago
–
As mentioned in the previous post, executing kubectl apply -f manifest.yaml is a process involving authentication, authorization, and admission. Continuing the series of articles that will culminate in the resource persistence in etcd, in this chapter we will discuss the Kubernetes authentication process — the first step in the security chain.
Authentication is responsible for answering the question: “Who is making this request?”
Only after this step does Kubernetes proceed to check what this entity can do (authorization) and whether the request is valid (admission).
Understanding the Request
Let’s continue with the same ex…
Featured
8 min read14 hours ago
–
As mentioned in the previous post, executing kubectl apply -f manifest.yaml is a process involving authentication, authorization, and admission. Continuing the series of articles that will culminate in the resource persistence in etcd, in this chapter we will discuss the Kubernetes authentication process — the first step in the security chain.
Authentication is responsible for answering the question: “Who is making this request?”
Only after this step does Kubernetes proceed to check what this entity can do (authorization) and whether the request is valid (admission).
Understanding the Request
Let’s continue with the same example, now executing a command with kubectl and enabling verbosity level 7:
kubectl get pods -v 7
Press enter or click to view image in full size
Observing the sequence of events in the image (not displayed here), we have that:
- When executing the command
kubectl get pods, - one of the first operations performed is reading the file available at
~/.kube/config, - immediately afterward, a request is made using the HTTP
GETmethod to the URI available at[https://127\.0\.0\.1:53806/api/v1/namespaces/kube-system/pods](https://127.0.0.1:53806/api/v1/namespaces/kube-system/pods,), - and finally, the list of pods available in the
kube-systemnamespace is presented.
By observing the execution of the command, we notice that reading the file ~/.kube/config is one of the first operations. The information available in it will serve as input to make the request to the kube-apiserver and return the list of pods in the kube-system namespace.
The Role of the kubeconfig File
The kubeconfig file stores information about clusters, users, namespaces, and security mechanisms used to authenticate to the clusters. In practice, all commands executed with kubectl read this file to determine how to connect and how to authenticate to the Kubernetes API server.
Continuing with the previous example, let’s try to make the same request that kubectl is making, but using an HTTP client. (I’m using httpie for a more presented response, but the same can be done using curl -s -X GET -k [https://127\.0\.0\.1:53806/api/v1/namespaces/kube-system/pods](https://127.0.0.1:53806/api/v1/namespaces/kube-system/pods):))::)
Press enter or click to view image in full size
As can be observed, all requests to the kube-apiserver must be associated with a common user or a ServiceAccount. In this case, as we are not passing any information that identifies us in the request, the user is treated as anonymous (system:anonymous).
It is possible to completely disable the anonymous user by passing the flag --anonymous-auth=false to the kube-apiserver. This way, all requests that do not have a known user associated will be completely ignored.
Press enter or click to view image in full size
For the next commands, I will use information available in kubeconfig to replicate the same behavior returned by kubectl, that is, we will use the same credentials. Don’t worry if you don’t understand what this information is; throughout this article, these gaps will be filled.
First, with yq, let’s extract the certificate information used to authenticate to the kube-apiserver. The information we need is the authority certificate, the client certificate, and the client key. With the certificates and keys in hand, we will pass them as parameters in the curl command.
# Extracts the Certificate Authority (CA) Certificateyq -r '.clusters[] | select(.name == "kind-kind") | .cluster.certificate-authority-data' ~/.kube/config | base64 -d > kind-kind-certificate-authority
# Extracts the Client Certificateyq -r '.users[] | select(.name == "kind-kind") | .user.client-certificate-data' ~/.kube/config | base64 -d > kind-kind-client-certificate
# Extracts the Client Keyyq -r '.users[] | select(.name == "kind-kind") | .user.client-key-data' ~/.kube/config | base64 -d > kind-kind-client-key
With the saved files, we execute the request with curl:
curl https://127.0.0.1:62246/api/v1/namespaces/kube-system/pods \ --cacert kind-kind-certificate-authority \ --cert kind-kind-client-certificate \ --key kind-kind-client-key --silent \ | jq '.items[].metadata.name' -r
Press enter or click to view image in full size
As we can observe, by passing the same information used by kubectl, we get the same result, successfully authenticating the request.
Location of kubeconfig
By default, the configuration file (kubeconfig) is stored in:
~/.kube/config
However, it is possible to define an alternative path through the KUBECONFIG environment variable.
For example, using kind, we can create two clusters and specify where the configuration file will be saved:
KUBECONFIG=/tmp/cluster-1-kubeconfig.yaml kind create cluster --name cluster-1KUBECONFIG=/tmp/cluster-2-kubeconfig.yaml kind create cluster --name cluster-2
Defining the Configuration File to Be Used
There are three main ways to indicate which configuration file kubectl should use.
1. Using the KUBECONFIG variable directly
You can define the file path for a single execution:
KUBECONFIG=/tmp/cluster-1-kubeconfig.yaml kubectl -n kube-system get pods
Press enter or click to view image in full size
To avoid repeating the variable in all commands, we can export it to the current environment:
export KUBECONFIG=/tmp/cluster-1-kubeconfig.yamlkubectl -n kube-system get pods
Press enter or click to view image in full size
2. Using multiple kubeconfig files
The KUBECONFIG variable can also contain a list of files, separated by : (on Unix/Linux/macOS systems) or ; (on Windows). kubectl will automatically merge these files into a single view:
KUBECONFIG="/tmp/cluster-1-kubeconfig.yaml:/tmp/cluster-2-kubeconfig.yaml" kubectl config view
Press enter or click to view image in full size
This functionality is extremely useful in scenarios with multiple clusters — such as development, staging, and production environments — allowing credentials and contexts to be unified into a single consolidated file.
3. Using the --kubeconfig flag
Another option is to specify the file directly on the command line, using the --kubeconfig flag:
kubectl --kubeconfig /tmp/cluster-1-kubeconfig.yaml -n kube-system get pods
This approach is especially practical in scripts or automation pipelines, where the file path needs to be explicitly defined.
Structure of the kubeconfig File
kubeconfig is a YAML file that follows a schema defining four main sections:
clusters– information about the cluster API address and the certificate used for communication.users– credentials and authentication mechanisms.contexts– combinations of cluster, user, and namespace.current-context– the active context, used bykubectlby default.
A basic example of a kubeconfig file:
apiVersion: v1kind: Configcurrent-context: kind-cluster-1clusters:- cluster: certificate-authority-data: "..." # Cluster CA in Base64 server: [https://127.0.0.1:56815](https://127.0.0.1:56815) name: kind-cluster-1users:- name: kind-cluster-1 user: client-certificate-data: "..." # Client certificate in Base64 client-key-data: "..." # Client private key in Base64contexts:- context: cluster: kind-cluster-1 namespace: kube-system user: kind-cluster-1 name: kind-cluster-1
clusters Section
The clusters list defines all Kubernetes clusters known to kubectl.
Each entry contains:
name: Unique name of the cluster within the file (referenced by contexts).cluster.server: URL of the Kubernetes API server (apiserver endpoint).cluster.certificate-authority-data: Certificate Authority (CA) certificate encoded in Base64, used to validate the server’s identity.- Alternatively, you can use
certificate-authority: /path/to/ca.crt.
Examples with kubectl config:
- To retrieve the list of available clusters
kubectl config get-clusters
- To save a new cluster, referencing the path to the Certificate Authority (CA)
kubectl config set-cluster kind-cluster-3 --server https://127.0.0.1:56815 --certificate-authority certificate.cer
- To save a new cluster, embedding the CA (storing the certificate inside the kubeconfig itself)
kubectl config set-cluster kind-cluster-3 --server https://127.0.0.1:56815 --certificate-authority certificate.cer --embed-certs
- To remove a cluster
kubectl config delete-cluster cluster-3
users Section
The users list defines the access credentials for authentication to the cluster.
Each entry contains:
name: Name of the user (referenced by contexts).user.client-certificate-dataanduser.client-key-data: Certificate and private key pair in Base64 (authentication via certificates).user.token: Authentication token (used in managed providers, such as EKS, GKE, or AKS).user.username/user.password: Basic authentication (rarely used in production).
In corporate environments, it is common to use exec plugins to generate dynamic tokens, such as OIDC providers or the AWS CLI with EKS:
user: exec: command: aws args: - "eks" - "get-token" - "--cluster-name" - "meu-cluster"
Examples with kubectl config:
- To retrieve the list of available users
kubectl config get-users
- To create credentials using Certificate and Key (referencing the file paths)
kubectl config set-credentials kind-cluster-3 --client-certificate client-certificate.crt --client-key client.key
- To create credentials using Certificate and Key (embedding them in the kubeconfig)
kubectl config set-credentials kind-cluster-3 --client-certificate client-certificate.crt --client-key client.key --embed-certs
- To create credentials using Username and Password (Basic Authentication)
kubectl config set-credentials kind-cluster-3 --username username --password password
- To create credentials using an authentication Token
kubectl config set-credentials kind-cluster-3 --token token
- To configure OIDC (OpenID Connect) credentials for external authentication:
kubectl config set-credentials kind-cluster-3 --auth-provider=oidc --auth-provider-arg=client-id=foo --auth-provider-arg=client-secret=bar
contexts Section
The contexts list combines a cluster, a user, and optionally, a default namespace.
Each entry contains:
name: Unique name of the context (referenced bycurrent-context).context.cluster: Name of the cluster (declared inclusters).context.user: Name of the user (declared inusers).context.namespace(optional): Defines the default namespace when usingkubectlcommands.
Examples with kubectl config:
- To retrieve the list of available contexts
kubectl config get-contexts
- To create a new context
kubectl config set-context prod-admin --cluster kind-cluster-1 --user kind-cluster-1
- To create a new context and set a default namespace
kubectl config set-context dev-user --cluster kind-cluster-2 --user dev-user --namespace app-frontend
- To switch the active context (the cluster/user that will be used for subsequent commands)
kubectl config use-context prod-admin
- To remove a context
kubectl config delete-context dev-user
current-context Section
Defines which context is currently active — that is, which cluster, user, and namespace will be used by default when executing kubectl without additional options.
To check the current context:
kubectl config current-context
To switch the active context, you can use:
kubectl config use-context context-name