Signing Images
Signing container images is a process that ensures their authenticity and integrity. This is achieved by adding a digital signature to the container image, which can be validated during deployment. The signature helps to verify that the image is from a trusted publisher and has not been modified.
Notation is an open-source supply chain tool developed by the Notary Project, which supports signing and verifying container images and other artifacts.
The following registries are compatible with the Notary Project OCI signature specification and its implementation in Notation:
- Azure Container Registry
- Amazon Elastic Container Registry
- GitHub Container Registry
- ORAS Distribution Registry
- Zot registry
Akeyless can be used to store certificates with signing keys that can be used by Notation with the Akeyless plugin for Notation, to sign and verify container images and other artifacts for the supported container registries.
Install the Notation CLI
To install the Notation CLI, follow the relevant doc according to your environment OS as described in the Notation official docs. In the following example for simplicity, we will use Homebrew package manager.
brew install notation
Akeyless Plugin Installation
The plugin directory varies depending on the operating system being used. The directory path in our example assumes Ubuntu. Please read the Notation directory structure for system configuration for more information.
Create a folder for the Akeyless Notation plugin configuration:
mkdir -p ~/.config/notation/plugins/akeyless
mkdir -p $HOME/Library/Application\ Support/notation/plugins/akeyless
mkdir %AppData%/notation/plugins
Download the Akeyless official Notation plugin for Akeyless public artifacts:
cd ~/.config/notation/plugins/akeyless
curl -o notation-akeyless https://rest.akeyless.io/Akeyless_Artifacts/Linux/notation-akeyless/notation-akeyless-linux-amd64
chmod +x notation-akeyless
cd $HOME/Library/Application\ Support/notation/plugins/akeyless
curl -o notation-akeyless https://rest.akeyless.io/Akeyless_Artifacts/MacOS/notation-akeyless/notation-akeyless-darwin-amd64
chmod +x notation-akeyless
cd %AppData%/notation/plugins
curl -o notation-akeyless https://rest.akeyless.io/Akeyless_Artifacts/Windows/notation-akeyless/notation-akeyless-windows-amd64.exe
Note
For ARM architecture download the relevant binaries from here
List the Notation Plugins list to verify that Akeyless is listed.
notation plugin ls
Configuration
Notation Plugins configuration supports the use of environment variables or static config file, our example will use a config file.
Depending on your OS type create the relevant config file accordingly:
cd /var/akeyless/conf
cat <<EOF > notation.conf
akeyless_url="https://<Your Gateway URL>:8000/api/v2 # Or using port :8081"
[auth]
access_id="<AccessID>"
access_key="<AccessKey>"
access_type="access_key"
EOF
cd C:\Users\<USER>\.akeyless\profiles
echo akeyless_url="https://<Your Gateway URL>:8081" > notation.conf
echo [auth] >> notation.conf
echo access_id="<AccessID>" >> notation.conf
echo access_key="<AccessKey>" >> notation.conf
echo access_type="access_key" >> notation.conf
Where:
-
akeyless_url
- Your Akeyless GatewayAPI v2
endpoint8000/api/v2
(or using your gateway url at port8081
)., if not set, by default will work with Akeyless public API endpointhttps://api.akeyless.io
. -
access_type
- The Authentication Method type, supporting:access_key
,aws_iam
,gcp
,azure_ad
certificate
,jwt
andk8s
. -
access_id
- The Auth method Access ID. -
access_key
- Relevant only for API Key Auth method. -
k8s_conf_name
- Relevant only for Kubernetes Auth method.
Create a Self-Signed Certificate
The Notary project specified the requirements for different types of certificates, the following examples will use a Self Signed CA certificate.
Note
It is possible to work with Akeyless PKI Issuer to generate the certificates, the PKI Issuer must be set with the
Code Signing
flag , andKey Usage List
ofcritical,DigitalSignature
.
Akeyless Supports both EC and RSA algorithms, run the following commands to create a key with a self signed certificate.
Create a CSR config file:
cat <<EOF > csr.conf
countryName = US
stateOrProvinceName = NY
localityName = NY
organizationName = Akeyless
organizationalUnitName = Security
commonName = akeylessSign
[ v3_req ]
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature
EOF
Create a key with a self-signed certificate:
akeyless create-dfc-key -n CodeSign -a RSA2048 --generate-self-signed-certificate true --certificate-format pem --conf-file-path csr.conf --certificate-ttl 30
Set Notation Default Key
notation key add --plugin akeyless --id /CodeSign --default Akeyless
Where:
-
id
- The full key name or the keyitem id
, as stored inside Akeyless. In our example, we used the created key namedCodeSign
. -
default
- Optional, to mark this key for Notation as a default key, with a friendly name for notation, in this example, we simply named itAkeyless
.
Verify that the key is added to the Notation keys:
notation key ls
Sign Image
For the simplicity of this example, the following steps will demonstrate the simple creation of a trust policy to sign docker artifacts.
docker run -d -p 5001:5000 ghcr.io/oras-project/registry:v1.0.0-rc.4
Use docker build
and docker push
to build and push a sample image to your registry.
docker build -t localhost:5001/net-monitor:v1 https://github.com/wabbit-networks/net-monitor.git#main
docker push localhost:5001/net-monitor:v1
IMAGE=$(docker inspect --format='{{index .RepoDigests 0}}' localhost:5001/net-monitor:v1)
Use notation ls
to list the current signatures for your image. The following example sets the value of $IMAGE
to the name of the image and its digest value.
notation ls $IMAGE
Confirm there are no signatures listed. And use notation sign
command to sign the image:
notation sign $IMAGE
Verify Image Signatures
To verify the container image, add the root certificate that signs the leaf certificate to the trust store and create trust policies for verification. For the self-signed certificate used in this tutorial, the root certificate is the self-signed certificate itself.
Note
Depending on your OS the follow the folder structure as described here
Get the certificate from Akeyless:
akeyless describe-item -n CodeSign --json --jq-expression .certificates | base64 -d > certificate.pem
Add the public certificate to a named trust store for signature verification:
notation certificate add --type ca --store selfSigned certificate.pem
Create a trustpolicy.json
with the following trust policy in the notation configuration directory.
Note: this is a very permissive trust policy. Read more on creating trust policies and trust stores here:
{
"version": "1.0",
"trustPolicies": [
{
"name": "trust-policy-example",
"registryScopes": [ "*" ],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:selfSigned" ],
"trustedIdentities": [
"*"
]
}
]
}
Add the policy to notation
notation policy import trustpolicy.json
Verify the signature
notation verify $IMAGE
Updated 8 days ago