Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions config/testdata/helmchart-from-oci/cosign-v3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: podinfo-cosign-v3
spec:
url: oci://ghcr.io/fluxcd-testing/cosign-testing/v3/charts
type: "oci"
interval: 1m
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmChart
metadata:
name: podinfo-cosign-v3-keyless
spec:
chart: podinfo
sourceRef:
kind: HelmRepository
name: podinfo-cosign-v3
version: '6.9.4'
interval: 1m
verify:
provider: cosign
matchOIDCIdentity:
- issuer: ^https://token\.actions\.githubusercontent\.com$
subject: ^https://github\.com/fluxcd-testing/cosign-testing/\.github/workflows/release\.yml@refs/tags/.*
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: podinfo-deploy-signed-with-key
name: podinfo-deploy-signed-with-v2-key
spec:
interval: 5m
url: oci://ghcr.io/stefanprodan/podinfo-deploy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: podinfo-deploy-signed-with-keyless
name: podinfo-deploy-signed-with-v2-keyless
spec:
interval: 5m
url: oci://ghcr.io/stefanprodan/manifests/podinfo
Expand Down
14 changes: 14 additions & 0 deletions config/testdata/ocirepository/signed-with-cosign-v3-key.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: podinfo-deploy-signed-with-v3-key
spec:
interval: 5m
url: oci://ghcr.io/fluxcd-testing/cosign-testing/v3/podinfo-deploy
ref:
semver: "6.9.4"
verify:
provider: cosign
secretRef:
name: cosign-testing-key
15 changes: 15 additions & 0 deletions config/testdata/ocirepository/signed-with-cosign-v3-keyless.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: podinfo-deploy-signed-with-v3-keyless
spec:
interval: 5m
url: oci://ghcr.io/fluxcd-testing/cosign-testing/v3/manifests/podinfo
ref:
semver: "6.9.4"
verify:
provider: cosign
matchOIDCIdentity:
- issuer: ^https://token\.actions\.githubusercontent\.com$
subject: ^https://github\.com/fluxcd-testing/cosign-testing/\.github/workflows/release\.yml@refs/tags/.*
216 changes: 111 additions & 105 deletions go.mod

Large diffs are not rendered by default.

573 changes: 280 additions & 293 deletions go.sum

Large diffs are not rendered by default.

17 changes: 13 additions & 4 deletions hack/ci/e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,29 @@ kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/helmchart-from-oc
kubectl -n source-system wait helmchart/podinfo --for=condition=ready --timeout=1m
kubectl -n source-system wait helmchart/podinfo-keyless --for=condition=ready --timeout=1m

kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/helmchart-from-oci/cosign-v3.yaml"
kubectl -n source-system wait helmchart/podinfo-cosign-v3-keyless --for=condition=ready --timeout=1m

kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/helmchart-from-oci/notation.yaml"
curl -sSLo notation.crt https://raw.githubusercontent.com/stefanprodan/podinfo/master/.notation/notation.crt
curl -sSLo trustpolicy.json https://raw.githubusercontent.com/stefanprodan/podinfo/master/.notation/trustpolicy.json
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 -
kubectl -n source-system wait helmchart/podinfo-notation --for=condition=ready --timeout=1m

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

kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-key --for=condition=ready --timeout=1m
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-keyless --for=condition=ready --timeout=1m
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-v2-key --for=condition=ready --timeout=1m
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-v2-keyless --for=condition=ready --timeout=1m
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-v3-key --for=condition=ready --timeout=1m
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-v3-keyless --for=condition=ready --timeout=1m

kubectl -n source-system apply -f "${ROOT_DIR}/config/testdata/ocirepository/signed-with-notation.yaml"
kubectl -n source-system wait ocirepository/podinfo-deploy-signed-with-notation --for=condition=ready --timeout=1m
13 changes: 7 additions & 6 deletions internal/controller/helmchart_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/notaryproject/notation-go/verifier/trustpolicy"
"github.com/opencontainers/go-digest"
"github.com/sigstore/cosign/v2/pkg/cosign"
"github.com/sigstore/cosign/v3/pkg/cosign"
helmgetter "helm.sh/helm/v4/pkg/getter"
helmreg "helm.sh/helm/v4/pkg/registry"
helmrepo "helm.sh/helm/v4/pkg/repo/v1"
Expand Down Expand Up @@ -131,9 +131,10 @@ type HelmChartReconciler struct {
kuberecorder.EventRecorder
helper.Metrics

Storage *storage.Storage
Getters helmgetter.Providers
ControllerName string
Storage *storage.Storage
Getters helmgetter.Providers
ControllerName string
CosignVerifierFactory *scosign.CosignVerifierFactory

Cache *cache.Cache
TTL time.Duration
Expand Down Expand Up @@ -1330,7 +1331,7 @@ func (r *HelmChartReconciler) makeVerifiers(ctx context.Context, obj *sourcev1.H
for k, data := range pubSecret.Data {
// search for public keys in the secret
if strings.HasSuffix(k, ".pub") {
verifier, err := scosign.NewCosignVerifier(ctx, append(defaultCosignOciOpts, scosign.WithPublicKey(data))...)
verifier, err := r.CosignVerifierFactory.NewCosignVerifier(ctx, append(defaultCosignOciOpts, scosign.WithPublicKey(data))...)
if err != nil {
return nil, err
}
Expand All @@ -1354,7 +1355,7 @@ func (r *HelmChartReconciler) makeVerifiers(ctx context.Context, obj *sourcev1.H
}
defaultCosignOciOpts = append(defaultCosignOciOpts, scosign.WithIdentities(identities))

verifier, err := scosign.NewCosignVerifier(ctx, defaultCosignOciOpts...)
verifier, err := r.CosignVerifierFactory.NewCosignVerifier(ctx, defaultCosignOciOpts...)
if err != nil {
return nil, err
}
Expand Down
94 changes: 52 additions & 42 deletions internal/controller/helmchart_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ import (
"github.com/notaryproject/notation-go/signer"
"github.com/notaryproject/notation-go/verifier/trustpolicy"
. "github.com/onsi/gomega"
coptions "github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/sign"
"github.com/sigstore/cosign/v2/pkg/cosign"
coptions "github.com/sigstore/cosign/v3/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v3/cmd/cosign/cli/sign"
"github.com/sigstore/cosign/v3/pkg/cosign"
hchart "helm.sh/helm/v4/pkg/chart/v2"
"helm.sh/helm/v4/pkg/chart/v2/loader"
helmreg "helm.sh/helm/v4/pkg/registry"
Expand Down Expand Up @@ -111,9 +111,10 @@ func TestHelmChartReconciler_deleteBeforeFinalizer(t *testing.T) {
g.Expect(k8sClient.Delete(ctx, helmchart)).NotTo(HaveOccurred())

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

r := &HelmChartReconciler{
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Storage: st,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Storage: st,
CosignVerifierFactory: testCosignVerifierFactory,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}

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

r := &HelmChartReconciler{
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: testStorage,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: testStorage,
CosignVerifierFactory: testCosignVerifierFactory,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}

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

r := &HelmChartReconciler{
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: st,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: st,
CosignVerifierFactory: testCosignVerifierFactory,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}

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

r := &HelmChartReconciler{
Client: clientBuilder.Build(),
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
Client: clientBuilder.Build(),
CosignVerifierFactory: testCosignVerifierFactory,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}

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

r := &HelmChartReconciler{
EventRecorder: record.NewFakeRecorder(32),
Storage: testStorage,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
EventRecorder: record.NewFakeRecorder(32),
Storage: testStorage,
CosignVerifierFactory: testCosignVerifierFactory,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}

obj := &sourcev1.HelmChart{
Expand Down Expand Up @@ -2163,7 +2169,8 @@ func TestHelmChartReconciler_reconcileSubRecs(t *testing.T) {
WithScheme(testEnv.GetScheme()).
WithStatusSubresource(&sourcev1.HelmChart{}).
Build(),
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
CosignVerifierFactory: testCosignVerifierFactory,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}
obj := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -2877,11 +2884,12 @@ func TestHelmChartRepository_reconcileSource_verifyOCISourceSignature_keyless(t
clientBuilder.WithObjects(repository)

r := &HelmChartReconciler{
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: testStorage,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: testStorage,
CosignVerifierFactory: testCosignVerifierFactory,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}

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

r := &HelmChartReconciler{
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: st,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: testStorage,
CosignVerifierFactory: testCosignVerifierFactory,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}

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

r := &HelmChartReconciler{
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: st,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
Client: clientBuilder.Build(),
EventRecorder: record.NewFakeRecorder(32),
Getters: testGetters,
Storage: st,
CosignVerifierFactory: testCosignVerifierFactory,
patchOptions: getPatchOptions(helmChartReadyCondition.Owned, "sc"),
}

obj := &sourcev1.HelmChart{
Expand Down Expand Up @@ -3468,7 +3478,7 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignatureCosign(t *tes
Timeout: timeout,
}

err = sign.SignCmd(ro, ko, coptions.SignOptions{
err = sign.SignCmd(ctx, ro, ko, coptions.SignOptions{
Upload: true,
SkipConfirmation: true,
TlogUpload: false,
Expand Down
15 changes: 8 additions & 7 deletions internal/controller/ocirepository_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import (
gcrv1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/notaryproject/notation-go/verifier/trustpolicy"
"github.com/sigstore/cosign/v2/pkg/cosign"
"github.com/sigstore/cosign/v3/pkg/cosign"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
Expand Down Expand Up @@ -140,10 +140,11 @@ type OCIRepositoryReconciler struct {
helper.Metrics
kuberecorder.EventRecorder

Storage *storage.Storage
ControllerName string
TokenCache *cache.TokenCache
requeueDependency time.Duration
Storage *storage.Storage
ControllerName string
TokenCache *cache.TokenCache
CosignVerifierFactory *scosign.CosignVerifierFactory
requeueDependency time.Duration

patchOptions []patch.Option
}
Expand Down Expand Up @@ -696,7 +697,7 @@ func (r *OCIRepositoryReconciler) verifySignature(ctx context.Context, obj *sour
for k, data := range pubSecret.Data {
// search for public keys in the secret
if strings.HasSuffix(k, ".pub") {
verifier, err := scosign.NewCosignVerifier(ctxTimeout, append(defaultCosignOciOpts, scosign.WithPublicKey(data))...)
verifier, err := r.CosignVerifierFactory.NewCosignVerifier(ctxTimeout, append(defaultCosignOciOpts, scosign.WithPublicKey(data))...)
if err != nil {
return soci.VerificationResultFailed, err
}
Expand Down Expand Up @@ -732,7 +733,7 @@ func (r *OCIRepositoryReconciler) verifySignature(ctx context.Context, obj *sour
}
defaultCosignOciOpts = append(defaultCosignOciOpts, scosign.WithIdentities(identities))

verifier, err := scosign.NewCosignVerifier(ctxTimeout, defaultCosignOciOpts...)
verifier, err := r.CosignVerifierFactory.NewCosignVerifier(ctxTimeout, defaultCosignOciOpts...)
if err != nil {
return soci.VerificationResultFailed, err
}
Expand Down
Loading