Skip to content

Commit 6d61914

Browse files
JasonTheDevelopersoulebjagpreetstamberdarkowlzz
committed
feat(notation): add support for notary signature
* feat(notation): add verifier handler This verifier (part of the oci package) is responsible for verifying notary signatures using notation. Signed-off-by: Jason <[email protected]> * feat(notation): add notation to list of providers This is so that users are able to set as a provider in either OCIRepository or HelmChart to verify the authenticity of the signature via notation Signed-off-by: Jason <[email protected]> * feat(notation): add notation verifier to helmchart controller If implemented, this commit will use notation to verify the signature if notation is set in the HelmChart deployment Signed-off-by: Jason <[email protected]> * feat(notation): add notation verifier to ocirepository controller If implemented, this commit will use notation to verify the signature if notation is set in the OCIRepository deployment Signed-off-by: Jason <[email protected]> * feat(notation): update go.mod and go.sum with notation dependencies This commit updates go.mod and go.sum with notation dependencies Signed-off-by: Jason <[email protected]> * wip Signed-off-by: Jason <[email protected]> * feat(notation): add notation back to ocirepository_controller During the merge from main the ocirepository_controller.go was moved and git determined the file was delete. I took the changes from main and I have added back the logic for checking against notation. I have also add the ability to use insecure registries and registries running on localhost:port. Signed-off-by: Jason <[email protected]> * docs(dev): update vscode debugger config with needed args to run main.go The DEVELOPMENT.md contains an example to debug source-controller. The config was missing required arguments needed to run main.go. Signed-off-by: Jason <[email protected]> * build(env): set up development environment Signed-off-by: Jason <[email protected]> * test(notation): unit test notation options Signed-off-by: Jason <[email protected]> * feat(notation): add .crt as option in helm controller Signed-off-by: Jason <[email protected]> * test(notation): add oci tests Signed-off-by: Jason <[email protected]> * fix(notation): do not try authenticate if auth is nil Signed-off-by: Jason <[email protected]> * feat(helm): pass repo obj into verifier Signed-off-by: Jason <[email protected]> * test(notation): add helm tests Signed-off-by: Jason <[email protected]> * chore: run go mod tidy Signed-off-by: Jason <[email protected]> * docs(notation): helmchats.md includes notation changes Signed-off-by: Jason <[email protected]> * docs(notation): ocirepositories.md includes notation changes Signed-off-by: Jason <[email protected]> * docs(typo): fix notaiton -> notation Signed-off-by: Jason <[email protected]> * test(notation): add notation oci configuration to testdata Signed-off-by: Jason <[email protected]> * test(notation): add notation helm chart configuration to testdata Signed-off-by: Jason <[email protected]> * fix(notation): out-of-bounds warning Signed-off-by: Jason <[email protected]> * test(notation): add helm chart and oci deployment to e2e.sh Signed-off-by: Jason <[email protected]> * feat(notation): log error if validation step failed Signed-off-by: Jason <[email protected]> * fix(notation): check if trust store name contains type and name + update message Signed-off-by: Jason <[email protected]> * docs(notation): fix vocabulary used Signed-off-by: Jason <[email protected]> * refactor(notation): use cert name from secret when saving to disk Signed-off-by: Jason <[email protected]> * docs(notation): comment functions that had none Signed-off-by: Jason <[email protected]> * refactor(notation): load certs from memory Signed-off-by: Jason <[email protected]> * chore(dep): update go.mod and go.sum Signed-off-by: Jason <[email protected]> * refactor(oci): move secret fetch into own func Signed-off-by: Jason <[email protected]> * fix(notation): handle DER certs as well as PEM Signed-off-by: Jason <[email protected]> * refactor(helm): move insecure setting to getter.client_opts Signed-off-by: Jason <[email protected]> * refactor(notation): enforce trustpolicy.json Signed-off-by: Jason <[email protected]> * style: fix indentation Signed-off-by: Jason <[email protected]> * refactor(notation): merge notationoptions with options struct Signed-off-by: Jason <[email protected]> * feat(notation): handle authn.Authenticator Signed-off-by: Jason <[email protected]> * test(verifier): cover new keychain and auth options Signed-off-by: Jason <[email protected]> * revert(devcontainer): remove dev env from project Signed-off-by: Jason <[email protected]> * refactor(notation): authenticator to take precedence over keychain Signed-off-by: Jason <[email protected]> * refactor(notation): remove keychain and auth checker Signed-off-by: Jason <[email protected]> * refactor(notation): use auth acesstoken when setting up notation authenticator Signed-off-by: Jason <[email protected]> * refactor(notation): reduced MaxSignatureAttempts from 50 to 3 Signed-off-by: Jason <[email protected]> * fix(verifier): was not handling nil auth options Signed-off-by: Jason <[email protected]> * refactor(typo): TrustStore -> TrustPolicy Signed-off-by: Jason <[email protected]> * docs(helm): remove typo Co-authored-by: souleb <[email protected]> Signed-off-by: JasonTheDeveloper <[email protected]> * refactor(oci): reuse keychain and auth Signed-off-by: Jason <[email protected]> * refactor(helm): return certSecretName from retrieveSecret func Signed-off-by: Jason <[email protected]> * create contant for the trust policy file name. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * fix(notation): handle digest and -1 panic in verifier Signed-off-by: Jason <[email protected]> * refactor(notation): move repo url creation to a separate func Signed-off-by: Jason <[email protected]> * docs(oci): add link to signing and verification workflow Signed-off-by: Jason <[email protected]> * chore(verify): fix make verify Signed-off-by: Jason <[email protected]> * docs(helm): add link to signing and verification workflow Signed-off-by: Jason <[email protected]> * refactor(notation): move remote repo construction to own func Signed-off-by: Jason <[email protected]> * refactor(oci): use trust policy file constant Signed-off-by: Jason <[email protected]> * doc(license): include license header at top of files Signed-off-by: Jason <[email protected]> * refactor(type): verififyOptions -> verifyOptions Co-authored-by: Sunny <[email protected]> Signed-off-by: JasonTheDeveloper <[email protected]> * fix(refactor): verififyOptions -> verifyOptions Signed-off-by: Jason <[email protected]> * refactor(notation): relocate DefaultTrustPolicyKey to notation.go Signed-off-by: Jason <[email protected]> * style(order): move imports to match schema Signed-off-by: Jason <[email protected]> * style(order): remove new line and reorder imports Signed-off-by: Jason <[email protected]> * style(order): move dep in go.mod to like block Signed-off-by: Jason <[email protected]> * revert(makefile): remove cluster target Signed-off-by: Jason <[email protected]> * refactor(message): update missing verification secret message to reduce confusion Signed-off-by: Jason <[email protected]> * Update the notation secret name in documentation. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Increate readability by wrapping the method lines. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Update comment regarding retrieveSecret method Signed-off-by: Jagpreet Singh Tamber <[email protected]> * move string resource to common file and use in auth.go and notation.go Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Add tests for insecure field and fix circular dependency. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * docs(oci): change example name notation-public-keys -> notation-config Signed-off-by: Jason <[email protected]> * refactor(oci): increate readability by wrapping the method lines Signed-off-by: Jason <[email protected]> * refactor(notation): move to own package Signed-off-by: Jason <[email protected]> * refactor(notation): use new notation package Signed-off-by: Jason <[email protected]> * refactor(oci): separate cosign into own package Signed-off-by: Jason <[email protected]> * refactor(notation): update func names Signed-off-by: Jason <[email protected]> * refactor(notation): remove notary word from package Signed-off-by: Jason <[email protected]> * test(e2e): download policy and cert from new branch Signed-off-by: Jason <[email protected]> * feat(notation): return a list of errors if notation error occur Signed-off-by: Jason <[email protected]> * feat(verify): check if using cosign before logging with keyless Signed-off-by: Jason <[email protected]> * test(e2e): switch to using stefanprodan's podinfo Signed-off-by: Jason <[email protected]> * test(e2e): ensure 6.6.x is pulled Signed-off-by: Jason <[email protected]> * feat(verify): introduce ignore, verified and unverified states Signed-off-by: Jason <[email protected]> * chore(dep): update go.mod Signed-off-by: Jason <[email protected]> * docs(notation): update wording from key to certificate Signed-off-by: Jason <[email protected]> * feat(notation): log outcome when action is set to log Signed-off-by: Jason <[email protected]> * refactor(notation): PublicKey -> RootCertificate Signed-off-by: Jason <[email protected]> * revert(cosign): remove 'remote' from test name Signed-off-by: Jason <[email protected]> * refactor(notation): move trust policy cleanup to own function Signed-off-by: Jason <[email protected]> * test(notation): add tests to check trust policy cleaner works as expected Signed-off-by: Jason <[email protected]> * refactor(oci): remove hardcoded verification name from logs Signed-off-by: Jason <[email protected]> * refactor(notation): update options struct to be private Signed-off-by: Jason <[email protected]> * docs(notation): remove mention of NotationOptions and cleanup Signed-off-by: Jason <[email protected]> * docs(notation): add comment as to why trustStore is implemented within the package Signed-off-by: Jason <[email protected]> * refactor(notation): move outcome checker to own func Signed-off-by: Jason <[email protected]> * docs(notation): add comments around what is happening in checkOutcome Signed-off-by: Jason <[email protected]> * Use default retry client from oras Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Upate the log message and test cases for verification check. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Make options in cosign package private. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Add unit tests for repoUrlWithDigest method. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * update test variable names according to the naming convention Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Remove the cache from http client. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * refactor(doc): stringResource -> StringResource Co-authored-by: souleb <[email protected]> Signed-off-by: JasonTheDeveloper <[email protected]> * docs(helm): add comments detailing what each func does Signed-off-by: Jason <[email protected]> * chore(dep): update image-spec from 1.1.0-rc5 to 1.1.0 Signed-off-by: Jason <[email protected]> * Update internal/oci/notation/notation_test.go Co-authored-by: souleb <[email protected]> Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Update internal/oci/notation/notation.go Co-authored-by: souleb <[email protected]> Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Logger should only be logged if the truststores and identities are present. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Logger should only be logged if the truststores and identities are present. Signed-off-by: Jagpreet Singh Tamber <[email protected]> * move cleanUpTrustpolicy call Signed-off-by: Jagpreet Singh Tamber <[email protected]> * Fix build Signed-off-by: Jagpreet Singh Tamber <[email protected]> * feat(helm): support for VerificationReult Signed-off-by: Jason <[email protected]> * docs(readme): update to add notation Signed-off-by: Jason <[email protected]> * refactor(notation): switch wording from 'removing' to 'ignoring' Signed-off-by: Jason <[email protected]> * docs: add comments to public func and const Signed-off-by: Jason <[email protected]> * feat(oci): error message when parsing trustpolicy.json more helpful Signed-off-by: Jason <[email protected]> * refactor(notation): pass all certificate data in one go Signed-off-by: Jason <[email protected]> * test(notation): fix messaging and refactor Signed-off-by: Jason <[email protected]> * test(notation): move g Signed-off-by: Jason <[email protected]> * feat(oci): add default to verify switch Signed-off-by: Jason <[email protected]> * style(notation): pluralised certificate Signed-off-by: Jason <[email protected]> * style(notation): move WithRootCertificates to defaultNotationOciOpts Signed-off-by: Jason <[email protected]> * style(helm): defaultNotaryOciOpts -> defaultNotationOciOpts Signed-off-by: Jason <[email protected]> * style(typo): orrcured -> occurred Signed-off-by: Jason <[email protected]> * refactor(notation): trustStore -> trustPolicy Signed-off-by: Jason <[email protected]> * test(notation): move g in remaining tests Signed-off-by: Jason <[email protected]> --------- Signed-off-by: Jason <[email protected]> Signed-off-by: JasonTheDeveloper <[email protected]> Signed-off-by: Jagpreet Singh Tamber <[email protected]> Co-authored-by: souleb <[email protected]> Co-authored-by: Jagpreet Singh Tamber <[email protected]> Co-authored-by: Sunny <[email protected]>
1 parent 565f6ee commit 6d61914

30 files changed

+2755
-249
lines changed

DEVELOPMENT.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ make run
5858

5959
### Building the container image
6060

61-
Set the name of the container image to be created from the source code. This will be used
61+
Set the name of the container image to be created from the source code. This will be used
6262
when building, pushing and referring to the image on YAML files:
6363

6464
```sh
@@ -79,7 +79,7 @@ make docker-push
7979
```
8080

8181
Alternatively, the three steps above can be done in a single line:
82-
82+
8383
```sh
8484
IMG=registry-path/source-controller TAG=latest BUILD_ARGS=--push \
8585
make docker-build
@@ -128,7 +128,8 @@ Create a `.vscode/launch.json` file:
128128
"type": "go",
129129
"request": "launch",
130130
"mode": "auto",
131-
"program": "${workspaceFolder}/main.go"
131+
"program": "${workspaceFolder}/main.go",
132+
"args": ["--storage-adv-addr=:0", "--storage-path=${workspaceFolder}/bin/data"]
132133
}
133134
]
134135
}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ and is a core component of the [GitOps toolkit](https://fluxcd.io/flux/component
2727
## Features
2828

2929
* authenticates to sources (SSH, user/password, API token, Workload Identity)
30-
* validates source authenticity (PGP, Cosign)
30+
* validates source authenticity (PGP, Cosign, Notation)
3131
* detects source changes based on update policies (semver)
3232
* fetches resources on-demand and on-a-schedule
3333
* packages the fetched resources into a well-known format (tar.gz, yaml)

api/v1beta2/ocirepository_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ type OCILayerSelector struct {
182182
// OCIRepositoryVerification verifies the authenticity of an OCI Artifact
183183
type OCIRepositoryVerification struct {
184184
// Provider specifies the technology used to sign the OCI Artifact.
185-
// +kubebuilder:validation:Enum=cosign
185+
// +kubebuilder:validation:Enum=cosign;notation
186186
// +kubebuilder:default:=cosign
187187
Provider string `json:"provider"`
188188

config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ spec:
468468
OCI Artifact.
469469
enum:
470470
- cosign
471+
- notation
471472
type: string
472473
secretRef:
473474
description: |-

config/crd/bases/source.toolkit.fluxcd.io_ocirepositories.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ spec:
224224
OCI Artifact.
225225
enum:
226226
- cosign
227+
- notation
227228
type: string
228229
secretRef:
229230
description: |-
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
apiVersion: source.toolkit.fluxcd.io/v1beta2
3+
kind: HelmRepository
4+
metadata:
5+
name: podinfo-notation
6+
spec:
7+
url: oci://ghcr.io/stefanprodan/charts
8+
type: "oci"
9+
interval: 1m
10+
---
11+
apiVersion: source.toolkit.fluxcd.io/v1beta2
12+
kind: HelmChart
13+
metadata:
14+
name: podinfo-notation
15+
spec:
16+
chart: podinfo
17+
sourceRef:
18+
kind: HelmRepository
19+
name: podinfo-notation
20+
version: '6.6.0'
21+
interval: 1m
22+
verify:
23+
provider: notation
24+
secretRef:
25+
name: notation-config
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
apiVersion: source.toolkit.fluxcd.io/v1beta2
3+
kind: OCIRepository
4+
metadata:
5+
name: podinfo-deploy-signed-with-notation
6+
spec:
7+
interval: 5m
8+
url: oci://ghcr.io/stefanprodan/podinfo-deploy
9+
ref:
10+
semver: "6.6.x"
11+
verify:
12+
provider: notation
13+
secretRef:
14+
name: notation-config

docs/spec/v1beta2/helmcharts.md

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -252,15 +252,20 @@ For practical information, see
252252

253253
**Note:** This feature is available only for Helm charts fetched from an OCI Registry.
254254

255-
`.spec.verify` is an optional field to enable the verification of [Cosign](https://github.com/sigstore/cosign)
255+
`.spec.verify` is an optional field to enable the verification of [Cosign](https://github.com/sigstore/cosign) or [Notation](https://github.com/notaryproject/notation)
256256
signatures. The field offers three subfields:
257257

258-
- `.provider`, to specify the verification provider. Only supports `cosign` at present.
258+
- `.provider`, to specify the verification provider. The supported options are `cosign` and `notation` at present.
259259
- `.secretRef.name`, to specify a reference to a Secret in the same namespace as
260-
the HelmChart, containing the Cosign public keys of trusted authors.
261-
- `.matchOIDCIdentity`, to specify a list of OIDC identity matchers. Please see
260+
the HelmChart, containing the public keys of trusted authors. For Notation this Secret should also include the [trust policy](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-policy) in
261+
addition to the CA certificate.
262+
- `.matchOIDCIdentity`, to specify a list of OIDC identity matchers (only supported when using `cosign` as the verification provider). Please see
262263
[Keyless verification](#keyless-verification) for more details.
263264

265+
#### Cosign
266+
267+
The `cosign` provider can be used to verify the signature of an OCI artifact using either a known public key or via the [Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure.
268+
264269
```yaml
265270
---
266271
apiVersion: source.toolkit.fluxcd.io/v1beta2
@@ -281,7 +286,7 @@ following attributes to the HelmChart's `.status.conditions`:
281286
- `status: "True"`
282287
- `reason: Succeeded`
283288

284-
#### Public keys verification
289+
##### Public keys verification
285290

286291
To verify the authenticity of HelmChart hosted in an OCI Registry, create a Kubernetes
287292
secret with the Cosign public keys:
@@ -303,7 +308,7 @@ Note that the keys must have the `.pub` extension for Flux to make use of them.
303308
Flux will loop over the public keys and use them to verify a HelmChart's signature.
304309
This allows for older HelmCharts to be valid as long as the right key is in the secret.
305310

306-
#### Keyless verification
311+
##### Keyless verification
307312

308313
For publicly available HelmCharts, which are signed using the
309314
[Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure,
@@ -362,6 +367,55 @@ instance hosted at [rekor.sigstore.dev](https://rekor.sigstore.dev/).
362367
Note that keyless verification is an **experimental feature**, using
363368
custom root CAs or self-hosted Rekor instances are not currently supported.
364369

370+
#### Notation
371+
372+
The `notation` provider can be used to verify the signature of an OCI artifact using known
373+
trust policy and CA certificate.
374+
375+
```yaml
376+
---
377+
apiVersion: source.toolkit.fluxcd.io/v1beta2
378+
kind: HelmChart
379+
metadata:
380+
name: podinfo
381+
spec:
382+
verify:
383+
provider: notation
384+
secretRef:
385+
name: notation-config
386+
```
387+
388+
When the verification succeeds, the controller adds a Condition with the
389+
following attributes to the HelmChart's `.status.conditions`:
390+
391+
- `type: SourceVerified`
392+
- `status: "True"`
393+
- `reason: Succeeded`
394+
395+
To verify the authenticity of an OCI artifact, create a Kubernetes secret
396+
containing Certificate Authority (CA) root certificates and the a `trust policy`
397+
398+
```yaml
399+
---
400+
apiVersion: v1
401+
kind: Secret
402+
metadata:
403+
name: notation-config
404+
type: Opaque
405+
data:
406+
certificate1.pem: <BASE64>
407+
certificate2.crt: <BASE64>
408+
trustpolicy.json: <BASE64>
409+
```
410+
411+
Note that the CA certificates must have either `.pem` or `.crt` extension and your trust policy must
412+
be named `trustpolicy.json` for Flux to make use of them.
413+
414+
For more information on the signing and verification process see [Signing and Verification Workflow](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/signing-and-verification-workflow.md).
415+
416+
Flux will loop over the certificates and use them to verify an artifact's signature.
417+
This allows for older artifacts to be valid as long as the right certificate is in the secret.
418+
365419
## Working with HelmCharts
366420

367421
### Triggering a reconcile

docs/spec/v1beta2/ocirepositories.md

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ patches:
237237
target:
238238
kind: Deployment
239239
name: source-controller
240-
```
240+
```
241241

242242
When using pod-managed identity on an AKS cluster, AAD Pod Identity
243243
has to be used to give the `source-controller` pod access to the ACR.
@@ -279,7 +279,7 @@ patches:
279279
target:
280280
kind: ServiceAccount
281281
name: source-controller
282-
```
282+
```
283283

284284
The Artifact Registry service uses the permission `artifactregistry.repositories.downloadArtifacts`
285285
that is located under the Artifact Registry Reader role. If you are using
@@ -454,7 +454,7 @@ metadata:
454454
spec:
455455
ref:
456456
digest: "sha256:<SHA-value>"
457-
```
457+
```
458458

459459
This field takes precedence over all other fields.
460460

@@ -501,14 +501,23 @@ for more information.
501501
### Verification
502502

503503
`.spec.verify` is an optional field to enable the verification of [Cosign](https://github.com/sigstore/cosign)
504+
or [Notation](https://github.com/notaryproject/notation)
504505
signatures. The field offers three subfields:
505506

506-
- `.provider`, to specify the verification provider. Only supports `cosign` at present.
507+
- `.provider`, to specify the verification provider. The supported options are `cosign` and `notation` at present.
507508
- `.secretRef.name`, to specify a reference to a Secret in the same namespace as
508-
the OCIRepository, containing the Cosign public keys of trusted authors.
509-
- `.matchOIDCIdentity`, to specify a list of OIDC identity matchers. Please see
509+
the OCIRepository, containing the Cosign public keys of trusted authors. For Notation this Secret should also
510+
include the [trust policy](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/trust-store-trust-policy.md#trust-policy) in
511+
addition to the CA certificate.
512+
- `.matchOIDCIdentity`, to specify a list of OIDC identity matchers (only supported when using `cosign` as the
513+
verification provider). Please see
510514
[Keyless verification](#keyless-verification) for more details.
511515

516+
#### Cosign
517+
518+
The `cosign` provider can be used to verify the signature of an OCI artifact using either a known public key
519+
or via the [Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure.
520+
512521
```yaml
513522
---
514523
apiVersion: source.toolkit.fluxcd.io/v1beta2
@@ -529,7 +538,7 @@ following attributes to the OCIRepository's `.status.conditions`:
529538
- `status: "True"`
530539
- `reason: Succeeded`
531540

532-
#### Public keys verification
541+
##### Public keys verification
533542

534543
To verify the authenticity of an OCI artifact, create a Kubernetes secret
535544
with the Cosign public keys:
@@ -551,7 +560,7 @@ Note that the keys must have the `.pub` extension for Flux to make use of them.
551560
Flux will loop over the public keys and use them to verify an artifact's signature.
552561
This allows for older artifacts to be valid as long as the right key is in the secret.
553562

554-
#### Keyless verification
563+
##### Keyless verification
555564

556565
For publicly available OCI artifacts, which are signed using the
557566
[Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure,
@@ -593,6 +602,55 @@ instance hosted at [rekor.sigstore.dev](https://rekor.sigstore.dev/).
593602
Note that keyless verification is an **experimental feature**, using
594603
custom root CAs or self-hosted Rekor instances are not currently supported.
595604

605+
#### Notation
606+
607+
The `notation` provider can be used to verify the signature of an OCI artifact using known
608+
trust policy and CA certificate.
609+
610+
```yaml
611+
---
612+
apiVersion: source.toolkit.fluxcd.io/v1beta2
613+
kind: OCIRepository
614+
metadata:
615+
name: <repository-name>
616+
spec:
617+
verify:
618+
provider: notation
619+
secretRef:
620+
name: notation-config
621+
```
622+
623+
When the verification succeeds, the controller adds a Condition with the
624+
following attributes to the OCIRepository's `.status.conditions`:
625+
626+
- `type: SourceVerified`
627+
- `status: "True"`
628+
- `reason: Succeeded`
629+
630+
To verify the authenticity of an OCI artifact, create a Kubernetes secret
631+
containing Certificate Authority (CA) root certificates and the a `trust policy`
632+
633+
```yaml
634+
---
635+
apiVersion: v1
636+
kind: Secret
637+
metadata:
638+
name: notation-config
639+
type: Opaque
640+
data:
641+
certificate1.pem: <BASE64>
642+
certificate2.crt: <BASE64>
643+
trustpolicy.json: <BASE64>
644+
```
645+
646+
Note that the CA certificates must have either `.pem` or `.crt` extension and your trust policy must
647+
be named `trustpolicy.json` for Flux to make use of them.
648+
649+
For more information on the signing and verification process see [Signing and Verification Workflow](https://github.com/notaryproject/specifications/blob/v1.0.0/specs/signing-and-verification-workflow.md).
650+
651+
Flux will loop over the certificates and use them to verify an artifact's signature.
652+
This allows for older artifacts to be valid as long as the right certificate is in the secret.
653+
596654
### Suspend
597655

598656
`.spec.suspend` is an optional field to suspend the reconciliation of a

go.mod

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ require (
4444
github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20231202142526-55ffb0092afd
4545
github.com/google/uuid v1.6.0
4646
github.com/minio/minio-go/v7 v7.0.66
47+
github.com/notaryproject/notation-core-go v1.0.2
48+
github.com/notaryproject/notation-go v1.1.0
4749
github.com/onsi/gomega v1.31.1
4850
github.com/opencontainers/go-digest v1.0.0
4951
github.com/opencontainers/go-digest/blake3 v0.0.0-20231025023718-d50d2fec9c98
52+
github.com/opencontainers/image-spec v1.1.0
5053
github.com/ory/dockertest/v3 v3.10.0
5154
github.com/otiai10/copy v1.14.0
5255
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
@@ -64,6 +67,7 @@ require (
6467
k8s.io/apimachinery v0.28.6
6568
k8s.io/client-go v0.28.6
6669
k8s.io/utils v0.0.0-20231127182322-b307cd553661
70+
oras.land/oras-go/v2 v2.3.1
6771
sigs.k8s.io/controller-runtime v0.16.3
6872
sigs.k8s.io/yaml v1.4.0
6973
)
@@ -87,6 +91,7 @@ require (
8791
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
8892
github.com/Azure/go-autorest/logger v0.2.1 // indirect
8993
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
94+
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
9095
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 // indirect
9196
github.com/BurntSushi/toml v1.3.2 // indirect
9297
github.com/MakeNowJust/heredoc v1.0.0 // indirect
@@ -169,11 +174,14 @@ require (
169174
github.com/fluxcd/gitkit v0.6.0 // indirect
170175
github.com/fluxcd/pkg/apis/acl v0.1.0 // indirect
171176
github.com/fsnotify/fsnotify v1.7.0 // indirect
177+
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
178+
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
172179
github.com/go-chi/chi v4.1.2+incompatible // indirect
173180
github.com/go-errors/errors v1.5.1 // indirect
174181
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
175182
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
176183
github.com/go-jose/go-jose/v3 v3.0.1 // indirect
184+
github.com/go-ldap/ldap/v3 v3.4.6 // indirect
177185
github.com/go-logr/stdr v1.2.2 // indirect
178186
github.com/go-logr/zapr v1.3.0 // indirect
179187
github.com/go-openapi/analysis v0.22.0 // indirect
@@ -265,7 +273,6 @@ require (
265273
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
266274
github.com/oklog/ulid v1.3.1 // indirect
267275
github.com/oleiade/reflections v1.0.1 // indirect
268-
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
269276
github.com/opencontainers/runc v1.1.5 // indirect
270277
github.com/opentracing/opentracing-go v1.2.0 // indirect
271278
github.com/pborman/uuid v1.2.1 // indirect
@@ -312,6 +319,8 @@ require (
312319
github.com/tjfoc/gmsm v1.4.1 // indirect
313320
github.com/transparency-dev/merkle v0.0.2 // indirect
314321
github.com/vbatts/tar-split v0.11.5 // indirect
322+
github.com/veraison/go-cose v1.2.0 // indirect
323+
github.com/x448/float16 v0.8.4 // indirect
315324
github.com/xanzy/go-gitlab v0.96.0 // indirect
316325
github.com/xanzy/ssh-agent v0.3.3 // indirect
317326
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect

0 commit comments

Comments
 (0)