From 447607165a4adfd4f441ea4b2bb736b36957d2a2 Mon Sep 17 00:00:00 2001 From: Vishal Choudhary Date: Thu, 9 Nov 2023 11:52:31 +0530 Subject: [PATCH 1/5] feat: add GHSA-vfp6-jrw2-99g9 fixes in cosign v1.13.1 Signed-off-by: Vishal Choudhary --- pkg/cosign/fetch.go | 10 ++++ test/e2e_test.go | 114 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/pkg/cosign/fetch.go b/pkg/cosign/fetch.go index 1fc761157ea..a9a0ce2760f 100644 --- a/pkg/cosign/fetch.go +++ b/pkg/cosign/fetch.go @@ -29,6 +29,8 @@ import ( "golang.org/x/sync/errgroup" ) +const maxAllowedSigsOrAtts = 100 + type SignedPayload struct { Base64Signature string Payload []byte @@ -78,6 +80,10 @@ func FetchSignaturesForReference(ctx context.Context, ref name.Reference, opts . return nil, fmt.Errorf("no signatures associated with %s", ref) } + if len(l) > maxAllowedSigsOrAtts { + return nil, fmt.Errorf("maximum number of signatures on an image is %d, found %d", maxAllowedSigsOrAtts, len(l)) + } + signatures := make([]SignedPayload, len(l)) var g errgroup.Group g.SetLimit(runtime.NumCPU()) @@ -130,6 +136,10 @@ func FetchAttestationsForReference(ctx context.Context, ref name.Reference, opts return nil, fmt.Errorf("no attestations associated with %s", ref) } + if len(l) > maxAllowedSigsOrAtts { + return nil, fmt.Errorf("maximum number of signatures on an image is %d, found %d", maxAllowedSigsOrAtts, len(l)) + } + attestations := make([]AttestationPayload, len(l)) var g errgroup.Group g.SetLimit(runtime.NumCPU()) diff --git a/test/e2e_test.go b/test/e2e_test.go index 48aced25951..faf5ddf0013 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -361,6 +361,88 @@ func TestAttestationReplaceCreate(t *testing.T) { } } +func TestExcessiveAttestations(t *testing.T) { + repo, stop := reg(t) + defer stop() + td := t.TempDir() + + imgName := path.Join(repo, "cosign-attest-download-e2e") + + _, _, cleanup := mkimage(t, imgName) + defer cleanup() + + _, privKeyPath, _ := keypair(t, td) + ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} + + ctx := context.Background() + + slsaAttestation := `{ "buildType": "x", "builder": { "id": "2" }, "recipe": {} }` + slsaAttestationPath := filepath.Join(td, "attestation.slsa.json") + if err := os.WriteFile(slsaAttestationPath, []byte(slsaAttestation), 0600); err != nil { + t.Fatal(err) + } + + vulnAttestation := ` + { + "invocation": { + "parameters": null, + "uri": "invocation.example.com/cosign-testing", + "event_id": "", + "builder.id": "" + }, + "scanner": { + "uri": "fakescanner.example.com/cosign-testing", + "version": "", + "db": { + "uri": "", + "version": "" + }, + "result": null + }, + "metadata": { + "scanStartedOn": "2022-04-12T00:00:00Z", + "scanFinishedOn": "2022-04-12T00:10:00Z" + } +} +` + ref, err := name.ParseReference(imgName) + if err != nil { + t.Fatal(err) + } + regOpts := options.RegistryOptions{} + ociremoteOpts, err := regOpts.ClientOpts(ctx) + if err != nil { + t.Fatal(err) + } + + for i := 0; i < 102; i++ { + vulnAttestationPath := filepath.Join(td, fmt.Sprintf("attestation-%d.vuln.json", i)) + if err := os.WriteFile(vulnAttestationPath, []byte(vulnAttestation), 0600); err != nil { + t.Fatal(err) + } + + // Attest to create a vuln attestation + attestCommand := attest.AttestCommand{ + KeyOpts: ko, + PredicatePath: vulnAttestationPath, + PredicateType: "vuln", + Timeout: 30 * time.Second, + Replace: false, + } + must(attestCommand.Exec(ctx, imgName), t) + } + + attOpts := options.AttestationDownloadOptions{} + _, err = cosign.FetchAttestationsForReference(ctx, ref, attOpts.PredicateType, ociremoteOpts...) + if err == nil { + t.Fatalf("Expected an error, but 'err' was 'nil'") + } + expectedError := "maximum number of attestations on an image is 100, found 102" + if err.Error() != expectedError { + t.Errorf("Exted the error to be: '%s' but it was '%s'", expectedError, err.Error()) + } +} + func TestAttestationReplace(t *testing.T) { repo, stop := reg(t) defer stop() @@ -505,6 +587,38 @@ func TestDuplicateSign(t *testing.T) { } } +func TestExcessiveSignatures(t *testing.T) { + repo, stop := reg(t) + defer stop() + td := t.TempDir() + + imgName := path.Join(repo, "cosign-e2e") + + _, _, cleanup := mkimage(t, imgName) + defer cleanup() + + ctx := context.Background() + + for i := 0; i < 102; i++ { + _, privKeyPath, _ := keypair(t, td) + + // Sign the image + ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} + so := options.SignOptions{ + Upload: true, + } + must(sign.SignCmd(ro, ko, options.RegistryOptions{}, nil, []string{imgName}, "", "", true, "", "", "", false, false, "", false), t) + } + err := download.SignatureCmd(ctx, options.RegistryOptions{}, imgName) + if err == nil { + t.Fatal("Expected an error, but 'err' was 'nil'") + } + expectedErr := "maximum number of signatures on an image is 100, found 102" + if err.Error() != expectedErr { + t.Fatalf("Expected the error '%s', but got the error '%s'", expectedErr, err.Error()) + } +} + func TestKeyURLVerify(t *testing.T) { // TODO: re-enable once distroless images are being signed by the new client t.Skip() From 6b073209fe128b64d73a24db4985c15664365f29 Mon Sep 17 00:00:00 2001 From: Vishal Choudhary Date: Thu, 9 Nov 2023 12:18:01 +0530 Subject: [PATCH 2/5] fix: e2e tests Signed-off-by: Vishal Choudhary --- test/e2e_test.go | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/test/e2e_test.go b/test/e2e_test.go index faf5ddf0013..005c94f1d3a 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -421,19 +421,12 @@ func TestExcessiveAttestations(t *testing.T) { t.Fatal(err) } - // Attest to create a vuln attestation - attestCommand := attest.AttestCommand{ - KeyOpts: ko, - PredicatePath: vulnAttestationPath, - PredicateType: "vuln", - Timeout: 30 * time.Second, - Replace: false, - } - must(attestCommand.Exec(ctx, imgName), t) + // Attest again with replace=true, replacing the previous attestation + must(attest.AttestCmd(ctx, ko, options.RegistryOptions{}, imgName, "", "", false, vulnAttestationPath, false, + "vuln", false, 30*time.Second, false), t) } - attOpts := options.AttestationDownloadOptions{} - _, err = cosign.FetchAttestationsForReference(ctx, ref, attOpts.PredicateType, ociremoteOpts...) + _, err = cosign.FetchAttestationsForReference(ctx, ref, ociremoteOpts...) if err == nil { t.Fatalf("Expected an error, but 'err' was 'nil'") } @@ -604,9 +597,6 @@ func TestExcessiveSignatures(t *testing.T) { // Sign the image ko := options.KeyOpts{KeyRef: privKeyPath, PassFunc: passFunc} - so := options.SignOptions{ - Upload: true, - } must(sign.SignCmd(ro, ko, options.RegistryOptions{}, nil, []string{imgName}, "", "", true, "", "", "", false, false, "", false), t) } err := download.SignatureCmd(ctx, options.RegistryOptions{}, imgName) From 7b85628efe714f017a96c2bf652e98fb454fedab Mon Sep 17 00:00:00 2001 From: Vishal Choudhary Date: Thu, 9 Nov 2023 12:38:31 +0530 Subject: [PATCH 3/5] fix: typo in error Signed-off-by: Vishal Choudhary --- pkg/cosign/fetch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cosign/fetch.go b/pkg/cosign/fetch.go index a9a0ce2760f..8d0177a5baf 100644 --- a/pkg/cosign/fetch.go +++ b/pkg/cosign/fetch.go @@ -137,7 +137,7 @@ func FetchAttestationsForReference(ctx context.Context, ref name.Reference, opts } if len(l) > maxAllowedSigsOrAtts { - return nil, fmt.Errorf("maximum number of signatures on an image is %d, found %d", maxAllowedSigsOrAtts, len(l)) + return nil, fmt.Errorf("maximum number of attestations on an image is %d, found %d", maxAllowedSigsOrAtts, len(l)) } attestations := make([]AttestationPayload, len(l)) From 7d822cd0d684958d5d18282464f70f38f3093611 Mon Sep 17 00:00:00 2001 From: Vishal Choudhary Date: Thu, 9 Nov 2023 19:32:38 +0530 Subject: [PATCH 4/5] update ko-local Signed-off-by: Vishal Choudhary --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 89815494e8a..5f6144ffb76 100644 --- a/Makefile +++ b/Makefile @@ -148,9 +148,9 @@ ko-sget: .PHONY: ko-local ko-local: $(create_kocache_path) - LDFLAGS="$(LDFLAGS)" GIT_HASH=$(GIT_HASH) GIT_VERSION=$(GIT_VERSION) \ + KO_DOCKER_REPO=ko.local LDFLAGS="$(LDFLAGS)" GIT_HASH=$(GIT_HASH) GIT_VERSION=$(GIT_VERSION) \ KOCACHE=$(KOCACHE_PATH) ko build --base-import-paths \ - --tags $(GIT_VERSION) --tags $(GIT_HASH) --local \ + --tags $(GIT_VERSION) --tags $(GIT_HASH) \ $(ARTIFACT_HUB_LABELS) \ github.com/sigstore/cosign/cmd/cosign From 7b8a21d58250e79fef473c3bab5ab8fe54fa07b2 Mon Sep 17 00:00:00 2001 From: Vishal Choudhary Date: Thu, 9 Nov 2023 20:07:18 +0530 Subject: [PATCH 5/5] feat: upgrade scaffolding version Signed-off-by: Vishal Choudhary --- .github/workflows/kind-verify-attestation.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/kind-verify-attestation.yaml b/.github/workflows/kind-verify-attestation.yaml index d1fc50af09e..4b567da5f03 100644 --- a/.github/workflows/kind-verify-attestation.yaml +++ b/.github/workflows/kind-verify-attestation.yaml @@ -36,7 +36,7 @@ jobs: env: KO_DOCKER_REPO: "registry.local:5000/policy-controller" - SCAFFOLDING_RELEASE_VERSION: "v0.4.8" + SCAFFOLDING_RELEASE_VERSION: "v0.6.8" GO111MODULE: on GOFLAGS: -ldflags=-s -ldflags=-w KOCACHE: ~/ko