Skip to content

Container Image Signing

Finch supports signing and verifying container images with cosign.

Cosign Prerequisites

Before you can leverage Finch to sign container images you will need to have the cosign binary on your local machine to generate the private / public keys. See the cosign documentation to find the various installation options.

Cosign supports self-managed keys and keyless signing. At this time only self-managed keys are supported on Finch.

Generate a Self Managed Key

Before we can sign a container image, you need to generate a self managed key. This could be a new key generated by cosign or an imported existing key. To generate a new key:

  1. Generate a cosign private and public key.

    cosign generate-key-pair
    

    A cosign private and public key will be created and placed in the directory where the command was run, this key could also be stored in a KMS.

Sign a container image with cosign

  1. To sign a container image, the image needs to exist locally. This could be an existing container image pulled down from a remote registry to be signed or a new image that has just been built by finch build. In this walkthrough we will pull down an existing image.

    finch pull public.ecr.aws/finch/hello-finch:latest
    
  2. A container image is signed with Finch when it is pushed to a container registry, therefore in preparation for the finch push we need to re tag the container image with the an appropriate destination tag. A container repository may also need to be created in the upstream repository. The below command is tagging the container image to an Amazon ECR repository URI, but this could be any OCI container registry.

    AWS_ACCOUNT_ID=111222333444
    AWS_REGION=eu-west-1
    
    finch tag \
        public.ecr.aws/finch/hello-finch:latest \
        $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
    
    $AWS_ACCOUNT_ID="111222333444"
    $AWS_REGION="eu-west-1"
    
    finch tag `
        public.ecr.aws/finch/hello-finch:latest `
        "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch"
    
  3. Push and sign the container image with the finch push --sign cosign command.

    finch push \
        --sign=cosign  \
        --cosign-key cosign.key \
        $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
    
    finch push `
        --sign=cosign  `
        --cosign-key cosign.key `
        "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch"
    
  4. Verify the Container Image and the Signature with the cosign verify command.

    cosign verify \
        --key cosign.pub \
        $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
    
    cosign verify `
        --key cosign.pub `
        "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch"
    

Verify a Container Image Signature with cosign

Once a container image has been signed and pushed to a registry, you can verify the signature against the public key when you pull and run the container image.

Pulling a Container Image

To verify the image signature when pulling a container image, you can pass the --verify flag in to the finch pull command. Ensure you have access to the public key that signed the container image and that it is stored in the local directory.

AWS_ACCOUNT_ID=111222333444
AWS_REGION=eu-west-1

finch pull \
    --verify=cosign  \
    --cosign-key cosign.pub \
    $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
$AWS_ACCOUNT_ID="111222333444"
$AWS_REGION="eu-west-1"

finch pull `
    --verify=cosign  `
    --cosign-key cosign.pub `
    "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch"

Running a Container Image

To verify the image signature when running a container, you can pass the --verify flag in to the finch run command. Ensure you have access to the public key that signed the container image and that it is stored in the local directory.

AWS_ACCOUNT_ID=111222333444
AWS_REGION=eu-west-1

finch run --rm \
    --verify=cosign  \
    --cosign-key cosign.pub \
    $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
$AWS_ACCOUNT_ID="111222333444"
$AWS_REGION="eu-west-1"

finch run --rm `
    --verify=cosign  `
    --cosign-key cosign.pub `
    "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch"

Container Image Signing with Compose and cosign

When leveraging Compose to define services, you can use the x-nerdctl-sign and x-nerdctl-verify keys to sign and verify container images.

In this walkthrough we will use the hello-finch sample application.

git clone https://github.com/runfinch/finch.git
cd finch/contrib/hello-finch

Sign a container image with compose

  1. Create a Compose file. We define the hello-finch service, pass a build key to provide the build context, as well as a x-nerdctl-sign and x-nerdctl-cosign-private-key keys.

    cat <<EOF > compose.yaml
    services:
      hello-finch:
        image: $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
        build: .
        x-nerdctl-sign: cosign
        x-nerdctl-cosign-private-key: cosign.key
    EOF
    
    @"
    services:
      hello-finch:
        image: $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
        build: .
        x-nerdctl-sign: cosign
        x-nerdctl-cosign-private-key: cosign.key
    "@ > compose.yaml
    
  2. Build the container image finch compose build

    finch compose build
    
  3. Finally push the container image up to the container registry, ensuring the cosign keys are generated and exist locally.

    finch compose push
    
  4. To verify the container image and the signature have been pushed correctly, you can use the cosign verify command.

    cosign verify \
        --key cosign.pub \
        $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
    
    cosign verify `
        --key cosign.pub `
        "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch"
    

Verify a container image with compose

  1. To verify a container image signature, update the existing compose file with the x-nerdctl-verify and x-nerdctl-cosign-public-key keys.

    cat <<EOF > compose.yaml
    services:
      hello-finch:
        image: $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
        build: .
        x-nerdctl-sign: cosign
        x-nerdctl-cosign-private-key: cosign.key
        x-nerdctl-verify: cosign
        x-nerdctl-cosign-public-key: cosign.pub
    EOF
    
    @"
    services:
      hello-finch:
        image: $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/hello-finch
        build: .
        x-nerdctl-sign: cosign
        x-nerdctl-cosign-private-key: cosign.key
        x-nerdctl-verify: cosign
        x-nerdctl-cosign-public-key: cosign.pub
    "@ > compose.yaml
    
  2. The image signatures can be verified when pulling the container images.

    finch compose pull
    
  3. Signatures can also be verified when running the containers.

    finch compose run