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 is 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 Certificate Signing Request 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 approve 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.