Notary

Verify CNCF Notary format signatures using X.509 certificates.

Notary (https://notaryproject.dev/) is a CNCF project that provides a specification and tooling for securing software supply chains.

The Notation CLI can be used to sign images and attestations in a CI/CD pipeline. This quickstart guide provides a complete example of siging and verifying a container image using Notation: https://notaryproject.dev/docs/quickstart/.

The Notation CLI can also be used to inspect details of the container image signature:

 1notation inspect ghcr.io/kyverno/test-verify-image@sha256:b31bfb4d0213f254d361e0079deaaebefa4f82ba7aa76ef82e90b4935ad5b105
 2Inspecting all signatures for signed artifact
 3ghcr.io/kyverno/test-verify-image@sha256:b31bfb4d0213f254d361e0079deaaebefa4f82ba7aa76ef82e90b4935ad5b105
 4└── application/vnd.cncf.notary.signature
 5    └── sha256:7f870420d92765b42cec0f71ee8e25bf39b692f64d95d6f6607e9e6e54300265
 6        ├── media type: application/jose+json
 7        ├── signature algorithm: RSASSA-PSS-SHA-256
 8        ├── signed attributes
 9        │   ├── signingScheme: notary.x509
10        │   └── signingTime: Mon May 22 14:45:04 2023
11        ├── user defined attributes
12        │   └── (empty)
13        ├── unsigned attributes
14        │   └── signingAgent: Notation/1.0.0
15        ├── certificates
16        │   └── SHA256 fingerprint: da1f2d7d648dfacc7ebd59f98a9f35c753c331d80ca4280bb94060f4af4a5357
17        │       ├── issued to: CN=test,O=Notary,L=Seattle,ST=WA,C=US
18        │       ├── issued by: CN=test,O=Notary,L=Seattle,ST=WA,C=US
19        │       └── expiry: Thu May 19 21:15:18 2033
20        └── signed artifact
21            ├── media type: application/vnd.docker.distribution.manifest.v2+json
22            ├── digest: sha256:b31bfb4d0213f254d361e0079deaaebefa4f82ba7aa76ef82e90b4935ad5b105
23            └── size: 938

You can also use an OCI registry client to discover signatures and attestations for an image:

 1oras discover ghcr.io/kyverno/test-verify-image:signed -o tree
 2ghcr.io/kyverno/test-verify-image:signed
 3├── application/vnd.cncf.notary.signature
 4│   └── sha256:7f870420d92765b42cec0f71ee8e25bf39b692f64d95d6f6607e9e6e54300265
 5├── vulnerability-scan
 6│   └── sha256:f89cb7a0748c63a674d157ca84d725ff3ac09cc2d4aee9d0ec4315e0fe92a5fd
 7│       └── application/vnd.cncf.notary.signature
 8│           └── sha256:ec45844601244aa08ac750f44def3fd48ddacb736d26b83dde9f5d8ac646c2f3
 9└── sbom/cyclone-dx
10    └── sha256:8cad9bd6de426683424a204697dd48b55abcd6bb6b4930ad9d8ade99ae165414
11        └── application/vnd.cncf.notary.signature
12            └── sha256:61f3e42f017b72f4277c78a7a42ff2ad8f872811324cd984830dfaeb4030c322

Verifying Image Signatures

The following policy checks whether an image is signed with a valid X.509 key that matches the provided public certificate:

 1---
 2apiVersion: kyverno.io/v2beta1
 3kind: ClusterPolicy
 4metadata:
 5  name: check-image-notary
 6spec:
 7  validationFailureAction: Enforce
 8  webhookTimeoutSeconds: 30
 9  failurePolicy: Fail  
10  rules:
11    - name: verify-signature-notary
12      match:
13        any:
14        - resources:
15            kinds:
16              - Pod
17      verifyImages:
18      - type: Notary
19        imageReferences:
20        - "ghcr.io/kyverno/test-verify-image*"
21        attestors:
22        - count: 1
23          entries:
24          - certificates:
25              cert: |-
26                -----BEGIN CERTIFICATE-----
27                MIIDTTCCAjWgAwIBAgIJAPI+zAzn4s0xMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV
28                BAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEPMA0GA1UECgwG
29                Tm90YXJ5MQ0wCwYDVQQDDAR0ZXN0MB4XDTIzMDUyMjIxMTUxOFoXDTMzMDUxOTIx
30                MTUxOFowTDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAldBMRAwDgYDVQQHDAdTZWF0
31                dGxlMQ8wDQYDVQQKDAZOb3RhcnkxDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3
32                DQEBAQUAA4IBDwAwggEKAoIBAQDNhTwv+QMk7jEHufFfIFlBjn2NiJaYPgL4eBS+
33                b+o37ve5Zn9nzRppV6kGsa161r9s2KkLXmJrojNy6vo9a6g6RtZ3F6xKiWLUmbAL
34                hVTCfYw/2n7xNlVMjyyUpE+7e193PF8HfQrfDFxe2JnX5LHtGe+X9vdvo2l41R6m
35                Iia04DvpMdG4+da2tKPzXIuLUz/FDb6IODO3+qsqQLwEKmmUee+KX+3yw8I6G1y0
36                Vp0mnHfsfutlHeG8gazCDlzEsuD4QJ9BKeRf2Vrb0ywqNLkGCbcCWF2H5Q80Iq/f
37                ETVO9z88R7WheVdEjUB8UrY7ZMLdADM14IPhY2Y+tLaSzEVZAgMBAAGjMjAwMAkG
38                A1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0G
39                CSqGSIb3DQEBCwUAA4IBAQBX7x4Ucre8AIUmXZ5PUK/zUBVOrZZzR1YE8w86J4X9
40                kYeTtlijf9i2LTZMfGuG0dEVFN4ae3CCpBst+ilhIndnoxTyzP+sNy4RCRQ2Y/k8
41                Zq235KIh7uucq96PL0qsF9s2RpTKXxyOGdtp9+HO0Ty5txJE2txtLDUIVPK5WNDF
42                ByCEQNhtHgN6V20b8KU2oLBZ9vyB8V010dQz0NRTDLhkcvJig00535/LUylECYAJ
43                5/jn6XKt6UYCQJbVNzBg/YPGc1RF4xdsGVDBben/JXpeGEmkdmXPILTKd9tZ5TC0
44                uOKpF5rWAruB5PCIrquamOejpXV9aQA/K2JQDuc0mcKz
45                -----END CERTIFICATE-----                

With this policy configured, Kyverno will verify matching container image signatures and only allow the pod to be configured if the signatures are valid:

1kubectl run test --image=ghcr.io/kyverno/test-verify-image:signed --dry-run=server
2pod/test created (server dry run)

Kyverno will also mutate the pod to replace the image tag with its digest:

1kubectl run test --image=ghcr.io/kyverno/test-verify-image:signed --dry-run=server -o yaml | grep "image: "
2  - image: ghcr.io/kyverno/test-verify-image:signed@sha256:b31bfb4d0213f254d361e0079deaaebefa4f82ba7aa76ef82e90b4935ad5b105

Attempting to run a pod with an unsigned image will be blocked:

 1kubectl run test --image=ghcr.io/kyverno/test-verify-image:unsigned --dry-run=server
 2Error from server: admission webhook "mutate.kyverno.svc-fail" denied the request:
 3
 4resource Pod/default/test was blocked due to the following policies
 5
 6check-image-notary:
 7  verify-signature-notary: 'failed to verify image ghcr.io/kyverno/test-verify-image:unsigned:
 8    .attestors[0].entries[0]: failed to verify ghcr.io/kyverno/test-verify-image@sha256:74a98f0e4d750c9052f092a7f7a72de7b20f94f176a490088f7a744c76c53ea5:
 9    no signature is associated with "ghcr.io/kyverno/test-verify-image@sha256:74a98f0e4d750c9052f092a7f7a72de7b20f94f176a490088f7a744c76c53ea5",
10    make sure the image was signed successfully'

Verifying Image Attestations

Kyverno does not support verifying attestations signed by Notary. This feature is being implemented and scheduled for the next minor release.

Last modified May 30, 2023 at 4:32 AM PST: Notary and other minor changes (#876) (c0fa248)