Skip to main content

Ubuntu does an excellent job of setting a trust chain that can be tracked all the way down to the original code both with hashes and signatures. You can follow the base code signature and hashes all the way up to the final signed/hashed distribution.  How about docker?

The standard method to start a docker Ubuntu Focal container is to call sudo docker pull ubuntu:focal . The signature verification is done by docker, now that Docker has implemented the variable "DOCKER_CONTENT_TRUST=1" . This verifies digital signatures on containers before docker pulls the docker container image.

Note however that "export DOCKER_CONTENT_TRUST=1" only affects your shell, not the sudo shell, so either modify bash rc include files or call as sudo -E docker pull ubuntu:focal  or sudo DOCKER_CONTENT_TRUST=1 docker pull ubuntu:focal .

But what about the chain of trust? What about a sha256sum check on download?   Even though Ubuntu provides a base image for Docker to use, It turns out that docker does "stuff" to distros before putting it in the Docker repository and that changes the checksum between the official released Ubuntu image and what's in the docker repository. See https://github.com/tianon/docker-brew-ubuntu-core/issues/185 for more on the security issue.

How to check that the changes made to the docker repo container image vs the  officially-released ubuntu container are not unsigned binaries?

sudo DOCKER_CONTENT_TRUST=1 docker pull ubuntu:focal

    ...    ubuntu:focal@sha256:cbcf86d7781dbb3a6aa2bcea25403f6b0b443e20b9959165cf52d2cc9608e4b9

sudo docker inspect ubuntu:focal | grep ubuntu@sha256

    ...    "ubuntu@sha256:cbcf86d7781dbb3a6aa2bcea25403f6b0b443e20b9959165cf52d2cc9608e4b9"

Re-create the tar image that docker uses in their container by extracting the layers and then extracting the layers all to one combined directory.

mkdir -p docker.ubuntu.cc9608e4b9/combined

docker save ubuntu:focal > ubuntu.focal.cc9608e4b9.tar

tar --directory=docker.ubuntu.cc9608e4b9 -xf ubuntu.focal.cc9608e4b9.tar

for LAYER in $(ls docker.ubuntu.cc9608e4b9/layer.tar); do   tar --directory docker.ubuntu.cc9608e4b9/combined/ -xf $LAYER; done

 

Download the original Ubuntu docker image from the official ubuntu docker repository. Note: https://partner-images.canonical.com/core/focal/current/ is the latest, but see https://partner-images.canonical.com/core/focal/ for testing older versions.

wget https://partner-images.canonical.com/core/focal/current/ubuntu-focal-core-cloudimg-amd64-root.tar.gz

wget https://partner-images.canonical.com/core/focal/current/SHA256SUMS

grep amd64 SHA256SUMS | sha256sum --check --


Should get ubuntu-focal-core-cloudimg-amd64-root.tar.gz: OK .

mkdir ubuntu.focal.current

tar --directory=ubuntu.focal.current -zxf ubuntu-focal-core-cloudimg-amd64-root.tar.gz

Now compare docker container image extracted tar with ubuntu cloud image extracted tar

diff -r ubuntu.focal.current/ ubuntu.focal.cc9608e4b9/combined/

 

I'm expanding on this a bit at https://github.com/AJRepo/docker_image_checks . It's actually quite challenging because Ubuntu is updated frequently as is Docker and so the Docker Image you are analyzing can be behind the official release by quite a bit.