New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Secrets: write-up best practices, do's and don'ts, roadmap #13490
Comments
ping @ewindisch @diogomonica @NathanMcCauley This is just a quick write-up. Feel free to modify/update the description if you think that's nescessary :) |
This is useful infos: As is this: |
@dreamcat4 there are some plans to implement a generic "secrets API", which would allow you to use either Vault, or Keywiz or you-name-it with Docker, but all in the same way. It's just an early thought, so it will require additional research. |
@thaJeztah Yep Sorry I don't want to detract from those efforts / discussion in any way. I am more thinking maybe it's a useful exercise also (as part of that longer process and while we are waiting) to see how far we can get right now. Then it shows up more clearly to others the limits and deficiencies in current process. What underlying is missing and needed the most to be added to improve the secrets. Also it's worth considering about the different situations of run-time secrets VS build-time secrets. For which there is also an area overlap area. And perhaps also (for docker) we may also be worth to consider limitations (pros/cons) between solutions that provide a mechanism to handle the secrets "in-memory". As opposed to a more heavily file-based secrets methods or network based ones e.g. local secrets server. Which are the current hacks on the table (until proper secrets API). This can help us to understand some of the unique value (for example of stronger security) added by a docker secrets API which could not otherwise be achieved by using hacks on top of the current docker feature set. However I am not a security expert. So I cannot really comment on those things with such a great certainty. |
@dreamcat4 yes, you're right; for the short term, those links are indeed useful.
Thanks! I think I had that in my original description, must have gotten lost in the process. I will add a bullet
Neither am I, that's why I "pinged" the security maintainers; IMO, this should be something written by them 😇 |
@thaJeztah great summary. I'll try to poke at this whenever I find some time. |
@diogomonica although not directly related, there a long open feature request for forwarding SSH key agent during build; #6396 given the number of comments, it would be good to give that some thinking too. (If even to take a decision on it whether or not it can/should be implemented) |
Assuming you could mount volumes as user other than root (I know it's impossible, but humour me), would that be a favourable approach to getting secrets into containers? If so, I'd advocate for an alternative to We could then emphasize a |
I've recently read a good article about that from @jrslv where he propose to build a special docker image with secrets just to build your app, and than build another image for distribution using results from running build image. So you have two Dockerfiles:
Now we can build our distribution like that: # !/bin/sh
docker build -t hello-world-build -f Dockerfile.build .
docker run hello-world-build >build.tar.gz
docker build -t hello-world -f Dockerfile.dist ^ Your secrets are safe, as you never push I recommend to read @jrslv article for more details http://resources.codeship.com/ebooks/continuous-integration-continuous-delivery-with-docker |
Thanks for sharing @kepkin ! I like the idea of exporting the files and loading them in through a separate Dockerfile. It feels like squashing without the "intermediate layers being in the build cache" issue. However, I'm nervous that it'll complicate development and might require a third Dockerfile for simplicity. |
@kepkin no offense but that doesn't make any sense. Secrets are definitely not safe, since they are in the tarball and the tarball is being |
@TomasTomecek if I understand the example correctly, the tarball is not the image-layers, but just the binary that was built inside the build container. See for example; https://github.com/docker-library/hello-world/blob/master/update.sh (no secrets involved here, but just a simple example of a build container) |
@TomasTomecek I'm talking about secrets for building Docker image. For instance, you need to pass ssh key to checkout source code from your private GitHub repository. And the tarball contains only build artifacts but doesn't contain GitHub key. |
@kepkin right, now I read your post again and can see it. Sorry about that. Unfortunately it doesn't solve the issue when you need secrets during deployment/building the distribution image (e.g. fetching artifacts and authenticating with artifact service). But it's definitely a good solution for separation between build process and release process. |
@TomasTomecek that's exactly how I fetch artifacts actually. In Docker.build image I download some binary dependencies from Amazon S3 image which require AWS key & secret. After retrieving and building, I create a tarball with everything I need. |
The biggest pain point is secret rotations for me you've to maintain a graph of secret to services dependencies, and update twice each service (to get back to original secret name) listing secrets from services doesn't seem to be easy (I gave up after some attempts around You also have to specify the secret destination, when it's not the default I just hope for a simpler way to rotate secrets |
@caub here's some CLI help: Docker docs for formatting help come up with the rest of your inspect format:
That'll list all secret names in a service. If you wanted both name and ID, you could:
I always have my CI/CD (service update commands) or stack files hardcode the path so you don't have that issue on rotation. With labels you can have CI/CD automation identify the right secret if you're not using stack files (without needing the secret name, which would be different each time). |
@thaJeztah Are we ready to close this issue? |
For older versions of docker, using multistage build with copying secrets before build command is viable option, right?
|
@andriy-f yes, that works, as long as you;
|
build time secrets are now possible when using buildkit as builder; see the blog post here https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066 and the documentation; https://docs.docker.com/develop/develop-images/build_enhancements/ the |
Thank you @thaJeztah I did just a little more digging and found that article shortly after posting (previous post is now deleted). Thanks again! |
Cool. That closes the build time secrets question. Anything for runtime/devtime (ssh in OS X)? |
What is the current best-practice for run-time secrets to pass e.g. to an entrypoint script, without the need to set up some external service? Right now, it seems the build-time secret solution is easier than run-time. I could just mount a local |
Best practice is to encrypt secrets with a public key and allow only your runtime controller to decrypt and mount them. Encrypted secrets can be stored in a Git repository. For Kubernetes there is https://github.com/bitnami-labs/sealed-secrets |
Nice. What about in a simple setup that is not a cluster? Just a single Dockerfile..? |
There are basic tools to store secrets in a repository like https://git-secret.io/ Possible workflow:
|
I’ve seen this pattern many times and wondered to myself, “why would the software development team (who are busy installing npm and god knows what on their machines)“, be entrusted with runtime secrets such as the magic key that allows you to run up a $50k google bill overnight?
Surely this is a problem for the operations/security teams? Do they really need the application software developers handling this stuff?
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Yes. They need the tools and documentation the most. When they deploy with docker, they need to inject a lot of secrets in them. And they often version the compose files, kubernetes manifests, helm charts, terraform manifests, ansible playbooks or whatever they use to deploy the containers in git, so storing encrypted bundles there is useful to them too.
Operations don't need them to, but developers themselves do. The build and test infrastructure also involves a bunch of secrets. |
In our Would love to get feedback about this approach. Anything wildly wrong with that ? Thanks. |
@petef19 you might benefit from the bit of knowledge on mounting secrets using the new DOCKER_BUILDKIT support in Docker: https://snyk.io/blog/10-best-practices-to-containerize-nodejs-web-applications-with-docker/ |
thanks for the link, great read. Regarding using With our approach ("unplugged" shared volumes) - and please chime in with opinions - there is no sensitive data left on the host or in the container (after it was build and service started). But the drawback may be scalability, as we currently only run a couple of servers, so not stress tested in that regard. |
Well yes, but the point is that you mount secrets for a build stage that you don't actually use in the resulting image, and it's a nicer way of mounting data into that layer only. |
right, but what if you need the sensitive data to configure the service when the final container starts ? |
Correct, with the For |
It looks like @petef19 is seeking a run-time solution for when containers are running, not when they are built. To achieve that, there are the usual suspects:
** The above are organized from the least secure way of managing secrets to the most (my opinion only) ** |
yes, runtime secrets to configure services as they start up. I can extend your list... (5) use cmd args Out of these, (3), (6) and (7) can all be used with Question is could an attacker that hijacks the container still get out through the "unplugged" shared volume, although the "tunnel" does not exist anymore.... ? Especially if all secret mounts are Re (4): this seems to be a secure approach and easily scalable, but since the API connection creds are in the container (which are a secret itself) couldn't a hijacker use those creds to query the API for secrets.... ? |
This comment has been minimized.
This comment has been minimized.
Since my issue #45642 was closed and points to this one, I want to add that since "runtime secrets" are not possible, the recommendation is to use a one-node swarm to access swarm secrets. But this is not easy to do and maintain, and no longer works if we use docker rootless (no overlay network, so no swarm mode). Now that |
Handling secrets (passwords, keys and related) in Docker is a recurring topic. Many pull-requests have been 'hijacked' by people wanting to (mis)use a specific feature for handling secrets.
So far, we only discourage people to use those features, because they're either provenly insecure, or not designed for handling secrets, hence "possibly" insecure. We don't offer them real alternatives, at least, not for all situations and if, then without a practical example.
I just think "secrets" is something that has been left lingering for too long. This results in users (mis)using features that are not designed for this (with the side effect that discussions get polluted with feature requests in this area) and making them jump through hoops just to be able to work with secrets.
Features / hacks that are (mis)used for secrets
This list is probably incomplete, but worth a mention
curl
-ing the secrets and remove them afterwards, all in a single layer. (also see https://github.com/dockito/vault)So, what's needed?
The above should be written / designed with both build-time and run-time secrets in mind
@calavera created a quick-and-dirty proof-of-concept on how the new Volume-Drivers (#13161) could be used for this; https://github.com/calavera/docker-volume-keywhiz-fs
In good tradition, here are some older proposals for handling secrets;
docker secret
storage feature" Continuation of thedocker secret
storage feature #6697The text was updated successfully, but these errors were encountered: