Notary v2 is a framework designed to sign and validate container images and other artifacts stored in OCI-compliant registries. It plays a key role in securing the software supply chain by verifying that artifacts originate from trusted sources and remain unaltered during transit or storage.
This guide will help you to sign and update Docker images in the Artifactory Docker repository.
Step 1: Install and configure Notation CLI
You can download and install the notation CLI from here.
$ notation version
Notation - a tool to sign and verify artifacts.
Version: 1.3.1
Go version: go1.23.6
Git commit: bb571ddfb04f9d175daf64520fd18e7bea8ecbdf
Step 2: Login into the Artifactory docker repository using the Notation CLI (The method is same as you login using docker client)
$ notation login test-docker.myartifactory.vm
Username: xxxx
Password:
Login Succeeded
Step 3: List the signatures in the container image using its digest
(The input should be in the format: <registry>/<image>:<tag> or <registry>/<image>@<digest>. However, it is strongly recommended to use the digest format)
Command: notation ls <registry>/<image>@<digest>
$ notation ls
test-docker.myartifactory.vm/dotnet/sdk@sha256:2ae6b3ae6e93bb88c4649bfabf224a0e13444af698e48bdc7e91ab57cbdcb651
test-docker.myartifactory.vm/dotnet/sdk@sha256:2ae6b3ae6e93bb88c4649bfabf224a0e13444af698e48bdc7e91ab57cbdcb651 has no associated signature
Note: You can find that currently it is not signed.
Step 4: Generate the Certificate to sign the images
Command: notation cert generate-test --default <mytrusted-host.vm>
notation cert generate-test --default shis.vm
Note: To list the key and certs, run the below commands. The * prefix is the default key.
notation key ls
notation cert ls
Step 5: Sign the image
Command: notation sign <registry>/<image>@<digest>
$ notation sign test-docker.myartifactory.vm/dotnet/sdk@sha256:2ae6b3ae6e93bb88c4649bfabf224a0e13444af698e48bdc7e91ab57cbdcb651
Successfully signed test-docker.myartifactory.vm/dotnet/sdk@sha256:2ae6b3ae6e93bb88c4649bfabf224a0e13444af698e48bdc7e91ab57cbdcb651
Step 6: Confirm whether the signature is added
Command: notation ls <registry>/<image>@<digest>
$ notation ls test-docker.myartifactory.vm/dotnet/sdk@sha256:2ae6b3ae6e93bb88c4649bfabf224a0e13444af698e48bdc7e91ab57cbdcb651
test-docker.myartifactory.vm/dotnet/sdk@sha256:2ae6b3ae6e93bb88c4649bfabf224a0e13444af698e48bdc7e91ab57cbdcb651
└── application/vnd.cncf.notary.signature
└── sha256:4d7a56efd17a0a3255adc4b2771b8b4bf2786e71bdbb3db8d89ba19bf121248b
Step 7: Create a trustpolicy to trust only the certificate we have used to sign
$cat <<EOF > ./trustpolicy.json
{
"version": "1.0",
"trustPolicies": [
{
"name": "trust-policy-example",
"registryScopes": [ "*" ],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:shis.vm" ],
"trustedIdentities": [
"*"
]
}
]
}
EOF
$notation policy import ./trustpolicy.json
$notation policy show
Step 8: Verify whether the image can be trusted
Command: notation verify <registry>/<image>@<digest>
$ notation verify test-docker.myartifactory.vm/dotnet/sdk@sha256:2ae6b3ae6e93bb88c4649bfabf224a0e13444af698e48bdc7e91ab57cbdcb651
Successfully verified signature for test-docker.myartifactory.vm/dotnet/sdk@sha256:2ae6b3ae6e93bb88c4649bfabf224a0e13444af698e48bdc7e91ab57cbdcb651
Reference:
Notation
Notaryproject