Manage Secrets in Portainer for Docker and Kubernetes
Deploying a very basic Docker container isn’t all that hard. With just a couple of quick commands, you can have an NGINX/Alpine Linux container up and running and even do so with persistent storage. That level of simplicity is one of the beauties of Docker.
However, deploying a basic container vs. a full-stack application are two very different tasks. And then, when those deployments require security, things can get considerably more complicated.
You might even need to use environmental variables or (especially) secrets.
What are secrets? Secrets are encrypted tokens that can serve as passwords to gain access to applications without potential exposure to outside parties. They are a built-in feature of the Docker and Kubernetes orchestrators that serve as a convenient method of adding credentials to your deployments without exposing them such that a hacker could gain access to passwords or tokens and use them against you. Secrets are made secure in Docker deployments because they are not housed in container manifests and are encrypted at rest and during transit. This way, those secrets are only available to the services that have been granted explicit access and only while the service tasks are running.
So, instead of hard-coding your credentials and/or tokens in the YAML manifests, you use secrets to obfuscate that information from sight.
The problem with using secrets with Docker is that it can get far more complicated and/or not nearly as efficient as you’d like it to be. In fact, using secrets with the Docker CLI can get pretty confusing and if you make one mistake, you might have to undo everything you’d just done and do it all over again.
Here’s an example. Let’s say you want to create a secret called tns_secret. To do this, you’d log into your Docker Swarm controller (as the secrets feature isn’t available to a standalone Docker instance) and issue the command:
printf "H3r3 !$ my sup3r s3cret p@$$w0rd" | docker secret create tns_secret -
Verify the secret was created with:
docker secret ls
You should see something like this:
ajebh69739ox06irww7gz3svz tns_secret 8 seconds ago 8 seconds ago
Next, you would deploy a service that makes use of the new secret like so:
docker service create --name redis --secret tns_secret redis:alpine
Although that process isn’t terribly challenging, it’s not very efficient. And isn’t efficiency the name of the game? You want to empower your teams to work smarter, not harder which leads them to more effective, reliable, and secure containerized deployments. Imagine you have a complicated full-stack application to deploy. That, in and of itself, can be a bit daunting. Now, add the complexity of secrets to that full-stack deployment and the Docker CLI will take considerably more time and effort.
Portainer allows you to create secrets that can not only be used by a single deployment but can be reused for as many apps and stacks as needed. Even better, those secrets are encrypted and encoded such that they cannot be viewed, even from within the GUI. As soon as you create a secret, it’s not only usable for your deployments, the content of the secret is encrypted such that it cannot be viewed… even by an administrator.
Even better, an admin can create all the secrets that are needed for a company and configure access such that it’s available only to admins, restricted users, or even the public.
That’s not only efficient, but it’s also secure.
You can find out how to manage secrets with Portainer in my piece “Container Security: Manage Secrets with Portainer.”
What About Third-Party Secrets Services?
There are plenty of third-party services that can house and serve up the required secrets for your containerized deployments. They work, but many of them can get overly complicated to use. Not only is the creation of those secrets often harder than necessary, but integrating those third-party services into your deployments adds yet another layer of complexity to the mix.
When you use Portainer, it’s all there, ready to go. On top of which, once your teams are up to speed with Portainer, the entire workflow is seamless, so there are fewer hurdles to overcome.
Environment Variables vs. Secrets
Another way of passing credentials and keys to your deployments is by way of environmental variables. This is a very handy tool for defining various types of items within your deployments. Environment variables are used in a key pair format, such as USERNAME:PASSWORD. And, as you might expect, you can create environment variables that pass credentials to your deployments.
Even though you can, you shouldn’t. Why? Because anyone can read environment variables. They aren’t encrypted or encoded. Instead, they’re passed to the containers in plain text, so using this feature for secrets is a bad idea that could expose your services such that any hacker might steal those precious credentials.
The Kubernetes Caveat
Unlike in Docker, where secrets are encrypted so no one can read them once they’re created, Kubernetes secrets are stored unencrypted in the API server’s data store. That means anyone with API access can not only read but modify a secret. According to the Kubernetes documentation, because of this underlying issue, there are several steps you must take to ensure the security of your secrets, which are:
- Enable Encryption at Rest for Secrets.
- Enable or configure RBAC rules with least-privilege access to Secrets.
- Restrict Secret access to specific containers.
- Consider using external Secret store providers.
How to Create a Secret in Portainer
The first thing you must know is that the Secrets feature is only available via Portainer deployed to either a Docker Swarm or a Kubernetes cluster. On a standalone server, you won’t find the secrets feature in the menu.
On a Docker Swarm, creating a secret is as simple as clicking Secrets in the left navigation, clicking Add Secret, giving the secret a name, typing the actual secret in the Secret field, configuring access control, and clicking Save (Figure 1).
With Kubernetes, secrets are created similarly, only you’ll find more options available during the process (Figure 2).
How to Use a Secret in Portainer
Using a secret in Portainer is just as easy. Create your service as you normally would, click Secrets near the bottom of the page, and click Add A Secret. In the resulting Secret drop-down (Figure 3), select the secret you want to use, finish creating the service, and then click Create The Service.
That’s efficiency. Imagine having to do the same thing over and over from the CLI.
Truth be told, using secrets from the CLI isn’t all that challenging. However, when services and deployments get even more complicated, so too does the use of secrets. On top of that, do you want your teams spending more time having to remember and typing complicated commands or using an effective GUI tool that empowers them to work with a much higher level of efficiency?
In the end, if you want your teams to work securely with ease, you’ll want the power and simplicity that comes with Portainer.