How to Generate a Self-Signed Certificate for Kubernetes?

Photo of author

By admin

Technology has evolved across ages, still creating a self-signed certificate for Kubernetes is nevertheless hard. We will show you how to create a self-signed Kubernetes certificate with the help of just a few commands. But in case you can’t create the self-signed one, you can definitely go for the TLS certificate. The certificate will be signed by the Certificate Authority (CA) so that it can prove the authenticity of the copy.

Generally, people use these CA certificates to authorize any work process. We will shortly come into the part where you are able to learn how to create a self-signed certification for Kubernetes. But before that, let’s have a look at the things you require to create a self-signed certificate.

Prerequisites for Creating a Self-Signed Certificate for Kubernetes

If you have a Kubernetes cluster on your computer, it will help you with the process. But if not, you can create one. But make sure that there is the kubectl command-line tool on your system and it is configured properly. You can check out this guide where you will find how to properly set up and configure the kubectl command-line tool. The kubectl command-line tool will help your computer to interact with the cluster. Also, make sure that you are following this guide and running the commands on a cluster that has at least two cluster nodes. Apart from the cluster nodes that have the role of control plane hosts, you will need two separate ones.

However, if there is no Kubernetes cluster, you can construct one by using minikube. Apart from that, you can use one of these Kubernetes playgrounds as an alternative to minikube:

Alternatively, you can create a Kind Kubernetes in a docker cluster using the commands given below.

kind create cluster

export KUBECONFIG=”$(kind get kubeconfig-path –name=”kind”)”

To test if the cluster is set up properly, use the command below:

kubectl cluster-info

You can also check the version of your cluster with the following command:

kubectl version

After making sure that your PC is running a proper Kubernetes cluster, it’s time to move on to the next section. Here we can create a self-signed certificate using different methods.

Create a Self-Signed Certificate with Cert-Manager

Generally, you can create a self-generated certificate with the cert-manager, but for that, you will have to install the cert-manager first. Use the following command to install cert-manager:

kubectl create namespace cert-manager

kubectl apply –validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.13.1/cert-manager.yaml

If there is a validation error in the x-Kubernetes-preserve-unknown-fields, you can add the –validate command to the above command and then run the whole command again. After that, create a namespace where you could work to create a certificate. Creating the namespace will require the following command:

kubectl create namespace sandbox

If you want to request a certificate from any namespace, you can create a cluster issuer in Kubernetes. Here is the command to create a cluster issuer:

kubectl apply -n sandbox -f <(echo “

apiVersion: cert-manager.io/v1alpha2

kind: Issuer

metadata:

name: selfsigned-issuer

spec:

selfSigned: {}

“)

Then create a self signed certificate that is usable for the services in the sandbox namespace:

kubectl apply -n sandbox -f <(echo ‘

apiVersion: cert-manager.io/v1alpha2

kind: Certificate

metadata:

name: first-tls

spec:

secretName: first-tls

dnsNames:

– “*.sandbox.svc.cluster.local”

– “*.sandbox”

issuerRef:

name: selfsigned-issuer

‘)

After creating the certificate, check out its resource:

$ kubectl -n sandbox get certificate

NAME READY SECRET AGE

first-tls True first-tls 9s

And its subsequent secret:

$ kubectl -n sandbox get secret first-tls

NAME TYPE DATA AGE

first-tls kubernetes.io/tls 3 73s

To check whether or not the certificate is valid, use the following command:

openssl x509 -in <(kubectl -n sandbox get secret \

first-tls -o jsonpath='{.data.tls\.crt}’ | base64 -d) \

-text -noout

However, this method will only allow you to create a self-signed certificate in Kubernetes. But if you want to find TLS certificates that are signed by the CA, you can do that too. A TLS certificate will help you perform client or server authentication in Kubernetes more easily and you can generate the certificate using the cert-manager as well.

Create Multiple TLS Certificates with Cert-Manager

Again, you need to install the cert-manager. You can check out the command required to install the cert-manager in the previous section. Also, create a namespace and cluster issuer here with the same commands discussed previously. Now, create a CA certificate using the commands below:

kubectl apply -n sandbox2 -f <(echo ‘

apiVersion: cert-manager.io/v1alpha2

kind: Certificate

metadata:

name: sandbox2-ca

spec:

secretName: sandbox2-ca-tls

commonName: sandbox2.svc.cluster.local

usages:

– server auth

– client auth

isCA: true

issuerRef:

name: selfsigned-issuer

‘)

Check if the certificate and secret were created well:

$ kubectl -n sandbox2 get certificate sandbox2-ca

NAME READY SECRET AGE

sandbox2-ca True sandbox2-ca-tls 15s

$ kubectl -n sandbox2 get secret sandbox2-ca-tls

NAME TYPE DATA AGE

sandbox2-ca-tls kubernetes.io/tls 3 22s

However, this time, you will have to create a second cluster issuer. You will have to produce an Issuer resource from the CA secret you have made in the previous command:

kubectl apply -n sandbox2 -f <(echo ‘

apiVersion: cert-manager.io/v1alpha2

kind: Issuer

metadata:

name: sandbox2-ca-issuer

spec:

ca:

secretName: sandbox2-ca-tls’)

Now, create a TLS certificate from the second cluster issuer:

kubectl apply -n sandbox2 -f <(echo ‘

apiVersion: cert-manager.io/v1alpha2

kind: Certificate

metadata:

name: sandbox2-server

spec:

secretName: sandbox2-server-tls

isCA: false

usages:

– server auth

– client auth

dnsNames:

– “server.sandbox2.svc.cluster.local”

– “server”

issuerRef:

name: sandbox2-ca-issuer

‘)

Create another CA certificate from the same issuer:

kubectl apply -n sandbox2 -f <(echo ‘

apiVersion: cert-manager.io/v1alpha2

kind: Certificate

metadata:

name: sandbox2-client

spec:

secretName: sandbox2-client-tls

isCA: false

usages:

– server auth

– client auth

dnsNames:

– “client.sandbox2.svc.cluster.local”

– “client”

issuerRef:

name: sandbox2-ca-issuer

Now check if all the certificates are created:

$ kubectl -n sandbox2 get certificate

NAME READY SECRET AGE

sandbox2-ca True sandbox2-ca-tls 7m34s

sandbox2-client True sandbox2-client-tls 7s

sandbox2-server True sandbox2-server-tls 16s

$ kubectl -n sandbox2 get secret

NAME TYPE DATA AGE

sandbox2-ca-tls kubernetes.io/tls 3 8m14s

sandbox2-client-tls kubernetes.io/tls 3 48s

sandbox2-server-tls kubernetes.io/tls

 

Now, validate the certificate against the CA:

$ openssl verify -CAfile \

<(kubectl -n sandbox2 get secret sandbox2-ca-tls \

-o jsonpath='{.data.ca\.crt}’ | base64 -d) \

<(kubectl -n sandbox2 get secret sandbox2-server-tls \

-o jsonpath='{.data.tls\.crt}’ | base64 -d)

/proc/self/fd/18: OK

$ openssl verify -CAfile \

<(kubectl -n sandbox2 get secret sandbox2-ca-tls \

-o jsonpath='{.data.ca\.crt}’ | base64 -d) \

<(kubectl -n sandbox2 get secret sandbox2-client-tls \

-o jsonpath='{.data.tls\.crt}’ | base64 -d)

/proc/self/fd/18: OK

Here, now validate the client-server authentication and manage an openssl server as the environment method:

touch test.txt

openssl s_server \

-cert <(kubectl -n sandbox2 get secret sandbox2-server-tls -o jsonpath='{.data.tls\.crt}’ | base64 -d) \

-key <(kubectl -n sandbox2 get secret sandbox2-server-tls -o jsonpath='{.data.tls\.key}’ | base64 -d) \

-CAfile <(kubectl -n sandbox2 get secret sandbox2-ca-tls -o jsonpath='{.data.ca\.crt}’ | base64 -d) \

-WWW -port 12345 \

-verify_return_error -Verify 1 &

And run an openssl client test and search for the HTTP/1.0 200 ok in the client output:

echo -e ‘GET /test.txt HTTP/1.1\r\n\r\n’ | \

openssl s_client \

-cert <(kubectl -n sandbox2 get secret sandbox2-client-tls -o jsonpath='{.data.tls\.crt}’ | base64 -d) \

-key <(kubectl -n sandbox2 get secret sandbox2-client-tls -o jsonpath='{.data.tls\.key}’ | base64 -d) \

-CAfile <(kubectl -n sandbox2 get secret sandbox2-client-tls -o jsonpath='{.data.ca\.crt}’ | base64 -d) \

-connect localhost:12345 -quiet

To stop the background process, use this simple one-line command:

kill %1

Create Certificates via CFSSL

You can also generate certificates with CFSSL. CFSSL is a command-line tool for CFSSL container administration and consists of the following programs:

  • Multirootca – It is a certificate authority server
  • Mkbundle – It is a certificate pool bundle builder
  • Cfssljson – It is a certificate generator that uses json outputs from the cfssl and multirootca for the CFSSL tool.

In the following steps, we are going to talk about how to create a self-signed certificate with CFSSL. But firstly, download and install the CFSSL tool from https://github.com/cloudflare/cfssl/releases. Alternatively, you can use the following steps to install CFSSL using GO language pancakes with the following command:

sudo apt install golang

Then apply the syntax given below to download cfssl:

go get -u github.com/cloudflare/cfssl/cmd/cfssl

Copy the file from ~/go/bin to the appropriate folder:

sudo cp ~/go/bin/cfssl /usr/local/bin/cfssl

And lastly, repeat the process with cfssljson:

go get -u github.com/cloudflare/cfssl/cmd/cfssljson

sudo cp ~/go/bin/cfssljson /usr/local/bin/cfssljson

After you install the tool, you will have to create a self-signed certificate authority. However, you will also have to create a file named ca.json. Have a look at the following section to do so.

Create a Certificate Authority

The example below creates a file that we will call ca.json and the file defines the following terms:

  • CN refers to the common name for the authority
  • algo is the algorithm that has been used for the certificate
  • size is the algorithm size in bits
  • C refers to the country
  • L refers to locality or city
  • ST is State or province
  • O is Organization
  • OU is Organizational Unit

This example file is for the organization and its unit is “Example Company Root CA”. The organization is based on the United States territory, New York. So, the C of the file will be the USA, L will be New York, and so on.

{

“CN”: “Example Company Root CA”,

“key”: {

“algo”: “rsa”,

“size”: 2048

},

“names”: [

{

“C”: “US”,

“L”: “New York”,

“ST”: “New York”,

“O”: “Example Company”,

“OU”: “Example Company Root CA”

}

]

}

Once created, save the json file in a text editor and later use it to create ca.pem and ca-key.pem files with the following cfssl command:

cfssl gencert -initca ca.json | cfssljson -bare ca

Perform the cfssl.json Configuration File

The cfssl.json configuration file will have details about the certificate such as its expedition date and usage for peer, server, and client. Now the json file will look like this:

{

“signing”: {

“default”: {

“expiry”: “8760h”

},

“profiles”: {

“intermediate_ca”: {

“usages”: [

“signing”,

“digital signature”,

“key encipherment”,

“cert sign”,

“crl sign”,

“server auth”,

“client auth”

],

“expiry”: “8760h”,

“ca_constraint”: {

“is_ca”: true,

“max_path_len”: 0,

“max_path_len_zero”: true

}

},

“peer”: {

“usages”: [

“signing”,

“digital signature”,

“key encipherment”,

“client auth”,

“server auth”

],

“expiry”: “8760h”

},

“server”: {

“usages”: [

“signing”,

“digital signing”,

“key encipherment”,

“server auth”

],

“expiry”: “8760h”

},

“client”: {

“usages”: [

“signing”,

“digital signature”,

“key encipherment”,

“client auth”

],

“expiry”: “8760h”

}

}

}

}

Save the file and exit. The next section will be about creating an Intermediate Certificate Authority. So, check it out and apply the next steps.

Generate an Intermediate Certificate Authority

After creating the json file in the previous section, there is another file that you need to create that will be called intermediate-ca.json. The intermediate-ca.json file defines the intermediate certificate authority and almost looks like the previously created ca.json file. Here is what the content of this file will be:

“CN”: ” Example Company Intermediate CA”,

“key”: {

“algo”: “rsa”,

“size”: 2048

},

“names”: [

{

“C”: “US”,

“L”: “New York”,

“ST”: “New York”,

“O”: “Example Company”,

“OU”: “Example Company Intermediate CA”

}

],

“ca”: {

“expiry”: “42720h”

}

}

This is not the end of this file. You will have to sign the certificate and create a host certificate, which is discussed in the next section.

Sign the Certificate and Create a Host Certificate

Create the intermediate_ca.pem, intermediate_ca.csr and intermediate_ca-key.pem files after creating the previous ones and sign the intermediate CA by following the commands below:

cfssl gencert -initca intermediate-ca.json | cfssljson -bare intermediate_ca

Finally, sign the certificate using the CA and the cfssl.json configuration file:

cfssl sign -ca ca.pem -ca-key ca-key.pem -config cfssl.json -profile intermediate_ca intermediate_ca.csr | cfssljson -bare intermediate_ca

If you have not created the host certificate for peer, server, and client profiles, then create the host1.json file with the important host information:

{

“CN”: “host.example-company.com”,

“key”: {

“algo”: “rsa”,

“size”: 2048

},

“names”: [

{

“C”: “US”,

“L”: “New York”,

“O”: “Example Company”,

“OU”: “Example Company Intermediate CA”,

“ST”: “New York”

}

],

“hosts”: [

“host1.example-company.com”,

“localhost”

]

}

You can create a host certificate using the configuration file. Type cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config cfssl.json -profile=peer host1.json | cfssljson -bare host-1-peer to create the peer certificate that performs communication between the server.

cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config cfssl.json -profile=peer host1.json | cfssljson -bare host-1-peer

Type cfssl gencert -ca intermediate_ca.pem -ca-key intermediate_ca-key.pem -config cfssl.json -profile=server host1.json | cfssljson -bare host-1-server that will allow you to create a server certificate.

There are several additional options that let you generate a self-signed certificate for Kubernetes. But using the cert-management tool and CFSSL are the best ways. The simplest way to get the license is by using the kubectl get csr my-svc.my-namespace -o jsonpath='{.status.certificate}’ \

| base64 –decode > server.crt command. Although greatest time users are unsure of the ways to get the certificate signing requests approved. In that case, follow the section below.

How to Approve Certificate Signing Requests?

The Kubernetes administrator that has the appropriate permissions for changing the cluster files can manually approve or deny the certificate signing requests. You will have to use the kubectl certificate approval and kubectl certificate to deny commands for that. But you should also write an automated certificate controller in case you want to overuse this command. The approver of the certificate verifies if the Kubernetes self-signed certificate meets the following requirements:

  1. The subject of the certificate signing request needs the same private key that you use to sign in to the CSR. So, if a third party tries to get the certificate, the authority can recognize it. This also helps the authority to verify if the pod controls the private key that is required to generate the CSR.
  2. The subject of the CSR will be authorized, which will make sure that the CSR contains the right subject and not an invalid one. Also, the subject of the CSR will verify if the pod can participate in the requested service.

If your CSR meets these requirements, the approver of the Kubernetes certificate will approve your CSR otherwise, your request will be denied. So, before generating the certificate, try to take certain conditions into account. There are some drawbacks of self-signed certificates as well and before you try to get one, you need to consider them as well.

Know More About the Request Signing Process in Kubernetes

The type of CertificateSigningRequest resource helps the client to generate an X.509 certificate according to the signing request. In the spec.request field, there will be a PEM-encoded PKCS#10 signing request, and the request is situated in the CertificateSigningRequest object. It is an important signing request key that you need to have besides the API version. The signing request needs to be approved before it is signed and the signer will be the recipient of the certificate only (one who has made the signing request). The certificate signer request is often approved or declined automatically by the controller. Or else, you will have to manually approve it using the REST API.

Once the certificate has been approved, you will have to confirm the certificate. The controller will verify the signing conditions before creating the certificate. Once the controller updates the status of the certificate—whether or not it was approved, you will find the status in the status.certificate field of the requested certificate. The field will be empty or will contain an X.509 certificate. But once the request is approved, it will be deleted within 1 hour. The case is the same for the two other scenarios—denied and pending requests.

What are the Disadvantages of Self-Signed Certificates on Kubernetes?

Have a look at the possible disadvantages of self-signed certificates on Kubernetes:

1. Browser Warnings

Sometimes when you are trying to connect to an HTTPS website through your browser, it shows untrusted connections. So, while creating a website, self-certificates may not be the best option for you.

2. Authentication Issue

A self-signed certificate is not signed by any authority hence, it faces authentication issues. Whenever intruders want, they can displace the self-signed record with the attacker’s own hazardous definitions. And when the browser is connecting to the website with the self-signed certificate, it won’t be able to understand the subject of the certificate and communicate with it.

3. Warranty

While the third-party CA offers warranties against certain losses when there is an issue with the certificate, self-signed certificates don’t come with such warrants.

4. Customers trusts

A signed certificate such as HTTPS ensures a website’s visitors that it is safe to shop online from the website. If your website is running a self-signed certificate, it creates an untrusted environment as it conveys that your site is not authenticated. That’s why customers are not likely to trust your website.

The drawbacks mentioned above cannot be eliminated as it is a part of the self-signed certificate. But if you ignore these disadvantages and focus on other things such as the ease of generating a self-signed certificate on Kubernetes, it won’t be a problem. Also, it is suggested to place a service in front of the Kubernetes deployment that manages pods. Have a look at the section below to know how to do it.

How to Manage TSL Between Microservices in Kubernetes?

First, we want you to put service before the deployment that manages the pods in a Kubernetes cluster. The service then will generate a stable DNS and IP endpoint that will help the pods that have been deleted. By doing so, you can assign a new IP address to the pods when the pods are newly constructed again. You can enable the DNS service recovery using the ClusterIP type service. The format of the ClusterIP type service will be <service name>.<kubernetes namespace>.svc.<cluster domain>. And the cluster domain will be cluster.local as usual.

Therefore, you can use the assigned ClusterIP and the newly created DNS as the names of your self-created certificate. But what about the Kubernetes internal CA? What to do when you are generating a third-party approved certificate?

1. Kubernetes Internal CA

Kubernetes comes with internal CA and API methods to generate CSR and sign them up by the CA that would secure the microservices we talked about in the previous section. The internal CA in Kubernetes is managed by the kubelet and other internal cluster processes for the Kubernetes API server authentication purposes. However, there is no auto-renewal process for the signed certificate but the cert has a 30 days time period within which it will stay signed.

2. Certificate Management for Kubernetes

We have talked about the usage of cert-manager earlier in this article. The cert-manager helps your cluster to automatically create and manage certificates using the custom resources. If you apply the CA Issuer Type and obtain certificate sources, that will generate a certificate for Kubernetes Secret. You will find more info about this on the Kubernetes official website but you can also have a fair idea from the previous sections of this article.

Final Verdict

If your Kubernetes cluster has the requirements specified in the previous section, then you could easily generate a certificate. However, this tutorial indicates that the signer of the Kubernetes certificate should be able to complete the documents API. Kubernetes controller manager already implements the default execution pre-set by a signer. You can simply pass the –cluster-signing-cert-file parameters to the controller manager with your Certificate Authority’s keypair paths.

Generally, generating a self-signed certificate for Kubernetes takes a lot of procedures than the CA-signed certificates. If you want, you can choose to create multiple TLS certificates with cert-manager; but still, it has some complications. However, if you carefully follow the steps mentioned in this article, you can easily generate a self-signed certificate on Kubernetes. Whenever you are creating a certificate and following the commands to create one, make sure you are following the right commands in the right order.

Leave a Comment