Transport Layer Security (TLS)

What is Transport Layer Security (TLS)?

Transport Layer Security (TLS) is a network security protocol established in 1999 by the Internet Engineering Task Force (IETF) to improve the security of web applications. The protocol facilitates authentication and encryption of the conversation and preserves the data integrity of any communication occurring on the network. TLS is also used in Kubernetes clusters. It enables safer communication between Kubernetes resources such as pods, containers, and other workload resources.

Understanding TLS

The Transport Layer Security (TLS) protocol encrypts communications over a network. These include text conversations such as messaging or email, Voice over IP (VoIP), and more. The protocol was developed as an improved version of Secure Socket Layer (SSL) in 1999 and is used today by several websites. The prefix https denotes that the website or web-based application uses TLS to secure its communications on the internet. 

TLS accomplishes three things:

  • Authentication: It helps any party verify that the party on the other end is who they claim to be.
  • Data Encryption: It transforms the contents of the communication between two parties into a code through cryptography. Only the intended party can decode the contents.
  • Data Integrity: TLS helps validate that the data being exchanged between entities is not forged or tampered with.

TLS accomplishes the three aforementioned tasks with a TLS handshake. This method initiates a connection between any two parties. 

Example: A TLS handshake between a client device and a web server

  • The client and the web server send a message with their TLS version.
  • The two determine which cipher suite to use. A cipher suite is a group of algorithms and keys used for encryption and decryption of the message. 
  • The identity of the server is authenticated using a TLS certificate. A TLS certificate specifies who owns the website’s domain and server’s public key. This information is used for authenticating the server.
  • The session keys for encrypting the conversation after the handshake is generated.

With the TLS handshake, the protocol improves any web application’s security by ensuring its communications are encrypted and the interactions, such as client requests, are only from authenticated users.

TLS in Kubernetes

In Kubernetes, TLS must be integrated into all resources such as Kubelet, API Server, pods, and other objects to ensure secure communication between them. This can be carried out via TLS bootstrapping, which involves the following steps:

  • Bootstrapping initialization
  • Configuration of individual components
  • Creation of Certificate Authority key and certificate
  • Bootstrap authentication with Bootstrap tokens and Token authentication file
  • Authorization for objects to create a CSR
  • Approval of CSR
  • Signing of CSR
  • Uploading the CSR to the bundle

Benefits of TLS in Kubernetes

TLS offers four primary benefits in a Kubernetes environment:

  • Data and contents of communication within and outside the environment can be made confidential. Furthermore, the encryption allows the engineers to ensure data integrity.
  • All requests are authenticated, preventing malicious users and cyber criminals from conducting a successful security attack or breach.
  • Since TLS encryptions require a decryption key that is stored securely, even if attackers can intercept a message or a data transfer, they will not be able to decrypt it without the respective key. Thus TLS prevents man-in-the-middle attacks.
  • Implementing TLS in a web application is a standard practice that must be adhered to. With the protocol’s deployment, the web application meets compliance regulations and increases the website’s credibility.

Implementing TLS in Kubernetes

To integrate TLS in the Kubernetes environment, engineers must create TLS certificates that the TLS server or client must trust. This is done by creating a bundle of TLS certificates for various Kubernetes resources. The standard way to create TLS for Kubernetes service accessed through DNS:

Create a Certificate Signing Request

cat <<EOF | cfssl genkey - | cfssljson -bare server
{
  "hosts": [
    "my-svc.my-namespace.svc.cluster.local",
    "my-pod.my-namespace.pod.cluster.local",
    "192.0.2.24",
    "10.0.34.2"
  ],
  "CN": "my-pod.my-namespace.pod.cluster.local",
  "key": {
    "algo": "ecdsa",
    "size": 256
  }
}
EOF

With the above command, a private key and a certificate signing request (CSR) is generated. In the above example:

192.0.2.24 is the service’s cluster IP, my-svc.my-namespace.svc.cluster.local is the service’s DNS name, 10.0.34.2 is the pod’s IP, and my-pod.my-namespace.pod.cluster.local is the pod’s DNS name.

The command generates server.csr containing the PEM encoded PKCS#10 certification request and server-key.pem containing the PEM encoded key to the certificate still to be created.

Create a CSR Object

cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: my-svc.my-namespace
spec:
  request: $(cat server.csr | base64 | tr -d '\n')
  signerName: example.com/serving
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF

The above command generates the CSR manifest (YAML) and sends it to the API Server.

Approve CSR

kubectl certificate approve my-svc.my-namespace

With the above command, the CSR is approved. However, the engineer needs to be a cluster administrator authorized to approve the certificate request. Alternatively, certificates can be automatically approved.

Sign the CSR

A signer ideally looks for approved CSR and their signername. Once the approval is checked, the certificate is signed and uploaded to the API.

Create a Certificate Authority

cat <<EOF | cfssl gencert -initca - | cfssljson -bare ca
{
  "CN": "My Example Signer",
  "key": {
    "algo": "rsa",
    "size": 2048
  }
}
EOF

In Kubernetes, one requires an authority to provide a digital signature on a new certificate. The above command will generate a new CA key in a new certificate authority key file called ca-key.pem and certificate ca.pem.

Issue a certificate

{
    "signing": {
        "default": {
            "usages": [
                "digital signature",
                "key encipherment",
                "server auth"
            ],
            "expiry": "876000h",
            "ca_constraint": {
                "is_ca": false
            }
        }
    }
}

Use a server-signing-config.json signing configuration and the certificate authority key file and certificate to sign the certificate request:

kubectl get csr my-svc.my-namespace -o jsonpath='{.spec.request}' | \
  base64 --decode | \
  cfssl sign -ca ca.pem -ca-key ca-key.pem -config server-signing-config.json - | \
  cfssljson -bare ca-signed-server

This produces a signed serving certificate file, ca-signed-server.pem.

Issue a certificate

Finally, populate the signed certificate in the API object’s status:

kubectl get csr my-svc.my-namespace -o json | \
  jq '.status.certificate = "'$(base64 ca-signed-server.pem | tr -d '\n')'"' | \
  kubectl replace --raw /apis/certificates.k8s.io/v1/certificatesigningrequests/my-svc.my-namespace/status -f -

This is the general procedure for creating a TLS certificate, verifying it, and uploading it to the bundle.

To integrate TLS into different Kubernetes components, engineers must bootstrap the components. This would ensure that all communications between control plane components, such as the API server, and worker node components, such as kubelet and kube-proxy, are private and uninterrupted. Furthermore, all communications will only occur between trusted components. You must also ensure that your etcd which stores all Kubernetes secrets, is integrated with TLS, as one of the secrets will comprise TLS private keys and certificate bundles.

Challenges and considerations for TLS in Kubernetes

Integrating TLS into a Kubernetes environment is challenging due to the complex configuration procedure. Each object or resource must be integrated into TLS, which is a tedious process. This consumes additional time, energy, and cost.

Furthermore, all certificates are signed for a specific time. Once it has lapsed, the certificate’s validity expires. Renewing the certificate becomes difficult. Besides this, certification rotation will also consume too much time. 

If certificate rotation, renewal, and revocation become the primary focus, the performance of the Kubernetes environment is hampered, which would lead to a higher latency in responding to client requests. Moreover, Kubernetes environments are, more often than not, dynamic in nature. Thus, in a continuously changing environment where resources are added and removed based on the requirements, managing TLS would be incredibly difficult.

Stay up to date