Skip to content

Commit a2238f7

Browse files
authored
Merge pull request #1961 from fluxcd/cosign-v3-bundles
Discover cosign v3 NewBundleFormat for verification
2 parents 13b8fb8 + e78e094 commit a2238f7

16 files changed

Lines changed: 756 additions & 541 deletions
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
apiVersion: source.toolkit.fluxcd.io/v1
3+
kind: HelmRepository
4+
metadata:
5+
name: podinfo-cosign-v3
6+
spec:
7+
url: oci://ghcr.io/fluxcd-testing/cosign-testing/v3/charts
8+
type: "oci"
9+
interval: 1m
10+
---
11+
apiVersion: source.toolkit.fluxcd.io/v1
12+
kind: HelmChart
13+
metadata:
14+
name: podinfo-cosign-v3-keyless
15+
spec:
16+
chart: podinfo
17+
sourceRef:
18+
kind: HelmRepository
19+
name: podinfo-cosign-v3
20+
version: '6.9.4'
21+
interval: 1m
22+
verify:
23+
provider: cosign
24+
matchOIDCIdentity:
25+
- issuer: ^https://token\.actions\.githubusercontent\.com$
26+
subject: ^https://github\.com/fluxcd-testing/cosign-testing/\.github/workflows/release\.yml@refs/tags/.*

config/testdata/ocirepository/signed-with-key.yaml renamed to config/testdata/ocirepository/signed-with-cosign-v2-key.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
apiVersion: source.toolkit.fluxcd.io/v1
33
kind: OCIRepository
44
metadata:
5-
name: podinfo-deploy-signed-with-key
5+
name: podinfo-deploy-signed-with-v2-key
66
spec:
77
interval: 5m
88
url: oci://ghcr.io/stefanprodan/podinfo-deploy

config/testdata/ocirepository/signed-with-keyless.yaml renamed to config/testdata/ocirepository/signed-with-cosign-v2-keyless.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
apiVersion: source.toolkit.fluxcd.io/v1
33
kind: OCIRepository
44
metadata:
5-
name: podinfo-deploy-signed-with-keyless
5+
name: podinfo-deploy-signed-with-v2-keyless
66
spec:
77
interval: 5m
88
url: oci://ghcr.io/stefanprodan/manifests/podinfo
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/v1
3+
kind: OCIRepository
4+
metadata:
5+
name: podinfo-deploy-signed-with-v3-key
6+
spec:
7+
interval: 5m
8+
url: oci://ghcr.io/fluxcd-testing/cosign-testing/v3/podinfo-deploy
9+
ref:
10+
semver: "6.9.4"
11+
verify:
12+
provider: cosign
13+
secretRef:
14+
name: cosign-testing-key
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
apiVersion: source.toolkit.fluxcd.io/v1
3+
kind: OCIRepository
4+
metadata:
5+
name: podinfo-deploy-signed-with-v3-keyless
6+
spec:
7+
interval: 5m
8+
url: oci://ghcr.io/fluxcd-testing/cosign-testing/v3/manifests/podinfo
9+
ref:
10+
semver: "6.9.4"
11+
verify:
12+
provider: cosign
13+
matchOIDCIdentity:
14+
- issuer: ^https://token\.actions\.githubusercontent\.com$
15+
subject: ^https://github\.com/fluxcd-testing/cosign-testing/\.github/workflows/release\.yml@refs/tags/.*

go.mod

Lines changed: 111 additions & 105 deletions
Large diffs are not rendered by default.

go.sum

Lines changed: 280 additions & 293 deletions
Large diffs are not rendered by default.

hack/ci/e2e.sh

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,29 @@ kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/helmchart-from-oc
8585
kubectl -n source-system wait helmchart/podinfo --for=condition=ready --timeout=1m
8686
kubectl -n source-system wait helmchart/podinfo-keyless --for=condition=ready --timeout=1m
8787

88+
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/helmchart-from-oci/cosign-v3.yaml"
89+
kubectl -n source-system wait helmchart/podinfo-cosign-v3-keyless --for=condition=ready --timeout=1m
90+
8891
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/helmchart-from-oci/notation.yaml"
8992
curl -sSLo notation.crt https://raw.githubusercontent.com/stefanprodan/podinfo/master/.notation/notation.crt
9093
curl -sSLo trustpolicy.json https://raw.githubusercontent.com/stefanprodan/podinfo/master/.notation/trustpolicy.json
9194
kubectl -n source-system create secret generic notation-config --from-file=notation.crt --from-file=trustpolicy.json --dry-run=client -o yaml | kubectl apply -f -
9295
kubectl -n source-system wait helmchart/podinfo-notation --for=condition=ready --timeout=1m
9396

9497
echo "Run OCIRepository verify tests"
95-
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/ocirepository/signed-with-key.yaml"
96-
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/ocirepository/signed-with-keyless.yaml"
98+
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/ocirepository/signed-with-cosign-v2-key.yaml"
99+
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/ocirepository/signed-with-cosign-v2-keyless.yaml"
100+
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/ocirepository/signed-with-cosign-v3-key.yaml"
101+
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/ocirepository/signed-with-cosign-v3-keyless.yaml"
97102
curl -sSLo cosign.pub https://raw.githubusercontent.com/stefanprodan/podinfo/master/.cosign/cosign.pub
98103
kubectl -n source-system create secret generic cosign-key --from-file=cosign.pub --dry-run=client -o yaml | kubectl apply -f -
104+
curl -sSLo cosign-testing.pub https://raw.githubusercontent.com/fluxcd-testing/cosign-testing/main/cosign.pub
105+
kubectl -n source-system create secret generic cosign-testing-key --from-file=cosign-testing.pub --dry-run=client -o yaml | kubectl apply -f -
99106

100-
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-key --for=condition=ready --timeout=1m
101-
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-keyless --for=condition=ready --timeout=1m
107+
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-v2-key --for=condition=ready --timeout=1m
108+
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-v2-keyless --for=condition=ready --timeout=1m
109+
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-v3-key --for=condition=ready --timeout=1m
110+
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-v3-keyless --for=condition=ready --timeout=1m
102111

103112
kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/ocirepository/signed-with-notation.yaml"
104113
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-notation --for=condition=ready --timeout=1m

internal/controller/helmchart_controller.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131
"github.com/google/go-containerregistry/pkg/v1/remote"
3232
"github.com/notaryproject/notation-go/verifier/trustpolicy"
3333
"github.com/opencontainers/go-digest"
34-
"github.com/sigstore/cosign/v2/pkg/cosign"
34+
"github.com/sigstore/cosign/v3/pkg/cosign"
3535
helmgetter "helm.sh/helm/v4/pkg/getter"
3636
helmreg "helm.sh/helm/v4/pkg/registry"
3737
helmrepo "helm.sh/helm/v4/pkg/repo/v1"
@@ -131,9 +131,10 @@ type HelmChartReconciler struct {
131131
kuberecorder.EventRecorder
132132
helper.Metrics
133133

134-
Storage *storage.Storage
135-
Getters helmgetter.Providers
136-
ControllerName string
134+
Storage *storage.Storage
135+
Getters helmgetter.Providers
136+
ControllerName string
137+
CosignVerifierFactory *scosign.CosignVerifierFactory
137138

138139
Cache *cache.Cache
139140
TTL time.Duration
@@ -1330,7 +1331,7 @@ func (r *HelmChartReconciler) makeVerifiers(ctx context.Context, obj *sourcev1.H
13301331
for k, data := range pubSecret.Data {
13311332
// search for public keys in the secret
13321333
if strings.HasSuffix(k, ".pub") {
1333-
verifier, err := scosign.NewCosignVerifier(ctx, append(defaultCosignOciOpts, scosign.WithPublicKey(data))...)
1334+
verifier, err := r.CosignVerifierFactory.NewCosignVerifier(ctx, append(defaultCosignOciOpts, scosign.WithPublicKey(data))...)
13341335
if err != nil {
13351336
return nil, err
13361337
}
@@ -1354,7 +1355,7 @@ func (r *HelmChartReconciler) makeVerifiers(ctx context.Context, obj *sourcev1.H
13541355
}
13551356
defaultCosignOciOpts = append(defaultCosignOciOpts, scosign.WithIdentities(identities))
13561357

1357-
verifier, err := scosign.NewCosignVerifier(ctx, defaultCosignOciOpts...)
1358+
verifier, err := r.CosignVerifierFactory.NewCosignVerifier(ctx, defaultCosignOciOpts...)
13581359
if err != nil {
13591360
return nil, err
13601361
}

internal/controller/helmchart_controller_test.go

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ import (
4343
"github.com/notaryproject/notation-go/signer"
4444
"github.com/notaryproject/notation-go/verifier/trustpolicy"
4545
. "github.com/onsi/gomega"
46-
coptions "github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
47-
"github.com/sigstore/cosign/v2/cmd/cosign/cli/sign"
48-
"github.com/sigstore/cosign/v2/pkg/cosign"
46+
coptions "github.com/sigstore/cosign/v3/cmd/cosign/cli/options"
47+
"github.com/sigstore/cosign/v3/cmd/cosign/cli/sign"
48+
"github.com/sigstore/cosign/v3/pkg/cosign"
4949
hchart "helm.sh/helm/v4/pkg/chart/v2"
5050
"helm.sh/helm/v4/pkg/chart/v2/loader"
5151
helmreg "helm.sh/helm/v4/pkg/registry"
@@ -111,9 +111,10 @@ func TestHelmChartReconciler_deleteBeforeFinalizer(t *testing.T) {
111111
g.Expect(k8sClient.Delete(ctx, helmchart)).NotTo(HaveOccurred())
112112

113113
r := &HelmChartReconciler{
114-
Client: k8sClient,
115-
EventRecorder: record.NewFakeRecorder(32),
116-
Storage: testStorage,
114+
Client: k8sClient,
115+
EventRecorder: record.NewFakeRecorder(32),
116+
Storage: testStorage,
117+
CosignVerifierFactory: testCosignVerifierFactory,
117118
}
118119
// NOTE: Only a real API server responds with an error in this scenario.
119120
_, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: client.ObjectKeyFromObject(helmchart)})
@@ -792,10 +793,11 @@ func TestHelmChartReconciler_reconcileSource(t *testing.T) {
792793
}
793794

794795
r := &HelmChartReconciler{
795-
Client: clientBuilder.Build(),
796-
EventRecorder: record.NewFakeRecorder(32),
797-
Storage: st,
798-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
796+
Client: clientBuilder.Build(),
797+
EventRecorder: record.NewFakeRecorder(32),
798+
Storage: st,
799+
CosignVerifierFactory: testCosignVerifierFactory,
800+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
799801
}
800802

801803
obj := sourcev1.HelmChart{
@@ -1128,11 +1130,12 @@ func TestHelmChartReconciler_buildFromHelmRepository(t *testing.T) {
11281130
g.Expect(err).ToNot(HaveOccurred())
11291131

11301132
r := &HelmChartReconciler{
1131-
Client: clientBuilder.Build(),
1132-
EventRecorder: record.NewFakeRecorder(32),
1133-
Getters: testGetters,
1134-
Storage: testStorage,
1135-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
1133+
Client: clientBuilder.Build(),
1134+
EventRecorder: record.NewFakeRecorder(32),
1135+
Getters: testGetters,
1136+
Storage: testStorage,
1137+
CosignVerifierFactory: testCosignVerifierFactory,
1138+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
11361139
}
11371140

11381141
repository := &sourcev1.HelmRepository{
@@ -1380,11 +1383,12 @@ func TestHelmChartReconciler_buildFromOCIHelmRepository(t *testing.T) {
13801383
}
13811384

13821385
r := &HelmChartReconciler{
1383-
Client: clientBuilder.Build(),
1384-
EventRecorder: record.NewFakeRecorder(32),
1385-
Getters: testGetters,
1386-
Storage: st,
1387-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
1386+
Client: clientBuilder.Build(),
1387+
EventRecorder: record.NewFakeRecorder(32),
1388+
Getters: testGetters,
1389+
Storage: st,
1390+
CosignVerifierFactory: testCosignVerifierFactory,
1391+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
13881392
}
13891393

13901394
repository := &sourcev1.HelmRepository{
@@ -1907,8 +1911,9 @@ func TestHelmChartReconciler_getSource(t *testing.T) {
19071911
WithObjects(mocks...)
19081912

19091913
r := &HelmChartReconciler{
1910-
Client: clientBuilder.Build(),
1911-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
1914+
Client: clientBuilder.Build(),
1915+
CosignVerifierFactory: testCosignVerifierFactory,
1916+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
19121917
}
19131918

19141919
tests := []struct {
@@ -2023,9 +2028,10 @@ func TestHelmChartReconciler_reconcileDelete(t *testing.T) {
20232028
g := NewWithT(t)
20242029

20252030
r := &HelmChartReconciler{
2026-
EventRecorder: record.NewFakeRecorder(32),
2027-
Storage: testStorage,
2028-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
2031+
EventRecorder: record.NewFakeRecorder(32),
2032+
Storage: testStorage,
2033+
CosignVerifierFactory: testCosignVerifierFactory,
2034+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
20292035
}
20302036

20312037
obj := &sourcev1.HelmChart{
@@ -2163,7 +2169,8 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
21632169
WithScheme(testEnv.GetScheme()).
21642170
WithStatusSubresource(&sourcev1.HelmChart{}).
21652171
Build(),
2166-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
2172+
CosignVerifierFactory: testCosignVerifierFactory,
2173+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
21672174
}
21682175
obj := &sourcev1.HelmChart{
21692176
ObjectMeta: metav1.ObjectMeta{
@@ -2877,11 +2884,12 @@ func TestHelmChartRepository_reconcileSource_verifyOCISourceSignature_keyless(t
28772884
clientBuilder.WithObjects(repository)
28782885

28792886
r := &HelmChartReconciler{
2880-
Client: clientBuilder.Build(),
2881-
EventRecorder: record.NewFakeRecorder(32),
2882-
Getters: testGetters,
2883-
Storage: testStorage,
2884-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
2887+
Client: clientBuilder.Build(),
2888+
EventRecorder: record.NewFakeRecorder(32),
2889+
Getters: testGetters,
2890+
Storage: testStorage,
2891+
CosignVerifierFactory: testCosignVerifierFactory,
2892+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
28852893
}
28862894

28872895
obj := &sourcev1.HelmChart{
@@ -3182,11 +3190,12 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureNotation(t *t
31823190
clientBuilder.WithObjects(repository, secret, caSecret)
31833191

31843192
r := &HelmChartReconciler{
3185-
Client: clientBuilder.Build(),
3186-
EventRecorder: record.NewFakeRecorder(32),
3187-
Getters: testGetters,
3188-
Storage: st,
3189-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
3193+
Client: clientBuilder.Build(),
3194+
EventRecorder: record.NewFakeRecorder(32),
3195+
Getters: testGetters,
3196+
Storage: testStorage,
3197+
CosignVerifierFactory: testCosignVerifierFactory,
3198+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
31903199
}
31913200

31923201
obj := &sourcev1.HelmChart{
@@ -3433,11 +3442,12 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureCosign(t *tes
34333442
clientBuilder.WithObjects(repository, secret)
34343443

34353444
r := &HelmChartReconciler{
3436-
Client: clientBuilder.Build(),
3437-
EventRecorder: record.NewFakeRecorder(32),
3438-
Getters: testGetters,
3439-
Storage: st,
3440-
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
3445+
Client: clientBuilder.Build(),
3446+
EventRecorder: record.NewFakeRecorder(32),
3447+
Getters: testGetters,
3448+
Storage: st,
3449+
CosignVerifierFactory: testCosignVerifierFactory,
3450+
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
34413451
}
34423452

34433453
obj := &sourcev1.HelmChart{
@@ -3468,7 +3478,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureCosign(t *tes
34683478
Timeout: timeout,
34693479
}
34703480

3471-
err = sign.SignCmd(ro, ko, coptions.SignOptions{
3481+
err = sign.SignCmd(ctx, ro, ko, coptions.SignOptions{
34723482
Upload: true,
34733483
SkipConfirmation: true,
34743484
TlogUpload: false,

0 commit comments

Comments
 (0)