How to Secure Kubernetes Ingress?
Published 07/13/2022
This blog was originally published by ARMO here.
Written by Ben Hirschberg, VP R&D & Co-founder, ARMO.
Ingress aims to simplify the way you create access to your Kubernetes services by leveraging traffic routing rules that are defined during the creation of the Ingress resource. This ultimately allows you to expose HTTP and HTTPS from outside the Kubernetes cluster so you no longer need to expose each service separately—something that can be expensive and tedious as an application scales, resulting in an increase in services.
Ingress also plays a vital role in securing your Kubernetes application because you can provision TLS within the Ingress resource itself. This is crucial considering other forms of securing Kubernetes applications such as network policies, which are built on an application-centric concept that determines and secures how pods communicate with each other.
Restricting pod-to-pod networking is a step in the right direction to securing a Kubernetes application. But network policies are not synonymous with firewalls, as this method only determines whether a connection is allowed—not authentication or encryption in transport, which TLS allows and is configured in the Ingress resources.
This article will look into how we can secure Ingress resources via adding TLS to Ingress and then procuring TLS/SSL certificates.
SSL/TLS for Kubernetes Ingress
Configuring Ingress in your Kubernetes application involves configuring an Ingress controller and defining the Ingress resource. The Ingress controller handles SSL, whereas the TLS certificate references are added to the Ingress resource as a Kubernetes secret object, which is accessed by the Ingress controller and made a part of its configuration. For the purposes of this blog, we’ll use the NGINX controller.
Configuring the Controller for SSL
Let’s start by configuring the controller. This is fairly simple since we are using NGINX. We need to add the ssl_certificate_by_lua_block in our nginx.conf. This is a directive run when NGINX is about to perform the SSL handshake
ssl_certificate_by_lua_block { certificate.call() }
Create a TLS-Secure Object
For this, you need to create the Kubernetes secret object that will contain the certificate-related information. It will be this secret that will be referred to in the Ingress object so you don’t need to put sensitive information in the resource definition itself.
The secret object will contain the server.crt and the server.key that we procure from the certificate authority. How we actually acquire this will be explained after we set up the TLS resource.
You have to create the secret in the namespace where you have your Kubernetes application. So, you need a secret YAML definition like the one shown below:
apiVersion: v1 kind: Secret metadata: name: armo-tls-example namespace: dev type: kubernetes.io/tls data: server.crt: | <crt contents here> server.key: | <private key contents here>
The secrets file can be generated by using the following command:
kubectl create secret armo-tls-example \ --namespace dev \ --key server.key \ --cert server.crt
You should specify the file paths of server.crt and server.key in the command. In the example above, you can see that we have named the secrets object armo-tls-example. We will refer to this object by this name in our Ingress resource YAML definition.
Add a TLS Definition to the Ingress Resource
Now that you’ve created the secret object, you need to leverage it in the Ingress resource YAML definition. For example, if the Ingress resource YAML file is as below:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: armo-ingress-example spec: ingressClassName: nginx rules: - host: armoexample.com http: paths: - path: /kubernetes pathType: Prefix backend: service: name: armoservice1 port: number: 80 - path: /kubernetes/security/ pathType: Prefix backend: service: name: armoservice2 port: number: 80
With the TLS definition block, the YAML definition should be as follows:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: armo-ingress-example spec: ingressClassName: nginx tls: - hosts: - armoexample.com secretName: armo-tls-example rules: - host: armoexample.com http: paths: - path: /kubernetes pathType: Prefix backend: service: name: armoservice1 port: number: 80 - path: /kubernetes/security/ pathType: Prefix backend: service: name: armoservice2 port: number: 80
This adds the TLS block under the spec field of the YAML definition. The secret is referenced by the name chosen when it was created, armo-tls-example. You also need to make sure the TLS block and rules block have the same host since the TLS is being applied to the Ingress traffic per the rules defined.
Acquiring SSL Certificates
Acquiring SSL certificates requires the setup of an issuer and a certificate authority (CA). The issuer simplifies the lifecycle automation of the certificates generated by the CA by defining how to procure, renew, and utilize the certificates.
We’ll be using cert-manager, which is one of the most popular certificate issuers. For the CA, we’ll use Let’s Encrypt, also one of the more popular CA tools.
The first thing you need to do is install cert-manager in your Kubernetes cluster. This is fairly simple if you use Helm. If needed, you can refer to cert-manager’s documentation.
After verifying that you have installed cert-manager correctly, move on to creating the certificate issuer YAML definition for Let’s Encrypt. Remember, cert-manager alone cannot issue certificates. It is the CA, Let’s Encrypt in this case, that will handle the actual certificate issuance.
The certificate issuer YAML for Let’s Encrypt would be as shown below:
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: armo-letsencrypt-example spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: example@ domain.com privateKeySecretRef: name: armo-letsencrypt-example solvers: - http01: ingress: class: nginx
From the YAML description above, the major things to consider are:
- The API version used to build the resource is that of cert-manager. Check cert-manager documentation to ensure you’re using the latest stable API version.
- The Let’s Encrypt access details are captured in the email and privateKeySecretRef fields.
- The acme field is the issuer type. You can read more about ACME in cert-manager’s documentation.
Now that the certificate issuer is set up, you need to reference it in your Ingress resource YAML description. This can be done using annotations in the YAML file.
Considering the Ingress YAML file we used in the previous sections, the new YAML file should be the following:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: armo-ingress-example annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: armo-letsencrypt-example spec: ingressClassName: nginx tls: - hosts: - armoexample.com secretName: armo-tls-example rules: - host: armoexample.com http: paths: - path: /kubernetes pathType: Prefix backend: service: name: armoservice1 port: number: 80 - path: /kubernetes/security/ pathType: Prefix backend: service: name: armoservice2 port: number: 80
Here you have added the cert-manager.io/cluster-issuer to ensure that cert-manager detects the usage of the armo-letsencrypt-example cluster issuer, as is defined in the YAML, and procures a certificate. This will be for the name defined in the TLS hostname field that you previously added.
Adding these annotations to your Ingress resource definition should complete the steps required to provision your SSL certificates.
Conclusion
Ingress is a powerful Kubernetes resource, and being able to secure it effectively allows you to use it to its full potential. It also allows you to harden your Kubernetes application security.
This piece has covered the basics of setting up TLS in Ingress as a way to bolster security. However, there are many more complex security measures and practices you can apply. That is where solutions such as Kubescape can be called upon.
Kubescape is a Kubernetes open-source platform providing a multi-cloud K8s single pane of glass, including risk analysis, security compliance, RBAC visualizer, and image vulnerabilities scanning.
To better explore how Kubescape can help you increase the security of your Kubernetes environments and clusters, visit the Kubescape GitHub page.
Related Articles:
How to Demystify Zero Trust for Non-Security Stakeholders
Published: 12/19/2024
Why Digital Pioneers are Adopting Zero Trust SD-WAN to Drive Modernization
Published: 12/19/2024
Managed Security Service Provider (MSSP): Everything You Need to Know
Published: 12/18/2024
Zero-Code Cloud: Building Secure, Automated Infrastructure Without Writing a Line
Published: 12/16/2024