Hacker News new | past | comments | ask | show | jobs | submit login
Introducing Docker Secrets Management (docker.com)
264 points by ferrantim on Feb 9, 2017 | hide | past | favorite | 92 comments



I think with this release things have come full circle for me. I was part of the team that 5 years ago built Keywhiz at Square, starting the whole "secrets should be files exposed as an in-memory filesystem" thing.

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


The docs explicitly state "You cannot remove a secret that a running service is using". I'm not comfortable with sensitive secrets remaining plaintext in memory after the running service possibly does not need it anymore (e.g. maybe the service only needs it on startup). It seems like you could rotate the key with something else, but that doesn't seem ideal. Or can the container itself remove the secret "file"?

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.


You can update a service to not use a secret once it's not needed. Of course this will restart the task(s) I think. Definitely worth thinking about. Maybe a single-read secret or something.

If a service is compromised, you should always assume the secret is compromised.


> Maybe a single-read secret or something.

I like this idea. As a benefit, you wouldn't have to rely on developers of individual services to make sure the secret is cleared. This would also have the benefit of causing an error if something else happened to read the secret before the intended service, indicating a possible compromise (or maybe just a misconfiguration).

(I use a similar concept with `xclip -l' to allow reading passwords from the clipboard a single time before it quits.)


So I guess the best-practice approach would be to chown/chmod/rm the file after reading its contents (assuming it'll be restored when you restart the container).

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


Thanks!

- 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.


Thanks, I'm interested in trying this out.


Are the values loaded on the fly each time they're read or is the /run/secrets mount statically defined when the container starts up?

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?


> Is there a way to restrict access to reading said secrets once the container is running?

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....


From what I understand there are no secruity mechanisms other than authentication to the cluster. How do you prevent somebody that got access to the cluster to just read all your secrets?

Can I plug in my own secret store?


- We're working on external store support. First implementation will probably be w/ Vault, but we would love for this to come from the community.

- 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.


That is the same trust boundary as in Kubernetes currently: https://kubernetes.io/docs/user-guide/secrets/

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.


Note exactly the same (for now):

> Currently, anyone with root on any node can read any secret from the apiserver, by impersonating the kubelet

> If multiple replicas of etcd are run, then the secrets will be shared between them. By default, etcd does not secure peer-to-peer communication with SSL/TLS, though this can be configured.


Agree, it would be better if the nodes could not trivially request other secrets. But you can request new containers placed on any node and a root escape that works on one node almost certainly works on the rest.

We usually recommend subdividing the node acls by namespace when running disjoint node sets (where tenant A can't schedule onto tenant B's nodes). More fiddly than it has to be in Kubernetes today.


We are currently facing the same problem and came to the same conclusion, we are subdividing our node pools by namespace (and using namespacing for multi-tenancy) but it "feels" very convoluted and a smell that there's a feature missing in Kubernetes itself to handle this more graciously.


The node placement admission controller was definitely intended for that. In combination with a simple controller for allocating namespaces to sets of nodes.

The real solution is of course to limit what nodes can see - I won't say it's trivial, but it's an O(1) check based on the pods scheduled on that node.


I think in this case you'd already be compromised if you have to worry about a user being able to essentially maliciously place a container. Really a job for RBAC and not the scheduler itself.


I'm referring mostly to users who are legitimately able to run workloads on a non-zero percentage of the cluster. It's fairly hard to defend against a user with the ability to schedule even a limited amount of workloads, because good scheduling usually spreads (in which case you can compromise more machines and then take them out of service briefly) or packs (in which case you get put on nice target rich environments).

That's partially why we (openshift) just don't allow containers to run as root by default - it sucks for new users (most images assume root) but it dramatically lowers the risk of compromise across the board in any scenario with multi-tenancy. Agree that with isolated nodes per tenant you wouldn't have this issue, which is a more straightforward RBAC story.


What about non swarm containers? Like straight docker and docker-compose?


docker-compose 1.11.0 will be released soon with support for secrets, probably using the same system.


Exactly. The new version of compose supports defining docker secrets inside of the compose file.


But the question is whether secrets can be used outside swarm. It doesn't look so at first glance.


secrets only work with Swarm services. New compose (1.11) uses a new format version ( v3.1) that allows you to add secrets for services and deploy using docker client ( no need for docker-compose). I don't think there's any plans atm to support secrets for non-swarm containers :(


Is Docker PCI compliant? My application deals with a lot of PII data. There was a lot of concern in my team over SOC-2 and PCI compliance when I suggested using Docker. We also talked to one of the solution architects from Amazon and he wasn't sure if Docker is ready for PII data.


A single software piece can't be PCI compliant but only how you use it.

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.)


> solution architects from Amazon and he wasn't sure if Docker is ready for PII data.

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.


I think it's pretty well agreed that multi-tenant Docker isn't a good security solution.

Use it for for operational isolation, not for critical security isolation.


That's what I've heard as well, and I agree with that assessment, given that the requirement is to separate untrusted code execution.

At the same time, going back to the initial quote:

> solution architects from Amazon and he wasn't sure if Docker is ready for PII data

A lot of companies are using containers to execute code that manages all kinds of regulated data right now, ya?

The security limitations of Linux namespaces and friends are mostly related to the execution of untrusted code.


You can make a PCI compliant installation w/ Docker yes.


This is a bit off-topic, but I'll hope for the second "A" in AMA: I still have a bit trouble figuring out how docker envisions URL routing to work. Currently we use a simple setup with Hipache that forwards to our hosts running containers und multiple ports. This would work for failover and scaling as well, however at the point where DBs come into play it gets troublesome because hipache just routes in a round-robin manner instead of keeping routes persistent for each client IP (so you could end up showing them different replicas that are not in sync yet).

Anyways, my issue is: Does Swarm integrate a solution for URL routing and if so, does it tackle the persistency problem?


In the commercial product(DDC) there is something called HTTP Routing Mesh that basically adds URL routing to backend services using the underlying routing mesh in Swarm. It supports both HTTP and HTTPS ( w/SNI). It adds RBAC too to make sure only permitted services can be exposed externally. More details here:

https://success.docker.com/Datacenter/Apply/Docker_Reference...

Hope this helps!


is anyone running this stuff in production yet ? not just secrets.. but the whole Docker Swarm with the v3 compose file format thing ?

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.


I can honestly say the only thing we found the full Docker line up (Containers, Swarm, Machine, etc.) good for large scale dev or staging/testing stuff. There are definitely uses for each of these tools, or other combinations, that have been successful for other people. It seems like Docker has a lot to focus on keeping up with the superior orchestration platforms that are out now. This in turn means quickly outdated (or missing) docs, inconsistent behavior of certain features, and other little "gotchas".

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.


I'd recommend people read the "Risks" section of Kubernetes Docs on secrets before using it... https://kubernetes.io/docs/user-guide/secrets/#risks.

secrets stored in plain text and (by default) transmitted in plain text between etcd services, does not fill me with confidence on their security.


Both of these are easy to fix. Configure etcd with peer certificates for clustering and a cert for client-server connections (https://coreos.com/etcd/docs/latest/v2/security.html). If you need encryption at rest, encrypt the filesystem.

If setting up a secure cluster is daunting, then use a distribution that handles it for you. OpenShift (https://www.openshift.org/) is built on kubernetes, and it's install is secure by default.

Disclaimer: I work for Red Hat, and spend lots of time on OpenShift consulting.


kubernetes is NOT easy to setup in a secure way. I am part of several k8s SIG and we have been discussing these issues for a while now. e. g. https://github.com/kubernetes/kubernetes/issues/27343

there are tons of these niggling issues that are cropping up.

the complexity of using k8s goes up exponentially every day. I have bo doubt it is a great piece of tech.. but at this point, it seems tailor made for consulting.


There's still rooted node / kubelet access control to worry about, which does not look to be a problem with Docker. (https://github.com/kubernetes/kubernetes/issues/40476)


A rooted node has access to everything that lands on that node, and anyone who can reproducibly escape to root on a node from a container can do so on any node they can schedule on.

It's definitely something we'll fix in Kubernetes, but rooting workloads is the primary problem, and secondary acl defense in depth is good but won't block most attacks for long.


There's no way to schedule anything from a worker node -- Swarm follows a push model for all scheduling decisions; worker nodes never pull anything. This is the best ACL model possible: the one that doesn't exist because worker nodes have zero ability to perform actions.

Default ACLs are clearly the most important line of defense in an orchestrator's security model, because whether a container escape can happen is not something the orchestration system has control over.


I'm not sure I disagree, but pull vs push with the same ACL rules in place is the same outcome. A secure Kubernetes configuration would also not be able to schedule from a worker. Partition of secrets is important, but anyone able to trigger node compromise still sees secrets and workloads anywhere they can schedule.


At a design level, push removes an entire class of vulnerabilities, full stop. Pull requires good ACL'ing and properly implemented controls for the lifetime of the orchestration system's implementation. Pull makes the system vulnerable to both misconfiguration and incorrect ACL code implementation. Pull is clearly inferior.

Being able to trigger node compromise should have nothing to do with being able to schedule.


The thing is with security, default matter. Many people will not change default settings (especially in complex products like Kubernetes), that's why I suggested that people thinking about using Kubernetes should read and be aware of those risks.

On OpenShift I'd be very interested to see a list of the secure defaults that have been chosen, is there a list of the changes from base Docker/Kubernetes policies available anywhere?


Can you explain to me the benefits of this like I'm 5 years old? Thanks, and sorry I have technical debt.


Since diogomonicapt didn't answer i'll try to give an ELI5 answer ;)

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.


If the environment is super easy to read when you have gained access to the container, so is a filesystem... The use of secrets is more to transmit secrets to the container without giving it to people.


The problem is applications unintentionally leaking the ENV. Think a hoptoad exception that attaches the current ENV to the report that sends up to the remote server.

Or think about you exec'ing imagemagik and now the process running potentially adversarial code also has access to your parent's env.

Or think about an application crashing and doing an unintentional core dump to disk.


Way better than I could have answered ;)


Probably they were concerned that users have to store the secrets (certificates, etc...) in the container filesystem - or mount/share the location on the host were the certificate for a specific app is present. Probably there are more ways to do it, but also probably none is end-to-end secure.

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.


Looks awesome, congratulations on the release!


This secrets infrastructure is only available at run-time and with Swarm? Are you looking to handle build-time secrets?



OMG, so much smoother than what I do now. Thanks for the link.


This looks amazing. Solving secret distribution across containers will be very useful. Being able to see via `docker secret` exactly which services are using which secrets is an unexpected treat.

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.


You can specify the UID, GID, and mode of the secret from within the container: https://docs.docker.com/engine/reference/commandline/service..., and pass the same configuration to the service update command as well.


Oh, that's great to know. That coupled with filling out the size to an uninteresting length with nulls (or another delimiter) covers my concerns. For example:

    $ echo "my secret" | dd bs=512 conv=sync | docker secret create my_secret_data -


This is interesting, but in my opinion, it's not quite as universally useful as some of the secret management in other security tools because you have to explicitly manage the secret within your application by reading that in-memory filesystem.

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.


Kubernetes supports this already. You have the choice to either mount the secret into the container file system or set it as a environment variable. https://kubernetes.io/docs/user-guide/secrets/#using-secrets...


But Kubernetes secrets are stored - and by default transmitted amongst managers - in plain text. And Kube will share secrets with all kubelets, no questions asked. They're not "secrets".


Yes, the kubernetes secrets resource is not a replacement for a secret store. Your specific point is being worked on: https://github.com/kubernetes/kubernetes/issues/12742

You can use Vault(https://github.com/Boostport/kubernetes-vault) or extend Kubernetes easily for your specific secret as a replacement if you need extra security.


"priority/backlog" for 18 months. Kube doesn't care about security.


You should probably disclose that you work for Docker.

Looking at your profile/comments you seem to be openly hostile towards Kubernetes. On that note: this is quite representative of the mentality I encountered while working there. Open Source is hard and bashing other projects is not something I consider to be fair game (regardless of whether the other side is adopting that stance or not).

Meanwhile, I admire Hashicorp's attitude of focusing primarily on improving their product without taking part in this silly "orchestration war".

(and thanks to cpuguy83 for having a more sensible view of what it's like to work on Open Source projects)


Encrypted storage isn't as important when you can restrict the access to the secrets. Just because the secrets are in plaintext in etcd doesn't mean everyone can read them.

Then you need a mutual authenticated connection from the api server to etcd + encrypted etcd hard drives + networking policies that only the api-servers are able to communicate with etcd and your secrets are pretty safely stored.


I agree. I also care more about access control than encryption. But if you obtain a kubelet's credentials, you can read all secrets. It would be nice if a kubelet's access was restricted to only what the kubelet needs to know. That would limit the impact of a node in a cluster being rooted.


> It would be nice if a kubelet's access was restricted to only what the kubelet needs to know.

This seems like a fairly difficult problem to solve with meaningful security confidence. The only easy way I can see this working is if you pre-define groupings of kubelets and specify which pods may run on which kubelets, and enforce secret access the same way. Without this kind of hard separation, any kubelet is a candidate for running any pod and needing any pod's secrets at a moment's notice.

Furthermore, this sort of separation would require some kind of PKI; you could not just trust any given kubelet to accurately claim which groups a member of. You'd need to provision the kubelet groups with a secret that proves their membership in the group, and we're back to the secret distribution problem again.

And while it's true that a given kubelet may not be running a certain pod at the moment (and thus doesn't need the secret), that does not seem to be a hard security boundary. An attacker who controls the kubelet can manipulate which pods run on it, such as by terminating pods until the desired one is scheduled on it, or falsely advertising a huge amount of available resources to entice the scheduler to run pods on it, and so on. Ultimately if a kubelet is a candidate for running a pod, then it is simply a matter of coincidence whether it possesses the pod's secrets at a given moment or not.

That said, limiting kublets to have access only to secrets required by active pods will make things harder for an attacker, and so will provide value. But we should also evaluate the priority of that work in context of how hard it will be for an attacker to defeat that same restriction (e.g., advertise 1 petabyte of free RAM and disk, and 1000 idle CPU cores).


You raise some good points, like the kubelet killing off pods in hopes of getting a new pod with juicier secrets associated with it, but nevertheless the ticket mentioned by the sibling comment (https://github.com/kubernetes/kubernetes/issues/40476) sounds like a property that Docker's secret handling already has. It would be great to see Kubernetes work this way, too.

Coincidentally, I'm working on a project that uses Kubernetes and it has a very locked down pod placement policy, so the attack you described would be significantly scoped down. But I don't think the same is true of most Kubernetes deployments.


Defending the cluster from malicious nodes is not in the primary threat model of Kubernetes today. A malicious node can do many things, like lie about its capacity, scan container memory for juicy secrets, inject arbitrary outgoing or ongoing traffic, and in general be a jerk.

Securing nodes, preventing container escape, subdividing role access, constraining placement, limiting master surface area, and end to end audits have been the initial focus. Until those are in place, node secret access was less critical.

It is something that several folks are interested in working on soon.


There is a issue open for this too... https://github.com/kubernetes/kubernetes/issues/40476


This is not fair to say at all.

Everything takes time to design and implement, and human power to work on the hard/not-fun things is pretty hard to come by in such hugely active projects...


How about replacing your entry point with:

    envdir /run/secrets <stuff>


Linux does not hide process environments, you can cat /proc/[pid]/environ to read them. It is not a good way to pass secrets.


True, but people do it anyway and a large number of applications are preconfigured to use them. But to the point, the same tool that hides the secret and encrypts the variable in 'docker inspect' will also show it as encrypted in /proc/[pid]/environ as well.


That would be a kernel patch then. Good luck getting that upstream.


On mobile so no URLs, etc, but cf. "hidepid" mount option for /proc.


Comparing this to Vault (with which I have been very satisfied):

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?


Comparison of this with other secretes management frameworks here https://medium.com/on-docker/secrets-and-lie-abilities-the-s...


wrote this as a comment when that article was posted to YC:

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


Vault is really wonderful to work with, and its integration with consul makes it phenomenally powerful.


What kind of stuff do you get from the integration? I mean, aside from the obvious stuff like a clustered storage backend and leader election?


This is really nice. What is the equivalent in the kubernetes world?


Kubernetes supported secrets for nearly 2 years: https://kubernetes.io/docs/user-guide/secrets/

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/


Secrets as in passwords and keys stored at rest in plain text. So not really secrets.


It's not so much the plain text part that bothers me, it's the access control.

Quoting the docs at https://kubernetes.io/docs/user-guide/secrets/#security-prop...:

"Currently, anyone with root on any node can read any secret from the apiserver, by impersonating the kubelet. It is a planned feature to only send secrets to nodes that actually require them, to restrict the impact of a root exploit on a single node."

As your cluster grows, your risk grows.


Is there a way to manage secrets during the build process itself without specifying them on the command line / docker compose files?


It would be neat if you could inject secrets as environment variables. Something like:

    --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.


We explicitly chose not to support secrets as ENV variables, since they are prone to being leaked (child processes inhering parent's env; easy to leak ps -e; bug reports usually include ENV of the application; core dumps include ENV of the application, etc etc)


Makes sense, but how do child processes not have access to the secrets files?


My unstated assumption was that when calling something like imagetragick you would be doing the appropriate privilege dropping using setuid and setgid. This is obviously not necessarily the case, but it's at least a lot more common than people cleaning up the ENV before creating a child process.


They do. That point is less valid.


Not sure if anyone from docker is watching, but the images are cut off at the side on mobile.


Yes, someone from Docker is watching :-). I've alerted the blog team. Thanks for letting us know.


Will we be able to use this on Docker Cloud soon?


I believe it is coming soon yes.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: