Kubernetes Security

Secure connection from an application running in Kubernetes to external databases.

The Problem - Security

 

You see, in this day and age, cybercrime is rampant. Hackers are constantly looking for vulnerabilities to exploit in order to gain access to sensitive information or disrupt critical systems. From government agencies to private businesses, nobody is safe.

That's why security is crucial. It's not just about protecting data, it's about protecting people. It's about ensuring that sensitive information, such as personal data, financial information, and intellectual property, is kept safe and secure.

That's why companies are investing more and more in security measures. From encryption to firewalls to employee training, companies are taking a multi-layered approach to security to ensure that their systems and data are as secure as possible.

So if you're working in technology, or really any industry that deals with sensitive information, security should always be at the forefront of your mind. And that's something that should always be taken seriously.

 

Implement secure k8s applications

You're a SRE engineer, and you've been tasked with deploying on AKS infrastructure a new application. You've got all sorts of cool tools and technologies at your disposal, and you're ready to start building.

But wait a minute, hold up. Before you start deploying, you need to think about something crucial: data protection. That's right, it's not just about deploying a cool application that works well, it's about ensuring that the data of the application is kept safe and secure.

Think about it like this. You're building a bank vault, and the vault is only as strong as its weakest point. If you've got a big, heavy door with all sorts of security features, but the walls are made of cardboard, then the whole thing is worthless.

It's the same with your application. If you've got all sorts of fancy security features in place, but your data is transferred in an unencrypted way, then it's all for nothing. Hackers will be able to easily access that data and use it for their own nefarious purposes.

You need to think about stuff like encryption, access control, and data backup and recovery. You need to design your infrastructure in such a way that if one layer of security fails, there are other layers in place to protect the data.

So don't just think about building and deploying a cool application. Think about protecting the data that the application deals with. Because in the end, that's what really matters.

 

Secure connection from a k8s application to an external database

Picture this, you're a SRE engineer tasked with deploying an application using Kubernetes.

Everything's going great until you realize that your application needs to connect to a database that's outside of the Kubernetes cluster.

You know that if you don't secure that connection, you're leaving your application and its users vulnerable to attacks from cybercriminals.

Is that really needed?

The problem with securing connections from Kubernetes applications to databases outside the cluster is a common one, faced by SRE engineers.

When an application running inside a Kubernetes cluster needs to access a database outside the cluster, the data transmitted between them is not secure by default. This leaves both the application and the data vulnerable to attacks from cybercriminals.

 

 

Use cases / user stories

       A company has a Kubernetes cluster running a web application that needs to access a database hosted on a cloud provider's infrastructure. The company wants to ensure that all traffic between the application and the database is secure and encrypted, but they're concerned that the default network connections between the cluster and the database may be vulnerable to attacks.

       A software engineer is working on a new project that involves deploying a Kubernetes application that accesses a database outside the cluster. The engineer wants to ensure that the connection between the application and the database is secure, but is unsure of the best way to do this without adding complexity to the deployment process.

       A government agency is running a Kubernetes cluster that includes applications that access databases with sensitive information. The agency is required to comply with strict security regulations and needs to ensure that all connections between the cluster and the databases are secure and meet compliance requirements.

 

In all of these scenarios, the problem is the same: how to ensure that the connections between the Kubernetes applications and the external databases are secure and protected from cyberattacks.

 

 

Solution Proposal

 

You start brainstorming ways to secure that connection, and after some research, you come up with a solution: a VPN. By setting up a VPN, you can create a secure tunnel between your application in Kubernetes and the database outside of the cluster.

 

Solution description

The solution of setting up a VPN connection provides a secure and encrypted tunnel for all traffic, ensuring that the data transmitted between the application and the database is protected from potential security vulnerabilities.

So, this way, all traffic between the application in the cluster and the database will be transmitted through a secure and encrypted connection, providing the best security.

 

Here is a high level infrastructure diagram of the VPN implementation

 

 

Implementation

 

You roll up your sleeves, grab a cup of coffee, and get to work. You start building the VPN image by creating a Docker image that includes all the necessary components for the VPN.

This includes installing and configuring strongSwan, which is an open-source modular and portable IPsec-based VPN solution. Additionally, a custom configuration file is created to set up the VPN connection parameters.

The Docker image is then tested locally to ensure that the VPN is set up correctly and that it can connect to the external database. Once the image is ready, it can be pushed to a container registry, such as Docker Hub or Azure Container Registry.

Now it's time to deploy that image to Kubernetes. You create a deployment that includes the VPN image and configure the necessary environment variables, including the IP address and port of the database. You also create a Kubernetes service to expose the VPN deployment to your application.

Finally, you test the connection between your application and the database, and it works flawlessly. You sit back, take a sip of your coffee, and smile. You've solved the problem of securing connections from Kubernetes applications to databases, and you've done it in style.

 

Image build

 

Building a StrongSwan VPN Docker image is a relatively straightforward process that involves a few key steps:

 

Choose a base image: Start by selecting a suitable base image for your Docker container. This will provide the foundation for your StrongSwan VPN image. A popular option is the Alpine Linux distribution, which is lightweight and secure.

 

Open a text editor or IDE and create a new file named Dockerfile in your project directory. Add custom configuration files or other assets in the project directory.

 

Build the Docker image using the docker build command. You can then run the image using the docker run command.

 

That's it! By following these steps, you can easily create a Dockerfile that specifies the configuration for your Docker container and build a Docker image from it.

 

Docker can build images automatically by reading the instructions from a Dockerfile.

A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image.

 

More info can be found at: https://docs.docker.com/engine/reference/builder/

 

Here are the Dockerfile commands that we will use next to build the Dockerfile

 

FROM -> sets the alpine image + version to run on the image;

ENV -> initiates the global variable for PSK;

VOLUME -> creates an internal volume where the VPN config files are mounted (such as ipsec.conf);

COPY -> imports the necessary scripts to the image

 

RUN – installs various dependencies to the image;

-update -> updates the image with the latest packages

-supervisor -> a process management system that has the purpose to start the ipsec service and run the other dependent script;

-strongswan -> installs strongswan

-bash -> installs bash

 

ENTRYPOINT instruction is used to set executables that will always run when the container is initiated.

 

 

 

1) The Dockerfile – the document that contains all the commands a user could call on the command line to assemble an image.

 

Choose alpine version from here: https://hub.docker.com/_/alpine?tab=description

Always take the next one before "edge", in your case the 3.17.3 will be a newer alpine version:

 

 

 

FROM alpine:3.17.3

ENV VPN_PSK password

VOLUME ["/etc/ipsec.d"]

 

COPY run_supervisord.sh /opt/bin/run_supervisord.sh

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

COPY strongswan.conf /etc/strongswan.conf

COPY run.sh /opt/bin/run.sh

 

RUN apk update && apk add supervisor && apk add strongswan && apk add --no-cache --upgrade bash

 

ENTRYPOINT ["bash", "/opt/bin/run_supervisord.sh"]

 

2) The run_supervisord.sh script us ran on container startup and has the purpose to start supervisord.

 

#!/bin/bash

/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf

 

3) The supervisord.conf is the conf file of supervisord, where you define which services should be started by the supervisord.

 

[supervisord]

nodaemon=true

 

[program:runsh]

command=/bin/bash /opt/bin/run.sh

startsecs=0

startretries=0

priority=1

 

[program:ipsec]

command=ipsec start --nofork

redirect_stderr=true

numprocs=1

stdout_logfile=/dev/fd/1

stdout_logfile_maxbytes=0

priority=10

 

Details about each supervisord option here -> http://supervisord.org/configuration.html

 

4) run.sh -> script that is used to do the following:

-set the PSK from the global variable $VPN_PSK to ipsec.secrets

-copy the ipsec.conf from /etc/ipsec.d/ to /etc/

 

#!/bin/bash

#PATH=/bin:/bin/bash:/usr/lib/bash:/bin/cp:/bin/sh:/bin/busybox:/bin/ash:/bin/cat

 

if [[ "$VPN_PSK" = "password" ]]; then

# Generate a random password

VPN_PSK=$VPN_PSK;

fi;

 

if [[ -f "/etc/ipsec.d/ipsec.conf" ]]; then

cp -f /etc/ipsec.d/ipsec.conf /etc/ipsec.conf;

fi;

 

cat > /etc/ipsec.secrets <<EOF

# This file holds shared secrets or RSA private keys for authentication.

# RSA private key for this host, authenticating it to any other host

# which knows the public part.  Suitable public keys, for ipsec.conf, DNS,

# or configuration of other implementations, can be extracted conveniently

# with "ipsec showhostkey".

: PSK "$VPN_PSK"

EOF

 

5) Strongswan.conf

 

Has the purpose to set the parameter "make_before_break = yes";

More details about "make-before-break", here -> https://docs.strongswan.org/docs/5.9/config/rekeying.html

 

 

CONFIG FILE example:

 

# strongswan.conf - strongSwan configuration file

# Refer to the strongswan.conf(5) manpage for details

# Configuration changes should be made in the included files

 

charon {

load_modular = yes

make_before_break = yes

plugins {

include strongswan.d/charon/*.conf

                }

}

 

include strongswan.d/*.conf

 

 

Once the above 5 files are defined, you have to create an image. In order to create the image, you need:

 

1) Put all the files under 1 single folder;

2) Open a shell session from folder at point 1, with powershell of gitbash, and run

 

docker build .

 

3) Once the image is build, take the ID of the image with command:

Docker images

 

 

 

Copy the "Image ID"

 

4) Create a tag with your image ID:

 

Docker tag <image-id> <repository>/<name>:<tag number>

E.g.: docker tag 8e746f94dac3 username/VPNimage:v1

 

5) Once the tag is created, push it to your repo of choice:

 

Docker push <image-id> <repository>/<name>:<tag number>

E.g.: docker push username/VPNimage:v1

 

 

 

 

To run the VPN image that was previously built in an AKS (Azure Kubernetes Service) cluster, you can follow these steps:

 

Push the VPN image to a container registry such as Azure Container Registry or Docker Hub. This will make the image accessible to your AKS cluster.

 

Create a Kubernetes manifest file that defines the deployment and the VPN pod.

Apply the manifest file to your AKS cluster using the kubectl apply command.

 

That's it! By following these steps, you can run the VPN image in your AKS cluster and ensure that your applications have a secure connection to your databases. Remember to update your VPN deployment and image as needed to keep your infrastructure secure and up to date.

 

Next Steps

 

After securing the connections from Kubernetes application to databases, the next step to secure AKS (Azure Kubernetes Service) would be to implement a comprehensive security strategy for the entire AKS infrastructure.

Next we will present some steps you can take to secure your AKS cluster.

Some of these topics will be tackled in separate articles.

 

What next?

 

       Enable RBAC (Role-Based Access Control) to control access to your AKS cluster resources and Azure AD (Active Directory) to manage access to your AKS cluster.

       Use Azure Security Center to monitor and detect threats to your AKS cluster.

       IPtables firewall on containers.

       PGP (Pretty good privacy) on SFTP pod

       Implement Network Policies to restrict traffic flow within your AKS cluster.

       Use WAF before your AKS cluster.

       Implement a backup and disaster recovery plan to protect against data loss or system failures.

 

By implementing these steps, you can significantly improve the security of your AKS cluster and protect your applications and data from threats. It's important to regularly review and update your security strategy to stay ahead of emerging threats and vulnerabilities.

 

References

 

Strongswan - https://www.strongswan.org/

Docker - https://docs.docker.com/reference/

AKS - https://learn.microsoft.com/en-us/azure/aks/

The case for cloud development

Jun, 2023 Yalos Team

I would like to present the design paradigm behind many of Kubernetes algorithms in the hope that this could be useful to other teams that develop cloud-based software. While these are concepts that I have found in k8s they could apply in various other cases. Chiefly on the architecture of k8s is that the hardware is not assumed to be 100% reliable.

read

a consulting boutique that delivers software at scale, all around the world, with continuous operation.