Securing Containers using Docker Content Trust
Trust is a key issue when exchanging data across networked systems. It is particularly important to assure the integrity and the publisher of all the data a system relies on while interacting through an unreliable medium like the internet.
Strong cryptographic assurances are needed to secure data. This is where Docker Content Trust (DCT) comes into the picture.
Strong cryptographic assurances are provided by Docker Content Trust (DCT) regarding the types of software and versions being used in your infrastructure. With version 1.8 of Docker Engine, Docker Content Trust debuted.
The security measures added by Docker Content Trust check the consistency of container images, the container files that house application components, and content, that are kept in registries like Docker Hub.
With registries, Docker Content Trust addresses two issues:
- Users downloading a container image from a remote repository may upload one that contains malware but is unable to verify its integrity.
- Second, users may upload out-of-date containers to a registry, which could affect the company’s interoperability, compatibility, or performance.
How DCT operates?
Docker Content Trust is quite straightforward. Docker Content Trust is based on the Docker Notary tool to publish and manage trusted content and The Update Framework (TUF), which is a framework to secure software update systems. The Notary project provides a client-server foundation for establishing a trust to verify and work with content collections.
Users can securely obtain the publisher’s public key, and then use it to verify the content. Notary depends on TUF for secure software distribution and updates operations.
Docker Content Trust Keys:
Trust for an image tag is managed through the use of signing keys. DCT is associated with the TAG portion of an image.When a DCT operation is initially used, a key set is generated.
The following key classes make up a key set:
- an offline key that is the root of DCT for an image tag
- repository or tagging keys that sign tags
- a server-managed key, such as the timestamp key, which ensures freshness security for your repository.
Trust for an image tag is managed through the use of signing keys. DCT is not enabled by default in docker client. The steps below must be followed to set up DCT.
To enable DCT, issue the below command on your Linux docker node:
$ export DOCKER_CONTENT_TRUST=1
DOCKER_CONTENT_TRUST=0 for disabling DCT.
Steps to Enable Docker Content Trust:
- Generate Key
- Add Signer to the docker repository.
- Sign Image
I am going to use the docker hub for the steps to enable docker content trust for illustration.
Step1: Login to the docker hub.
dev@srini:~$ docker login
Step 2: Produce the trust key. The trusted key basically establishes your user identity and grants you access to sign images for the repository.
docker trust key generate <signer name>
dev@raghu:~$ docker trust key generate srinidev
Generating key for srinidev...
Enter passphrase for new srinidev key with ID 5259740:
Repeat passphrase for new srinidev key with ID 5259740:
Successfully generated and loaded private key. Corresponding public key available: /Users/docker/srinidev.pub
Step 3: Add Signer to the docker repository.
docker trust signer add –key <keyfile> <user name> <repo>
dev@srini:~$ docker trust signer add --key srinidev.pub srinidev srinidev/springboot-test
Adding signer "srinidev" to srinidev/springboot...
Initializing signed repository for srinidev/springboot...
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 443ffc9:
Repeat passphrase for new root key with ID 443ffc9:
Enter passphrase for new repository key with ID d6ef6dd:
Repeat passphrase for new repository key with ID d6ef6dd:
Successfully initialized "srinidev/springboot"
Successfully added signer: srinidev to srinidev/springboot
dev@srini:~$ docker build -t srinidev/springboot:unsigned
Sending build context to Docker daemon 3.072kB
Step 1/2 : FROM busybox:latest
latest: Pulling from library/busybox
05669b0daf1fb: Pull complete
Status: Downloaded newer image for busybox:latest
Step 2/2 : CMD Hello this is busybox!
---> Running in g8ea53541c3f
Removing intermediate container k8ea53541c3f
Successfully built 827bac2bb535
Successfully tagged srinidev/springboot:unsigned
Step 5: Push the image to docker registry.
dev@srini:~$ docker push srinidev/springboot:unsigned
Step 6: issue the command: $ export DOCKER_CONTENT_TRUST=1
Step 7: Run the docker image and check whether the docker content trust is working or not.
dev@srini:~$ docker run srinidev/springboot:unsigned
docker: No valid trust data for unsigned.
See 'docker run --help'.
Because the image is unsigned and no signature data is provided, it cannot be launched 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.
Step 8: Now let’s test and build the new signed image.
dev@srini:~$ docker build -t srinidev/springboot:signed
Step 9: Sign the docker image using following command.
dev@srini:~$ docker trust sign srinidev/springboot:signed
Signing and pushing trust data for local image srinidev/springboot:signed, may overwrite remote trust data
The push refers to repository [docker.io/srinidev/springboot:signed]
a6d503001157: Layer already exists
signed: digest: sha256:e8d2db0f9cc124273e5f3bbbd2006bf2f3629953983df859e3aa8092134fa373 size: 567
Signing and pushing trust metadata
Enter passphrase for srinidev key with ID 5239740:
Successfully signed docker.io/srinidev/springboot:signed
The DTS command will generate the signature and push the signature data as well as the image itself to the docker registry. Basically, it signs the image and does a docker push as well.
Step 10: Run the new docker signed image.
dev@srini:~$ docker run srinidev/springboot:signed
If the above steps are running successfully, it indicates that Docker content trust is working. To use the remote repositories with signed and certified images, users must enable the opt-in Docker Content Trust functionality.
Please refer to my blog for more articles: