source-controller icon indicating copy to clipboard operation
source-controller copied to clipboard

HelmChart / OCIRepository - Notation v2 verification support proposal

Open JasonTheDeveloper opened this issue 2 years ago • 2 comments

Flux currently supports cosign as a verification method to check HelmCharts and OCIRepositories are signed by the source author. This proposal is to start the conversation around introducing notation as another method for validating signed artifacts.

Current Setup (Cosign)

Currently, to verify OCIRepository and HelmChart using cosign (using known public keys) you'd deploy something like this:

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
  name: <repository-name>
spec:
  verify:
    provider: cosign
    secretRef:
      name: cosign-public-keys

With spec.verify.secretRef.name secret structured like so:

apiVersion: v1
kind: Secret
metadata:
  name: cosign-public-keys
type: Opaque
data:
  key1.pub: <BASE64>
  key2.pub: <BASE64>

If you use the keyless option you'd omit spec.verify.secretRef from your configuration.

Notation Integration Proposal

Notation requires 2 components to function correctly. A pubic .pem key and a trust store/policy. There are two ways I can think of moving forward and they are:

Option 1 - Reusing the Existing Secret Reference

Just like with cosign, the trust store + trust policy could be included as part of the secret reference along with the public keys. Something like so:

apiVersion: v1
kind: Secret
metadata:
  name: notation-public-keys
type: Opaque
data:
  key1.pem: <BASE64>
  key2.pem: <BASE64>
  policy.json: <BASE64>

Benefit:

  • Minimal change
  • Would not need to introduce a new CRD
  • Reuses what's already implemented

Note: I have implemented this approach as part of my POC as at the time I felt it was the path of least resistance.

Option 2 - Creating a CRD for Notation Public Key and Trust Store

This option would require a new CRD just for the sake of notation. I'm thinking something a long the lines of how Ratify has implemented the trust store. Something like this:

apiVersion: source.toolkit.fluxcd.io/v1beta3
kind: Verifier
metadata:
  name: verifier-notary
spec:
  name: notation
  parameters:
     certStores:
       secretRef:
         - notation-public-keys
     trustPolicyDoc:
      version: "1.0"
      trustPolicies:
        - name: default
          registryScopes:
            - "*"
          signatureVerification:
            level: strict
          trustStores:
            - ca:certs
          trustedIdentities:
            - "*"

Your secret reference could look something like this:

apiVersion: v1
kind: Secret
metadata:
  name: notation-public-keys
type: Opaque
data:
  key1.pem: <BASE64>
  key2.pem: <BASE64>

And you would reference the verifier like so:

apiVersion: source.toolkit.fluxcd.io/v1beta3
kind: OCIRepository
metadata:
  name: <repository-name>
spec:
  verify:
    provider: notation
    verifierRef:
      name: verifier-notary

Benefit:

  • More explicit (specific to notation's implementation)

JasonTheDeveloper avatar Apr 12 '23 22:04 JasonTheDeveloper

I vote for Option 1. I would not want to maintain a dedicated CRD for Notation in Flux, as this would mean creating CRDs for cosign, openpgp, gitsign, sshsign, etc.

We can make it easy for Notation users to generate the secret with the Flux CLI by adding a new subcommand to flux create secret e.g. flux create secret notation --trust-store --trust-policy.

stefanprodan avatar Apr 13 '23 07:04 stefanprodan

For the same reasons as Stefan, my vote goes to option 1 as well.

hiddeco avatar Apr 13 '23 08:04 hiddeco