...

Source file src/github.com/sigstore/cosign/v2/test/e2e_tsa_test.go

Documentation: github.com/sigstore/cosign/v2/test

     1  // Copyright 2024 The Sigstore Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //go:build e2e && cross
    16  
    17  package test
    18  
    19  import (
    20  	"context"
    21  	"crypto/x509"
    22  	"encoding/pem"
    23  	"net/http/httptest"
    24  	"path"
    25  	"path/filepath"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/secure-systems-lab/go-securesystemslib/encrypted"
    30  	"github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
    31  	"github.com/sigstore/cosign/v2/cmd/cosign/cli/sign"
    32  	cliverify "github.com/sigstore/cosign/v2/cmd/cosign/cli/verify"
    33  	"github.com/sigstore/cosign/v2/pkg/cosign"
    34  	tsaclient "github.com/sigstore/timestamp-authority/pkg/client"
    35  	tsaserver "github.com/sigstore/timestamp-authority/pkg/server"
    36  	"github.com/spf13/viper"
    37  )
    38  
    39  func TestTSAMTLS(t *testing.T) {
    40  	repo, stop := reg(t)
    41  	defer stop()
    42  	td := t.TempDir()
    43  
    44  	imgName := path.Join(repo, "cosign-tsa-mtls-e2e")
    45  
    46  	_, _, cleanup := mkimage(t, imgName)
    47  	defer cleanup()
    48  
    49  	pemRootRef, pemLeafRef, pemKeyRef := generateSigningKeys(t, td)
    50  
    51  	// Set up TSA server with TLS
    52  	timestampCACert, timestampServerCert, timestampServerKey, timestampClientCert, timestampClientKey := generateMTLSKeys(t, td)
    53  	timestampServerURL, timestampChainFile, tsaCleanup := setUpTSAServerWithTLS(t, td, timestampCACert, timestampServerKey, timestampServerCert)
    54  	t.Cleanup(tsaCleanup)
    55  
    56  	ko := options.KeyOpts{
    57  		KeyRef:          pemKeyRef,
    58  		PassFunc:        passFunc,
    59  		TSAServerURL:    timestampServerURL,
    60  		TSAClientCACert: timestampCACert,
    61  		TSAClientCert:   timestampClientCert,
    62  		TSAClientKey:    timestampClientKey,
    63  		TSAServerName:   "server.example.com",
    64  	}
    65  	so := options.SignOptions{
    66  		Upload:     true,
    67  		TlogUpload: false,
    68  		Cert:       pemLeafRef,
    69  		CertChain:  pemRootRef,
    70  	}
    71  	must(sign.SignCmd(ro, ko, so, []string{imgName}), t)
    72  
    73  	verifyCmd := cliverify.VerifyCommand{
    74  		IgnoreTlog:       true,
    75  		IgnoreSCT:        true,
    76  		CheckClaims:      true,
    77  		CertChain:        pemRootRef,
    78  		TSACertChainPath: timestampChainFile,
    79  		CertVerifyOptions: options.CertVerifyOptions{
    80  			CertIdentityRegexp:   ".*",
    81  			CertOidcIssuerRegexp: ".*",
    82  		},
    83  	}
    84  	must(verifyCmd.Exec(context.Background(), []string{imgName}), t)
    85  }
    86  
    87  func TestSignBlobTSAMTLS(t *testing.T) {
    88  	td := t.TempDir()
    89  	blob := time.Now().Format("Mon Jan 2 15:04:05 MST 2006")
    90  	blobPath := mkfile(blob, td, t)
    91  	timestampPath := filepath.Join(td, "timestamp.txt")
    92  	bundlePath := filepath.Join(td, "cosign.bundle")
    93  
    94  	_, privKey, pubKey := keypair(t, td)
    95  
    96  	// Set up TSA server with TLS
    97  	timestampCACert, timestampServerCert, timestampServerKey, timestampClientCert, timestampClientKey := generateMTLSKeys(t, td)
    98  	timestampServerURL, timestampChainFile, tsaCleanup := setUpTSAServerWithTLS(t, td, timestampCACert, timestampServerKey, timestampServerCert)
    99  	t.Cleanup(tsaCleanup)
   100  
   101  	signingKO := options.KeyOpts{
   102  		KeyRef:               privKey,
   103  		PassFunc:             passFunc,
   104  		TSAServerURL:         timestampServerURL,
   105  		TSAClientCACert:      timestampCACert,
   106  		TSAClientCert:        timestampClientCert,
   107  		TSAClientKey:         timestampClientKey,
   108  		TSAServerName:        "server.example.com",
   109  		RFC3161TimestampPath: timestampPath,
   110  		BundlePath:           bundlePath,
   111  	}
   112  	sig, err := sign.SignBlobCmd(ro, signingKO, blobPath, true, "", "", false)
   113  	must(err, t)
   114  
   115  	verifyKO := options.KeyOpts{
   116  		KeyRef:               pubKey,
   117  		TSACertChainPath:     timestampChainFile,
   118  		RFC3161TimestampPath: timestampPath,
   119  		BundlePath:           bundlePath,
   120  	}
   121  
   122  	verifyCmd := cliverify.VerifyBlobCmd{
   123  		KeyOpts: verifyKO,
   124  		SigRef:  string(sig),
   125  		CertVerifyOptions: options.CertVerifyOptions{
   126  			CertIdentityRegexp:   ".*",
   127  			CertOidcIssuerRegexp: ".*",
   128  		},
   129  		IgnoreTlog: true,
   130  	}
   131  	must(verifyCmd.Exec(context.Background(), blobPath), t)
   132  }
   133  
   134  func generateSigningKeys(t *testing.T, td string) (string, string, string) {
   135  	rootCert, rootKey, _ := GenerateRootCa()
   136  	pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
   137  	pemRootRef := mkfile(string(pemRoot), td, t)
   138  
   139  	leafCert, privKey, _ := GenerateLeafCert("xyz@nosuchprovider.com", "oidc-issuer", rootCert, rootKey)
   140  	pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
   141  	pemLeafRef := mkfile(string(pemLeaf), td, t)
   142  
   143  	x509Encoded, _ := x509.MarshalPKCS8PrivateKey(privKey)
   144  	encBytes, _ := encrypted.Encrypt(x509Encoded, keyPass)
   145  	keyPem := pem.EncodeToMemory(&pem.Block{
   146  		Type:  cosign.CosignPrivateKeyPemType,
   147  		Bytes: encBytes})
   148  	pemKeyRef := mkfile(string(keyPem), td, t)
   149  
   150  	return pemRootRef, pemLeafRef, pemKeyRef
   151  }
   152  
   153  func generateMTLSKeys(t *testing.T, td string) (string, string, string, string, string) {
   154  	rootCert, rootKey, _ := GenerateRootCa()
   155  	pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
   156  	pemRootRef := mkfile(string(pemRoot), td, t)
   157  
   158  	serverLeafCert, serverPrivKey, _ := GenerateLeafCertWithSubjectAlternateNames([]string{"server.example.com"}, nil, nil, nil, "oidc-issuer", rootCert, rootKey)
   159  	serverPemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: serverLeafCert.Raw})
   160  	serverPemLeafRef := mkfile(string(serverPemLeaf), td, t)
   161  	serverX509Encoded, _ := x509.MarshalPKCS8PrivateKey(serverPrivKey)
   162  	serverKeyPem := pem.EncodeToMemory(&pem.Block{
   163  		Type:  cosign.ECPrivateKeyPemType,
   164  		Bytes: serverX509Encoded})
   165  	serverPemKeyRef := mkfile(string(serverKeyPem), td, t)
   166  
   167  	clientLeafCert, clientPrivKey, _ := GenerateLeafCert("tsa-mtls-client", "oidc-issuer", rootCert, rootKey)
   168  	clientPemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: clientLeafCert.Raw})
   169  	clientPemLeafRef := mkfile(string(clientPemLeaf), td, t)
   170  	clientX509Encoded, _ := x509.MarshalPKCS8PrivateKey(clientPrivKey)
   171  	clientKeyPem := pem.EncodeToMemory(&pem.Block{
   172  		Type:  cosign.ECPrivateKeyPemType,
   173  		Bytes: clientX509Encoded})
   174  	clientPemKeyRef := mkfile(string(clientKeyPem), td, t)
   175  	return pemRootRef, serverPemLeafRef, serverPemKeyRef, clientPemLeafRef, clientPemKeyRef
   176  }
   177  
   178  func setUpTSAServerWithTLS(t *testing.T, td, timestampCACert, timestampServerKey, timestampServerCert string) (string, string, func()) {
   179  	viper.Set("timestamp-signer", "memory")
   180  	viper.Set("timestamp-signer-hash", "sha256")
   181  	viper.Set("disable-ntp-monitoring", true)
   182  	viper.Set("tls-host", "0.0.0.0")
   183  	viper.Set("tls-port", 3000)
   184  	viper.Set("tls-ca", timestampCACert)
   185  	viper.Set("tls-key", timestampServerKey)
   186  	viper.Set("tls-certificate", timestampServerCert)
   187  	tsaAPIServer := tsaserver.NewRestAPIServer("localhost", 3000, []string{"https"}, false, 10*time.Second, 10*time.Second)
   188  	tsaServer := httptest.NewServer(tsaAPIServer.GetHandler())
   189  	tsaClient, err := tsaclient.GetTimestampClient(tsaServer.URL)
   190  	must(err, t)
   191  	tsaChain, err := tsaClient.Timestamp.GetTimestampCertChain(nil)
   192  	must(err, t)
   193  	timestampServerURL := tsaServer.URL + "/api/v1/timestamp"
   194  	timestampChainFile := mkfile(tsaChain.Payload, td, t)
   195  	return timestampServerURL, timestampChainFile, tsaServer.Close
   196  }
   197  

View as plain text