Step 12 - Verify TLog Signature

- Thomas Jungbauer Thomas Jungbauer ( Lastmod: 2024-05-08 ) - 2 min read

Since the image has been deployed on DEV now, we need to prepare everything for production. Before we start, we need to confirm that the whole signing process has been passed and that our signature has been applied correctly. With CoSign we signed our image and used Rekor to create a transparency log. We will use this log to confirm that the image was signed.


The goals of this step are:

  • Verify if the image has been signed using Rekor transparency log.

CoSign public key

Before we start, we need a secret in the Namespace ci that provides the PUBLIC key of CoSign. This key was generated in a previous Step 5 - CoSign - Signing the Image

kind: Secret
apiVersion: v1
  name: cosign-secret (1)
  namespace: ci
data: >-
    <base64 CoSign PUBLIC key>
type: Opaque
1base64 decoded PUBLIC key of CoSign

Create the Task

The following task will use several steps to fetch and parse the transparency log, that has been created. The different tasks are using images from Redhat-gpte. The command line tool rekor-cli will be used to verify the entries in the log.

kind: Task
  name: rekor-verify
  namespace: ci
    - default: image-registry-secret (1)
      name: registrySecret
      type: string
    - default: cosign-secret (2)
      name: cosignSecret
      type: string
    - default: >-
      name: image
      type: string
    - default: ''
      name: pipelinetoolsImage
      type: string
    - env:
        - name: REGISTRY_SECRET
              key: .dockerconfigjson
              name: $(params.registrySecret)
        - name: COSIGN_PUBLIC_KEY
              name: $(params.cosignSecret)
      image: $(params.pipelinetoolsImage)
      name: cosign-verify-image
      resources: {}
      script: >

        mkdir -p /home/cosign/.docker/

        echo "${REGISTRY_SECRET}" > /home/cosign/.docker/config.json

        echo "${COSIGN_PUBLIC_KEY}" > /workspace/

        cosign verify --key /workspace/ $(params.image) --output-file

        cat /workspace/cosign.verify | jq --raw-output '.[0] | .critical |
        .image | .["docker-manifest-digest"]' > /workspace/cosign.sha

        rekor-cli search --sha $(cat /workspace/cosign.sha) --format json >

        cat /workspace/ | jq '.UUIDs[0]' | sed 's/\"//g' >

        rekor-cli get --uuid $(cat /workspace/rekor.uuid) --format json >

        cat /workspace/rekor.get | jq -r .Attestation
1Registry pull secret.
2CoSign public key.

Update the Pipeline

The Pipeline object must be extended with another Task:

    - name: verify-tlog-signature
      params: (1)
        - name: registrySecret (2)
          value: tjungbau-secure-supply-chain-demo-pull-secret
        - name: cosignSecret (3)
          value: cosign-secret
        - name: image
          value: '$(params.IMAGE_REPO):$(params.IMAGE_TAG)'
      runAfter: (4)
        - yaml-lint
        - kube-score
        - kube-linter
        kind: Task
        name: rekor-verify
1The parameters required for this task.
2Pull secret for, which was created during step 5.
3CoSign public key.
4This task runs after the linting tasks.

Execute the Pipeline

Triggering the pipeline will now check the signature of an image.

The logs should show something like this:

Rekor Image Signature Verification
Figure 1. Rekor Image Signature Verification

As you can see: The image has been signed correctly and the transparency logs can be parsed.


Finally, everything has been verified and we can bring everything into production. The final two steps will create a new branch in the Git manifest repository and a pull request that can be manually merged.