Using a delegation key

The collaborator can now push to the repository using Docker Content Trust. Docker will automatically choose and pick the right key for the targets/release role.

Edit the file on the Docker-in-Docker container:

FROM alpine

RUN true
RUN uname
RUN echo collaborating

Build the new image:

❯ DOCKER_CONTENT_TRUST_SERVER=https://notary.docker.io docker build -t <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app:1.0.3 .

Push the new image:

❯ docker push <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app:1.0.3

The push refers to a repository [<aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app]
011b303988d2: Pushed
1.0.3: digest: sha256:71482bc2bcf58d113dd109d944749707580b0ea7bb76df81624b68e4d0834268 size: 2980
Signing and pushing trust metadata
Enter passphrase for repository key with ID e93a684 (<aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app):
Successfully signed "<aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app":1.0.3

Test on the repository owner side that the image signed by the collaborator is valid:

❯ docker pull <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app:1.0.3
Pull (1 of 1): <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app:1.0.3@sha256:71482bc2bcf58d113dd109d944749707580b0ea7bb76df81624b68e4d0834268
sha256:71482bc2bcf58d113dd109d944749707580b0ea7bb76df81624b68e4d0834268: Pulling from app
3690ec4760f9: Already exists
Digest: sha256:71482bc2bcf58d113dd109d944749707580b0ea7bb76df81624b68e4d0834268
Status: Downloaded newer image for <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app@sha256:71482bc2bcf58d113dd109d944749707580b0ea7bb76df81624b68e4d0834268
Tagging <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app@sha256:71482bc2bcf58d113dd109d944749707580b0ea7bb76df81624b68e4d0834268 as <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app:1.0.3

Notice that the digest from the collaborator matches the one received on the owner side.

Now attempt to edit the Dockerfile on the owner side again:

FROM alpine

RUN true
RUN uname
RUN date

And build it:

❯ docker build -t <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app:1.0.4 .

Everything looks good. Now try to push it:

❯ docker push <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app:1.0.4

The push refers to a repository [<aws_account_id>.ecr.us-east-1.amazonaws.com/app]
011b303988d2: Pushed
1.0.4: digest: sha256:19cbb30c36b9855aff3ccf7b052bbf6032b7acf4510ea311e82a2e51d926fd8d size: 2966
Signing and pushing trust metadata
Failed to sign "<aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app":1.0.4 - no valid signing keys for delegation roles
no valid signing keys for delegation roles

What happened here was that when delegation was enabled for this repository, Docker now requires keys to be valid under the targets/releases role. Remember that the original key, created upon repository initialization (first push), was listed with the targets role instead.

So in order to enable the repository owner to also be able to sign images, the owner needs to follow the exact same steps as all collaborators, i.e., creating and adding its owner targets/release key to the repository.

While following the collaborator instructions, you may get this error if you have your Yubikey plugged in when running notary key import:

ERRO[0007] failed to import key to store: yubikey only supports storing root keys, got user for key: 6965a1ee8ff68a211d769243c0b171f90cb03a337d2337cc91650b843a5bc1ff

When the import command is ran, Notary assumes that if a Yubikey is plugged in, it should copy the private key there too. However, a Yubikey should only be used for root keys, so when attempting to import a user key, it throws out this harmless error. In the future, it will likely be ignored.

After you've imported the key, the resulting list should be:

❯ notary -d ~/.docker/trust key list

ROLE       GUN                          KEY ID                                                              LOCATION
----       ---                          ------                                                              --------
root                                    bf98cc496cb05fd2b88b01d3200900ff05ec83a1f3690690f2c9341976b64728    yubikey
user                                    a726c2f62f2239055b7a1881c12d0de636b62e0a2c1ef21044083c51962f1959    ~/.docker/trust/private
targets    ...st-1.amazonaws.com/app    9c738a648878fab6124f70f78879dc1da89bae6ac0574c0ea6dfa6f20e80816c    ~/.docker/trust/private

Continue with the delegation key steps, adding the new to the delegation and publishing the changes. You will be asked to enter your original targets key, just like when adding the first collaborator key.

After you're done with your own delegation key, re-issue the push command:

❯ docker push <aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app:1.0.4
The push refers to a repository [<aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app]
011b303988d2: Layer already exists
1.0.4: digest: sha256:19cbb30c36b9855aff3ccf7b052bbf6032b7acf4510ea311e82a2e51d926fd8d size: 2966
Signing and pushing trust metadata
Enter passphrase for user key with ID a726c2f:
Successfully signed "<aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/app":1.0.4

Notice that the passphrase is for your own delegation key now and the push finally works.

results matching ""

    No results matching ""