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
Add support for non-swarm container secrets #43543
Conversation
vendor.mod
Outdated
@@ -32,6 +32,7 @@ require ( | |||
github.com/docker/go-units v0.4.0 | |||
github.com/docker/libkv v0.2.2-0.20211217103745-e480589147e3 | |||
github.com/docker/libtrust v0.0.0-20150526203908-9cbd2a1374f4 | |||
github.com/docker/swarmkit v1.12.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we avoid importing swarmkit v1 and v2 simultaneously?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AkihiroSuda, resolved in 760200f.
Can we have integration tests? |
// SecretConfig holds self-sufficient data about a secret of a container. | ||
type SecretConfig struct { | ||
ID string `json:",omitempty"` // Unique identifier of the secret | ||
Data []byte `json:",omitempty"` // Raw content of the secret file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is the right thing to do.
While I can acknowledge the problem that docker secret
is not currently supported for non-swarmkit containers, I don't think we should use this approach to provide it;
docker secret
was created to provide a secure way to pass secrets (not using env-vars, or plain-text files); storing the secret as plain text in the container's configuration means that these secrets leak (which is not the expectation from users when using such a feature)- in the current implementation in this PR, the secret-data is stored in the container Config, which also lands in any image that may be created from the container (think of
docker commit
).
Storing the secret this way would mean it doesn't provide benefits over using an --env
or mounting a file from the host inside the container.
We definitely should have a look at other options though (one option is to use the existing docker secret
feature, but using an alternative backend for storing the secret, or enabling the swarm store by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your consideration @thaJeztah.
I don't think this is the right thing to do.
As I mentioned in the PR description, I totally agree that storing secret content as raw string in the container's configuration file is not the perfect solution.
Storing the secret this way would mean it doesn't provide benefits over using an
--env
or mounting a file from the host inside the container.
But, I do not completely agree with this statement. I believe the concept of secrets has two main properties:
- They should be transmitted, and stored securely, as they might contain confidential data
- They should be configured to be mounted to the container with proper setup, i.e., destination file permissions and mode
This PR, although it has some security concerns around storing secrets, fixes the issue with the second point, which currently is not supported by Docker, as discussed in #40046.
Regarding the storage concern, as I realized, please correct me if I'm wrong, the current solution by Swarmkit is encrypting the snapshot of its raft state before being persisted, and decrypting the file during the startup process. To prevent adding the container's secrets into its Config
property, I tried using boltdb
in a similar solution to how the daemon stores information about volumes in <daemon_root>/volumes/metadata.db
file, to <daemon_root>/secrets.db
(see this commit), which simply stores a key-value pair of containerID->secrets
. It gets loaded upon daemon startup, and closed/persisted at daemon shutdown phase. This solution has the benefit of not adding a new field to container Config
field, and simplicity compared to moving toward Swarmkit
in any way, but due to my lack of information about encryption/decryption, it actually stores secrets in a raw format. I'm also open to any further research or implementing a solution around dealing with secret storage, if you'd guide me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Swarm secrets are stored in swarm's raft store (which is encrypted), and (but it's been a while since I looked at the full implementation), it uses a memfs
mount to prevent the mounted file from being written to disk.
For transmitting the data, we should also make sure that it doesn't end up in logs (for example, with the daemon in debug mode, API request calls may be logged).
That said; I don't think using the SwarmKit store for this is ideal; using the SwarmKit store means that secrets will always have to be "imported" into that store (which somewhat makes sense for swarm services, to distribute them, but for situations where a secure store is already available for secrets, means that the secret is duplicated); I know some work was done to allow swarm services to use an external store (see moby/swarmkit#2326), so possibly something like that should be explored as an option (and make it available for both "swarm" and "non-swarm" containers, allowing docker secret
and docker config
to be used for both).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about using an encryption algorithm similar to what Swarmkit is doing to encrypt its raft snapshots, then using a memfs
or ramfs
mount typed storage with the same simple storage mechanism, e.g., boltdb
, implementation for daemon's local container secrets, instead of making changes to Swarmkit?
This improves re-usability of the method with identical behaviour, but with a more relaxed interface Signed-off-by: Morteza Behboodian <29199390+xeptore@users.noreply.github.com>
Signed-off-by: Morteza Behboodian <29199390+xeptore@users.noreply.github.com>
Assigning generated IDs to container's raw secrets before setting its config field Signed-off-by: Morteza Behboodian <29199390+xeptore@users.noreply.github.com>
Signed-off-by: Morteza Behboodian <29199390+xeptore@users.noreply.github.com>
Signed-off-by: Morteza Behboodian <29199390+xeptore@users.noreply.github.com>
Signed-off-by: Morteza Behboodian <29199390+xeptore@users.noreply.github.com>
We've needed this since forever. Running a single-server stack - just to have access to secrets functionality - has proved to be very hard to maintain. This feature is sorely needed. I hope you can agree on all the underlying technical matters. |
I'm going to close this PR, as I did not see much interest, and did not receive enough useful feedback from maintainers after a while. |
Noooo. @thaJeztah Will your team reconsider this? It's a major source of pain - lots of issues here and on StackOverflow show that to be the case. |
With the risk of sounding tone-deaf: Have you considered running docker swarm on that single node? |
I don't think there is no interest, but I think right now the focus is on making 22.06 stable (I am only a community member, so please take this with a grain of salt). |
@xeptore Thanks for your efforts... I hope you'll reconsider opening and leaving this in the queue. 😄 |
Sure @lonix1. I have some open questions both here and in Slack. I'll reopen this PR once I have answers to them. Cheers |
Hey @xeptore, how does your PR compare to docker/compose#9386? |
@lonix1, as the title of docker/compose#9386 suggests, it's about build secrets. They are kind of build-time secrets, compared to the end goal of this PR, which is about (runtime mounted) secrets. AFAIK, build secret is a relatively new Docker Buildkit feature, which are the type of secrets you need during Docker image build process, e.g., GitHub access token to download some dependencies from GitHub's package registry during build time ( |
Thank you for those details. I'm still unfamiliar with the new "buildkit" stuff, but I had a feeling that it differs to what's being discussed here. I think the approach in this PR is preferable. I'm saddened they didn't accept it. |
Hi again @xeptore... if this is still important to you, please upvote this new feature request, and/or add your opinions there. @epopisces @marcoaureliocardoso I see you upvoted this issue. Please upvote that feature request and add your comments if any? |
Closes #40046.
What I did
How I did it
Secrets
field to thegithub.com/docker/docker/api/types/container.Config
typeHow to verify it
ContainerCreate
daemon API with the request body containing the newly addedConfig.Secrets
fieldConfig.Secrets
section of the container'sconfig.v2.json
file to see secrets associated to the container/mounts/secrets/<secret-id>
of the container root directory, similar to Swarm secretsdocker-compose
project from herepassword.txt
secret file below, you can verify that the secrets defined for the service, are being mounted to the container with proper permission and mode:compose.yml
:password.txt
Description for the changelog
config.v2.json
file, instead of storing them in an in-memory or file-based database, without any encryption/decryption mechanism, as it's a local container, and file permissions seems enough for me. Also, it's simpler!config.v2.json
file.Considerations
config.v2.json
file might introduce, I cannot see any other major issues