Repository navigation
Fix DCT Security Theater (TOFU) #2752
Description
Activity
Yes, this is one of the design goals for Notary v2, to resolve this use case.
You can distribute the ~/.docker/trust directory to your build servers to provider initial keys.
@justincormack Thank you. Can you please inform what is the minimum required files to pin the root public key used to sign a given set of images in the
docker.iotrust library? Just theroot.jsonfile or others as well?Is this documented anywhere?
- added a commit that references this issue
on Oct 3, 2020 @zyitingftnt afaik, docker has not documented this anywhere.
I wrote-up the commands (with a verification) for how seed/pin a given docker publisher's public keys (trust initialization) here:
@zyitingftnt those links are great! How did you find those docs??
Trick to disable TOFU for unprivileged users (on Linux)
It seems to disables TOFU on nonprivileged users.
Sorry if this is already known, but I discovered it a few seconds ago on my own and did not find it here yet.
I am very new to Docker because I did not understand how to use it in a secure fashion. Today I had to learn about this security theater, because I needed to create my first VM which includes Docker (this not yet includes the fixes here). So I looked for a way to globally disable TOFU (and globally enforce
DOCKER_CONTENT_TRUST, for me it looks like this can be done by wrapping thedockercommand with divert).The trick seems to be to prevent the client from creating new
root.jsonfiles withinmetadata/, as it seems to "properly fail" then.Here is a script which does this:
mkdir -p ~/.docker/trust || :; find ~/.docker/trust/. -type f -name root.json -print0 | xargs --null chmod 444 --; find ~/.docker/trust/. -type d -print0 | while read -rd '' dir; do if [ -d "$dir/metadata" ]; then chmod 755 "$dir"; else chmod 555 "$dir"; fi; done;I am not sure this works if
dockeris run fromroot, though, as I haven't tested it.For the examples below I already had ~/.docker/trust primed with the library/debian key.
Now all we need to implement is a way to download the
root.jsonfiles and verify them somehow. I, for my part, probably will just prime them using Ansible.Example:
docker@docker:~$ echo $DOCKER_CONTENT_TRUST 1 docker@docker:~$ docker run hello-world docker: error establishing connection to trust repository: mkdir /home/docker/.docker/trust/tuf/docker.io/library/hello-world: permission denied. See 'docker run --help'.But
docker@docker:~$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE docker@docker:~$ find ~/.docker/trust -ls 158657 4 dr-xr-xr-x 4 docker docker 4096 Apr 7 16:14 /home/docker/.docker/trust 158658 4 dr-xr-xr-x 3 docker docker 4096 Apr 7 16:14 /home/docker/.docker/trust/tuf 158659 4 dr-xr-xr-x 3 docker docker 4096 Apr 7 16:14 /home/docker/.docker/trust/tuf/docker.io 158660 4 dr-xr-xr-x 3 docker docker 4096 Apr 7 16:49 /home/docker/.docker/trust/tuf/docker.io/library 158655 4 drwxr-xr-x 3 docker docker 4096 Apr 7 17:32 /home/docker/.docker/trust/tuf/docker.io/library/debian 158663 4 dr-xr-xr-x 2 docker docker 4096 Apr 7 16:53 /home/docker/.docker/trust/tuf/docker.io/library/debian/metadata 158668 4 -r--r--r-- 1 docker docker 2393 Apr 7 16:53 /home/docker/.docker/trust/tuf/docker.io/library/debian/metadata/root.json 158664 4 dr-xr-xr-x 2 docker docker 4096 Apr 7 16:14 /home/docker/.docker/trust/private docker@docker:~$ docker pull debian Using default tag: latest Pull (1 of 1): debian:latest@sha256:e97ee92bf1e11a2de654e9f3da827d8dce32b54e0490ac83bfc65c8706568116 docker.io/library/debian@sha256:e97ee92bf1e11a2de654e9f3da827d8dce32b54e0490ac83bfc65c8706568116: Pulling from library/debian 71215d55680c: Pull complete Digest: sha256:e97ee92bf1e11a2de654e9f3da827d8dce32b54e0490ac83bfc65c8706568116 Status: Downloaded newer image for debian@sha256:e97ee92bf1e11a2de654e9f3da827d8dce32b54e0490ac83bfc65c8706568116 Tagging debian@sha256:e97ee92bf1e11a2de654e9f3da827d8dce32b54e0490ac83bfc65c8706568116 as debian:latest docker.io/library/debian:latest docker@docker:~$ find ~/.docker/trust -ls 158657 4 dr-xr-xr-x 4 docker docker 4096 Apr 7 16:14 /home/docker/.docker/trust 158658 4 dr-xr-xr-x 3 docker docker 4096 Apr 7 16:14 /home/docker/.docker/trust/tuf 158659 4 dr-xr-xr-x 3 docker docker 4096 Apr 7 16:14 /home/docker/.docker/trust/tuf/docker.io 158660 4 dr-xr-xr-x 3 docker docker 4096 Apr 7 16:49 /home/docker/.docker/trust/tuf/docker.io/library 158655 4 drwxr-xr-x 4 docker docker 4096 Apr 7 17:32 /home/docker/.docker/trust/tuf/docker.io/library/debian 158663 4 dr-xr-xr-x 2 docker docker 4096 Apr 7 16:53 /home/docker/.docker/trust/tuf/docker.io/library/debian/metadata 158668 4 -r--r--r-- 1 docker docker 2393 Apr 7 16:53 /home/docker/.docker/trust/tuf/docker.io/library/debian/metadata/root.json 158666 4 drwx------ 2 docker docker 4096 Apr 7 17:32 /home/docker/.docker/trust/tuf/docker.io/library/debian/changelist 158664 4 dr-xr-xr-x 2 docker docker 4096 Apr 7 16:14 /home/docker/.docker/trust/privateNote that
changelistwas added.Looks like some crude, uncomfortable and unfriendly workaround for me, however for me it is better than nothing.
It does not prevent from using SHAs. AFAICS this is the right thing to do.
Compare:
docker@docker:~$ docker pull debian:buster Pull (1 of 1): debian:buster@sha256:f6b3b7c7b049c2c7d0f19ae988b4eac64fd8e127fa891c9de1d3cf3f8c33cad4 docker.io/library/debian@sha256:f6b3b7c7b049c2c7d0f19ae988b4eac64fd8e127fa891c9de1d3cf3f8c33cad4: Pulling from library/debian a9a7bf5145e4: Pull complete Digest: sha256:f6b3b7c7b049c2c7d0f19ae988b4eac64fd8e127fa891c9de1d3cf3f8c33cad4 Status: Downloaded newer image for debian@sha256:f6b3b7c7b049c2c7d0f19ae988b4eac64fd8e127fa891c9de1d3cf3f8c33cad4 Tagging debian@sha256:f6b3b7c7b049c2c7d0f19ae988b4eac64fd8e127fa891c9de1d3cf3f8c33cad4 as debian:buster docker.io/library/debian:buster docker@docker:~$ docker trust inspect debian:buster [ { "Name": "debian:buster", "SignedTags": [ { "SignedTag": "buster", "Digest": "f6b3b7c7b049c2c7d0f19ae988b4eac64fd8e127fa891c9de1d3cf3f8c33cad4", "Signers": [ "Repo Admin" ] } ], "Signers": [], "AdministrativeKeys": [ { "Name": "Root", "Keys": [ { "ID": "575d013f89e3cbbb19e0fb06aa33566c22718318e0c9ffb1ab5cc4291e07bf84" } ] }, { "Name": "Repository", "Keys": [ { "ID": "5717dcd81d9fb5b73aa15f2d887a6a0de543829ab9b2d411acce9219c2f8ba3a" } ] } ] } ]with:
docker@docker:~$ docker pull hello-world@sha256:e2fc4e5012d16e7fe466f5291c476431beaa1f9b90a5c2125b493ed28e2aba57 docker.io/library/hello-world@sha256:e2fc4e5012d16e7fe466f5291c476431beaa1f9b90a5c2125b493ed28e2aba57: Pulling from library/hello-world c1ec31eb5944: Pull complete Digest: sha256:e2fc4e5012d16e7fe466f5291c476431beaa1f9b90a5c2125b493ed28e2aba57 Status: Downloaded newer image for hello-world@sha256:e2fc4e5012d16e7fe466f5291c476431beaa1f9b90a5c2125b493ed28e2aba57 docker.io/library/hello-world@sha256:e2fc4e5012d16e7fe466f5291c476431beaa1f9b90a5c2125b493ed28e2aba57 docker@docker:~$ docker trust inspect hello-world [] mkdir /home/docker/.docker/trust/tuf/docker.io/library/hello-world: permission deniedReacted by Michael Altfield- closing because we removed
docker trustfrom the CLI; remove support for client-side docker content trust validation #6603
- closing because we removed
So, uhh, you guys just decided to give up on any chance of providing security in docker?
Description
In my setup, Docker Content Trust is 100% security theater. It provides zero security because of TOFU.
Steps to reproduce the issue:
...
Describe the results you received:
Every time I execute my CI build pipeline (which necessarily runs in a new instance on every run), docker downloads the image without telling me it was also downloading the key at the same time, which means it's actually not able to cryptographically verify the authenticity and integrity of the image.
Describe the results you expected:
By default, if running
docker pulland the root key is not already downloaded, then the command should:fail in non-interactive mode or
inform the user that the key isn't present and that it will have to download & TOFU the root key in order to proceed. Print a URL to a doc that provides more information on the risks in this, then prompt the user if they want to abort or continue with the tofu
It should not proceed as normal if the key is not present, misleading the user into thinking that their image download was cryptographically verified in a secure manner (when it wasn't).
Additional information you deem important (e.g. issue happens only occasionally):
Output of
docker version:Output of
docker info:Additional environment details (AWS, VirtualBox, physical, etc.):
QubesOS -> Debian 10
See Also