Building it a second time was interesting. One of the biggest reasons why Keywhiz didn't go anywhere was the fact that it is incredibly hard to setup, and requires you to bring your own PKI. This time we didn't make that mistake and integrated directly into Swarm, which is the right place for it to live, and turns setting up your own PKI into a one-liner.
Anyway, AMA.
Disclosure: I work on the Docker Security team
Consequently, because it's mounted as a filesytem, what if the service is compromised and vulnerable to arbitrary code execution, directory traversal, etc? The secret could then be leaked.
Am I misinterpreting something? How would others here handle this?
Edit: To clarify: rotating a secret will cause the service to restart. So I guess by "doesn't seem ideal", I mean it doesn't seem like an option.
If a service is compromised, you should always assume the secret is compromised.
So far my approach was defining environment variables in the various docker-compoose files (in a separate deployment git repo), but this looks like a really nice alternative.
Do you have plans to update the library images to give us a choice between using ENV and secrets (for DB server passwords and the like)?
On an aside: I've gotten the Docker Datacenter announcement mail today. I only took the time to skim its contents quickly and at first thought this was a DDC-only thing. Glad to hear it isn't, keep up the awesome work.
edit: clarified my docker-compose usage
- Exposing secrets as in-memory files has a lot of advantages over ENV variables (harder to leak).
- We already started updating a few images (MySQL, for example), so they can use Docker secrets.
- Definitely not DDC only, but note that RBAC over secrets is a feature of the commercial product.
If it's static, follow up to that would be, how are changes propagated to already running instances?
Is there a way to restrict access to reading said secrets once the container is running? Say you're running possibly malicious code that has access to the local filesystem (ex: CI test runner) is there a way to restrict a process from reading those files? Can we simply delete them (i.e. "burn after reading") or are they fully virtual?
I don't know anything about docker, but the best way I found to do this in linux in general was aa_changehat() [0]. You write an apparmor profile for startup and a sub-profile for the running app/service. After setup, you call aa_changehat() to switch the current process to use the subprofile. You then throw away your magic token, so there is no way to switch back.
You don't even have to link to libapparmor, under the hood aa_changehat() just writes some string somewhere in /proc, so you can replicate that. Note, I haven't actually done this, but working on it right now.
[0] http://manpages.ubuntu.com/manpages/wily/man2/aa_change_hat....
Can I plug in my own secret store?
- If you have access to the managers, you have access to all the secrets (and access to administer the whole cluster), but normal swarm nodes only have access to the secrets required to run services that will be scheduled on them. Also this are erased as soon as the service is deleted or rescheduled on some other node.
It is the most important step that you can package containers without having to know the production secrets and to have a "standard" was to retrieve them.
No one, without production access, has a way to obtain them.
You have to argue that Docker uses the Linux isolation mechanisms that make those containers virtual machines in the sense and spirit of PCI.
Treating containers as VMs makes some other requirements even easier like the request to have a minimal system and to only have one function per server - thats how you want containers to work anyway.
(Btw PCI has nothing to do with PII.)
I'm curious if you can relate what his reasoning was?
Docker is, among other things, a wrapper around a bunch of Linux kernel functions, the likes of which have been used for many, many years by companies like Google to facilitate all kinds of useful isolation.
Anyways, my issue is: Does Swarm integrate a solution for URL routing and if so, does it tackle the persistency problem?
https://success.docker.com/Datacenter/Apply/Docker_Reference...
Hope this helps!
We have been testing out production clusters with Swarm 1.13 and I think its neat. But what do I know - I'm not a cloud hosting specialist. And the lack of success stories out there is making us nervous.
Depending on the size of your team, I would recommend Kontena (www.kontena.io) or Kubernetes (https://kubernetes.io/). While I haven't used the latter, a group of two devs is re-architecting our entire system to use Docker and Kontena. Nearing the end, the whole process seemed incredibly fast to iterate. While K8s seems far more proven in real production environments, it seemed much more daunting to us with more features than we needed for our use case.
Docker-containers have many advantages, but one of the big drawbacks until now was that it was really hard to pass secrets into them. Imagine you are a simple, stupid Java-container. You handle HTTP-Request and need to access other services like Databases in order to function. In order to connect to the postgres-instance you need to know 3 things: the URL, the database-name and a password. Getting the URL and the database name is easy, just pass them via environment-variables. The tricky thing is how to pass the secret. Environment variables are not encrypted and super easy to read as soon as you have gained access to the container. There were some solutions, but they were complicated. So most just passed them via env-variables. Huge security risk. Very bad.
This solves the problem.
With this you can securely store the certificates; takes away the developer's responsibility of taking care of managing and distributing them to their apps, swarm will take care of that in a secure end-to-end fashion.
I'd much prefer passing a secret as an environment variable if that can be done securely. It's possible with some tools, but not out of the box with Docker itself.
eg, with one tool, you can do:
# docker run --rm -e PASSWORD={supersecret_password} someimage:latest program
Then '{supersecret_password}' gets replaced in the container at runtime with the value stored in the tool or from an integration with a separate dedicated secret management tool like HashiCorp Vault, and value gets masked external to the container such as when running 'docker inspect' command.
The benefit is that you don't need to modify or maintain a lot of pre-packaged applications that read environment variables instead of looking to the contents of a file on the disk, so it just works out the box.
However, under ordinary circumstances, you may not want to pass secrets as environment variables in docker (or at least be careful about it). A 'docker inspect' command can show any docker user the environment variable and its value, if you don't have a tool to encrypt the contents.
envdir /run/secrets <stuff>I'm a little worried about two aspects of what has been shown. From the article it shows:
$ docker exec $(docker ps --filter name=redis -q) ls -l /run/secrets
total 4
-r--r--r-- 1 root root 17 Dec 13 22:48 my_secret_data
From this we can tell exactly how long the secret is. If the secret service didn't do it for us, I'd like for the secrets to be null-padded to a uniform 2-4K of bytes.I'm also a bit worried that the default protection on the file has it set to world-readable. Since it appears that secret distribution is independent of the container setup itself, there doesn't appear to be any way of setting ownership and permissions on this file. That is, if one were able to chmod/chown the file in the Dockerfile, running a `docker service update --secret-rm` and `docker service update --secret-add` would reset such 'fixes'.
A great start, and I can't wait to start using it.
$ echo "my secret" | dd bs=512 conv=sync | docker secret create my_secret_data -tl;dr: author looks at secret management services and reviews them
KeyWhiz: Provides everything you need but with complex PKI management, meaning setup and maintenance is a pain. Secure.
Vault: A+ would test again. Awesome rotation policies, on-demand secret generation via backends, master key sharing. Legit and secure, everything you need but has to be configured on top of your cluster.
Docker: Super easy to use, and it's built in. 10/10 would use again. Keys encrypted at rest, keys encrypted over the wire, and shared with only nodes who need them. Secure all round
Kube: Totally insecure. Plaintext at rest, plaintext over the network, shared everywhere. Basically a plaintext POC
They currently debate over pluggable secret stores: https://github.com/kubernetes/kubernetes/issues/10439
You can use Hashicorp Vault as a third party resource to store your secrets: https://github.com/Boostport/kubernetes-vault
Kubernetes also supports RBAC to control access to secrets: https://kubernetes.io/docs/admin/authorization/
--secret="my_secret:MY_SECRET"
Obviously you could have a script that does MY_SECRET=$(cat /run/secrets/my_secret) ./whatever
but a lot of existing containers can be configured via environment variables.The article mentions a single master key for cluster encryption. Are there any plans to split this as in Shamir's Secret Sharing?
How do secrets and secret authorizations renew and expire?
Any plans for limited-use tokens/secrets?