Create Kubernetes manifests to expose PersistentVolumeClaims
You may have encountered a situation in your day-to-day product development where you needed to get your hands on some persistent files that reside on the Kubernetes cluster. A common and safe approach is to perform port forwarding, either with the help of Kubectl or pure SSH using a bastion host.
In either case, once you’re done with the task, you’ll end the session, and for each future interaction, you’ll go through the same manual process every time.
It might be ideal, security-wise, to keep your environment as sealed as possible, giving adversaries no chance and is a valid reason to keep it that way.
But, if you want a long exposure to the underlying storage on the internet, this article is for you.
Since this file server will be publicly exposed to the Internet, your first and most important line of defense is the authentication layer. To put that in perspective, a formal definition of authentication it is necessary.
Authentication is the act of proving a claim, such as the identity of a computer system user. [source]
In simple terms, authentication occurs when a system user proves that they are who they say they are.
Now that we’ve cleared that up, let’s look at some options for integrating authentication into our web server (below).
- Use Nginx or Apache as attorneywith the help of
htpasswd
a apache tool which allows an encrypted username-password pair to be stored in a file, which can then be used to verify a given password. - Ory Oathkeeper as a attorneywith the help of Kratosanother of Ory’s products, such as identity provider. This is somewhat more complex than the previous approach, and it takes some learning curve to master configuring and provisioning those two. I’ll cover another article later on this, so stay tuned! 😉
Of course, you can add many more to this list, but to keep this article short, and honestly, since I don’t know many other solutions, I’ll stick to the above two items for now.
Another point I want to mention here is that since this article is about internet exposure, I’m not talking about private network solutions here. Even so, you can imagine that it will also be one sure option.
Now that we know Ory’s products are not the easiest to provision and the author is not an authentication expert 😁 keep it simple and go for the first approach.
create the htpasswd
Archive
htpasswd
is a fairly simple tool for enforcing a Essential authentication mechanism on any platform. It works by taking a username and password as input. The result will be a one-way encoded password to a file or standard output that can then be used to verify the user credential. Still, it can not be reverted (de-hashed) to the original password in a reasonable amount of time, at least not in 2023, with our current computing power!
For a simple demo, take a look at the snippet below.
This will just create a new file for a user and try to verify it with both the correct and incorrect password.
We will use the same on our “Secure File Server”, publicly exposed on the Internet.
reverse proxy
Unless you want to handle authentication at the file server layer (I know I won’t), you’ll use a reverse proxy to sit right up front, receiving all the traffic and failing everyone with the wrong credentials. You can even add another restriction measure, including but not limited to rate limiting, logging, instrumentation, reporting, etc.
Apache and Nginx can work with a htpasswd
file generated to verify the credential. You can view the links below for more information on each:
I’m sure other web hosts are fine, doing the same as the one mentioned here.
In this article, I will be using Nginx, and since it will be hosted on Kubernetes, it will be an Nginx docker container. This allows me to mount any number of configuration files on the /etc/nginx/conf.d
directory, and the Nginx web server process picks it up.
So if I can mount any config file in the directory, I can write a config file to a Kubernetes configuration map, and mount it in the desired directory of the container. This is powerful and quite flexible.
This is the configuration that I am about to mount in the Nginx container.
The named inputproxy_pass
that you see in the configuration file points to the file server that will expose the file system directory using the HTTP protocol. More on this in the next section.
There are only a few to mention among the many other static web hosts.
Of course, this list can grow longer, but we are trying to keep it short and informative. 😇
In this article, I’ll use the built-in Python module: http.server
. It has a simple and intuitive interface and makes it easy to use.
The way you can serve static content with it is as follows:
ADDRESS=0.0.0.0 PORT=8000 DIRECTORY=/tmp
python -m http.server -b $ADDRESS -d $DIRECTORY $PORT
This works great, especially since you don’t need to do a lot of magic to make it work.
Have this web server running and accessible from the Nginx container means you can mount your PersistentVolumeClaims on the static web server and put the Nginx described above right in front of it to gain unauthenticated access to your valuable data on the Kubernetes cluster.
Mount Kubernetes ConfigMap as a volume
Before wrapping everything up in a unified manifest, this approach uses one last piece of critical information that needs a little explanation. But if you’ve already mastered how to mount a ConfigMap as a volume in a container in Kubernetes, feel free to skip this section.
To mount a Kubernetes ConfigMap as a volume, use the projection in the volumes section of the container definition, as shown below. [source]:
Just at the same level as containers
there’s a volumes
defined, which can accept a couple of volume types, one of which is ConfigMap. This allows you to define some script and pass it as a volume to the running container.
After creating the above manifest, this is what the container logs will show.
kubectl logs job/demo -c demo
total 0
drwxr-xr-x 2 root root 45 Feb 4 06:58 ..2023_02_04_06_58_34.2149416564
lrwxrwxrwx 1 root root 32 Feb 4 06:58 ..data -> ..2023_02_04_06_58_34.2149416564
lrwxrwxrwx 1 root root 21 Feb 4 06:58 favorite-color -> ..data/favorite-color
lrwxrwxrwx 1 root root 16 Feb 4 06:58 names.txt -> ..data/names.txt
red
Alex
Jane
Sam
Now that we’ve looked at all the information piece by piece, it’s time to put it together to serve as a unified manifesto, to be used for a single purpose: An HTTP service file server.
The second file, an Ingress resource, is optional but still included as this article is about exposing a static HTTP web server to the public. You will only get internet exposure if you create the Ingress.
To implement another security measure, you can assign a UUID-generated value to your subdomain to avoid having just username and password as your ONLY security measure. It can be something like this:
415cb00c-5310-4877-8e28-34b05cadc99d.example.com
Otherwise, you’re only as secure as your username and password, and if your brand gives away the username you’ve assigned, then you’re only as secure as your password, and that’s different from where you’d like to be. to put on. in!
Also, remember that you will need HTTPS. You never want some random colleague eavesdropping on your connection, watching you transmit valuable customer data over the Internet.
Since we’re talking about Kubernetes, there’s no tie-in to any cloud provider, and just apply this practice anywhere with a Kubernetes cluster.
This will effectively mean that you can safely expose your dynamic provisioned persistent volumes to the internet!
Take the “safe” part with a grain of salt as this isn’t the safest bet, but you can still protect yourself by assigning a random string to your Ingress subdomain. In this way, the attacker will have to find the URL among many combinations on the Internet, which will take many years. At that point, we may all be gone by then!
Have a great rest of the day. stay tunedand take care!