1. User Authentication

By default the Kube-api-server does not have user authentication. Instead you can use signed certificates to authenticate a user and the users group, as the kube-api-server will trust certificates signed by its own certificate-authority and has an internal mechanism known as certificate signing requests with which approval can be sought to sign certificates with the internal CA.cert.

1.1. Certificate as User Authentication Step-by-Step

To have a certificate represent a user there are 3 requirements of the certificate:

  • the CN (common name field) is populated with the username desired, or more specifically the username the administrator has/ expects for you with your roles/ role bindings.

  • the O (organisation filed) is populated with the groups of the user that the administrator is expecting (can specify multiple).

  • the certificate is signed by the kubernetes certificate authority (part of any kubernetes cluster)

To do this you must have completed the following Prerequisites -> Generate the Users Private Key -> Generate a Certificate Signing Request -> Use CSR in Kubernetes yaml File to Request Signing by Administrator.

1.1.1. Prerequisites

1.1.2. Generate the Users Private Key

First to get this certificate to represent a user we need to generate a private key. This private key is a secret that only the user should have as for all intensive purposes it is the user when embedded in a certificate as far as the kube-api is concerned.

Bash shell example; Generating private key

openssl genrsa -out username.key 2048

Replace username with the desired username

1.1.3. Generate a Certificate Signing Request

Warning

The username and group (s) used here must match what the roles/ role bindings are expecting, or else they simply wont allow the user under RBAC to access anything even if they are accepted.

Now that we have the private key we want to use, we need to create a certificate signing request (CSR) to associate the private key with a certificate that contains all the additional information we want it to be related to like the common name, and organisation fields.

Bash shell example; certificate signing request generation

openssl req -new -key username.key -out username.csr -subj "/CN=username/O=group"

OR

Bash shell example; multi group certificate signing request generation

openssl req -new -key username.key -out username.csr -subj "/CN=username/O=group1/O=group2"

Warning

Make sure you replace username and group with the correct/ desired username and group specified by your cluster administrator. (the last username and group are not highlighted as quoted)

Note

It is advisable to check your now created CSR which should if you followed the above be called username.csr. You can check your CSR by:

Bash shell example; inspect CSR

openssl req --noout -text -in username.csr

You should see something akin to the following towards the top:

Certificate Request:
  Data:
      Version: 1 (0x0)
      Subject: CN = username, O = group
      Subject Public Key Info:
          Public Key Algorithm: rsaEncryption
              RSA Public-Key: (2048 bit)
              Modulus:

If these are not correct, create a new certificate now, otherwise you will be waiting for acceptance to only get rejected because they are incorrect later.

See also:

1.1.4. Use CSR in Kubernetes yaml File to Request Signing by Administrator

Now that we have a private-key, and a certificate signing request (.csr) file, we can now ask the kubernetes api to consider us for authentication, where an admin can accept/ decline us or a pre-defined rule can accept/ decline us.

To do so we need to define a short YAML file as seen below:

 1apiVersion: certificates.k8s.io/v1
 2kind: CertificateSigningRequest
 3metadata:
 4  name: <YOURNAME>
 5spec:
 6  groups:
 7  - system:authenticated
 8  request: <YOUR certificate_signing_request.csr GOES HERE as BASE64 ENCODED>
 9  signerName: kubernetes.io/kube-apiserver-client
10  usages:
11  - client auth

We need to substitute our name or more specifically the name we used earlier in the CN field. If you have forgotten what it was or need to double check please refer to Generate a Certificate Signing Request which tells you how to inspect the certificate as well as generate it. We also need to insert our certificate in one line and Base64 encoded. If encoding the certificate gives you any problems try our Helm helper template (you will need to have Helm installed) Located here. Simply download the files pointed to here and run:

Bash shell example; Helm CSR template generator

helm template folder/path/to/csr --set username=username,csr=secrets/file-name.csr

This will paste the correct contents to your terminal which you can paste into a file, should it be correct. There should be no blank entries in particular where there are comments, there should be text between the comment and the preceeding colon of the same line I.E request: jhaiusdf912iudifgakdujh27dhf # comment NOT request: # comment. check both request and name. If one or the other is blank that means you have set the names or paths wrong.

where:

  • folder/path/to/ is the path to the folder containing the Chart.yaml file of the helm chart.

  • secrets/file-name is the relative path from the above folder to find your csr file created in Generate a Certificate Signing Request.

Note

our CSR should be embedded in the above file next to request. This CSR should be embedded as Base64. If you are on linux you can use the following to get the properly formatted base64 string to insert:

cat username.csr | base64 | tr -d "n"

Now that we have a CSR yaml file lets call it csr.yaml for consistency. We can submit this to kubernetes and await approval. We can do this in two ways:

  • Ask our administrator (or someone else with permissions) to submit the file to the api-server for approval

  • Submit the file ourselves for approval to cut out the middleman, if we have credentials to do so, like some generic CSR submitting user (Ask your admin if there is one).

Please do mention the CSR submission to someone who can approve it, as an hour after submission it will automatically be removed from the kube-api-server by default, effectively being declined.

Note

An authorised kubernetes administrator will then likeley run:

Bash shell example; get/ check csrs’

kubectl get csr -o wide
Bash shell example; approve or decline the csr

kubectl certificate approve|decline username
Bash shell example; get CSR if approved, and give to user without perms

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

1.1.5. Use Approved CSR to Authenticate to Kube-Api

We now should have both a private key (username.key) from Generate the Users Private Key, and a signed certificate (username.crt) from kubernetes in Use CSR in Kubernetes yaml File to Request Signing by Administrator. The last thing we need is the public certificate-authority certificate so that our client when connecting to the kube-api can also verify that it is also signed by the certificate-authority, to prevent redirecting attacks of some sort. You will either be given the certificate-authority certificate (usually called ca.cert) by your admin, if not you should request it as you will need it to communicate to the kube-api server to issue your commands.

Given these 3 things along with we know our username and more than likely know the ip address where the kube-api is running we can finally configure out kubectl config file.

I have provided another Helm template so you can generate your kubectl config with it or you can replicate a similar example to the documentation / use kubectl commands to generate the config. This template is at https://github.com/DreamingRaven/deep-kube-docs/tree/master/helpers/kubectl

simply run as before:

Bash shell example; generate a kubectl config

helm template folder/path/to/kubectl --set username=username,ca_cert=certificates/ca.cert,user_cert=certificates/username.cert,user_key=certificates/username.key,kube_api_address=https://192.168.1.102:6443

where:

  • folder/path/to/ is the path to the parent folder that contains Chart.yaml exists on your system after you downloaded this helm chart from https://github.com/DreamingRaven/deep-kube-docs/tree/master/helpers/kubectl

  • username is the username you used throught this process

  • 192.168.1.102 is the accessible address of the machine hosting the kube-api-server

  • 6443 is the port the kube-api-server is listening on, by default: 6443

See also: