docker / cli

The Docker CLI
Apache License 2.0
4.98k stars 1.94k forks source link

Docker Content Trust image signing #2530

Open marcofranssen opened 4 years ago

marcofranssen commented 4 years ago

I'm trying following scenario.

On my laptop I have created a delegation key. On a server I have created the target and authorized my delegation key Now when signing my Docker image via docker trust I'm getting following error.

An error occurred during validation: rpc error: code = 5 desc = key 6505d5d177b8ad1868d721f0043d0f16f4fc7cdbf27a0940c6f1ef52a95b15b9 not found

This 6505…. key is the private key for the target on the other machine, which I don’t have on my current machine.

Is what I'm trying even possible? Do I somehow have to synchronize all the keys to be able to do this?

Wanted to keep the targets on a server for backup reasons as well for limiting who has access to those keys.

This ticket was also created in this repo.

https://github.com/theupdateframework/notary/issues/1558

krufab commented 4 years ago

To improve security, you need to create a delegation key, then import that key in the build server. Be careful that sometimes the key import step seems to complete successfully, but it doesn't. Look your .docker/trust/private folder to see if the key has been imported. Check my comment here: https://github.com/docker/cli/issues/1095#issuecomment-707003138

For the rest, this is the process that works for me:

# In bash

# Setup variables
export DOCKER_CONTENT_TRUST_SERVER="https://notary.example.com"
export DOCKER_REGISTRY="harbor.example.com/vrt-system-docker-registry"
export NOTARY_OPTIONS="-s ${DOCKER_CONTENT_TRUST_SERVER} -d ${HOME}/.docker/trust"

export NOTARY_ROOT_PASSPHRASE="some_password1"
export NOTARY_TARGETS_PASSPHRASE="some_password2"
export NOTARY_SNAPSHOT_PASSPHRASE="some_password3"
export NOTARY_AUTH="$(base64 <<<"some_user:some_password4")"

# Create users' keys
export DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE="some_password5"
docker trust key generate devops
export DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE="some_password6"
docker trust key generate another_user

# Here begins the delegation process for the-image
export IMAGE="the-image"
# Init registry for "the-image" (it will require the root, target and snapshot passhprases and the auth)
notary ${NOTARY_OPTIONS} init --publish ${DOCKER_REGISTRY}/${IMAGE}
# Rotate the snapshot key to have it managed by the server
notary ${NOTARY_OPTIONS} key rotate ${DOCKER_REGISTRY}/${IMAGE} snapshot --server-managed
# Add all the delegation keys to allow pushing for "the-image"
notary ${NOTARY_OPTIONS} delegation add --publish ${DOCKER_REGISTRY}/${IMAGE} targets/releases devops.pub another_user.pub --all-paths

# Important: Export the keys with notary
# Check https://github.com/docker/cli/issues/2031
# Check https://github.com/docker/cli/issues/1095#issuecomment-707003138
notary -d $HOME/.docker/trust key list
notary -d $HOME/.docker/trust key export --key devops_key_id -o new_devops_private.key

# Copy / store the new_devops_private.key on your build server

# On your build server:
export DOCKER_CONTENT_TRUST=1
export DOCKER_CONTENT_TRUST_SERVER="https://notary.example.com"
export DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE="some_password5"
docker trust key load --name devops path/to/the/new_devops_private.key
docker push

With this process, delegated keys will be able to push for all the tags for the specified image. Even though you can reuse the same root and users' keys, it seems that you need to init the repository and delegate all the required keys for each new image (i.e. my-new-image).

marcofranssen commented 4 years ago

That is the same process as we were about to target in our research environment. Thanks for sharing that input. I think that gives a good input to the community on how to tackle this kind of scenario.

We have automated the part of creating the target, snapshot and delegation keys using a web interface. This allows to manage those keys using a web interface. It still requires some work and improvements. We do accept contributions. https://github.com/philips-labs/dct-notary-admin

That only leaves the following to be done in CI.

export DOCKER_CONTENT_TRUST=1
export DOCKER_CONTENT_TRUST_SERVER="https://notary.example.com"
export DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE="some_password5"
docker trust key load --name devops path/to/the/new_devops_private.key
docker push
williamdes commented 4 months ago

For users searching for a solution, you can delete the need of a snapshot key: https://stackoverflow.com/a/78830014/5155484