Kubernetes: Set Up Authentication for Cluster Admin

Posted on Jan 15, 2022

This guide runs you through the steps necessary to get going with a Kubernetes cluster. We will cover the following tasks:

  1. Creating a user
  2. Granting cluster-admin privileges to that user
  3. Setting up a kubectl client to work with the new credentials

The first two steps assume that you have a working kubectl client with cluster-admin privileges. I know this may put you into some kind of bootstrapping issue. You may need to use an initial cluster-admin user like the one in K3s’ CLI: k3s kubectl.

Where ever needed, replace julius with your username. Replace foo with your cluster’s name, bar with your cluster’s context. I am assuming a working directory of ~/.kube/certs.

1. Creating a User

Kubernetes’ authentication system generally works using x509 public key pairs. We will create a key pair and generate a certificate signing request (CSR) from that. Then, we will approve the CSR and retrieve the signed certificate.

Create key pair

If not present already, create a decently strong RSA key.

openssl genrsa -out julius.key 4096

Create CSR

Make sure to set the CN to julius!

openssl req -new -key julius.key -out julius.csr

<<EOF > julius-csr.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: julius
spec:
  request: $(cat julius.csr | base64 | tr -d "\n")
  signerName: kubernetes.io/kube-apiserver-client
  usages:
    - client auth
EOF

As your existing kubectl client is probably running on a Kubernetes node, you need to transfer the certificate from your client:

scp julius-csr.yaml foo.example.com:.

You can use the key and CSR for multiple clusters, just like your SSH keys.

Apply CSR

kubectl apply -f julius-csr.yaml

Approve User

This will sign the certificate using a certificate trusted by the Kubernetes API.

kubectl certificate approve julius

Get the Certificate

Get the signed certificate. We will use it to authenticate to the API server.

kubectl get csr julius -o jsonpath='{.status.certificate}' | base64 -d > foo-julius.crt

As your existing kubectl client is probably running on a Kubernetes node, you need to transfer the certificate to your client:

scp foo.example.com:foo-julius.crt .

2. Grant Cluster Admin Privileges

This grants full control over every aspect of the cluster. Use with care!

kubectl create clusterrolebinding julius-cluster-admin-binding --clusterrole=cluster-admin --user=julius

Alternatively by applying a YAML:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: julius-cluster-admin-binding
subjects:
- kind: User
  name: julius
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

3. Set up kubectl client

Get the CA certificate of the cluster

Most Kubernetes clusters use their own CA. Your local kubectl needs to trust this CA in order to establish a connection to the API server, as it is secured by mTLS.

You can find the CA certificate as a ConfigMap in every namespace with the name kube-root-ca.crt.

So use your existing kubectl client to extract it:

kubectl get configmap kube-root-ca.crt -o jsonpath='{.data.ca\.crt}' > foo-ca.crt

As your existing kubectl client is probably running on a Kubernetes node, you need to transfer the certificate to your client:

scp foo.example.com:foo-ca.crt .

Set cluster entry

kubectl config set-cluster foo --server=https://foo.example.com:6443 --certificate-authority=foo-ca.crt

When using kubeadm you may run into problems with the API server’s certificate not covering the FQDN of your cluster.

Set user entry

kubectl config set-credentials julius@foo --client-key=julius.key --client-certificate=foo-julius.crt

Set context

kubectl config set-context bar --cluster=foo --user=julius@foo