Skip to content

Commit 55a2cdb

Browse files
authored
Merge pull request #1075 from JasonTheDeveloper/feat/notation
feat(notation): add support for notation in HelmChart and OCIRepository configuration
2 parents 565f6ee + 553945a commit 55a2cdb

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)