Create a Certificate-based Kubeconfig

Preface

The goal of this article is to allow someone to access our Kubernetes server, using a certificate that only that user have access.
The certificate will allow the administrator to manage the permission associated with the user, and revoke as needed.

First, the openssl tool is used to generate a Key and CSR. Then, a role is assigned to the newly created user. Then, a kubeconfig is created specifically for that user. Finally, How to use that certificate and authenticate to the Kubernetes api server.

Private key

We will create a directory were all the certs will be store during this demonstration

mkdir ~/certs

We then create the private key for Laurent with the -out flag to output result to laurent.key file and 4096 the size of the key being 4096-bit

$ openssl genrsa -out ~/certs/laurent.key 4096

Generating RSA private key, 4096 bit long modulus (2 primes)
.......................................................................................................++++
.......................................................................................................................................++++
e is 65537 (0x010001)

Certificate Signing Request (csr)

We will now prepare the certificate signing request configuration file. This is done in a text editor (for this demo we will use vi)

$ vi ~/certs/laurent.csr.cnf

Add the following content and adapt it to your need.

[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = laurent
O = developers
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth

The certificate signing request configuration file contains all necessary information, user identity, and proper usage parameters for the user. The last argument extendedKeyUsage=serverAuth,clientAuth will allow users to authenticate their local clients with the Leaseweb k8s cluster using the certificate once it’s signed.

Now the csr creation for Laurent.

$ openssl req -config ~/certs/laurent.csr.cnf -new -key ~/certs/laurent.key -nodes -out ~/certs/laurent.csr

We can take a look at the csr with this command

$ openssl req -in certs/laurent.csr --noout -text

Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: CN = laurent, O = developers
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (4096 bit)
                Modulus:
                    00:c7:f1:2c:bf:e6:b0:d8:76:38:55:43:6a:b8:e1:
[...]

Approval

We will now send this csr to kubernetes cluster and then approve it so that the user Laurent can access the cluster.

first we need the base64 of the csr file

$ cat ~/certs/laurent.csr | base64 | tr -d '\n'

LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJRWJEQ0NBbFFDQVFBd0p6RVFNQTRHQTFVRUF3d0hiR0YxY21WdWRERVRNQkVHQTFVRUNnd [...]

Then create the following CertificateSigningRequest manifest

$ vi laurent-csr.yml

With this content

laurent-csr.yml
---
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: laurent-authentication
spec:
  signerName: kubernetes.io/kube-apiserver-client
  groups:
    - system:authenticated
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJRWJEQ0NBbFFDQVFBd0p6RVFNQTRHQTFVRUF3d0hiR0YxY21WdWRERVRNQkVHQTFVRUNnd [...]
  usages:
  - client auth

Then we apply this manifest to k8s cluster

$ kubectl apply -f laurent-csr.yml

certificatesigningrequest.certificates.k8s.io/laurent-authentication created

We will now approved the new csr and save it to our certs directory.

We approved the csr

$ kubectl certificate approve laurent-authentication

Then we get the newly approved certificated

kubectl get csr laurent-authentication -o jsonpath='{.status.certificate}' | base64 --decode > ~/certs/laurent.crt

This will decode the base64 and save the result to our laurent.crt file.

kubeconfig

Next, you will create a specific kubeconfig file for the laurent user. This will give you more control over the user’s access to your cluster.

First you can make a copy of the kubeconfig you downloaded from the customer portal

cp <path_to_saved_kubeconfig> ~/certs/laurent.kubeconfig

We then modify the file and point the user section to the cert and key we have created.

laurent.kubeconfig
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FUR [...]
    server: https://212.7.193.11:6443
  name: k8s-0000001
contexts:
- context:
    cluster: k8s-0000001
    user: laurent # <- This is what need to be change
  name: k8s-0000001
current-context: k8s-0000001
kind: Config
preferences: {}
users:
- name: laurent
  user:
    client-certificate: certs/laurent.crt # <- This is what need to be change
    client-key: certs/laurent.key # <- This is what need to be change

Authentication

Finally, we test the newly created kubeconfig by authenticating

# kubectl --kubeconfig laurent.kubeconfig cluster-info

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Error from server (Forbidden): services is forbidden: User "laurent" cannot list resource "services" in API group "" in the namespace "kube-system"

We get an access Forbidden as we have a user but no role or permission setup yet.

Get Support

Need Technical Support?

Have a specific challenge with your setup?

Create a Ticket