Docker content trust 101

Docker content trust 101
Docker content trust 101

What is Docker Content Trust (DCT)? It basically allows the user to verify the integrity of the image and image provider before you pull or run them on your system. Meaning, It prevents a user from using a container image from an unknown source or building a container image from a base layer from an unknown source. Docker content trust isn’t enabled by default, by using following command we can enable it.

export DOCKER_CONTENT_TRUST=1

Why do you need Docker Content Trust?

To understand why you need to Docker content trust. You need to understand the security loopholes in your docker image 

Unsafe Registries

Docker images often contain sensitive info about the proprietary software and some times credentials, Say if you run the images from the external sources that are not trustworthy, it might increase the risk of man-in-the-middle attacks and tamper the credentials or run an external program which could have malicious code.

Old images in registries

Since registries are typically the source location for the images, over time you could get many vulnerable (serious security risks) and outdated images, that might impact your availability of the application.

Bottom line: DCT allows you to verify the integrity of the image (only unaltered image will be pulled) and the integrity of the image provider (force the user to sign and verify the image). In terms of portability and reusability, it is good to use a remote repository with appropriate security controls. DCT will be able to address these risks.

Structure of Docker Content Trust

Docker Content Trust has two different keys: Offline key (or)  Root key and Tagging key (or) repository key. These are generated when the provider submits (push) the image and are stored on the client-side. Each repository has a unique repository key. When you pull the image for the first time, the root key is used to establish trust with the repository.

  • Repository keys are the key allows you to sign image tags. They are generated for each new repository by the provider. Meaning that any user or system will need to authenticate to push/pull to the remote repository.
  • Root Key is the root of trust in your repository. You can use this same key for different repositories and back up the root key somewhere safe.

How to implement Docker Content Trust?

Docker engine uses the provider private key (repository key) to sign the image locally before the publisher pushes the image to the remote repository. Then when you pull this image, the docker engine will use the provider public key (root key) to validate/verify the integrity of the image before running on our system. Below are the high level and detailed steps to implement the docker content trust.

Steps to achieve Docker Content Trust:

  1. Generate Key
  2. Add Signer to docker repository.
  3. Sign  Image
  4. Enable DOCKER_CONTENT_TRUST in docker host

Details step to Implementation Docker Content Trust

Step 1

I am using docker hub for this example. If you don’t have a Docker ID, head over to this link and create one.

dev@raghu:~$ docker login
Username: raghudok
Password: *******
Login Succeeded

Step 2

Generate the trust key. Basically the trust key identifies you as a user and this gives the user access to sign images for the repo.

docker trust key generate <signer name>

dev@raghu:~$ docker trust key generate raghudok
Generating key for raghudok...
Enter passphrase for new raghudok key with ID 5259740: 
Repeat passphrase for new raghudok key with ID 5259740:
Successfully generated and loaded private key. Corresponding public key available: /Users/docker/raghudok.pub

Step 3

Add Signer to docker repository.

docker trust signer add –key <keyfile> <user name> <repo>

dev@raghu:~$ docker trust signer add --key raghudok.pub raghudok raghudok/dct-test
Adding signer "raghudok" to raghudok/dct-test...
Initializing signed repository for raghudok/dct-test...
You are about to create a new root signing key passphrase. This passphrase
will be used to protect the most sensitive key in your signing system. Please
choose a long, complex passphrase and be careful to keep the password and the
key file itself secure and backed up. It is highly recommended that you use a
password manager to generate the passphrase and keep it safe. There will be no
way to recover this key. You can find the key in your config directory.
Enter passphrase for new root key with ID 243ffc9:
Repeat passphrase for new root key with ID 243ffc9:
Enter passphrase for new repository key with ID d6ed6dd:
Repeat passphrase for new repository key with ID d6ed6dd:
Successfully initialized "raghudok/dct-test"
Successfully added signer: raghudok to raghudok/dct-test

Test with Unsigned Image: In the below steps we are going to Push/Pull unsigned docker image to/from docker hub. The reason behind that is, to demonstrate how DOCKER_CONTENT_TRUST behaves with untrusted images.

Step 4

Create an image to test  DCT

dev@raghu:~$ vi dockerfile
FROM busybox:latest
CMD echo Hello this is busybox!
dev@raghu:~$ docker build -t raghudok/dct-test:unsigned .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM busybox:latest
latest: Pulling from library/busybox
0669b0daf1fb: Pull complete
Digest: sha256:b26cd013274a657b86e706210ddd5cc1f82f50155791199d29b9e86e935ce135
Status: Downloaded newer image for busybox:latest
 ---> 83aa35aa1c79
Step 2/2 : CMD Hello this is busybox!
 ---> Running in f8ea53541c3f
Removing intermediate container f8ea53541c3f
 ---> 527bac2bb535
Successfully built 527bac2bb535
Successfully tagged raghudok/dct-test:unsigned
dev@raghu:~$ docker run raghudok/dct-test:unsigned
Hello this is busybox!

Step 5

Push it to docker registry

dev@raghu:~$ docker push raghudok/dct-test:unsigned
The push refers to repository [docker.io/raghudok/dct-test]
a6d503001157: Mounted from library/busybox
unsigned: digest: sha256:1284e9867f035651dbdb6cc98871f2af92a0b9eee7aa37bf3bd4dd0d68ac7232 size: 527

Step 6

Enable Docker content trust with the below command in docker host

export DOCKER_CONTENT_TRUST=1

Step 7

Run the docker image and check whether docker content trust is working or not.

dev@raghu:~$ docker run raghudok/dct-test:unsigned
docker: No valid trust data for unsigned.
See 'docker run --help'.

What is the meaning of the above error? Basically, the image is unsigned and there is no signature data available and therefore it is not going to run that image because docker content trust is enabled. So it is pretty evident that if DCT is enabled it will allow the user to pull/run the image on your system.

Test with Signed Image: In the below steps, we are going to Push/Pull signed docker image to/from the docker hub. The reason behind that is, to demonstrate how DOCKER_CONTENT_TRUST behaves with trusted images.

Step 8

Build a new image with the different tag name

dev@raghu:~$ docker build -t raghudok/dct-test:signed .
Sending build context to Docker daemon  4.608kB
Step 1/2 : FROM busybox:latest
 ---> 83aa35aa1c79
Step 2/2 : CMD echo Hello this is busybox!
 ---> Using cache
 ---> 9a0781df9d43
Successfully built 9a0781df9d43
Successfully tagged raghudok/dct-test:signed

Step 9

Sign the docker image

dev@raghu:~$ docker trust sign raghudok/dct-test:signed
Signing and pushing trust data for local image raghudok/dct-test:signed, may overwrite remote trust data
The push refers to repository [docker.io/raghudok/dct-test]
a6d503001157: Layer already exists
signed: digest: sha256:e8d2db0f9cc124273e5f3bbbd2006bf2f3629953983df859e3aa8092134fa373 size: 527
Signing and pushing trust metadata
Enter passphrase for raghudok key with ID 5259740:
Successfully signed docker.io/raghudok/dct-test:signed

Docker trust sign command will generate the signature and push the signature data as well the image itself to the docker registry. Basically it signs the image and does a docker push as well.

Step 10

Run the docker image

dev@raghu:~$ docker run raghudok/dct-test:signed
Hello this is busybox!

Docker content trust is working !!

Step 11

To disable docker content trust please use below command in docker host.

export DOCKER_CONTENT_TRUST=0

Conclusion

From the above steps, we have experimented running signed and unsigned images with Docker Content Trust enabled and disabled. Docker Content Trust is an opt-in feature and enabling this option, will enforce the users to use the remote repositories with signed and verified images. 

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top