Are you tired of downloading sketchy images from the internet and wondering if they’re going to steal your data or turn your computer into a zombie? Well, have no fear, because Docker Content Trust is here! With this powerful feature, you can rest easy knowing that your images are authentic and haven’t been tampered with by some nefarious hacker. So, put on your best pirate hat and get ready to set sail on a sea of digital signatures and trust servers. Arrrr!
Overview
Docker Content Trust is a feature of the Docker platform that allows users to ensure the authenticity and integrity of their images. It works by using digital signatures to ensure that images have not been tampered with and that they come from a trusted source.
The basic idea behind Docker Content Trust is that it allows users to ensure that the images they are using are exactly what they expect them to be. This is especially important in production environments, where running an untrusted image could lead to security vulnerabilities or other issues.
This is done by using the docker trust
command, which allows you to sign images and manage the keys that are used for signing. Once an image is signed, you can share it with others and they can use the trusted server to verify its authenticity.
In addition to signing images, Docker Content Trust also allows you to configure your Docker daemon to only accept images that have been signed by a trusted key. This can be done by setting the DOCKER_CONTENT_TRUST
environment variable to 1
. With this configuration, your daemon will only run images that have been signed by a trusted key, providing an additional layer of security.
Docker Content Trust is an important feature for ensuring the security and integrity of your images, and it is a valuable tool for anyone who is using Docker in production. With its help, you can ensure that the images you are using have not been tampered with and that they come from a trusted source.
Docker Registry
A Docker registry is a place where you can store and distribute your Docker images. It is a service that allows you to upload and download images, as well as manage access to them. There are several different types of registries, including public and private registries.
A public registry, such as Docker Hub, allows anyone to access and download images, while a private registry requires authentication before images can be accessed. A private registry can be self-hosted or it can be hosted by a third party. The main advantage of a private registry is that you have more control over the access and distribution of your images. You can also use it to store and distribute your internal images, which you don’t want to share publicly.
When you run the docker pull
or docker push
command, you’re interacting with a registry. The command is using the image name and tag to locate the image in the registry and download or upload it to your local machine.
Docker Content Trust, or DCT, is a feature that allows you to sign your images in a registry so that you can verify their authenticity and integrity when you download them. This feature is built into the Docker engine and works with any registry that supports the Docker Registry HTTP API v2.
Notary Server
A Notary server is a component of Docker Content Trust (DCT) that is responsible for managing the digital signatures of Docker images. It acts as a trust anchor, allowing you to verify the authenticity and integrity of images that you download from a registry.
When you use DCT to sign an image, the Notary server creates a digital signature of the image’s content, which is then stored in the registry along with the image. When you download the image, the Notary server can then verify that the image has not been tampered with by comparing the digital signature to the image’s content.
A Notary server can be self-hosted or it can be hosted by a third party. When using a public registry like Docker Hub, the Notary server is hosted by Docker Inc. and integrated with the registry. When you’re using a private registry, you can either use the Notary server that is built into the registry or set up your Notary server.
Notary servers are an essential component of DCT, as they are responsible for managing the trust between the registry and the client. They help ensure that the images that you download are authentic and have not been tampered with, which is important for maintaining the security and integrity of your applications.
Let’s go, show me the code
Docker Content Trust (DCT) is a security feature in Docker that allows users to ensure the integrity and authenticity of their images by using digital signatures. In this article, we are going to work with the Docker Hub so you will need to perform a few steps to set up Content Trust on it.
Prerequisites
First, you will need to have Docker and the Docker CLI installed on your system. If you don’t already have them, you can download them from the Docker website.
Log in to Docker Hub: Use the docker login
command to log in to your Docker Hub account.
$ docker login Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one. Username: yourdockerusername Password: ****************** WARNING! Your password will be stored unencrypted in /home/username/.docker/config.json. Configure a credential helper to remove this warning. See https://docs.docker.com/engine/reference/commandline/login/#credentials-store Login Succeeded
Please, remember that every time that you see the ‘username’ text in the command lines, you should type (or see the output of) your username
Create a new repository: Use the Docker Hub web interface to create a new repository for your signed images.
Next, you will need a delegation key pair, and to generate it you need to run the command docker trust key generate
. You can pass the key name as a parameter at the end of the command to turn your management simple, like in the following example:
$ docker trust key generate sillykey Generating key for sillykey... Enter passphrase for new sillykey key with ID 2de8912: Repeat passphrase for new sillykey key with ID 2de8912: Successfully generated and loaded private key. Corresponding public key available: /home/username/sillykey.pub
The next step is to add your key to your docker image repository:
$ docker trust signer add --key sillykey.pub sillykey yourdockerusername/silly-docker-image Adding signer "sillykey" to yourdockerusername/silly-docker-image... Initializing signed repository for yourdockerusername/silly-docker-image... 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 a2bc445: Repeat passphrase for new root key with ID a2bc445: Enter passphrase for new repository key with ID 76fa334: Repeat passphrase for new repository key with ID 76fa334: Successfully initialized "yourdockerusername/silly-docker-image" Successfully added signer: sillykey to yourdockerusername/silly-docker-image
It is very important that you back up your keys to a safe, secure location. The loss of the repository key is recoverable, but the loss of the root key is not. The Docker client stores its keys in ~/.docker/trust/private
. Before backing them up, you should tar
them into an archive:
$ umask 077; tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private; umask 022
If a publisher loses keys it means losing the ability to sign images for the repositories in question. If you lose a key, send an email to Docker Hub Support. As a reminder, the loss of a root key is not recoverable.
This loss also requires manual intervention from every consumer that used a signed tag from this repository prior to the loss.
Image consumers get the following error for content previously downloaded from the affected repo(s):
Meet all types of keys:
Key | Description |
---|---|
root key | Root of content trust for an image tag. When content trust is enabled, you create the root key once. Also known as the offline key, because it should be kept offline. |
targets | This key allows you to sign image tags, to manage delegations including delegated keys or permitted delegation paths. Also known as the repository key, since this key determines what tags can be signed into an image repository. |
snapshot | This key signs the current collection of image tags, preventing mix and match attacks. |
timestamp | This key allows Docker image repositories to have freshness security guarantees without requiring periodic content refreshes on the client’s side. |
delegation | Delegation keys are optional tagging keys and allow you to delegate signing image tags to other publishers without having to share your targets key. |
Ok, let’s continue, now you already have your repository and your keys, let’s create a funny image to sign and push it to the server. You can write a file called Dockerfile with the following code:
FROM debian:bullseye-slim RUN apt-get update RUN apt-get install cowsay -y WORKDIR /usr/games ENTRYPOINT ["./cowsay", "Docker is moo-sic to my ears!"]
Then, to build this image, you need to run the following command in the same directory in which you have created the Dockerfile file:
$ docker build -t yourdockerusername/silly-docker-image:1.0 .
Finally, you can run this image and see our application output:
$ docker run yourdockerusername/silly-docker-image:1.0 _______________________________ < Docker is moo-sic to my ears! > ------------------------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
Signing the images
To sign an image, you will need to use the docker trust sign
command. For example, to sign an image called “yourdockerusername/silly-docker-image:1.0”, you would run the following command:
$ docker trust sign yourdockerusername/silly-docker-image:1.0 Signing and pushing trust data for local image yourdockerusername/silly-docker-image:1.0, may overwrite remote trust data The push refers to repository [docker.io/yourdockerusername/silly-docker-image] c42edefc7587: Pushed 2146fcda67d0: Pushed 5f42c1eadfdc: Mounted from library/debian 1.0: digest: sha256:f7055def448b863a5048495e28efdc5e291fca790b944cc1226e0a6fb48dc60b size: 953 Signing and pushing trust metadata Enter passphrase for sillykey key with ID 2de8912: Successfully signed docker.io/yourdockerusername/silly-docker-image:1.0
This command will prompt you to enter your passphrase for the repository key.
After you’ve signed an image, you can use the docker trust inspect
command to view the signature details. For example, to view the signature details for “yourdockerusername/silly-docker-image:1.0”, you would run the following command:
$ docker trust inspect --pretty yourdockerusername/silly-docker-image:1.0 Signatures for yourdockerusername/silly-docker-image:1.0 SIGNED TAG DIGEST SIGNERS 1.0 f7055def448b863a5048495e28efdc5e291fca790b944cc1226e0a6fb48dc60b sillykey List of signers and their keys for yourdockerusername/silly-docker-image:1.0 SIGNER KEYS sillykey 2de89122b123 Administrative keys for yourdockerusername/silly-docker-image:1.0 Repository Key: c42edefc75871e4ce2146fcda67d03dda05cc26fdf93b17b55f42c1eadfdc322 Root Key: 1cf86b5e65d51bf2be47bc4a9d66b6bacc5935119a5729d090ad0fcee3a682af
Next, you will need to push the signed image to a registry. This can be done using the docker push
command. For example, to push “yourdockerusername/silly-docker-image:1.0” to the Docker Hub, you would run the following command:
$ docker push yourdockerusername/silly-docker-image:1.0 The push refers to repository [docker.io/yourdockerusername/silly-docker-image] c42edefc7587: Layer already exists 2146fcda67d0: Layer already exists 5f42c1eadfdc: Layer already exists 1.0: digest: sha256:f7055def448b863a5048495e28efdc5e291fca790b944cc1226e0a6fb48dc60b size: 953
Environment Settings
Content trust is disabled by default in the Docker Client. To enable it, set the environment DOCKER_CONTENT_TRUST
variable to 1
. This prevents users from working with tagged images unless they contain a signature.
$ export DOCKER_CONTENT_TRUST=1
Pull the Image
Finally, you can use the docker pull
command to download and verify an image. By default, the Docker client will check the image’s signatures before downloading it. If the image has been tampered with, the client will refuse to download it.
Here’s an example of how to use the docker pull
command:
$ docker pull yourdockerusername/silly-docker-image:1.0
It’s important to note that in order to use Docker Content Trust, the image must be signed and pushed to a registry that supports Notary.
Docker Content Trust is a powerful feature that can help ensure the integrity and authenticity of your images. By using digital signatures and a trusted server, you can ensure that your images are not tampered with during transit and that they come from a trusted source.
It is also important to ensure that your system is configured with the appropriate security settings, such as firewalls, permissions, and network isolation to enhance the security of your system.
I hope that this article helps you understand how to set up and use Docker Content Trust.