diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 2ed39fb45bb..9e3ad84fe04 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -32,7 +32,7 @@ on: workflow_dispatch: jobs: - e2e-secrets: + e2e-cross: strategy: matrix: os: [macos-latest, ubuntu-latest] @@ -45,34 +45,8 @@ jobs: go-version: '1.21' check-latest: true - - uses: imjasonh/setup-crane@00c9e93efa4e1138c9a7a5c594acd6c75a2fbf0c # v0.3 - - - name: Run e2e_test_attach.sh - shell: bash - run: ./test/e2e_test_attach.sh - - e2e-tsa-mtls: - strategy: - matrix: - os: [macos-latest, ubuntu-latest] - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 - with: - go-version: '1.21' - check-latest: true - - - uses: imjasonh/setup-crane@00c9e93efa4e1138c9a7a5c594acd6c75a2fbf0c # v0.3 - - - name: Run e2e_tsa_mtls.sh - shell: bash - run: make && PATH="$PWD:$PATH" ./test/e2e_tsa_mtls.sh - - - name: Run e2e_signblob_tsa_mtls.sh - shell: bash - run: make && PATH="$PWD:$PATH" ./test/e2e_signblob_tsa_mtls.sh + - name: Run cross platform e2e tests + run: go test -tags=e2e,cross -v ./test/... e2e-test-pkcs11: runs-on: ubuntu-latest @@ -81,7 +55,7 @@ jobs: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: '1.21' + go-version: '1.21' check-latest: true - name: Run pkcs11 end-to-end tests diff --git a/test/e2e_attach_test.go b/test/e2e_attach_test.go new file mode 100644 index 00000000000..fb3b7cbdd44 --- /dev/null +++ b/test/e2e_attach_test.go @@ -0,0 +1,495 @@ +// Copyright 2024 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build e2e && cross + +package test + +import ( + "bytes" + "context" + "crypto" + "crypto/rand" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "encoding/pem" + "fmt" + "net/http/httptest" + "os" + "path" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/go-openapi/strfmt" + "github.com/google/go-cmp/cmp" + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/v1/types" + "github.com/sigstore/cosign/v2/cmd/cosign/cli/attach" + "github.com/sigstore/cosign/v2/cmd/cosign/cli/download" + "github.com/sigstore/cosign/v2/cmd/cosign/cli/generate" + "github.com/sigstore/cosign/v2/cmd/cosign/cli/options" + cliverify "github.com/sigstore/cosign/v2/cmd/cosign/cli/verify" + "github.com/sigstore/cosign/v2/internal/pkg/cosign/tsa" + "github.com/sigstore/cosign/v2/internal/pkg/cosign/tsa/client" + "github.com/sigstore/cosign/v2/pkg/cosign" + "github.com/sigstore/cosign/v2/pkg/cosign/bundle" + ociremote "github.com/sigstore/cosign/v2/pkg/oci/remote" + tsaclient "github.com/sigstore/timestamp-authority/pkg/client" + "github.com/sigstore/timestamp-authority/pkg/server" + "github.com/spf13/viper" +) + +func TestAttachSignature(t *testing.T) { + ctx := context.Background() + + repo, stop := reg(t) + defer stop() + td := t.TempDir() + + imgName := path.Join(repo, "cosign-attach-e2e") + + imgRef, desc, cleanup := mkimage(t, imgName) + defer cleanup() + + // Generate payload + b := bytes.Buffer{} + must(generate.GenerateCmd(context.Background(), options.RegistryOptions{}, imgName, nil, &b), t) + payloadRef := mkfile(b.String(), td, t) + hash := sha256.Sum256(b.Bytes()) + + // Scenario 1: attach a single signature with certificate and certificate chain to an artifact + // and verify it using the root certificate. + rootCert1, rootKey1, _ := GenerateRootCa() + pemRoot1 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert1.Raw}) + pemRootRef1 := mkfile(string(pemRoot1), td, t) + subCert1, subKey1, _ := GenerateSubordinateCa(rootCert1, rootKey1) + leafCert1, privKey1, _ := GenerateLeafCert("foo@example.com", "oidc-issuer", subCert1, subKey1) + pemSub1 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert1.Raw}) + pemLeaf1 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert1.Raw}) + pemLeafRef1 := mkfile(string(pemLeaf1), td, t) + certChainRef1 := mkfile(string(append(pemSub1[:], pemRoot1[:]...)), td, t) + + signature1, _ := privKey1.Sign(rand.Reader, hash[:], crypto.SHA256) + b64signature1 := base64.StdEncoding.EncodeToString([]byte(signature1)) + sigRef1 := mkfile(b64signature1, td, t) + + err := attach.SignatureCmd(ctx, options.RegistryOptions{}, sigRef1, payloadRef, pemLeafRef1, certChainRef1, "", "", imgName) + must(err, t) + + remoteSigRef, err := name.ParseReference(fmt.Sprintf("%s:sha256-%s.sig", imgRef, strings.Split(desc.Digest.String(), ":")[1]), name.WeakValidation) + must(err, t) + + si, err := ociremote.SignedImage(remoteSigRef, ociremote.WithRemoteOptions(registryClientOpts(ctx)...)) + must(err, t) + + manifest, err := si.Manifest() + must(err, t) + + equals(manifest.Config.MediaType, types.MediaType("application/vnd.oci.image.config.v1+json"), t) + if len(manifest.Layers) != 1 { + t.Fatal("expected exactly one layer") + } + _, certOk := manifest.Layers[0].Annotations["dev.sigstore.cosign/certificate"] + equals(certOk, true, t) + _, chainOk := manifest.Layers[0].Annotations["dev.sigstore.cosign/chain"] + equals(chainOk, true, t) + + verifyCmd := cliverify.VerifyCommand{ + IgnoreSCT: true, + IgnoreTlog: true, + CertChain: pemRootRef1, + CertVerifyOptions: options.CertVerifyOptions{ + CertOidcIssuerRegexp: ".*", + CertIdentityRegexp: ".*", + }, + } + args := []string{imgName} + must(verifyCmd.Exec(ctx, args), t) + + // Scenario 2: Attaches second signature with another certificate and certificate chain to the + // same artifact and verify it using both root certificates separately. + rootCert2, rootKey2, _ := GenerateRootCa() + pemRoot2 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert2.Raw}) + pemRootRef2 := mkfile(string(pemRoot2), td, t) + subCert2, subKey2, _ := GenerateSubordinateCa(rootCert2, rootKey2) + leafCert2, privKey2, _ := GenerateLeafCert("foo@exampleclient.com", "oidc-issuer", subCert2, subKey2) + pemSub2 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert2.Raw}) + pemLeaf2 := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert2.Raw}) + pemLeafRef2 := mkfile(string(pemLeaf2), td, t) + certChainRef2 := mkfile(string(append(pemSub2[:], pemRoot2[:]...)), td, t) + + signature2, _ := privKey2.Sign(rand.Reader, hash[:], crypto.SHA256) + b64signature2 := base64.StdEncoding.EncodeToString([]byte(signature2)) + sigRef2 := mkfile(b64signature2, td, t) + + err = attach.SignatureCmd(ctx, options.RegistryOptions{}, sigRef2, payloadRef, pemLeafRef2, certChainRef2, "", "", imgName) + must(err, t) + + // verify using first root certificate + verifyCmd = cliverify.VerifyCommand{ + IgnoreSCT: true, + IgnoreTlog: true, + CertChain: pemRootRef1, + CertVerifyOptions: options.CertVerifyOptions{ + CertOidcIssuerRegexp: ".*", + CertIdentityRegexp: ".*", + }, + } + args = []string{imgName} + must(verifyCmd.Exec(ctx, args), t) + + // verify using second root cert + verifyCmd = cliverify.VerifyCommand{ + IgnoreSCT: true, + IgnoreTlog: true, + CertChain: pemRootRef2, + CertVerifyOptions: options.CertVerifyOptions{ + CertOidcIssuerRegexp: ".*", + CertIdentityRegexp: ".*", + }, + } + args = []string{imgName} + must(verifyCmd.Exec(ctx, args), t) +} + +func TestAttachWithRFC3161Timestamp(t *testing.T) { + ctx := context.Background() + // TSA server needed to create timestamp + viper.Set("timestamp-signer", "memory") + viper.Set("timestamp-signer-hash", "sha256") + apiServer := server.NewRestAPIServer("localhost", 0, []string{"http"}, false, 10*time.Second, 10*time.Second) + server := httptest.NewServer(apiServer.GetHandler()) + t.Cleanup(server.Close) + + repo, stop := reg(t) + defer stop() + td := t.TempDir() + + imgName := path.Join(repo, "cosign-attach-timestamp-e2e") + + _, _, cleanup := mkimage(t, imgName) + defer cleanup() + + b := bytes.Buffer{} + must(generate.GenerateCmd(context.Background(), options.RegistryOptions{}, imgName, nil, &b), t) + + rootCert, rootKey, _ := GenerateRootCa() + subCert, subKey, _ := GenerateSubordinateCa(rootCert, rootKey) + leafCert, privKey, _ := GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert, subKey) + pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw}) + pemSub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert.Raw}) + pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw}) + + payloadref := mkfile(b.String(), td, t) + + h := sha256.Sum256(b.Bytes()) + signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256) + b64signature := base64.StdEncoding.EncodeToString([]byte(signature)) + sigRef := mkfile(b64signature, td, t) + pemleafRef := mkfile(string(pemLeaf), td, t) + pemrootRef := mkfile(string(pemRoot), td, t) + + certchainRef := mkfile(string(append(pemSub[:], pemRoot[:]...)), td, t) + + t.Setenv("SIGSTORE_ROOT_FILE", pemrootRef) + + tsclient, err := tsaclient.GetTimestampClient(server.URL) + if err != nil { + t.Error(err) + } + + chain, err := tsclient.Timestamp.GetTimestampCertChain(nil) + if err != nil { + t.Fatalf("unexpected error getting timestamp chain: %v", err) + } + + file, err := os.CreateTemp(os.TempDir(), "tempfile") + if err != nil { + t.Fatalf("error creating temp file: %v", err) + } + defer os.Remove(file.Name()) + _, err = file.WriteString(chain.Payload) + if err != nil { + t.Fatalf("error writing chain payload to temp file: %v", err) + } + + tsBytes, err := tsa.GetTimestampedSignature(signature, client.NewTSAClient(server.URL+"/api/v1/timestamp")) + if err != nil { + t.Fatalf("unexpected error creating timestamp: %v", err) + } + rfc3161TSRef := mkfile(string(tsBytes), td, t) + + // Upload it! + err = attach.SignatureCmd(ctx, options.RegistryOptions{}, sigRef, payloadref, pemleafRef, certchainRef, rfc3161TSRef, "", imgName) + if err != nil { + t.Fatal(err) + } + + must(verifyKeylessTSA(imgName, file.Name(), true, true), t) +} + +func TestAttachWithRekorBundle(t *testing.T) { + ctx := context.Background() + + repo, stop := reg(t) + defer stop() + td := t.TempDir() + + imgName := path.Join(repo, "cosign-attach-timestamp-e2e") + + _, _, cleanup := mkimage(t, imgName) + defer cleanup() + + b := bytes.Buffer{} + must(generate.GenerateCmd(context.Background(), options.RegistryOptions{}, imgName, nil, &b), t) + + rootCert, rootKey, _ := GenerateRootCa() + subCert, subKey, _ := GenerateSubordinateCa(rootCert, rootKey) + leafCert, privKey, _ := GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert, subKey) + pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw}) + pemSub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert.Raw}) + pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw}) + + payloadref := mkfile(b.String(), td, t) + + h := sha256.Sum256(b.Bytes()) + signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256) + b64signature := base64.StdEncoding.EncodeToString([]byte(signature)) + sigRef := mkfile(b64signature, td, t) + pemleafRef := mkfile(string(pemLeaf), td, t) + pemrootRef := mkfile(string(pemRoot), td, t) + + t.Setenv("SIGSTORE_ROOT_FILE", pemrootRef) + + certchainRef := mkfile(string(append(pemSub[:], pemRoot[:]...)), td, t) + + localPayload := cosign.LocalSignedPayload{ + Base64Signature: b64signature, + Cert: string(pemLeaf), + Bundle: &bundle.RekorBundle{ + SignedEntryTimestamp: strfmt.Base64("MEUCIEDcarEwRYkrxE9ne+kzEVvUhnWaauYzxhUyXOLy1hwAAiEA4VdVCvNRs+D/5o33C2KBy+q2YX3lP4Y7nqRFU+K3hi0="), + Payload: bundle.RekorPayload{ + Body: "REMOVED", + IntegratedTime: 1631646761, + LogIndex: 693591, + LogID: "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d", + }, + }, + } + + jsonBundle, err := json.Marshal(localPayload) + if err != nil { + t.Fatal(err) + } + bundlePath := filepath.Join(td, "bundle.json") + if err := os.WriteFile(bundlePath, jsonBundle, 0644); err != nil { + t.Fatal(err) + } + + // Upload it! + err = attach.SignatureCmd(ctx, options.RegistryOptions{}, sigRef, payloadref, pemleafRef, certchainRef, "", bundlePath, imgName) + if err != nil { + t.Fatal(err) + } +} + +func TestUploadDownload(t *testing.T) { + repo, stop := reg(t) + defer stop() + td := t.TempDir() + ctx := context.Background() + + testCases := map[string]struct { + signature string + signatureType attach.SignatureArgType + expectedErr bool + }{ + "stdin containing signature": { + signature: "testsignatureraw", + signatureType: attach.StdinSignature, + expectedErr: false, + }, + "file containing signature": { + signature: "testsignaturefile", + signatureType: attach.FileSignature, + expectedErr: false, + }, + "raw signature as argument": { + signature: "testsignatureraw", + signatureType: attach.RawSignature, + expectedErr: true, + }, + "empty signature as argument": { + signature: "", + signatureType: attach.RawSignature, + expectedErr: true, + }, + } + + imgName := path.Join(repo, "cosign-e2e") + for testName, testCase := range testCases { + t.Run(testName, func(t *testing.T) { + ref, _, cleanup := mkimage(t, imgName) + payload := "testpayload" + payloadPath := mkfile(payload, td, t) + signature := base64.StdEncoding.EncodeToString([]byte(testCase.signature)) + restoreStdin := func() {} + + var sigRef string + if testCase.signatureType == attach.FileSignature { + sigRef = mkfile(signature, td, t) + } else if testCase.signatureType == attach.StdinSignature { + sigRef = "-" + restoreStdin = mockStdin(signature, td, t) + } else { + sigRef = signature + } + // Upload it! + err := attach.SignatureCmd(ctx, options.RegistryOptions{}, sigRef, payloadPath, "", "", "", "", imgName) + if testCase.expectedErr { + mustErr(err, t) + } else { + must(err, t) + } + restoreStdin() + + // Now download it! + se, err := ociremote.SignedEntity(ref, ociremote.WithRemoteOptions(registryClientOpts(ctx)...)) + must(err, t) + sigs, err := se.Signatures() + must(err, t) + signatures, err := sigs.Get() + must(err, t) + + if testCase.expectedErr { + if len(signatures) != 0 { + t.Fatalf("unexpected signatures %d, wanted 0", len(signatures)) + } + } else { + if len(signatures) != 1 { + t.Fatalf("unexpected signatures %d, wanted 1", len(signatures)) + } + + if b64sig, err := signatures[0].Base64Signature(); err != nil { + t.Fatalf("Base64Signature() = %v", err) + } else if diff := cmp.Diff(b64sig, signature); diff != "" { + t.Error(diff) + } + + if p, err := signatures[0].Payload(); err != nil { + t.Fatalf("Payload() = %v", err) + } else if diff := cmp.Diff(p, []byte(payload)); diff != "" { + t.Error(diff) + } + } + + // Now delete it! + cleanup() + }) + } +} + +func TestAttachSBOM_bom_flag(t *testing.T) { + repo, stop := reg(t) + defer stop() + td := t.TempDir() + ctx := context.Background() + bomData, err := os.ReadFile("./testdata/bom-go-mod.spdx") + must(err, t) + + testCases := map[string]struct { + bom string + bomType attach.SignatureArgType + expectedErr bool + }{ + "stdin containing bom": { + bom: string(bomData), + bomType: attach.StdinSignature, + expectedErr: false, + }, + "file containing bom": { + bom: string(bomData), + bomType: attach.FileSignature, + expectedErr: false, + }, + "raw bom as argument": { + bom: string(bomData), + bomType: attach.RawSignature, + expectedErr: true, + }, + "empty bom as argument": { + bom: "", + bomType: attach.RawSignature, + expectedErr: true, + }, + } + + for testName, testCase := range testCases { + t.Run(testName, func(t *testing.T) { + imgName := path.Join(repo, "sbom-image") + img, _, cleanup := mkimage(t, imgName) + var sbomRef string + restoreStdin := func() {} + if testCase.bomType == attach.FileSignature { + sbomRef = mkfile(testCase.bom, td, t) + } else if testCase.bomType == attach.StdinSignature { + sbomRef = "-" + restoreStdin = mockStdin(testCase.bom, td, t) + } else { + sbomRef = testCase.bom + } + + out := bytes.Buffer{} + _, errPl := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{Platform: "darwin/amd64"}, img.Name(), &out) + if errPl == nil { + t.Fatalf("Expected error when passing Platform to single arch image") + } + _, err := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{}, img.Name(), &out) + if err == nil { + t.Fatal("Expected error") + } + t.Log(out.String()) + out.Reset() + + // Upload it! + err = attach.SBOMCmd(ctx, options.RegistryOptions{}, options.RegistryExperimentalOptions{}, sbomRef, "spdx", imgName) + restoreStdin() + + if testCase.expectedErr { + mustErr(err, t) + } else { + sboms, err := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{}, imgName, &out) + if err != nil { + t.Fatal(err) + } + t.Log(out.String()) + if len(sboms) != 1 { + t.Fatalf("Expected one sbom, got %d", len(sboms)) + } + want, err := os.ReadFile("./testdata/bom-go-mod.spdx") + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(string(want), sboms[0]); diff != "" { + t.Errorf("diff: %s", diff) + } + } + + cleanup() + }) + } +} diff --git a/test/e2e_signblob_tsa_mtls.sh b/test/e2e_signblob_tsa_mtls.sh deleted file mode 100755 index 2f92cc795e3..00000000000 --- a/test/e2e_signblob_tsa_mtls.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright 2023 The Sigstore Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This test checks that verify-blob will iterate over all entries and check for at least one valid entry before erroring out -# This is to prevent verify-blob from only checking the most recent entry, which could result -# in a "denial of service" type attack if someone signs a piece of software -# with their own certificate which doesn't chain up to Sigstore - -set -ex - -COSIGN_CLI=./cosign -CERT_BASE="test/testdata" - -# the certificates listed below are generated with the `gen-tsa-mtls-certs.sh` script. -TIMESTAMP_CACERT=$CERT_BASE/tsa-mtls-ca.crt -TIMESTAMP_CLIENT_CERT=$CERT_BASE/tsa-mtls-client.crt -TIMESTAMP_CLIENT_KEY=$CERT_BASE/tsa-mtls-client.key -TIMESTAMP_SERVER_CERT=$CERT_BASE/tsa-mtls-server.crt -TIMESTAMP_SERVER_KEY=$CERT_BASE/tsa-mtls-server.key -TIMESTAMP_SERVER_NAME="server.example.com" -TIMESTAMP_SERVER_URL=https://localhost:3000/api/v1/timestamp -TIMESTAMP_CHAIN_FILE="timestamp-chain.pem" - -set +e -COSIGN_CLI=./cosign -command -v timestamp-server >& /dev/null -exit_code=$? -set -e -if [[ $exit_code != 0 ]]; then - rm -fr /tmp/timestamp-authority - git clone https://github.com/sigstore/timestamp-authority /tmp/timestamp-authority - pushd /tmp/timestamp-authority - make - export PATH="/tmp/timestamp-authority/bin:$PATH" - popd -fi - -timestamp-server serve --disable-ntp-monitoring --tls-host 0.0.0.0 --tls-port 3000 \ - --scheme https --tls-ca $TIMESTAMP_CACERT --tls-key $TIMESTAMP_SERVER_KEY \ - --tls-certificate $TIMESTAMP_SERVER_CERT & - -sleep 1 -curl -k -s --key test/testdata/tsa-mtls-client.key \ - --cert test/testdata/tsa-mtls-client.crt \ - --cacert test/testdata/tsa-mtls-ca.crt https://localhost:3000/api/v1/timestamp/certchain \ - > $TIMESTAMP_CHAIN_FILE -echo "DONE: $(ls -l $TIMESTAMP_CHAIN_FILE)" -echo "Creating a unique blob" -BLOB=verify-experimental-blob -date > $BLOB -cat $BLOB - -rm -f ca-key.pem cacert.pem cert.pem key.pem import-cosign.* -# use gencert to generate CA, keys and certificates -echo "generate keys and certificates with gencert" - -passwd=$(uuidgen | head -c 32 | tr 'A-Z' 'a-z') -go run test/gencert/main.go \ - && COSIGN_PASSWORD="$passwd" $COSIGN_CLI import-key-pair --key key.pem - -echo "Sign the blob with cosign first and upload to rekor" -COSIGN_PASSWORD="$passwd" $COSIGN_CLI sign-blob --yes \ - --key import-cosign.key \ - --timestamp-server-url "${TIMESTAMP_SERVER_URL}" \ - --timestamp-client-cacert ${TIMESTAMP_CACERT} --timestamp-client-cert ${TIMESTAMP_CLIENT_CERT} \ - --timestamp-client-key ${TIMESTAMP_CLIENT_KEY} --timestamp-server-name ${TIMESTAMP_SERVER_NAME} \ - --rfc3161-timestamp=timestamp.txt --tlog-upload=false \ - --bundle cosign.bundle $BLOB - -echo "Verifying ..." -$COSIGN_CLI verify-blob --bundle cosign.bundle \ - --certificate-identity-regexp '.*' --certificate-oidc-issuer-regexp '.*' \ - --rfc3161-timestamp=timestamp.txt --timestamp-certificate-chain=$TIMESTAMP_CHAIN_FILE \ - --insecure-ignore-tlog=true --key import-cosign.pub $BLOB - -$COSIGN_CLI verify-blob --bundle cosign.bundle \ - --certificate-identity-regexp '.*' --certificate-oidc-issuer-regexp '.*' \ - --rfc3161-timestamp=timestamp.txt --timestamp-certificate-chain=$TIMESTAMP_CHAIN_FILE \ - --private-infrastructure --key import-cosign.pub $BLOB - -# cleanup -rm -fr blob.sig ca-key.pem cacert.pem cert.pem cosign.bundle import-cosign.key \ - import-cosign.pub key.pem timestamp.txt timestamp-chain.pem \ - /tmp/timestamp-authority verify-experimental-blob -pkill -f 'timestamp-server' diff --git a/test/e2e_test.go b/test/e2e_test.go index 028a2cb622e..abbb5a3df04 100644 --- a/test/e2e_test.go +++ b/test/e2e_test.go @@ -13,8 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build e2e -// +build e2e +//go:build e2e && !cross package test @@ -22,11 +21,7 @@ import ( "bytes" "context" "crypto" - "crypto/rand" - "crypto/sha256" - "encoding/base64" "encoding/json" - "encoding/pem" "fmt" "io" "net/http" @@ -38,12 +33,8 @@ import ( "testing" "time" - "github.com/go-openapi/strfmt" "github.com/google/go-cmp/cmp" - "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/name" - "github.com/google/go-containerregistry/pkg/registry" - "github.com/google/go-containerregistry/pkg/v1/random" "github.com/google/go-containerregistry/pkg/v1/remote" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" k8s "k8s.io/client-go/kubernetes" @@ -64,124 +55,18 @@ import ( "github.com/sigstore/cosign/v2/cmd/cosign/cli/sign" cliverify "github.com/sigstore/cosign/v2/cmd/cosign/cli/verify" "github.com/sigstore/cosign/v2/internal/pkg/cosign/fulcio/fulcioroots" - "github.com/sigstore/cosign/v2/internal/pkg/cosign/tsa" - "github.com/sigstore/cosign/v2/internal/pkg/cosign/tsa/client" "github.com/sigstore/cosign/v2/pkg/cosign" "github.com/sigstore/cosign/v2/pkg/cosign/bundle" "github.com/sigstore/cosign/v2/pkg/cosign/env" "github.com/sigstore/cosign/v2/pkg/cosign/kubernetes" "github.com/sigstore/cosign/v2/pkg/oci/mutate" ociremote "github.com/sigstore/cosign/v2/pkg/oci/remote" - sigs "github.com/sigstore/cosign/v2/pkg/signature" "github.com/sigstore/sigstore/pkg/signature/payload" tsaclient "github.com/sigstore/timestamp-authority/pkg/client" "github.com/sigstore/timestamp-authority/pkg/server" "github.com/spf13/viper" ) -const ( - rekorURL = "http://127.0.0.1:3000" - fulcioURL = "http://127.0.0.1:5555" - certID = "foo@bar.com" -) - -var keyPass = []byte("hello") - -var passFunc = func(_ bool) ([]byte, error) { - return keyPass, nil -} - -var verify = func(keyRef, imageRef string, checkClaims bool, annotations map[string]interface{}, attachment string, skipTlogVerify bool) error { - cmd := cliverify.VerifyCommand{ - KeyRef: keyRef, - RekorURL: rekorURL, - CheckClaims: checkClaims, - Annotations: sigs.AnnotationsMap{Annotations: annotations}, - Attachment: attachment, - HashAlgorithm: crypto.SHA256, - MaxWorkers: 10, - IgnoreTlog: skipTlogVerify, - } - - args := []string{imageRef} - - return cmd.Exec(context.Background(), args) -} - -var verifyTSA = func(keyRef, imageRef string, checkClaims bool, annotations map[string]interface{}, attachment, tsaCertChain string, skipTlogVerify bool) error { - cmd := cliverify.VerifyCommand{ - KeyRef: keyRef, - RekorURL: rekorURL, - CheckClaims: checkClaims, - Annotations: sigs.AnnotationsMap{Annotations: annotations}, - Attachment: attachment, - HashAlgorithm: crypto.SHA256, - TSACertChainPath: tsaCertChain, - IgnoreTlog: skipTlogVerify, - MaxWorkers: 10, - } - - args := []string{imageRef} - - return cmd.Exec(context.Background(), args) -} - -var verifyKeylessTSA = func(imageRef string, tsaCertChain string, skipSCT bool, skipTlogVerify bool) error { - cmd := cliverify.VerifyCommand{ - CertVerifyOptions: options.CertVerifyOptions{ - CertOidcIssuerRegexp: ".*", - CertIdentityRegexp: ".*", - }, - RekorURL: rekorURL, - HashAlgorithm: crypto.SHA256, - TSACertChainPath: tsaCertChain, - IgnoreSCT: skipSCT, - IgnoreTlog: skipTlogVerify, - MaxWorkers: 10, - } - - args := []string{imageRef} - - return cmd.Exec(context.Background(), args) -} - -// Used to verify local images stored on disk -var verifyLocal = func(keyRef, path string, checkClaims bool, annotations map[string]interface{}, attachment string) error { - cmd := cliverify.VerifyCommand{ - KeyRef: keyRef, - RekorURL: rekorURL, - CheckClaims: checkClaims, - Annotations: sigs.AnnotationsMap{Annotations: annotations}, - Attachment: attachment, - HashAlgorithm: crypto.SHA256, - LocalImage: true, - MaxWorkers: 10, - } - - args := []string{path} - - return cmd.Exec(context.Background(), args) -} - -var verifyOffline = func(keyRef, imageRef string, checkClaims bool, annotations map[string]interface{}, attachment string) error { - cmd := cliverify.VerifyCommand{ - KeyRef: keyRef, - RekorURL: "notreal", - Offline: true, - CheckClaims: checkClaims, - Annotations: sigs.AnnotationsMap{Annotations: annotations}, - Attachment: attachment, - HashAlgorithm: crypto.SHA256, - MaxWorkers: 10, - } - - args := []string{imageRef} - - return cmd.Exec(context.Background(), args) -} - -var ro = &options.RootOptions{Timeout: options.DefaultTimeout} - func TestSignVerify(t *testing.T) { td := t.TempDir() err := downloadAndSetEnv(t, rekorURL+"/api/v1/log/publicKey", env.VariableSigstoreRekorPublicKey.String(), td) @@ -906,147 +791,6 @@ func TestAttestationRFC3161Timestamp(t *testing.T) { must(verifyAttestation.Exec(ctx, []string{imgName}), t) } -func TestAttachWithRFC3161Timestamp(t *testing.T) { - ctx := context.Background() - // TSA server needed to create timestamp - viper.Set("timestamp-signer", "memory") - viper.Set("timestamp-signer-hash", "sha256") - apiServer := server.NewRestAPIServer("localhost", 0, []string{"http"}, false, 10*time.Second, 10*time.Second) - server := httptest.NewServer(apiServer.GetHandler()) - t.Cleanup(server.Close) - - repo, stop := reg(t) - defer stop() - td := t.TempDir() - - imgName := path.Join(repo, "cosign-attach-timestamp-e2e") - - _, _, cleanup := mkimage(t, imgName) - defer cleanup() - - b := bytes.Buffer{} - must(generate.GenerateCmd(context.Background(), options.RegistryOptions{}, imgName, nil, &b), t) - - rootCert, rootKey, _ := GenerateRootCa() - subCert, subKey, _ := GenerateSubordinateCa(rootCert, rootKey) - leafCert, privKey, _ := GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert, subKey) - pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw}) - pemSub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert.Raw}) - pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw}) - - payloadref := mkfile(b.String(), td, t) - - h := sha256.Sum256(b.Bytes()) - signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256) - b64signature := base64.StdEncoding.EncodeToString([]byte(signature)) - sigRef := mkfile(b64signature, td, t) - pemleafRef := mkfile(string(pemLeaf), td, t) - pemrootRef := mkfile(string(pemRoot), td, t) - - certchainRef := mkfile(string(append(pemSub[:], pemRoot[:]...)), td, t) - - t.Setenv("SIGSTORE_ROOT_FILE", pemrootRef) - - tsclient, err := tsaclient.GetTimestampClient(server.URL) - if err != nil { - t.Error(err) - } - - chain, err := tsclient.Timestamp.GetTimestampCertChain(nil) - if err != nil { - t.Fatalf("unexpected error getting timestamp chain: %v", err) - } - - file, err := os.CreateTemp(os.TempDir(), "tempfile") - if err != nil { - t.Fatalf("error creating temp file: %v", err) - } - defer os.Remove(file.Name()) - _, err = file.WriteString(chain.Payload) - if err != nil { - t.Fatalf("error writing chain payload to temp file: %v", err) - } - - tsBytes, err := tsa.GetTimestampedSignature(signature, client.NewTSAClient(server.URL+"/api/v1/timestamp")) - if err != nil { - t.Fatalf("unexpected error creating timestamp: %v", err) - } - rfc3161TSRef := mkfile(string(tsBytes), td, t) - - // Upload it! - err = attach.SignatureCmd(ctx, options.RegistryOptions{}, sigRef, payloadref, pemleafRef, certchainRef, rfc3161TSRef, "", imgName) - if err != nil { - t.Fatal(err) - } - - must(verifyKeylessTSA(imgName, file.Name(), true, true), t) -} - -func TestAttachWithRekorBundle(t *testing.T) { - ctx := context.Background() - - repo, stop := reg(t) - defer stop() - td := t.TempDir() - - imgName := path.Join(repo, "cosign-attach-timestamp-e2e") - - _, _, cleanup := mkimage(t, imgName) - defer cleanup() - - b := bytes.Buffer{} - must(generate.GenerateCmd(context.Background(), options.RegistryOptions{}, imgName, nil, &b), t) - - rootCert, rootKey, _ := GenerateRootCa() - subCert, subKey, _ := GenerateSubordinateCa(rootCert, rootKey) - leafCert, privKey, _ := GenerateLeafCert("subject@mail.com", "oidc-issuer", subCert, subKey) - pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw}) - pemSub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert.Raw}) - pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw}) - - payloadref := mkfile(b.String(), td, t) - - h := sha256.Sum256(b.Bytes()) - signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256) - b64signature := base64.StdEncoding.EncodeToString([]byte(signature)) - sigRef := mkfile(b64signature, td, t) - pemleafRef := mkfile(string(pemLeaf), td, t) - pemrootRef := mkfile(string(pemRoot), td, t) - - t.Setenv("SIGSTORE_ROOT_FILE", pemrootRef) - - certchainRef := mkfile(string(append(pemSub[:], pemRoot[:]...)), td, t) - - localPayload := cosign.LocalSignedPayload{ - Base64Signature: b64signature, - Cert: string(pemLeaf), - Bundle: &bundle.RekorBundle{ - SignedEntryTimestamp: strfmt.Base64("MEUCIEDcarEwRYkrxE9ne+kzEVvUhnWaauYzxhUyXOLy1hwAAiEA4VdVCvNRs+D/5o33C2KBy+q2YX3lP4Y7nqRFU+K3hi0="), - Payload: bundle.RekorPayload{ - Body: "REMOVED", - IntegratedTime: 1631646761, - LogIndex: 693591, - LogID: "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d", - }, - }, - } - - jsonBundle, err := json.Marshal(localPayload) - if err != nil { - t.Fatal(err) - } - bundlePath := filepath.Join(td, "bundle.json") - if err := os.WriteFile(bundlePath, jsonBundle, 0644); err != nil { - t.Fatal(err) - } - - // Upload it! - err = attach.SignatureCmd(ctx, options.RegistryOptions{}, sigRef, payloadref, pemleafRef, certchainRef, "", bundlePath, imgName) - if err != nil { - t.Fatal(err) - } -} - func TestRekorBundle(t *testing.T) { td := t.TempDir() err := downloadAndSetEnv(t, rekorURL+"/api/v1/log/publicKey", env.VariableSigstoreRekorPublicKey.String(), td) @@ -1678,194 +1422,6 @@ func TestGenerate(t *testing.T) { equals(ss.Optional["foo"], "bar", t) } -func keypair(t *testing.T, td string) (*cosign.KeysBytes, string, string) { - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - if err := os.Chdir(td); err != nil { - t.Fatal(err) - } - defer func() { - os.Chdir(wd) - }() - keys, err := cosign.GenerateKeyPair(passFunc) - if err != nil { - t.Fatal(err) - } - - privKeyPath := filepath.Join(td, "cosign.key") - if err := os.WriteFile(privKeyPath, keys.PrivateBytes, 0600); err != nil { - t.Fatal(err) - } - - pubKeyPath := filepath.Join(td, "cosign.pub") - if err := os.WriteFile(pubKeyPath, keys.PublicBytes, 0600); err != nil { - t.Fatal(err) - } - return keys, privKeyPath, pubKeyPath -} - -func importKeyPair(t *testing.T, td string) (*cosign.KeysBytes, string, string) { - - const validrsa1 = `-----BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAx5piWVlE62NnZ0UzJ8Z6oKiKOC4dbOZ1HsNhIRtqkM+Oq4G+ -25yq6P+0JU/Qvr9veOGEb3R/J9u8JBo+hv2i5X8OtgvP2V2pi6f1s6vK7L0+6uRb -4YTT/UdMshaVf97MgEqbq41Jf/cuvh+3AV0tZ1BpixZg4aXMKpY6HUP69lbsu27o -SUN1myMv7TSgZiV4CYs3l/gkEfpysBptWlcHRuw5RsB+C0RbjRtbJ/5VxmE/vd3M -lafd5t1WSpMb8yf0a84u5NFaXwZ7CweMfXeOddS0yb19ShSuW3PPRadruBM1mq15 -js9GfagPxDS75Imcs+fA62lWvHxEujTGjYHxawIDAQABAoIBAH+sgLwmHa9zJfEo -klAe5NFe/QpydN/ziXbkAnzqzH9URC3wD+TpkWj4JoK3Sw635NWtasjf+3XDV9S/ -9L7j/g5N91r6sziWcJykEsWaXXKQmm4lI6BdFjwsHyLKz1W7bZOiJXDWLu1rbrqu -DqEQuLoc9WXCKrYrFy0maoXNtfla/1p05kKN0bMigcnnyAQ+xBTwoyco4tkIz5se -IYxorz7qzXrkHQI+knz5BawmNe3ekoSaXUPoLoOR7TRTGsLteL5yukvWAi8S/0rE -gftC+PZCQpoQhSUYq7wXe7RowJ1f+kXb7HsSedOTfTSW1D/pUb/uW+CcRKig42ZI -I9H9TAECgYEA5XGBML6fJyWVqx64sHbUAjQsmQ0RwU6Zo7sqHIEPf6tYVYp7KtzK -KOfi8seOOL5FSy4pjCo11Dzyrh9bn45RNmtjSYTgOnVPSoCfuRNfOcpG+/wCHjYf -EjDvdrCpbg59kVUeaMeBDiyWAlM48HJAn8O7ez2U/iKQCyJmOIwFhSkCgYEA3rSz -Fi1NzqYWxWos4NBmg8iKcQ9SMkmPdgRLAs/WNnZJ8fdgJZwihevkXGytRGJEmav2 -GMKRx1g6ey8fjXTQH9WM8X/kJC5fv8wLHnUCH/K3Mcp9CYwn7PFvSnBr4kQoc/el -bURhcF1+/opEC8vNX/Wk3zAG7Xs1PREXlH2SIHMCgYBV/3kgwBH/JkM25EjtO1yz -hsLAivmAruk/SUO7c1RP0fVF+qW3pxHOyztxLALOmeJ3D1JbSubqKf377Zz17O3b -q9yHDdrNjnKtxhAX2n7ytjJs+EQC9t4mf1kB761RpvTBqFnBhCWHHocLUA4jcW9v -cnmu86IIrwO2aKpPv4vCIQKBgHU9gY3qOazRSOmSlJ+hdmZn+2G7pBTvHsQNTIPl -cCrpqNHl3crO4GnKHkT9vVVjuiOAIKU2QNJFwzu4Og8Y8LvhizpTjoHxm9x3iV72 -UDELcJ+YrqyJCTe2flUcy96o7Pbn50GXnwgtYD6WAW6IUszyn2ITgYIhu4wzZEt6 -s6O7AoGAPTKbRA87L34LMlXyUBJma+etMARIP1zu8bXJ7hSJeMcog8zaLczN7ruT -pGAaLxggvtvuncMuTrG+cdmsR9SafSFKRS92NCxhOUonQ+NP6mLskIGzJZoQ5JvQ -qGzRVIDGbNkrVHM0IsAtHRpC0rYrtZY+9OwiraGcsqUMLwwQdCA= ------END RSA PRIVATE KEY-----` - - wd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - if err := os.Chdir(td); err != nil { - t.Fatal(err) - } - defer func() { - os.Chdir(wd) - }() - - err = os.WriteFile("validrsa1.key", []byte(validrsa1), 0600) - if err != nil { - t.Fatal(err) - } - - keys, err := cosign.ImportKeyPair("validrsa1.key", passFunc) - if err != nil { - t.Fatal(err) - } - - privKeyPath := filepath.Join(td, "import-cosign.key") - if err := os.WriteFile(privKeyPath, keys.PrivateBytes, 0600); err != nil { - t.Fatal(err) - } - - pubKeyPath := filepath.Join(td, "import-cosign.pub") - if err := os.WriteFile(pubKeyPath, keys.PublicBytes, 0600); err != nil { - t.Fatal(err) - } - return keys, privKeyPath, pubKeyPath - -} - -func TestUploadDownload(t *testing.T) { - repo, stop := reg(t) - defer stop() - td := t.TempDir() - ctx := context.Background() - - testCases := map[string]struct { - signature string - signatureType attach.SignatureArgType - expectedErr bool - }{ - "stdin containing signature": { - signature: "testsignatureraw", - signatureType: attach.StdinSignature, - expectedErr: false, - }, - "file containing signature": { - signature: "testsignaturefile", - signatureType: attach.FileSignature, - expectedErr: false, - }, - "raw signature as argument": { - signature: "testsignatureraw", - signatureType: attach.RawSignature, - expectedErr: true, - }, - "empty signature as argument": { - signature: "", - signatureType: attach.RawSignature, - expectedErr: true, - }, - } - - imgName := path.Join(repo, "cosign-e2e") - for testName, testCase := range testCases { - t.Run(testName, func(t *testing.T) { - ref, _, cleanup := mkimage(t, imgName) - payload := "testpayload" - payloadPath := mkfile(payload, td, t) - signature := base64.StdEncoding.EncodeToString([]byte(testCase.signature)) - restoreStdin := func() {} - - var sigRef string - if testCase.signatureType == attach.FileSignature { - sigRef = mkfile(signature, td, t) - } else if testCase.signatureType == attach.StdinSignature { - sigRef = "-" - restoreStdin = mockStdin(signature, td, t) - } else { - sigRef = signature - } - // Upload it! - err := attach.SignatureCmd(ctx, options.RegistryOptions{}, sigRef, payloadPath, "", "", "", "", imgName) - if testCase.expectedErr { - mustErr(err, t) - } else { - must(err, t) - } - restoreStdin() - - // Now download it! - se, err := ociremote.SignedEntity(ref, ociremote.WithRemoteOptions(registryClientOpts(ctx)...)) - must(err, t) - sigs, err := se.Signatures() - must(err, t) - signatures, err := sigs.Get() - must(err, t) - - if testCase.expectedErr { - if len(signatures) != 0 { - t.Fatalf("unexpected signatures %d, wanted 0", len(signatures)) - } - } else { - if len(signatures) != 1 { - t.Fatalf("unexpected signatures %d, wanted 1", len(signatures)) - } - - if b64sig, err := signatures[0].Base64Signature(); err != nil { - t.Fatalf("Base64Signature() = %v", err) - } else if diff := cmp.Diff(b64sig, signature); diff != "" { - t.Error(diff) - } - - if p, err := signatures[0].Payload(); err != nil { - t.Fatalf("Payload() = %v", err) - } else if diff := cmp.Diff(p, []byte(payload)); diff != "" { - t.Error(diff) - } - } - - // Now delete it! - cleanup() - }) - } -} - func TestSaveLoad(t *testing.T) { td := t.TempDir() err := downloadAndSetEnv(t, rekorURL+"/api/v1/log/publicKey", env.VariableSigstoreRekorPublicKey.String(), td) @@ -2081,97 +1637,6 @@ func TestAttachSBOM(t *testing.T) { mustErr(verify(pubKeyPath2, imgName, true, nil, "sbom", false), t) } -func TestAttachSBOM_bom_flag(t *testing.T) { - repo, stop := reg(t) - defer stop() - td := t.TempDir() - ctx := context.Background() - bomData, err := os.ReadFile("./testdata/bom-go-mod.spdx") - must(err, t) - - testCases := map[string]struct { - bom string - bomType attach.SignatureArgType - expectedErr bool - }{ - "stdin containing bom": { - bom: string(bomData), - bomType: attach.StdinSignature, - expectedErr: false, - }, - "file containing bom": { - bom: string(bomData), - bomType: attach.FileSignature, - expectedErr: false, - }, - "raw bom as argument": { - bom: string(bomData), - bomType: attach.RawSignature, - expectedErr: true, - }, - "empty bom as argument": { - bom: "", - bomType: attach.RawSignature, - expectedErr: true, - }, - } - - for testName, testCase := range testCases { - t.Run(testName, func(t *testing.T) { - imgName := path.Join(repo, "sbom-image") - img, _, cleanup := mkimage(t, imgName) - var sbomRef string - restoreStdin := func() {} - if testCase.bomType == attach.FileSignature { - sbomRef = mkfile(testCase.bom, td, t) - } else if testCase.bomType == attach.StdinSignature { - sbomRef = "-" - restoreStdin = mockStdin(testCase.bom, td, t) - } else { - sbomRef = testCase.bom - } - - out := bytes.Buffer{} - _, errPl := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{Platform: "darwin/amd64"}, img.Name(), &out) - if errPl == nil { - t.Fatalf("Expected error when passing Platform to single arch image") - } - _, err := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{}, img.Name(), &out) - if err == nil { - t.Fatal("Expected error") - } - t.Log(out.String()) - out.Reset() - - // Upload it! - err = attach.SBOMCmd(ctx, options.RegistryOptions{}, options.RegistryExperimentalOptions{}, sbomRef, "spdx", imgName) - restoreStdin() - - if testCase.expectedErr { - mustErr(err, t) - } else { - sboms, err := download.SBOMCmd(ctx, options.RegistryOptions{}, options.SBOMDownloadOptions{}, imgName, &out) - if err != nil { - t.Fatal(err) - } - t.Log(out.String()) - if len(sboms) != 1 { - t.Fatalf("Expected one sbom, got %d", len(sboms)) - } - want, err := os.ReadFile("./testdata/bom-go-mod.spdx") - if err != nil { - t.Fatal(err) - } - if diff := cmp.Diff(string(want), sboms[0]); diff != "" { - t.Errorf("diff: %s", diff) - } - } - - cleanup() - }) - } -} - func TestNoTlog(t *testing.T) { repo, stop := reg(t) defer stop() @@ -2222,141 +1687,6 @@ func TestGetPublicKeyCustomOut(t *testing.T) { equals(keys.PublicBytes, output, t) } -func mockStdin(contents, td string, t *testing.T) func() { - origin := os.Stdin - - p := mkfile(contents, td, t) - f, err := os.Open(p) - if err != nil { - t.Fatal(err) - } - os.Stdin = f - - return func() { os.Stdin = origin } -} - -func mkfile(contents, td string, t *testing.T) string { - f, err := os.CreateTemp(td, "") - if err != nil { - t.Fatal(err) - } - defer f.Close() - if _, err := f.Write([]byte(contents)); err != nil { - t.Fatal(err) - } - return f.Name() -} - -func mkfileWithExt(contents, td, ext string, t *testing.T) string { - f := mkfile(contents, td, t) - newName := f + ext - err := os.Rename(f, newName) - if err != nil { - t.Fatal(err) - } - return newName -} - -func mkimage(t *testing.T, n string) (name.Reference, *remote.Descriptor, func()) { - ref, err := name.ParseReference(n, name.WeakValidation) - if err != nil { - t.Fatal(err) - } - img, err := random.Image(512, 5) - if err != nil { - t.Fatal(err) - } - - regClientOpts := registryClientOpts(context.Background()) - - if err := remote.Write(ref, img, regClientOpts...); err != nil { - t.Fatal(err) - } - - remoteImage, err := remote.Get(ref, regClientOpts...) - if err != nil { - t.Fatal(err) - } - - cleanup := func() { - _ = remote.Delete(ref, regClientOpts...) - ref, _ := ociremote.SignatureTag(ref.Context().Digest(remoteImage.Descriptor.Digest.String()), ociremote.WithRemoteOptions(regClientOpts...)) - _ = remote.Delete(ref, regClientOpts...) - } - return ref, remoteImage, cleanup -} - -func mkimageindex(t *testing.T, n string) (name.Reference, *remote.Descriptor, func()) { - ref, err := name.ParseReference(n, name.WeakValidation) - if err != nil { - t.Fatal(err) - } - ii, err := random.Index(512, 5, 4) - if err != nil { - t.Fatal(err) - } - - regClientOpts := registryClientOpts(context.Background()) - - if err := remote.WriteIndex(ref, ii, regClientOpts...); err != nil { - t.Fatal(err) - } - - remoteIndex, err := remote.Get(ref, regClientOpts...) - if err != nil { - t.Fatal(err) - } - - cleanup := func() { - _ = remote.Delete(ref, regClientOpts...) - ref, _ := ociremote.SignatureTag(ref.Context().Digest(remoteIndex.Descriptor.Digest.String()), ociremote.WithRemoteOptions(regClientOpts...)) - _ = remote.Delete(ref, regClientOpts...) - } - return ref, remoteIndex, cleanup -} - -func must(err error, t *testing.T) { - t.Helper() - if err != nil { - t.Fatal(err) - } -} - -func mustErr(err error, t *testing.T) { - t.Helper() - if err == nil { - t.Fatal("expected error") - } -} - -func equals(v1, v2 interface{}, t *testing.T) { - if diff := cmp.Diff(v1, v2); diff != "" { - t.Error(diff) - } -} - -func reg(t *testing.T) (string, func()) { - repo := os.Getenv("COSIGN_TEST_REPO") - if repo != "" { - return repo, func() {} - } - - t.Log("COSIGN_TEST_REPO unset, using fake registry") - r := httptest.NewServer(registry.New()) - u, err := url.Parse(r.URL) - if err != nil { - t.Fatal(err) - } - return u.Host, r.Close -} - -func registryClientOpts(ctx context.Context) []remote.Option { - return []remote.Option{ - remote.WithAuthFromKeychain(authn.DefaultKeychain), - remote.WithContext(ctx), - } -} - // If a signature has a bundle, but *not for that signature*, cosign verification should fail. // This test is pretty long, so here are the basic points: // 1. Sign image1 with a keypair, store entry in rekor diff --git a/test/e2e_test_attach.sh b/test/e2e_test_attach.sh deleted file mode 100755 index 21937b7255b..00000000000 --- a/test/e2e_test_attach.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright 2023 The Sigstore Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This test case test two scenarios -# scenario 1: Attach a single signature with certificate and certificate chain to an artifact -# and verify it using root certificate -# scenario 2: Attaches second signature with diffrent certificate and certificate chain to same -# artifact and verify it using both root certificates separately - -set -ex - -go build -o cosign ./cmd/cosign -tmp=$(mktemp -d -t cosign-e2e-attach.XXXX) -cp cosign $tmp/ - -#copying key, cert, certchain and rootcert in temp folder -cp ./test/testdata/test_attach_private_key $tmp/private_key -cp ./test/testdata/test_attach_leafcert.pem $tmp/leafcert.pem -cp ./test/testdata/test_attach_certchain.pem $tmp/certchain.pem -cp ./test/testdata/test_attach_rootcert.pem $tmp/rootcert.pem -cp ./test/testdata/test_attach_second_private_key $tmp/secondprivate_key -cp ./test/testdata/test_attach_second_leafcert.pem $tmp/secondleafcert.pem -cp ./test/testdata/test_attach_second_certchain.pem $tmp/secondcertchain.pem -cp ./test/testdata/test_attach_second_rootcert.pem $tmp/secondrootcert.pem - -pushd $tmp - -pass="$RANDOM" -export COSIGN_PASSWORD=$pass - -SRC_IMAGE=busybox -SRC_DIGEST=$(crane digest busybox) -IMAGE_URI=ttl.sh/cosign-ci/$(uuidgen | head -c 8 | tr 'A-Z' 'a-z') -crane cp $SRC_IMAGE@$SRC_DIGEST $IMAGE_URI:1h -IMAGE_URI_DIGEST=$IMAGE_URI@$SRC_DIGEST - - -# `initialize` -./cosign initialize - -## Generate -./cosign generate $IMAGE_URI_DIGEST > payload.json - -## Scenario 1 Starts - -## Sign with First Leafcert Private Key -openssl dgst -sha256 -sign ./private_key -out payload.sig payload.json -cat payload.sig | base64 > payloadbase64.sig - -SIGNATURE=$(cat payloadbase64.sig | base64) -echo "Signature: $SIGNATURE" - -PAYLOAD=$(cat payload.json) -echo "Payload: $PAYLOAD" - -## Attach Signature, payload, cert and cert-chain -./cosign attach signature --signature ./payloadbase64.sig --payload ./payload.json --cert ./leafcert.pem --cert-chain ./certchain.pem $IMAGE_URI_DIGEST - -## confirm manifest conatins annotation for cert and cert chain -crane manifest $(./cosign triangulate $IMAGE_URI_DIGEST) | grep -q "application/vnd.oci.image.config.v1+json" -crane manifest $(./cosign triangulate $IMAGE_URI_DIGEST) | grep -q "dev.sigstore.cosign/certificate" -crane manifest $(./cosign triangulate $IMAGE_URI_DIGEST) | grep -q "dev.sigstore.cosign/chain" - -## Verify Signature, payload, cert and cert-chain using Root certificate only -./cosign verify $IMAGE_URI_DIGEST --insecure-ignore-sct --insecure-ignore-tlog --certificate-identity-regexp '.*' --certificate-oidc-issuer-regexp '.*' --cert-chain=./rootcert.pem - -## Scenario 2 Starts - -## Sign with Leafcert Private Key -openssl dgst -sha256 -sign ./secondprivate_key -out secondpayload.sig payload.json -cat secondpayload.sig | base64 > secondpayloadbase64.sig - -SIGNATURE2=$(cat secondpayloadbase64.sig | base64) -echo "Second Signature: $SIGNATURE2" - -## Attach Second Signature, payload, cert and cert-chain -./cosign attach signature --signature ./secondpayloadbase64.sig --payload ./payload.json --cert ./secondleafcert.pem --cert-chain ./secondcertchain.pem $IMAGE_URI_DIGEST - -## Verify Signature, payload, cert and cert-chain using Root certificate only -./cosign verify $IMAGE_URI_DIGEST --insecure-ignore-sct --insecure-ignore-tlog --certificate-identity-regexp '.*' --certificate-oidc-issuer-regexp '.*' --cert-chain=./rootcert.pem - -./cosign verify $IMAGE_URI_DIGEST --insecure-ignore-sct --insecure-ignore-tlog --certificate-identity-regexp '.*' --certificate-oidc-issuer-regexp '.*' --cert-chain=./secondrootcert.pem - -# clean up a bit -./cosign clean $IMAGE_URI_DIGEST --force=true -crane delete $IMAGE_URI_DIGEST || true - - -# completed -echo "SUCCESS" diff --git a/test/e2e_tsa_mtls.sh b/test/e2e_tsa_mtls.sh deleted file mode 100755 index adb0d062b77..00000000000 --- a/test/e2e_tsa_mtls.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright 2023 The Sigstore Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -exuo pipefail - -## Requirements -# - cosign -# - crane -# - go - -CERT_BASE="test/testdata" - -# the certificates listed below are generated with the `gen-tsa-mtls-certs.sh` script. -TIMESTAMP_CACERT=$CERT_BASE/tsa-mtls-ca.crt -TIMESTAMP_CLIENT_CERT=$CERT_BASE/tsa-mtls-client.crt -TIMESTAMP_CLIENT_KEY=$CERT_BASE/tsa-mtls-client.key -TIMESTAMP_SERVER_CERT=$CERT_BASE/tsa-mtls-server.crt -TIMESTAMP_SERVER_KEY=$CERT_BASE/tsa-mtls-server.key -TIMESTAMP_SERVER_NAME="server.example.com" -TIMESTAMP_SERVER_URL=https://localhost:3000/api/v1/timestamp -TIMESTAMP_CHAIN_FILE="timestamp-chain" - -set +e -COSIGN_CLI=./cosign -command -v timestamp-server >& /dev/null -exit_code=$? -set -e -if [[ $exit_code != 0 ]]; then - rm -fr /tmp/timestamp-authority - git clone https://github.com/sigstore/timestamp-authority /tmp/timestamp-authority - pushd /tmp/timestamp-authority - make - export PATH="/tmp/timestamp-authority/bin:$PATH" - popd -fi - -timestamp-server serve --disable-ntp-monitoring --tls-host 0.0.0.0 --tls-port 3000 \ - --scheme https --tls-ca $TIMESTAMP_CACERT --tls-key $TIMESTAMP_SERVER_KEY \ - --tls-certificate $TIMESTAMP_SERVER_CERT & - -sleep 1 -curl -k -s --key test/testdata/tsa-mtls-client.key \ - --cert test/testdata/tsa-mtls-client.crt \ - --cacert test/testdata/tsa-mtls-ca.crt https://localhost:3000/api/v1/timestamp/certchain \ - > $TIMESTAMP_CHAIN_FILE -echo "DONE: $(ls -l $TIMESTAMP_CHAIN_FILE)" - -IMG=${IMAGE_URI_DIGEST:-} -if [[ "$#" -ge 1 ]]; then - IMG=$1 -elif [[ -z "${IMG}" ]]; then - # Upload an image to ttl.sh - commands from https://docs.sigstore.dev/cosign/keyless/ - SRC_IMAGE=busybox - SRC_DIGEST=$(crane digest busybox) - IMAGE_URI=ttl.sh/$(uuidgen | head -c 8 | tr 'A-Z' 'a-z') - crane cp $SRC_IMAGE@$SRC_DIGEST $IMAGE_URI:3h - IMG=$IMAGE_URI@$SRC_DIGEST -fi - -echo "IMG (IMAGE_URI_DIGEST): $IMG, TIMESTAMP_SERVER_URL: $TIMESTAMP_SERVER_URL" - -rm -f *.pem import-cosign.* key.pem - -# use gencert to generate CA, keys and certificates -echo "generate keys and certificates with gencert" - -passwd=$(uuidgen | head -c 32 | tr 'A-Z' 'a-z') -rm -f *.pem import-cosign.* && go run test/gencert/main.go && COSIGN_PASSWORD="$passwd" $COSIGN_CLI import-key-pair --key key.pem - -COSIGN_PASSWORD="$passwd" $COSIGN_CLI sign --timestamp-server-url "${TIMESTAMP_SERVER_URL}" \ - --timestamp-client-cacert ${TIMESTAMP_CACERT} --timestamp-client-cert ${TIMESTAMP_CLIENT_CERT} \ - --timestamp-client-key ${TIMESTAMP_CLIENT_KEY} --timestamp-server-name ${TIMESTAMP_SERVER_NAME}\ - --upload=true --tlog-upload=false --key import-cosign.key --certificate-chain cacert.pem --cert cert.pem $IMG - -# key is now longer needed -rm -f key.pem import-cosign.* - -echo "cosign verify:" -$COSIGN_CLI verify --insecure-ignore-tlog --insecure-ignore-sct --check-claims=true \ - --certificate-identity-regexp 'xyz@nosuchprovider.com' --certificate-oidc-issuer-regexp '.*' \ - --certificate-chain cacert.pem --timestamp-certificate-chain $TIMESTAMP_CHAIN_FILE $IMG - -# cleanup -rm -fr ca-key.pem cacert.pem cert.pem timestamp-chain /tmp/timestamp-authority -pkill -f 'timestamp-server' diff --git a/test/e2e_tsa_test.go b/test/e2e_tsa_test.go new file mode 100644 index 00000000000..acd873a601c --- /dev/null +++ b/test/e2e_tsa_test.go @@ -0,0 +1,196 @@ +// Copyright 2024 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build e2e && cross + +package test + +import ( + "context" + "crypto/x509" + "encoding/pem" + "net/http/httptest" + "path" + "path/filepath" + "testing" + "time" + + "github.com/secure-systems-lab/go-securesystemslib/encrypted" + "github.com/sigstore/cosign/v2/cmd/cosign/cli/options" + "github.com/sigstore/cosign/v2/cmd/cosign/cli/sign" + cliverify "github.com/sigstore/cosign/v2/cmd/cosign/cli/verify" + "github.com/sigstore/cosign/v2/pkg/cosign" + tsaclient "github.com/sigstore/timestamp-authority/pkg/client" + tsaserver "github.com/sigstore/timestamp-authority/pkg/server" + "github.com/spf13/viper" +) + +func TestTSAMTLS(t *testing.T) { + repo, stop := reg(t) + defer stop() + td := t.TempDir() + + imgName := path.Join(repo, "cosign-tsa-mtls-e2e") + + _, _, cleanup := mkimage(t, imgName) + defer cleanup() + + pemRootRef, pemLeafRef, pemKeyRef := generateSigningKeys(t, td) + + // Set up TSA server with TLS + timestampCACert, timestampServerCert, timestampServerKey, timestampClientCert, timestampClientKey := generateMTLSKeys(t, td) + timestampServerURL, timestampChainFile, tsaCleanup := setUpTSAServerWithTLS(t, td, timestampCACert, timestampServerKey, timestampServerCert) + t.Cleanup(tsaCleanup) + + ko := options.KeyOpts{ + KeyRef: pemKeyRef, + PassFunc: passFunc, + TSAServerURL: timestampServerURL, + TSAClientCACert: timestampCACert, + TSAClientCert: timestampClientCert, + TSAClientKey: timestampClientKey, + TSAServerName: "server.example.com", + } + so := options.SignOptions{ + Upload: true, + TlogUpload: false, + Cert: pemLeafRef, + CertChain: pemRootRef, + } + must(sign.SignCmd(ro, ko, so, []string{imgName}), t) + + verifyCmd := cliverify.VerifyCommand{ + IgnoreTlog: true, + IgnoreSCT: true, + CheckClaims: true, + CertChain: pemRootRef, + TSACertChainPath: timestampChainFile, + CertVerifyOptions: options.CertVerifyOptions{ + CertIdentityRegexp: ".*", + CertOidcIssuerRegexp: ".*", + }, + } + must(verifyCmd.Exec(context.Background(), []string{imgName}), t) +} + +func TestSignBlobTSAMTLS(t *testing.T) { + td := t.TempDir() + blob := time.Now().Format("Mon Jan 2 15:04:05 MST 2006") + blobPath := mkfile(blob, td, t) + timestampPath := filepath.Join(td, "timestamp.txt") + bundlePath := filepath.Join(td, "cosign.bundle") + + _, privKey, pubKey := keypair(t, td) + + // Set up TSA server with TLS + timestampCACert, timestampServerCert, timestampServerKey, timestampClientCert, timestampClientKey := generateMTLSKeys(t, td) + timestampServerURL, timestampChainFile, tsaCleanup := setUpTSAServerWithTLS(t, td, timestampCACert, timestampServerKey, timestampServerCert) + t.Cleanup(tsaCleanup) + + signingKO := options.KeyOpts{ + KeyRef: privKey, + PassFunc: passFunc, + TSAServerURL: timestampServerURL, + TSAClientCACert: timestampCACert, + TSAClientCert: timestampClientCert, + TSAClientKey: timestampClientKey, + TSAServerName: "server.example.com", + RFC3161TimestampPath: timestampPath, + BundlePath: bundlePath, + } + sig, err := sign.SignBlobCmd(ro, signingKO, blobPath, true, "", "", false) + must(err, t) + + verifyKO := options.KeyOpts{ + KeyRef: pubKey, + TSACertChainPath: timestampChainFile, + RFC3161TimestampPath: timestampPath, + BundlePath: bundlePath, + } + + verifyCmd := cliverify.VerifyBlobCmd{ + KeyOpts: verifyKO, + SigRef: string(sig), + CertVerifyOptions: options.CertVerifyOptions{ + CertIdentityRegexp: ".*", + CertOidcIssuerRegexp: ".*", + }, + IgnoreTlog: true, + } + must(verifyCmd.Exec(context.Background(), blobPath), t) +} + +func generateSigningKeys(t *testing.T, td string) (string, string, string) { + rootCert, rootKey, _ := GenerateRootCa() + pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw}) + pemRootRef := mkfile(string(pemRoot), td, t) + + leafCert, privKey, _ := GenerateLeafCert("xyz@nosuchprovider.com", "oidc-issuer", rootCert, rootKey) + pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw}) + pemLeafRef := mkfile(string(pemLeaf), td, t) + + x509Encoded, _ := x509.MarshalPKCS8PrivateKey(privKey) + encBytes, _ := encrypted.Encrypt(x509Encoded, keyPass) + keyPem := pem.EncodeToMemory(&pem.Block{ + Type: cosign.CosignPrivateKeyPemType, + Bytes: encBytes}) + pemKeyRef := mkfile(string(keyPem), td, t) + + return pemRootRef, pemLeafRef, pemKeyRef +} + +func generateMTLSKeys(t *testing.T, td string) (string, string, string, string, string) { + rootCert, rootKey, _ := GenerateRootCa() + pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw}) + pemRootRef := mkfile(string(pemRoot), td, t) + + serverLeafCert, serverPrivKey, _ := GenerateLeafCertWithSubjectAlternateNames([]string{"server.example.com"}, nil, nil, nil, "oidc-issuer", rootCert, rootKey) + serverPemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: serverLeafCert.Raw}) + serverPemLeafRef := mkfile(string(serverPemLeaf), td, t) + serverX509Encoded, _ := x509.MarshalPKCS8PrivateKey(serverPrivKey) + serverKeyPem := pem.EncodeToMemory(&pem.Block{ + Type: cosign.ECPrivateKeyPemType, + Bytes: serverX509Encoded}) + serverPemKeyRef := mkfile(string(serverKeyPem), td, t) + + clientLeafCert, clientPrivKey, _ := GenerateLeafCert("tsa-mtls-client", "oidc-issuer", rootCert, rootKey) + clientPemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: clientLeafCert.Raw}) + clientPemLeafRef := mkfile(string(clientPemLeaf), td, t) + clientX509Encoded, _ := x509.MarshalPKCS8PrivateKey(clientPrivKey) + clientKeyPem := pem.EncodeToMemory(&pem.Block{ + Type: cosign.ECPrivateKeyPemType, + Bytes: clientX509Encoded}) + clientPemKeyRef := mkfile(string(clientKeyPem), td, t) + return pemRootRef, serverPemLeafRef, serverPemKeyRef, clientPemLeafRef, clientPemKeyRef +} + +func setUpTSAServerWithTLS(t *testing.T, td, timestampCACert, timestampServerKey, timestampServerCert string) (string, string, func()) { + viper.Set("timestamp-signer", "memory") + viper.Set("timestamp-signer-hash", "sha256") + viper.Set("disable-ntp-monitoring", true) + viper.Set("tls-host", "0.0.0.0") + viper.Set("tls-port", 3000) + viper.Set("tls-ca", timestampCACert) + viper.Set("tls-key", timestampServerKey) + viper.Set("tls-certificate", timestampServerCert) + tsaAPIServer := tsaserver.NewRestAPIServer("localhost", 3000, []string{"https"}, false, 10*time.Second, 10*time.Second) + tsaServer := httptest.NewServer(tsaAPIServer.GetHandler()) + tsaClient, err := tsaclient.GetTimestampClient(tsaServer.URL) + must(err, t) + tsaChain, err := tsaClient.Timestamp.GetTimestampCertChain(nil) + must(err, t) + timestampServerURL := tsaServer.URL + "/api/v1/timestamp" + timestampChainFile := mkfile(tsaChain.Payload, td, t) + return timestampServerURL, timestampChainFile, tsaServer.Close +} diff --git a/test/gencert/main.go b/test/gencert/main.go deleted file mode 100644 index 6ba336f13b0..00000000000 --- a/test/gencert/main.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2023 The Sigstore Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// code is based on the snippet https://gist.github.com/shaneutt/5e1995295cff6721c89a71d13a71c251 -// with a permissive (Public Domain) License. - -package main - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "log" - "math/big" - "net" - "os" - "time" -) - -func main() { - // set up our CA certificate - ca := &x509.Certificate{ - SerialNumber: big.NewInt(2019), - Subject: pkix.Name{ - Organization: []string{"CA Company, INC."}, - Country: []string{"US"}, - Province: []string{""}, - Locality: []string{"San Francisco"}, - StreetAddress: []string{"Golden Gate Bridge"}, - PostalCode: []string{"94016"}, - }, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(10, 0, 0), - IsCA: true, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning /*, x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth */}, - KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - BasicConstraintsValid: true, - EmailAddresses: []string{"ca@example.com"}, - } - - // create our private and public key - caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096) - if err != nil { - log.Fatal(err) - } - - // create the CA - caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey) - if err != nil { - log.Fatal(err) - } - - // pem encode - caCertFile, err := os.OpenFile("cacert.pem", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - log.Fatalf("unable to write to cacert.pem: %v", err) - } - err = pem.Encode(caCertFile, &pem.Block{ - Type: "CERTIFICATE", - Bytes: caBytes, - }) - if err != nil { - log.Fatalf("unable to write to cacert.pem: %v", err) - } - - caPrivKeyFile, err := os.OpenFile("ca-key.pem", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0400) - if err != nil { - log.Fatal(err) - } - defer caPrivKeyFile.Close() - err = pem.Encode(caPrivKeyFile, &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(caPrivKey), - }) - if err != nil { - log.Fatalf("unable to create to ca-key.pem: %v", err) //nolint:gocritic - } - - // set up our server certificate - cert := &x509.Certificate{ - SerialNumber: big.NewInt(2019), - Subject: pkix.Name{ - Organization: []string{"Company, INC."}, - Country: []string{"US"}, - Province: []string{""}, - Locality: []string{"San Francisco"}, - StreetAddress: []string{"Golden Gate Bridge"}, - PostalCode: []string{"94016"}, - }, - IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback}, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(10, 0, 0), - SubjectKeyId: []byte{1, 2, 3, 4, 6}, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning /* x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth */}, - KeyUsage: x509.KeyUsageDigitalSignature, - EmailAddresses: []string{"xyz@nosuchprovider.com"}, - DNSNames: []string{"next.hugeunicorn.xyz"}, - } - - certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096) - if err != nil { - log.Fatal(err) - } - - certBytes, err := x509.CreateCertificate(rand.Reader, cert, ca, &certPrivKey.PublicKey, caPrivKey) - if err != nil { - log.Fatal(err) - } - - certFile, err := os.OpenFile("cert.pem", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) - if err != nil { - log.Fatal(err) - } - defer certFile.Close() - err = pem.Encode(certFile, &pem.Block{ - Type: "CERTIFICATE", - Bytes: certBytes, - }) - if err != nil { - log.Fatalf("failed to encode cert: %v", err) - } - - keyFile, err := os.OpenFile("key.pem", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0400) - if err != nil { - log.Fatal(err) - } - defer keyFile.Close() - err = pem.Encode(keyFile, &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey), - }) - if err != nil { - log.Fatalf("failed to encode private key: %v", err) - } -} diff --git a/test/helpers.go b/test/helpers.go new file mode 100644 index 00000000000..86f7cdd9296 --- /dev/null +++ b/test/helpers.go @@ -0,0 +1,374 @@ +// +// Copyright 2024 The Sigstore Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build e2e + +package test + +import ( + "context" + "crypto" + "net/http/httptest" + "net/url" + "os" + "path/filepath" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" + "github.com/google/go-containerregistry/pkg/registry" + "github.com/google/go-containerregistry/pkg/v1/random" + "github.com/google/go-containerregistry/pkg/v1/remote" + + // Initialize all known client auth plugins + _ "k8s.io/client-go/plugin/pkg/client/auth" + + "github.com/sigstore/cosign/v2/cmd/cosign/cli/options" + cliverify "github.com/sigstore/cosign/v2/cmd/cosign/cli/verify" + "github.com/sigstore/cosign/v2/pkg/cosign" + ociremote "github.com/sigstore/cosign/v2/pkg/oci/remote" + sigs "github.com/sigstore/cosign/v2/pkg/signature" +) + +const ( + rekorURL = "http://127.0.0.1:3000" + fulcioURL = "http://127.0.0.1:5555" + certID = "foo@bar.com" +) + +var keyPass = []byte("hello") + +var passFunc = func(_ bool) ([]byte, error) { + return keyPass, nil +} + +var verify = func(keyRef, imageRef string, checkClaims bool, annotations map[string]interface{}, attachment string, skipTlogVerify bool) error { + cmd := cliverify.VerifyCommand{ + KeyRef: keyRef, + RekorURL: rekorURL, + CheckClaims: checkClaims, + Annotations: sigs.AnnotationsMap{Annotations: annotations}, + Attachment: attachment, + HashAlgorithm: crypto.SHA256, + MaxWorkers: 10, + IgnoreTlog: skipTlogVerify, + } + + args := []string{imageRef} + + return cmd.Exec(context.Background(), args) +} + +var verifyTSA = func(keyRef, imageRef string, checkClaims bool, annotations map[string]interface{}, attachment, tsaCertChain string, skipTlogVerify bool) error { + cmd := cliverify.VerifyCommand{ + KeyRef: keyRef, + RekorURL: rekorURL, + CheckClaims: checkClaims, + Annotations: sigs.AnnotationsMap{Annotations: annotations}, + Attachment: attachment, + HashAlgorithm: crypto.SHA256, + TSACertChainPath: tsaCertChain, + IgnoreTlog: skipTlogVerify, + MaxWorkers: 10, + } + + args := []string{imageRef} + + return cmd.Exec(context.Background(), args) +} + +var verifyKeylessTSA = func(imageRef string, tsaCertChain string, skipSCT bool, skipTlogVerify bool) error { + cmd := cliverify.VerifyCommand{ + CertVerifyOptions: options.CertVerifyOptions{ + CertOidcIssuerRegexp: ".*", + CertIdentityRegexp: ".*", + }, + RekorURL: rekorURL, + HashAlgorithm: crypto.SHA256, + TSACertChainPath: tsaCertChain, + IgnoreSCT: skipSCT, + IgnoreTlog: skipTlogVerify, + MaxWorkers: 10, + } + + args := []string{imageRef} + + return cmd.Exec(context.Background(), args) +} + +// Used to verify local images stored on disk +var verifyLocal = func(keyRef, path string, checkClaims bool, annotations map[string]interface{}, attachment string) error { + cmd := cliverify.VerifyCommand{ + KeyRef: keyRef, + RekorURL: rekorURL, + CheckClaims: checkClaims, + Annotations: sigs.AnnotationsMap{Annotations: annotations}, + Attachment: attachment, + HashAlgorithm: crypto.SHA256, + LocalImage: true, + MaxWorkers: 10, + } + + args := []string{path} + + return cmd.Exec(context.Background(), args) +} + +var verifyOffline = func(keyRef, imageRef string, checkClaims bool, annotations map[string]interface{}, attachment string) error { + cmd := cliverify.VerifyCommand{ + KeyRef: keyRef, + RekorURL: "notreal", + Offline: true, + CheckClaims: checkClaims, + Annotations: sigs.AnnotationsMap{Annotations: annotations}, + Attachment: attachment, + HashAlgorithm: crypto.SHA256, + MaxWorkers: 10, + } + + args := []string{imageRef} + + return cmd.Exec(context.Background(), args) +} + +var ro = &options.RootOptions{Timeout: options.DefaultTimeout} + +func keypair(t *testing.T, td string) (*cosign.KeysBytes, string, string) { + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + if err := os.Chdir(td); err != nil { + t.Fatal(err) + } + defer func() { + os.Chdir(wd) + }() + keys, err := cosign.GenerateKeyPair(passFunc) + if err != nil { + t.Fatal(err) + } + + privKeyPath := filepath.Join(td, "cosign.key") + if err := os.WriteFile(privKeyPath, keys.PrivateBytes, 0600); err != nil { + t.Fatal(err) + } + + pubKeyPath := filepath.Join(td, "cosign.pub") + if err := os.WriteFile(pubKeyPath, keys.PublicBytes, 0600); err != nil { + t.Fatal(err) + } + return keys, privKeyPath, pubKeyPath +} + +func importKeyPair(t *testing.T, td string) (*cosign.KeysBytes, string, string) { + + const validrsa1 = `-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAx5piWVlE62NnZ0UzJ8Z6oKiKOC4dbOZ1HsNhIRtqkM+Oq4G+ +25yq6P+0JU/Qvr9veOGEb3R/J9u8JBo+hv2i5X8OtgvP2V2pi6f1s6vK7L0+6uRb +4YTT/UdMshaVf97MgEqbq41Jf/cuvh+3AV0tZ1BpixZg4aXMKpY6HUP69lbsu27o +SUN1myMv7TSgZiV4CYs3l/gkEfpysBptWlcHRuw5RsB+C0RbjRtbJ/5VxmE/vd3M +lafd5t1WSpMb8yf0a84u5NFaXwZ7CweMfXeOddS0yb19ShSuW3PPRadruBM1mq15 +js9GfagPxDS75Imcs+fA62lWvHxEujTGjYHxawIDAQABAoIBAH+sgLwmHa9zJfEo +klAe5NFe/QpydN/ziXbkAnzqzH9URC3wD+TpkWj4JoK3Sw635NWtasjf+3XDV9S/ +9L7j/g5N91r6sziWcJykEsWaXXKQmm4lI6BdFjwsHyLKz1W7bZOiJXDWLu1rbrqu +DqEQuLoc9WXCKrYrFy0maoXNtfla/1p05kKN0bMigcnnyAQ+xBTwoyco4tkIz5se +IYxorz7qzXrkHQI+knz5BawmNe3ekoSaXUPoLoOR7TRTGsLteL5yukvWAi8S/0rE +gftC+PZCQpoQhSUYq7wXe7RowJ1f+kXb7HsSedOTfTSW1D/pUb/uW+CcRKig42ZI +I9H9TAECgYEA5XGBML6fJyWVqx64sHbUAjQsmQ0RwU6Zo7sqHIEPf6tYVYp7KtzK +KOfi8seOOL5FSy4pjCo11Dzyrh9bn45RNmtjSYTgOnVPSoCfuRNfOcpG+/wCHjYf +EjDvdrCpbg59kVUeaMeBDiyWAlM48HJAn8O7ez2U/iKQCyJmOIwFhSkCgYEA3rSz +Fi1NzqYWxWos4NBmg8iKcQ9SMkmPdgRLAs/WNnZJ8fdgJZwihevkXGytRGJEmav2 +GMKRx1g6ey8fjXTQH9WM8X/kJC5fv8wLHnUCH/K3Mcp9CYwn7PFvSnBr4kQoc/el +bURhcF1+/opEC8vNX/Wk3zAG7Xs1PREXlH2SIHMCgYBV/3kgwBH/JkM25EjtO1yz +hsLAivmAruk/SUO7c1RP0fVF+qW3pxHOyztxLALOmeJ3D1JbSubqKf377Zz17O3b +q9yHDdrNjnKtxhAX2n7ytjJs+EQC9t4mf1kB761RpvTBqFnBhCWHHocLUA4jcW9v +cnmu86IIrwO2aKpPv4vCIQKBgHU9gY3qOazRSOmSlJ+hdmZn+2G7pBTvHsQNTIPl +cCrpqNHl3crO4GnKHkT9vVVjuiOAIKU2QNJFwzu4Og8Y8LvhizpTjoHxm9x3iV72 +UDELcJ+YrqyJCTe2flUcy96o7Pbn50GXnwgtYD6WAW6IUszyn2ITgYIhu4wzZEt6 +s6O7AoGAPTKbRA87L34LMlXyUBJma+etMARIP1zu8bXJ7hSJeMcog8zaLczN7ruT +pGAaLxggvtvuncMuTrG+cdmsR9SafSFKRS92NCxhOUonQ+NP6mLskIGzJZoQ5JvQ +qGzRVIDGbNkrVHM0IsAtHRpC0rYrtZY+9OwiraGcsqUMLwwQdCA= +-----END RSA PRIVATE KEY-----` + + wd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + if err := os.Chdir(td); err != nil { + t.Fatal(err) + } + defer func() { + os.Chdir(wd) + }() + + err = os.WriteFile("validrsa1.key", []byte(validrsa1), 0600) + if err != nil { + t.Fatal(err) + } + + keys, err := cosign.ImportKeyPair("validrsa1.key", passFunc) + if err != nil { + t.Fatal(err) + } + + privKeyPath := filepath.Join(td, "import-cosign.key") + if err := os.WriteFile(privKeyPath, keys.PrivateBytes, 0600); err != nil { + t.Fatal(err) + } + + pubKeyPath := filepath.Join(td, "import-cosign.pub") + if err := os.WriteFile(pubKeyPath, keys.PublicBytes, 0600); err != nil { + t.Fatal(err) + } + return keys, privKeyPath, pubKeyPath + +} + +func mockStdin(contents, td string, t *testing.T) func() { + origin := os.Stdin + + p := mkfile(contents, td, t) + f, err := os.Open(p) + if err != nil { + t.Fatal(err) + } + os.Stdin = f + + return func() { os.Stdin = origin } +} + +func mkfile(contents, td string, t *testing.T) string { + f, err := os.CreateTemp(td, "") + if err != nil { + t.Fatal(err) + } + defer f.Close() + if _, err := f.Write([]byte(contents)); err != nil { + t.Fatal(err) + } + return f.Name() +} + +func mkfileWithExt(contents, td, ext string, t *testing.T) string { + f := mkfile(contents, td, t) + newName := f + ext + err := os.Rename(f, newName) + if err != nil { + t.Fatal(err) + } + return newName +} + +func mkimage(t *testing.T, n string) (name.Reference, *remote.Descriptor, func()) { + ref, err := name.ParseReference(n, name.WeakValidation) + if err != nil { + t.Fatal(err) + } + img, err := random.Image(512, 5) + if err != nil { + t.Fatal(err) + } + + regClientOpts := registryClientOpts(context.Background()) + + if err := remote.Write(ref, img, regClientOpts...); err != nil { + t.Fatal(err) + } + + remoteImage, err := remote.Get(ref, regClientOpts...) + if err != nil { + t.Fatal(err) + } + + cleanup := func() { + _ = remote.Delete(ref, regClientOpts...) + ref, _ := ociremote.SignatureTag(ref.Context().Digest(remoteImage.Descriptor.Digest.String()), ociremote.WithRemoteOptions(regClientOpts...)) + _ = remote.Delete(ref, regClientOpts...) + } + return ref, remoteImage, cleanup +} + +func mkimageindex(t *testing.T, n string) (name.Reference, *remote.Descriptor, func()) { + ref, err := name.ParseReference(n, name.WeakValidation) + if err != nil { + t.Fatal(err) + } + ii, err := random.Index(512, 5, 4) + if err != nil { + t.Fatal(err) + } + + regClientOpts := registryClientOpts(context.Background()) + + if err := remote.WriteIndex(ref, ii, regClientOpts...); err != nil { + t.Fatal(err) + } + + remoteIndex, err := remote.Get(ref, regClientOpts...) + if err != nil { + t.Fatal(err) + } + + cleanup := func() { + _ = remote.Delete(ref, regClientOpts...) + ref, _ := ociremote.SignatureTag(ref.Context().Digest(remoteIndex.Descriptor.Digest.String()), ociremote.WithRemoteOptions(regClientOpts...)) + _ = remote.Delete(ref, regClientOpts...) + } + return ref, remoteIndex, cleanup +} + +func must(err error, t *testing.T) { + t.Helper() + if err != nil { + t.Fatal(err) + } +} + +func mustErr(err error, t *testing.T) { + t.Helper() + if err == nil { + t.Fatal("expected error") + } +} + +func equals(v1, v2 interface{}, t *testing.T) { + if diff := cmp.Diff(v1, v2); diff != "" { + t.Error(diff) + } +} + +func reg(t *testing.T) (string, func()) { + repo := os.Getenv("COSIGN_TEST_REPO") + if repo != "" { + return repo, func() {} + } + + t.Log("COSIGN_TEST_REPO unset, using fake registry") + r := httptest.NewServer(registry.New()) + u, err := url.Parse(r.URL) + if err != nil { + t.Fatal(err) + } + return u.Host, r.Close +} + +func registryClientOpts(ctx context.Context) []remote.Option { + return []remote.Option{ + remote.WithAuthFromKeychain(authn.DefaultKeychain), + remote.WithContext(ctx), + } +} diff --git a/test/testdata/README.md b/test/testdata/README.md index 0f0c9a99c75..2469736fcf4 100644 --- a/test/testdata/README.md +++ b/test/testdata/README.md @@ -8,196 +8,3 @@ $ openssl req -key test/testdata/test_blob_private_key -x509 -days 3650 -out cer ``` and then you replace the old `test/testdata/test_blob_cert.pem` with the new certificate. - -# Generate Certificates and Certificate chain for Attach test -If the test/testdata/test_attach_leafcert.pem or test_attach_rootcert.pem or test_attach_certchain.pem expires than you can generate a new certificate and certificate using the given steps - -1. Generate a private key for Root certificate - -```shell -$ openssl genrsa -des3 -out rootCA.key 2048 -``` -2. Generate Root certificate - -```shell -$ openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1825 -out rootCA.crt -``` - in Certificate generation set following values - C = IN, ST = DEL, L = DEL, O = example.com, OU = sigstore, CN = sigstore, emailAddress = foo@example.com - -3. Generate Private key for Intermediate certificate - -```shell -$ openssl genrsa -out intermediateCA.key 2048 -``` -4. Generate CSR for Intermediate certificate - -```shell -$ openssl req -new -key intermediateCA.key -out intermediateCA.csr -``` - in Certificate generation set following values - C = IN, ST = DEL, L = DEL, O = example.com, OU = sigstore-sub, CN = sigstore-sub, emailAddress = foo@example.com - -5. Create intermediate certificate config file by name "intermediateConfigFile" having content - subjectKeyIdentifier = hash - authorityKeyIdentifier = keyid:always,issuer - basicConstraints = critical, CA:true, pathlen:0 - keyUsage = critical, digitalSignature, cRLSign, keyCertSign - -6. Create intermediate certificate - -```shell -$ openssl x509 -req -in intermediateCA.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -CAserial intermediateca.srl -out intermediateCA.crt -days 1825 -sha256 -extfile intermediateConfigFile -``` - -7. Create Private key for leaf certificate - -```shell -$ openssl genrsa -out leafCA.key 2048 -``` - -8. Create CSR for Leaf certificate - -```shell -$ openssl req -new -key leafCA.key -out leafCA.csr -``` - in certificate generation set following values - C = IN, ST = DEL, L = DEL, O = example.com, OU = sigstore-leaf, CN = sigstore-leaf, emailAddress = foo@example.com - -9. Create Leaf certificate config file by name "leafConfigFile" having content - authorityKeyIdentifier=keyid,issuer - basicConstraints=CA:FALSE - keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment - extendedKeyUsage=codeSigning - subjectAltName=email:copy - -10. Create Leaf certificate - -```shell -$ openssl x509 -req -in leafCA.csr -CA intermediateCA.crt -CAkey intermediateCA.key -CAcreateserial -CAserial leafca.srl -out leafCA.crt -days 1825 -sha256 -extfile leafConfigFile -``` - -11. Generate Certificate chain by concatenating Intermediate certificate and Root certificate - -```shell -$ cat intermediateCA.crt rootCA.crt > certChain.crt -``` - -12. copy private key of Leaf certificate to test/testdata/test_attach_private.key - -```shell -$ cp leafCA.key test/testdata/test_attach_private.key -``` - -13. copy root certificate to test/testdata/test_attach_rootcert.pem - -```shell -$ cp rootCA.crt test/testdata/test_attach_rootcert.pem -``` - -14. copy cert chain to test/testdata/test_attach_certchain.pem - -```shell -$ cp certChain.crt test/testdata/test_attach_certchain.pem -``` - -15. copy Leaf certificate to test/testdata/test_attach_leafcert.pem - -```shell -$ cp leafCA.crt test/testdata/test_attach_leafcert.pem -``` - -16. Generate a private key for Second Root certificate - -```shell -$ openssl genrsa -des3 -out secondrootCA.key 2048 -``` -17. Generate Second Root certificate - -```shell -$ openssl req -x509 -new -nodes -key secondrootCA.key -sha256 -days 1825 -out secondrootCA.crt -``` - in Certificate generation set following values - C = IN, ST = DEL, L = DEL, O = exampleclient.com, OU = sigstore, CN = sigstore, emailAddress = foo@exampleclient.com - -18. Generate Private key for second Intermediate certificate - -```shell -$ openssl genrsa -out secondintermediateCA.key 2048 -``` -19. Generate CSR for second Intermediate certificate - -```shell -$ openssl req -new -key secondintermediateCA.key -out secondintermediateCA.csr -``` - in Certificate generation set following values - C = IN, ST = DEL, L = DEL, O = exampleclient.com, OU = sigstore-sub, CN = sigstore-sub, emailAddress = foo@exampleclient.com - -20. Create intermediate certificate config file by name "intermediateConfigFile" having content - subjectKeyIdentifier = hash - authorityKeyIdentifier = keyid:always,issuer - basicConstraints = critical, CA:true, pathlen:0 - keyUsage = critical, digitalSignature, cRLSign, keyCertSign - -21. Create intermediate certificate - -```shell -$ openssl x509 -req -in secondintermediateCA.csr -CA secondrootCA.crt -CAkey secondrootCA.key -CAcreateserial -CAserial secondintermediateca.srl -out secondintermediateCA.crt -days 1825 -sha256 -extfile intermediateConfigFile -``` - -22. Create Private key for second leaf certificate - -```shell -$ openssl genrsa -out secondleafCA.key 2048 -``` - -23. Create CSR for second Leaf certificate - -```shell -$ openssl req -new -key secondleafCA.key -out secondleafCA.csr -``` - in certificate generation set following values - C = IN, ST = DEL, L = DEL, O = exampleclient.com, OU = sigstore-leaf, CN = sigstore-leaf, emailAddress = foo@exampleclient.com - -24. Create Leaf certificate config file by name "leafConfigFile" having content - authorityKeyIdentifier=keyid,issuer - basicConstraints=CA:FALSE - keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment - extendedKeyUsage=codeSigning - subjectAltName=email:copy - -25. Create Leaf certificate - -```shell -$ openssl x509 -req -in secondleafCA.csr -CA secondintermediateCA.crt -CAkey secondintermediateCA.key -CAcreateserial -CAserial secondleafca.srl -out secondleafCA.crt -days 1825 -sha256 -extfile leafConfigFile -``` - -26. Generate Certificate chain by concatenating second Intermediate certificate and second Root certificate - -```shell -$ cat secondintermediateCA.crt secondrootCA.crt > secondcertChain.crt -``` - -27. copy private key of second Leaf certificate to test/testdata/test_attach_second_private_key - -```shell -$ cp secondleafCA.key test/testdata/test_attach_second_private_key -``` - -28. copy root certificate to test/testdata/test_attach_second_rootcert.pem - -```shell -$ cp secondrootCA.crt test/testdata/test_attach_second_rootcert.pem -``` - -29. copy second cert chain to test/testdata/test_attach_second_certchain.pem - -```shell -$ cp secondcertChain.crt test/testdata/test_attach_second_certchain.pem -``` - -30. copy second Leaf certificate to test/testdata/test_attach_second_leafcert.pem - -```shell -$ cp secondleafCA.crt test/testdata/test_attach_second_leafcert.pem -``` diff --git a/test/testdata/gen-tsa-mtls-certs.sh b/test/testdata/gen-tsa-mtls-certs.sh deleted file mode 100755 index 8283b2c21be..00000000000 --- a/test/testdata/gen-tsa-mtls-certs.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright 2023 The Sigstore Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# This script generates certificates for testing -# mTLS connection from 'cosign' command to the TSA server. -# -# Requirements: -# step CLI tool - https://smallstep.com/docs/step-cli/ -# openssl command line tool: https://www.openssl.org/docs/manmaster/man1/openssl.html - -step certificate create "Sigstore Cosign Test CA" tsa-mtls-ca.crt tsa-mtls-ca.key --profile=root-ca --insecure --no-password --not-before=-10m --not-after=+87600h --force -step certificate create tsa-mtls-server tsa-mtls-server.crt tsa-mtls-server.key --san "server.example.com" --profile leaf --ca tsa-mtls-ca.crt --ca-key tsa-mtls-ca.key --insecure --no-password --not-before=-10m --not-after=+87600h --force -step certificate create tsa-mtls-client tsa-mtls-client.crt tsa-mtls-client.key --profile leaf --ca tsa-mtls-ca.crt --ca-key tsa-mtls-ca.key --insecure --no-password --not-before=-10m --not-after=+87600h --force -rm -fr tsa-mtls-ca.key - diff --git a/test/testdata/test_attach_certchain.pem b/test/testdata/test_attach_certchain.pem deleted file mode 100644 index 06ac9582360..00000000000 --- a/test/testdata/test_attach_certchain.pem +++ /dev/null @@ -1,48 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIECDCCAvCgAwIBAgIUW/XGBuFP99M7RhfzNG8/VYpC8LYwDQYJKoZIhvcNAQEL -BQAwgYUxCzAJBgNVBAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEU -MBIGA1UECgwLZXhhbXBsZS5jb20xETAPBgNVBAsMCHNpZ3N0b3JlMREwDwYDVQQD -DAhzaWdzdG9yZTEeMBwGCSqGSIb3DQEJARYPZm9vQGV4YW1wbGUuY29tMB4XDTIz -MDExNzExMjQxNFoXDTI4MDExNjExMjQxNFowgY0xCzAJBgNVBAYTAklOMQwwCgYD -VQQIDANERUwxDDAKBgNVBAcMA0RFTDEUMBIGA1UECgwLZXhhbXBsZS5jb20xFTAT -BgNVBAsMDHNpZ3N0b3JlLXN1YjEVMBMGA1UEAwwMc2lnc3RvcmUtc3ViMR4wHAYJ -KoZIhvcNAQkBFg9mb29AZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQC44+Yn+oMxy7rempqAz95ncbTN3QkwDz1YaIvTBudyMMGAOhVO -f3bW9ZGIXgyD3IDqxTPbmSrcaYod/6lndbVO55BikgY72zLtpN7s34RiO/P7NBDF -AjGugXXFVNBPrNpg7cR9UCzrKV0/YCT/bQc38GRbfK3rDW3CwDITer5H4HXCa4l8 -JEcTxFRCKV70UWvYBongOoYVUgK4x7noSBjhEQ5Ixbzeekx1Geu2VxtrsxjGFNL+ -qFMoiQmmQtuocdum14b3Tn4hZQSKx4vw+PzmZUwFBIfaZWOVKlsRrRq2SDHgec0P -HjH1bGoiJzN6oFyili7S2fqbgFYXYrrP+jtNAgMBAAGjZjBkMB0GA1UdDgQWBBQW -B/M1a+luUKSVQONO6VOwKpwS/DAfBgNVHSMEGDAWgBRm69SULL/iPHRJGshqmBcY -HUjz0jASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG -9w0BAQsFAAOCAQEAgyANtu4agUvdX2JiKn1yGM6lPi88lskwekY2iosodmqBy87H -KALdzANQ2KSNlR8YAIvf+pxxBi1LpwUuyN4EGa+pQO+jlVcBnjgWVGop4XOf/LsM -cBOP/tg02yQKRf6B1Poy10z+G+4Q7gFngoGzAS3Awg3Tp5k5hx74MVMUu4fCUppx -StVqF0rCmGACzOKQZMo/KrtU2E9pnW00MQQpf+1UXoFpxDtz+dgoZ16V0YQOgwYj -rTEVHVYWzZCATRMvkyM86AL4DjIthnRdhD0S87RMnafesn7h0eiF/OZ8MDadxfcG -A5F1aE+z+uXWV5AH81meqRyC+gKwvUxEu7dprw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIID7TCCAtWgAwIBAgIUD2ekQvcqyU64eTDfQ5aTYL8IA/4wDQYJKoZIhvcNAQEL -BQAwgYUxCzAJBgNVBAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEU -MBIGA1UECgwLZXhhbXBsZS5jb20xETAPBgNVBAsMCHNpZ3N0b3JlMREwDwYDVQQD -DAhzaWdzdG9yZTEeMBwGCSqGSIb3DQEJARYPZm9vQGV4YW1wbGUuY29tMB4XDTIz -MDExNzExMjE0MVoXDTI4MDExNjExMjE0MVowgYUxCzAJBgNVBAYTAklOMQwwCgYD -VQQIDANERUwxDDAKBgNVBAcMA0RFTDEUMBIGA1UECgwLZXhhbXBsZS5jb20xETAP -BgNVBAsMCHNpZ3N0b3JlMREwDwYDVQQDDAhzaWdzdG9yZTEeMBwGCSqGSIb3DQEJ -ARYPZm9vQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAqwQjQeFHlWSIWhMfWSkBWySDdla4G8FJK6XqvD/XmrRtzNV/t133+m3y6sRs -giXN1Ak1fh7jcfZ1WzXXBiLXi6tUJheZhvhMeqqTLodDPcFZaAQKvLgvKou+rtx1 -Kg9qPiuQ2xK/cYTpGiCNrOZf9Vz/L0SLc/L0dM/pTwdySYKrKmWNnVynzPrI4HVF -qrEpesTVZuHdysm8bSc/TLNkOu29BqROsdicReVJCvinONbJk+CseumDnd2hxST7 -WFjARQHpiMMynRmb7eW/6jt3wT6oYvpFhOhQxLVoLuLsmxMURRDXlkzHdIdtuVyW -/qylgQGPHUgyRyYiIGbeoTiW7wIDAQABo1MwUTAdBgNVHQ4EFgQUZuvUlCy/4jx0 -SRrIapgXGB1I89IwHwYDVR0jBBgwFoAUZuvUlCy/4jx0SRrIapgXGB1I89IwDwYD -VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABteomMmnLg49fZ6X5qVZ -wgjNZ+nTfr36AIV2XLAlC3BIwAz0ZuvlGtkGjyGKevjFGwWf+XCOf0K44/UChxoJ -VVJlJvYADJsO0Rleafg2FmejlS+GvXRomgHpJBQJJqlDfM7C7esScBzUXu1pS8hf -PvvUz+gK8UHyI26BaAsBwnRH8O/ceJgjJcgGeCsQJJ+779ao+38RfnkWjkdCjIbu -rtS3+e1zb3mJqR4Xs7rMVccsbchidh/X2ZrsgXpfXyRF6KXxMgteXqdrZt21ZC4Q -8vl389E9ikWnpLMHouZcYv9IcFAuXcOBfz4ES+aOzRBnvmsmaQ6N3gillQpza8y4 -Zg== ------END CERTIFICATE----- diff --git a/test/testdata/test_attach_leafcert.pem b/test/testdata/test_attach_leafcert.pem deleted file mode 100644 index 1d93d9af459..00000000000 --- a/test/testdata/test_attach_leafcert.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEGDCCAwCgAwIBAgIUJHDn2ZYAsfge8QUcXmItoqgQpZcwDQYJKoZIhvcNAQEL -BQAwgY0xCzAJBgNVBAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEU -MBIGA1UECgwLZXhhbXBsZS5jb20xFTATBgNVBAsMDHNpZ3N0b3JlLXN1YjEVMBMG -A1UEAwwMc2lnc3RvcmUtc3ViMR4wHAYJKoZIhvcNAQkBFg9mb29AZXhhbXBsZS5j -b20wHhcNMjMwMTE3MTEzNTI4WhcNMjgwMTE2MTEzNTI4WjCBjzELMAkGA1UEBhMC -SU4xDDAKBgNVBAgMA0RFTDEMMAoGA1UEBwwDREVMMRQwEgYDVQQKDAtleGFtcGxl -LmNvbTEWMBQGA1UECwwNc2lnc3RvcmUtbGVhZjEWMBQGA1UEAwwNc2lnc3RvcmUt -bGVhZjEeMBwGCSqGSIb3DQEJARYPZm9vQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsA5mQ+nqq83irr3Kg1DSZkX/KRQQoLW+cAyt -wSnRcr6QiJy8I2snWSE6UxGtFouTOM1qEYq8yj5QD7dhf3mGgv0eQ/Etk8KMNYsw -8IG/zsYlidrOSBdHEn3YSamZUwRajYRSGjTmxj40sigkouEPdeebeuduKynH3dF3 -m4Q2C6J754xpcXpa/5g2CkMAdmMLVeOkV3dHC2chFjS3gXnHBX4tFODS05jXim2H -aGFYP1RILlCmN5oARkxsAGV5DiZx5lE8rRqk9dYJvQiNEnbJek/rpJiY9wc0DvJk -Uq/dWdfuB0JvXp8DKB9IMzf1QzoPfLwiRYflMSlI7cjFr2RoyQIDAQABo2wwajAf -BgNVHSMEGDAWgBQWB/M1a+luUKSVQONO6VOwKpwS/DAJBgNVHRMEAjAAMAsGA1Ud -DwQEAwIE8DATBgNVHSUEDDAKBggrBgEFBQcDAzAaBgNVHREEEzARgQ9mb29AZXhh -bXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBAEq4DmlYkFDgUSIafo1ELzwdz6X0 -0hHaPQ6xJND3FRbsDu8qGcXNPLxjUXgEI/LJoRornMwt0RWIOyRKLPu+xGJf262i -RrZXA0NMyHat68STkI+CvAFH1v6e6eZmSMrbTDP6kdYeyxbnAQwPEawyiPjcNkDA -11rsDxm2gvLcKzBnVbvmD76JGvNwHgzV75z8bmp+XwMkErObJI8SyNUbk0d8SeUu -DBjarwaj1YObBvc2aC9ABwnbVxFWef5LTX9i1umr6L4aecYX2FNLl+6ZLNsOn/wO -SvayuhPKB5inMEhGG+DQOu0EFsgcqF+g9ADD3U1ZkqSq5jEvEDm+o9ScS+w= ------END CERTIFICATE----- diff --git a/test/testdata/test_attach_private_key b/test/testdata/test_attach_private_key deleted file mode 100644 index b7ef9b51414..00000000000 --- a/test/testdata/test_attach_private_key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAsA5mQ+nqq83irr3Kg1DSZkX/KRQQoLW+cAytwSnRcr6QiJy8 -I2snWSE6UxGtFouTOM1qEYq8yj5QD7dhf3mGgv0eQ/Etk8KMNYsw8IG/zsYlidrO -SBdHEn3YSamZUwRajYRSGjTmxj40sigkouEPdeebeuduKynH3dF3m4Q2C6J754xp -cXpa/5g2CkMAdmMLVeOkV3dHC2chFjS3gXnHBX4tFODS05jXim2HaGFYP1RILlCm -N5oARkxsAGV5DiZx5lE8rRqk9dYJvQiNEnbJek/rpJiY9wc0DvJkUq/dWdfuB0Jv -Xp8DKB9IMzf1QzoPfLwiRYflMSlI7cjFr2RoyQIDAQABAoIBAFsAJmYGO9FwCzKN -UWcM2KQanChMgcfACV57fzhv+B4aWDT05t5b3avZW/9iDJixrnhW3POSRcE38kQd -Ypz0YM3GLeWqfQd6MOTgPHykZFNp4i9eVO+4cHkjaS+yJVlez7uEYLfBDmP79Vr9 -GurB8C7ed2RQyYYwA2opgmx1K0ZZawYTyHDQxXTvJGLVk/0swAr0yiKS2ExGJZI3 -n59fuEc6L7Ubf/CA41WyO6BVx03WH1PokDzgZyx1wSfhSOsvk3sld1/V7L24HLHj -ayb/VL1z4vU/cVi3c28DZOYVLAlMVEEYSYZwRdQ732d8cYGYrJoXlII6XdWuj83n -lbGJInECgYEA5kcTGb+rRvBIwouVhgDjzmDyzd8VsArigD1G4wOh7LYazinDgxXL -Q2rNQsUlbrG1tqv6Jm49n8ZrbkOD66I4x7588zOxVmV+Hl+6jhA7ISpkc/tKxk+H -9OFbfU/KnCB6cFoXR9dd5Hvdu2Q6Nimugf+xZXtVdQnO65furLQGbNUCgYEAw7jV -CWC9w0SfMTfpjzSRTFSSH2y2io/d/koS6hcOH6XU17H+4sggoicgRPsg83LPkWkg -vmUE5PxanpxQU8tfPJncM/jFQDzzbaC6pzaxAfExc5ZFnmrxWgxHVVXQArcH8mTl -H+94OZCqv7nqUxWhDxia/gKHgF0RCJAR089a9iUCgYEAku+jNnjg94D3THv4yuri -cZvXEppYol4vrRhslQqKVhrU+9wWTxym+Lu7gfF+MyXeB1OxaLhLRho8Dr2x/bcj -eAEKhbzkWXalhQgcZ+3fbQg51O/yBJxW6mCqGknBxOHMfshdto+r79FB6QLJSipK -mdToAxMxsl6x1A68UyMEPokCgYB98y208TpstHY1OCPm8g8mra2y50S4+kgDYiu1 -1MxT9WV4wKSjz+GgN8l+WpUj1RhaHOrjWyLBMNwoAbN3mQJafzDDiS12X0LPo4U6 -IenatBn8phF7FprmNcyZz7UiaiKFDASefn5BnSUkaEGw4dRZYJ4tI/eK1Vkmx3+R -bHi+uQKBgFkauPtQ51M92Ah1Nc/ikcOS65aG2A3VDtoFSveeV1kGALbvV8CjSVlc -ZM+gseUUkp8RVWvQAAURvxAzDFsYaHeMrKKToOIORPOg0Pk8HNICPJWM8echHfZ8 -BAlVZ3K6i+q3pxzk/awMR8QCSubO62B0XvKZs17+p0uU5WBU+P7F ------END RSA PRIVATE KEY----- diff --git a/test/testdata/test_attach_rootcert.pem b/test/testdata/test_attach_rootcert.pem deleted file mode 100644 index 38a226cd217..00000000000 --- a/test/testdata/test_attach_rootcert.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIID7TCCAtWgAwIBAgIUD2ekQvcqyU64eTDfQ5aTYL8IA/4wDQYJKoZIhvcNAQEL -BQAwgYUxCzAJBgNVBAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEU -MBIGA1UECgwLZXhhbXBsZS5jb20xETAPBgNVBAsMCHNpZ3N0b3JlMREwDwYDVQQD -DAhzaWdzdG9yZTEeMBwGCSqGSIb3DQEJARYPZm9vQGV4YW1wbGUuY29tMB4XDTIz -MDExNzExMjE0MVoXDTI4MDExNjExMjE0MVowgYUxCzAJBgNVBAYTAklOMQwwCgYD -VQQIDANERUwxDDAKBgNVBAcMA0RFTDEUMBIGA1UECgwLZXhhbXBsZS5jb20xETAP -BgNVBAsMCHNpZ3N0b3JlMREwDwYDVQQDDAhzaWdzdG9yZTEeMBwGCSqGSIb3DQEJ -ARYPZm9vQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAqwQjQeFHlWSIWhMfWSkBWySDdla4G8FJK6XqvD/XmrRtzNV/t133+m3y6sRs -giXN1Ak1fh7jcfZ1WzXXBiLXi6tUJheZhvhMeqqTLodDPcFZaAQKvLgvKou+rtx1 -Kg9qPiuQ2xK/cYTpGiCNrOZf9Vz/L0SLc/L0dM/pTwdySYKrKmWNnVynzPrI4HVF -qrEpesTVZuHdysm8bSc/TLNkOu29BqROsdicReVJCvinONbJk+CseumDnd2hxST7 -WFjARQHpiMMynRmb7eW/6jt3wT6oYvpFhOhQxLVoLuLsmxMURRDXlkzHdIdtuVyW -/qylgQGPHUgyRyYiIGbeoTiW7wIDAQABo1MwUTAdBgNVHQ4EFgQUZuvUlCy/4jx0 -SRrIapgXGB1I89IwHwYDVR0jBBgwFoAUZuvUlCy/4jx0SRrIapgXGB1I89IwDwYD -VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABteomMmnLg49fZ6X5qVZ -wgjNZ+nTfr36AIV2XLAlC3BIwAz0ZuvlGtkGjyGKevjFGwWf+XCOf0K44/UChxoJ -VVJlJvYADJsO0Rleafg2FmejlS+GvXRomgHpJBQJJqlDfM7C7esScBzUXu1pS8hf -PvvUz+gK8UHyI26BaAsBwnRH8O/ceJgjJcgGeCsQJJ+779ao+38RfnkWjkdCjIbu -rtS3+e1zb3mJqR4Xs7rMVccsbchidh/X2ZrsgXpfXyRF6KXxMgteXqdrZt21ZC4Q -8vl389E9ikWnpLMHouZcYv9IcFAuXcOBfz4ES+aOzRBnvmsmaQ6N3gillQpza8y4 -Zg== ------END CERTIFICATE----- diff --git a/test/testdata/test_attach_second_certchain.pem b/test/testdata/test_attach_second_certchain.pem deleted file mode 100644 index 3bf4e7dd5f0..00000000000 --- a/test/testdata/test_attach_second_certchain.pem +++ /dev/null @@ -1,49 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEIDCCAwigAwIBAgIUP2BVjdyg37MRM6Xa2l0TSF2/+rcwDQYJKoZIhvcNAQEL -BQAwgZExCzAJBgNVBAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEa -MBgGA1UECgwRZXhhbXBsZWNsaWVudC5jb20xETAPBgNVBAsMCHNpZ3N0b3JlMREw -DwYDVQQDDAhzaWdzdG9yZTEkMCIGCSqGSIb3DQEJARYVZm9vQGV4YW1wbGVjbGll -bnQuY29tMB4XDTI0MDExODEwMTE0N1oXDTI5MDExNjEwMTE0N1owgZkxCzAJBgNV -BAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEaMBgGA1UECgwRZXhh -bXBsZWNsaWVudC5jb20xFTATBgNVBAsMDHNpZ3N0b3JlLXN1YjEVMBMGA1UEAwwM -c2lnc3RvcmUtc3ViMSQwIgYJKoZIhvcNAQkBFhVmb29AZXhhbXBsZWNsaWVudC5j -b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz37o+ObXK1b8/RqEv -MaQQp6X1aD1FptsW+X07ESqZz0XiJToGMdE2ETlFza9VyyeMwJF6YcFK3wfsakB0 -QG40nMt7KI8cT/sFot8WzQTVTSe0HfALvdOnY4OBM5mZPmQlemWfpipsTIiCyIXp -I2tWSjR7rtDlw2VW5N+wpyn+qid+EZRm/ZGzQhwAcH0u+di+6ynt2rdcSn1RMsRr -vGB0/yqbboRsBh5pWNl/42mCoWFRFk3vsUvxKDieTDdTy53vqi7MNB3wDZ3TRj1w -StExZYMzXeRi2VxSzt0k1u/YGgHmQOjPmxHSbQ929V+fXjw3xR06z77ojDxCCQvH -cLJxAgMBAAGjZjBkMB0GA1UdDgQWBBShacFO3pe6fgps4IcgbDV5zS5cZTAfBgNV -HSMEGDAWgBS6b9p3peGUOXzfDnq3w7NAlKX+dDASBgNVHRMBAf8ECDAGAQH/AgEA -MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAHnds5GMnQOX8QddM -1fqpacdBOS2FhkyNGBmAramSNAEnfYPp7lZqn/TjCytUsiNPliiXpp+LF8a8pZvD -xjayyKiEbHitJdvsMf/kP8uxgv4SdiT96ycDwHCAt1obgG71ywoi9nbBAkuTep5n -+PYB8G0cwCAvyNQE0sOUXYqHHMRwAI5ke13nqWBxDBrx12iTpCL/910XUhpSVlXX -Al8zx2LT7scRu83pZBPFvr9j7IexlinhMH37xgAVXa6BPpATvvAXZg5gn1gtYAex -Af79/eiJn6zJXnF066dXW7OBpV/cILPkBciyC5Il8UMukEM5I36XH4NqPBd/JBPd -VRrmug== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEBTCCAu2gAwIBAgIUKv9OVy7IcTL6gvqPRcJZKIX0/ucwDQYJKoZIhvcNAQEL -BQAwgZExCzAJBgNVBAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEa -MBgGA1UECgwRZXhhbXBsZWNsaWVudC5jb20xETAPBgNVBAsMCHNpZ3N0b3JlMREw -DwYDVQQDDAhzaWdzdG9yZTEkMCIGCSqGSIb3DQEJARYVZm9vQGV4YW1wbGVjbGll -bnQuY29tMB4XDTI0MDExODEwMDkzM1oXDTI5MDExNjEwMDkzM1owgZExCzAJBgNV -BAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEaMBgGA1UECgwRZXhh -bXBsZWNsaWVudC5jb20xETAPBgNVBAsMCHNpZ3N0b3JlMREwDwYDVQQDDAhzaWdz -dG9yZTEkMCIGCSqGSIb3DQEJARYVZm9vQGV4YW1wbGVjbGllbnQuY29tMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn9FAPZNON2O7k/fYqpI894aUf3ur -LyJsEx6RhC7JYjumc4VLvDA9vSauXeM4fQ+YDaOs9K8FujDbAFGsrltXBBA/Czsd -Ml/OMkkn5ZzDkTXqFXVer31M0fNLWMoAZ9q7c601ndRuTLDp8Ka3aR2Caj2W7VgO -mGDUhgaVo31Omx4TM5ydnSLGewRfw/7nFveHBGKaRG+tVF1zLZwTESGG5/lV8Vq1 -cSctqK9kDwfNFzZKjpIsEDoT2L3ZosevtC3lY07KqvtKEOS9QWTZSRECO0Tzescn -OP9Unb+miTTSl1tuu/gDULhYaCfDZu8bxIRaLt3tHV7falwbvUzO3wO8MQIDAQAB -o1MwUTAdBgNVHQ4EFgQUum/ad6XhlDl83w56t8OzQJSl/nQwHwYDVR0jBBgwFoAU -um/ad6XhlDl83w56t8OzQJSl/nQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B -AQsFAAOCAQEAVPnYFFhYdAquC2g5k3mA+brhBuxFY+Rf9COE3u4lREJsXxjudsBR -1dE+n9Zla2andkEyu9KQZlTb0WE7WfxDgKEtYCzRYhvtj9xFKCjzncH1w4Z2iN/R -n8qmBWSFN5se0J/7uGsZ1YIcR8BsbkofmgnvBydUSXjNY7lbDOkY79gm/wykgdLe -TNOnRz+z6ofEkduBsxwSyY1Ck9CrRNklcfEW6YY0Re4FzUpBIWgeWqmxhIqeOWFI -eH7n4hqOrENTN7/GJvZH8PnjQj4Nx27cj+EW6xh5QMjYXkaxFFgGyMs/8AaresZZ -geieV/J2gfe+zBuG5h5cJ+9kR26d/0InUA== ------END CERTIFICATE----- diff --git a/test/testdata/test_attach_second_leafcert.pem b/test/testdata/test_attach_second_leafcert.pem deleted file mode 100644 index f5ec7c98de8..00000000000 --- a/test/testdata/test_attach_second_leafcert.pem +++ /dev/null @@ -1,25 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIENjCCAx6gAwIBAgIUEc3nCZYvXtlMHd+tLM7x4zueFYgwDQYJKoZIhvcNAQEL -BQAwgZkxCzAJBgNVBAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEa -MBgGA1UECgwRZXhhbXBsZWNsaWVudC5jb20xFTATBgNVBAsMDHNpZ3N0b3JlLXN1 -YjEVMBMGA1UEAwwMc2lnc3RvcmUtc3ViMSQwIgYJKoZIhvcNAQkBFhVmb29AZXhh -bXBsZWNsaWVudC5jb20wHhcNMjQwMTE4MTAxNDA2WhcNMjkwMTE2MTAxNDA2WjCB -mzELMAkGA1UEBhMCSU4xDDAKBgNVBAgMA0RFTDEMMAoGA1UEBwwDREVMMRowGAYD -VQQKDBFleGFtcGxlY2xpZW50LmNvbTEWMBQGA1UECwwNc2lnc3RvcmUtbGVhZjEW -MBQGA1UEAwwNc2lnc3RvcmUtbGVhZjEkMCIGCSqGSIb3DQEJARYVZm9vQGV4YW1w -bGVjbGllbnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5MdM -RkWjtryLneymMdkz+I8IB8t/6LSwS7M2olnQYV1byLopYraDxCTxIeaizoeeyoK+ -F5HfwXid0X4vM/5PAdSjEq2Cf//+nnVJKQnAC96SCwQmUrKkzM69ASWsTCO3dK3d -iRTI/g6031tMDfkXj2nDDjnBGAl/YIuNSY4mUccrTaGfFbIHjCvQ3zHdsYi90vrx -miKaQRCwe2quE82ZcokkrxLQMM+qUha1TkJdKXAR28E2nZcnjcQFI5hrMMrc+PNb -CB20pZP/Mnw8tED7r+r/0LDs7GruCP+w/FH5K5E4cvyScMXYZ/TUTDv2rrTXzA8u -Rhq7xnEt9k7CQnpNSwIDAQABo3IwcDAfBgNVHSMEGDAWgBShacFO3pe6fgps4Icg -bDV5zS5cZTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DATBgNVHSUEDDAKBggrBgEF -BQcDAzAgBgNVHREEGTAXgRVmb29AZXhhbXBsZWNsaWVudC5jb20wDQYJKoZIhvcN -AQELBQADggEBAIJpBNO2/P3TYgp15vnBCCyDa9+BVy4C4CokM7COn24KXY8B6POT -Bk84/lI0Z6nKaSSO7wTWUkkf1UQy7eYuHPCyUMdaupbxnUtPj5+oQIh8X3wuuNzn -nfP++RBBx4qZwTCgdOj89CSw5eGSpPGEjPKacApn9cmZ6bk0ZHlKMQQRyRQ0tFdu -45Ou0r6LwZcf3kcZfSgEDzV2Kz5RKj1UID9vhQShgG0eNesfnSKY0NYxWb6u1tfZ -wHOx2N6wZ0g9tfvJxUcvkLlyg4AC6AOWQ6QINEjtJ4cq5VLkOJg2qjp7+NgfZJFl -yeAczjg+cqeX3jg+/iO9/GTokvXSHRTH85g= ------END CERTIFICATE----- diff --git a/test/testdata/test_attach_second_private_key b/test/testdata/test_attach_second_private_key deleted file mode 100644 index 6fd0a614935..00000000000 --- a/test/testdata/test_attach_second_private_key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEA5MdMRkWjtryLneymMdkz+I8IB8t/6LSwS7M2olnQYV1byLop -YraDxCTxIeaizoeeyoK+F5HfwXid0X4vM/5PAdSjEq2Cf//+nnVJKQnAC96SCwQm -UrKkzM69ASWsTCO3dK3diRTI/g6031tMDfkXj2nDDjnBGAl/YIuNSY4mUccrTaGf -FbIHjCvQ3zHdsYi90vrxmiKaQRCwe2quE82ZcokkrxLQMM+qUha1TkJdKXAR28E2 -nZcnjcQFI5hrMMrc+PNbCB20pZP/Mnw8tED7r+r/0LDs7GruCP+w/FH5K5E4cvyS -cMXYZ/TUTDv2rrTXzA8uRhq7xnEt9k7CQnpNSwIDAQABAoIBACZhtU840b2PplDJ -ahyE1y5FONCt+HifD9CzcWANd2NOWV60tMrF2hdnJzlLy1ag9Cf/hUrJA2QfC0Mh -S2QKr1CcTvuMNo+o8Bu/i5Wh+CFFpvTILnHDXNirepQdsOlZOKcPoFImNY5CA2BR -ndHeT3CVCs9xKw8QUNlusDZ97bncQhiTJ6Upqmd4432BVxk3uAvPuKlgjeyXQ2hQ -iYdNfWe+qQEqkOCV+JcDQDNXOb+l6bvfhECK/92xhCNu0U8hca5xy5nQlD/epJBn -ojzX+lyQxIs+T/sQF3IbN6pVZ5IGjgPx3LUw/0GSEAr++7SupFIJjgNDrDoOn7GA -7QufhOkCgYEA8g7IZd3PO4t3GK7bnX8yBOuGufwPkJlA2YS/Uh2cbW+YXPQEKqn8 -HQysBjJCuxRnsOkAXoV3u3Ym/eph8Cz+FVqiPt33hYy81ZGGJyOmBUu/9C/Lghxt -D2NbJ7kNFEWe+qvoa13Z7r2VzQdBKjagoMPed3lkEovF14MNzvU2ZKUCgYEA8fS1 -aJ2gcxShL4enPUXykxpbUP52VYJYO75ZLDwQmvlqiNK/EC8ZMCldMrFf1nMDFaG4 -tx+pIizE3rA89ZRTPsj19G3aU1C/B+/LQFM/r+ZpdyaLs5BnPPaPYIEPt6Ad34/O -lxazRv6+FHJJ1EbZlmhsUXOdmMYvtYlJ4N83Fy8CgYBqPBixtI7OKGCFwcB7OCbg -x+niWIEQSmKO1NcPGBXeZdrt+N6XRvFyYmxhb8+fwc3cc/aIhXVOHgXw7Nw9B9If -1x5cDxkiUOlTpkHFjbzAmEVPy2Y63XT0Cvwny+y0l/W1OJuR+6e5QxWq3WM5Pq5y -wGQz9V/5T8Tt2APIcBCGTQKBgHJElpQktU0ENieDUklOyoQMk4nJ00sI9vCoMecB -Kvp1xol9tjxHcgbb0icJu/BEevVxXhImArOgHw3of7Gfbj0dnYLlipGEdeOirQPh -DRfeonpiGuIf1ZHmA8qYyTp4hQM7IF8cmmhyEIUJgLKfD03IXTeOeaRYHNoIT3rD -EHqDAoGADyUkL/6rQcHR04MgGCQX8qkQRDXlfUZps8idu5dnFmoRdzaHdITlWZgJ -V+deNWItvFmEWQdyt8aQ7r+SKbtVLw2R56KKXbMDPx2HxRyomHQymJBX/E7BSKj7 -w02PrkC96WLnupa3RvXW35RJilTiVrPoCHhr2s/SxCXVNrACLeA= ------END RSA PRIVATE KEY----- diff --git a/test/testdata/test_attach_second_rootcert.pem b/test/testdata/test_attach_second_rootcert.pem deleted file mode 100644 index 5afb1cd9bcb..00000000000 --- a/test/testdata/test_attach_second_rootcert.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEBTCCAu2gAwIBAgIUKv9OVy7IcTL6gvqPRcJZKIX0/ucwDQYJKoZIhvcNAQEL -BQAwgZExCzAJBgNVBAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEa -MBgGA1UECgwRZXhhbXBsZWNsaWVudC5jb20xETAPBgNVBAsMCHNpZ3N0b3JlMREw -DwYDVQQDDAhzaWdzdG9yZTEkMCIGCSqGSIb3DQEJARYVZm9vQGV4YW1wbGVjbGll -bnQuY29tMB4XDTI0MDExODEwMDkzM1oXDTI5MDExNjEwMDkzM1owgZExCzAJBgNV -BAYTAklOMQwwCgYDVQQIDANERUwxDDAKBgNVBAcMA0RFTDEaMBgGA1UECgwRZXhh -bXBsZWNsaWVudC5jb20xETAPBgNVBAsMCHNpZ3N0b3JlMREwDwYDVQQDDAhzaWdz -dG9yZTEkMCIGCSqGSIb3DQEJARYVZm9vQGV4YW1wbGVjbGllbnQuY29tMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn9FAPZNON2O7k/fYqpI894aUf3ur -LyJsEx6RhC7JYjumc4VLvDA9vSauXeM4fQ+YDaOs9K8FujDbAFGsrltXBBA/Czsd -Ml/OMkkn5ZzDkTXqFXVer31M0fNLWMoAZ9q7c601ndRuTLDp8Ka3aR2Caj2W7VgO -mGDUhgaVo31Omx4TM5ydnSLGewRfw/7nFveHBGKaRG+tVF1zLZwTESGG5/lV8Vq1 -cSctqK9kDwfNFzZKjpIsEDoT2L3ZosevtC3lY07KqvtKEOS9QWTZSRECO0Tzescn -OP9Unb+miTTSl1tuu/gDULhYaCfDZu8bxIRaLt3tHV7falwbvUzO3wO8MQIDAQAB -o1MwUTAdBgNVHQ4EFgQUum/ad6XhlDl83w56t8OzQJSl/nQwHwYDVR0jBBgwFoAU -um/ad6XhlDl83w56t8OzQJSl/nQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B -AQsFAAOCAQEAVPnYFFhYdAquC2g5k3mA+brhBuxFY+Rf9COE3u4lREJsXxjudsBR -1dE+n9Zla2andkEyu9KQZlTb0WE7WfxDgKEtYCzRYhvtj9xFKCjzncH1w4Z2iN/R -n8qmBWSFN5se0J/7uGsZ1YIcR8BsbkofmgnvBydUSXjNY7lbDOkY79gm/wykgdLe -TNOnRz+z6ofEkduBsxwSyY1Ck9CrRNklcfEW6YY0Re4FzUpBIWgeWqmxhIqeOWFI -eH7n4hqOrENTN7/GJvZH8PnjQj4Nx27cj+EW6xh5QMjYXkaxFFgGyMs/8AaresZZ -geieV/J2gfe+zBuG5h5cJ+9kR26d/0InUA== ------END CERTIFICATE----- diff --git a/test/testdata/tsa-mtls-ca.crt b/test/testdata/tsa-mtls-ca.crt deleted file mode 100644 index a00e5807868..00000000000 --- a/test/testdata/tsa-mtls-ca.crt +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBiDCCAS6gAwIBAgIRAO5WlKM6/pv+v71d34HJ45owCgYIKoZIzj0EAwIwIjEg -MB4GA1UEAxMXU2lnc3RvcmUgQ29zaWduIFRlc3QgQ0EwHhcNMjMwNzE4MTkxNTM1 -WhcNMzMwNzE1MTkyNTM1WjAiMSAwHgYDVQQDExdTaWdzdG9yZSBDb3NpZ24gVGVz -dCBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH5fbJwVYaesvVy7eFkYnFfH -D8+VhQ9e7dOheDToOrHE6jPTHsJAI5n1ZJ5rbeSGkyi5Lk9LrFUy2HoTrKVkp+2j -RTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQW -BBQsoauxeQZNuzRFNlBbRpzmzTNX+jAKBggqhkjOPQQDAgNIADBFAiBsLBlOee4Y -uVLiu2nYRviEjJT+h/6Q+llfMIBTuEeAcwIhALb2uCAVtHbqKgoQiKpFG1jfUVTB -q85P2Vh4ZDfm7oOZ ------END CERTIFICATE----- diff --git a/test/testdata/tsa-mtls-client.crt b/test/testdata/tsa-mtls-client.crt deleted file mode 100644 index 0dc8f5b5751..00000000000 --- a/test/testdata/tsa-mtls-client.crt +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIByjCCAXCgAwIBAgIRAPGICdzqCMndm6pzcoTJ9ZUwCgYIKoZIzj0EAwIwIjEg -MB4GA1UEAxMXU2lnc3RvcmUgQ29zaWduIFRlc3QgQ0EwHhcNMjMwNzE4MTkxNTM1 -WhcNMzMwNzE1MTkyNTM1WjAaMRgwFgYDVQQDEw90c2EtbXRscy1jbGllbnQwWTAT -BgcqhkjOPQIBBggqhkjOPQMBBwNCAAQCh1LwmYHZsP7X4WYu/1+L1t1BNNmfznmn -IsDuiHzlpXP4wUR5aVK8lPLnn1RSvjQfRs4II7DJKzXhIHCfOLTqo4GOMIGLMA4G -A1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYD -VR0OBBYEFAeeFbpqHUgM/5reONOvh8XVdwnUMB8GA1UdIwQYMBaAFCyhq7F5Bk27 -NEU2UFtGnObNM1f6MBoGA1UdEQQTMBGCD3RzYS1tdGxzLWNsaWVudDAKBggqhkjO -PQQDAgNIADBFAiEAgvAPOyJr6n1Sb8y+lkYgIw9ErP0z93aSXpIAiheV1wMCIC9R -ISx675FDUb4biKcIXCjtrIZ1a3CXXyM4F4d/gw74 ------END CERTIFICATE----- diff --git a/test/testdata/tsa-mtls-client.key b/test/testdata/tsa-mtls-client.key deleted file mode 100644 index 669f67e305c..00000000000 --- a/test/testdata/tsa-mtls-client.key +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIGcXqJ5agofVh5OXlI4ZDoskEVCuyXM2JCLNj50YL777oAoGCCqGSM49 -AwEHoUQDQgAEAodS8JmB2bD+1+FmLv9fi9bdQTTZn855pyLA7oh85aVz+MFEeWlS -vJTy559UUr40H0bOCCOwySs14SBwnzi06g== ------END EC PRIVATE KEY----- diff --git a/test/testdata/tsa-mtls-server.crt b/test/testdata/tsa-mtls-server.crt deleted file mode 100644 index 387fdc38d78..00000000000 --- a/test/testdata/tsa-mtls-server.crt +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIBzDCCAXKgAwIBAgIQOBXrIyEghpZ2u7iDE+G72DAKBggqhkjOPQQDAjAiMSAw -HgYDVQQDExdTaWdzdG9yZSBDb3NpZ24gVGVzdCBDQTAeFw0yMzA3MTgxOTE1MzVa -Fw0zMzA3MTUxOTI1MzVaMBoxGDAWBgNVBAMTD3RzYS1tdGxzLXNlcnZlcjBZMBMG -ByqGSM49AgEGCCqGSM49AwEHA0IABBrc24F3Sian36yIwOlpAHqgm4cKSI5rUhIl -t+cfZsXNL9MUk95kQkSqJAQeSjCex5DT8wbiZJiyClA2ZI3y1JSjgZEwgY4wDgYD -VR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNV -HQ4EFgQUzsrb4Q+upQcIlr9oz1Hia3Vt6hwwHwYDVR0jBBgwFoAULKGrsXkGTbs0 -RTZQW0ac5s0zV/owHQYDVR0RBBYwFIISc2VydmVyLmV4YW1wbGUuY29tMAoGCCqG -SM49BAMCA0gAMEUCIFg+tEezu068P7STsB1j8I27Roj1pYR636yjM7ae69r8AiEA -/T+0eFkFXVwQ/JuRwyakl3f1fVO5qh5337nzAxTOHCw= ------END CERTIFICATE----- diff --git a/test/testdata/tsa-mtls-server.key b/test/testdata/tsa-mtls-server.key deleted file mode 100644 index 84681da46db..00000000000 --- a/test/testdata/tsa-mtls-server.key +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIKb9jANtuLLxAxxmanMz4zAb/PTNpTIN19M6SeXf2p0GoAoGCCqGSM49 -AwEHoUQDQgAEGtzbgXdKJqffrIjA6WkAeqCbhwpIjmtSEiW35x9mxc0v0xST3mRC -RKokBB5KMJ7HkNPzBuJkmLIKUDZkjfLUlA== ------END EC PRIVATE KEY-----