@@ -21,16 +21,20 @@ import (
2121 "bytes"
2222 "context"
2323 "crypto"
24+ "crypto/ecdsa"
2425 "crypto/ed25519"
26+ "crypto/elliptic"
2527 "crypto/rand"
2628 "crypto/sha256"
2729 "crypto/x509"
30+ "crypto/x509/pkix"
2831 "encoding/base64"
2932 "encoding/hex"
3033 "encoding/json"
3134 "encoding/pem"
3235 "fmt"
3336 "io"
37+ "math/big"
3438 "net/http"
3539 "net/http/httptest"
3640 "net/url"
@@ -572,8 +576,7 @@ func downloadTSACerts(downloadDirectory string, tsaServer string) (string, strin
572576 return leafPath , intermediatePath , rootPath , nil
573577}
574578
575- func prepareTrustedRoot (t * testing.T , tsaURL string ) string {
576- downloadDirectory := t .TempDir ()
579+ func trustedRootCmd (t * testing.T , downloadDirectory , tsaURL string ) * trustedroot.CreateCmd {
577580 caPath := filepath .Join (downloadDirectory , "fulcio.crt.pem" )
578581 caFP , err := os .Create (caPath )
579582 must (err , t )
@@ -602,8 +605,22 @@ func prepareTrustedRoot(t *testing.T, tsaURL string) string {
602605 must (downloadFile (tsaURL + "/api/v1/timestamp/certchain" , tsaFP ), t )
603606 cmd .TSACertChainPath = []string {tsaPath }
604607 }
608+ return cmd
609+ }
610+
611+ func prepareTrustedRoot (t * testing.T , tsaURL string ) string {
612+ downloadDirectory := t .TempDir ()
613+ cmd := trustedRootCmd (t , downloadDirectory , tsaURL )
605614 must (cmd .Exec (context .TODO ()), t )
606- return out
615+ return cmd .Out
616+ }
617+
618+ func prepareTrustedRootWithSelfSignedCertificate (t * testing.T , certPath , tsaURL string ) string {
619+ td := t .TempDir ()
620+ cmd := trustedRootCmd (t , td , tsaURL )
621+ cmd .CertChain = append (cmd .CertChain , certPath )
622+ must (cmd .Exec (context .TODO ()), t )
623+ return cmd .Out
607624}
608625
609626func TestSignVerifyWithTUFMirror (t * testing.T ) {
@@ -889,8 +906,12 @@ func TestSignAttestVerifyBlobWithSigningConfig(t *testing.T) {
889906 mirror := tufServer .URL
890907 trustedRoot := prepareTrustedRoot (t , tsaServer .URL )
891908 signingConfigStr := prepareSigningConfig (t , fulcioURL , rekorURL , "unused" , tsaServer .URL + "/api/v1/timestamp" )
909+ sc , err := os .ReadFile (signingConfigStr )
910+ must (err , t )
911+ fmt .Println (string (sc ))
912+ fmt .Println (fulcioURL )
892913
893- _ , err : = newTUF (tufMirror , []targetInfo {
914+ _ , err = newTUF (tufMirror , []targetInfo {
894915 {
895916 name : "trusted_root.json" ,
896917 source : trustedRoot ,
@@ -1094,6 +1115,113 @@ func TestSignAttestVerifyContainerWithSigningConfig(t *testing.T) {
10941115 must (verifyAttestation .Exec (ctx , []string {imgName }), t )
10951116}
10961117
1118+ func TestSignVerifyContainerWithSigningConfigWithCertificate (t * testing.T ) {
1119+ tufLocalCache := t .TempDir ()
1120+ t .Setenv ("TUF_ROOT" , tufLocalCache )
1121+ viper .Set ("timestamp-signer" , "memory" )
1122+ viper .Set ("timestamp-signer-hash" , "sha256" )
1123+ tsaAPIServer := server .NewRestAPIServer ("localhost" , 0 , []string {"http" }, false , 10 * time .Second , 10 * time .Second )
1124+ tsaServer := httptest .NewServer (tsaAPIServer .GetHandler ())
1125+ t .Cleanup (tsaServer .Close )
1126+ tufMirror := t .TempDir ()
1127+ tufServer := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
1128+ http .FileServer (http .Dir (tufMirror )).ServeHTTP (w , r )
1129+ }))
1130+ mirror := tufServer .URL
1131+
1132+ cert , privKey , err := selfSignedCertificate ()
1133+ must (err , t )
1134+ keysDir := t .TempDir ()
1135+ privKeyPath := filepath .Join (keysDir , "priv.key" )
1136+ privDer , err := x509 .MarshalECPrivateKey (privKey )
1137+ must (err , t )
1138+ keyWriter , err := os .OpenFile (privKeyPath , os .O_WRONLY | os .O_CREATE , 0o600 )
1139+ must (err , t )
1140+ defer keyWriter .Close ()
1141+ block := & pem.Block {
1142+ Type : "EC PRIVATE KEY" ,
1143+ Bytes : privDer ,
1144+ }
1145+ must (pem .Encode (keyWriter , block ), t )
1146+
1147+ certPath := filepath .Join (keysDir , "cert.pem" )
1148+ certWriter , err := os .OpenFile (certPath , os .O_WRONLY | os .O_CREATE , 0o600 )
1149+ must (err , t )
1150+ defer certWriter .Close ()
1151+ block = & pem.Block {
1152+ Type : "CERTIFICATE" ,
1153+ Bytes : cert .Raw ,
1154+ }
1155+ must (pem .Encode (certWriter , block ), t )
1156+
1157+ keys , err := cosign .ImportKeyPair (privKeyPath , passFunc )
1158+ must (err , t )
1159+ importKeyPath := filepath .Join (keysDir , "import-priv.key" )
1160+ must (os .WriteFile (importKeyPath , keys .PrivateBytes , 0o600 ), t )
1161+
1162+ trustedRoot := prepareTrustedRootWithSelfSignedCertificate (t , certPath , tsaServer .URL )
1163+ signingConfigStr := prepareSigningConfig (t , fulcioURL , rekorURL , "unused" , tsaServer .URL + "/api/v1/timestamp" )
1164+
1165+ _ , err = newTUF (tufMirror , []targetInfo {
1166+ {
1167+ name : "trusted_root.json" ,
1168+ source : trustedRoot ,
1169+ },
1170+ {
1171+ name : "signing_config.v0.2.json" ,
1172+ source : signingConfigStr ,
1173+ },
1174+ })
1175+ must (err , t )
1176+
1177+ repo , stop := reg (t )
1178+ defer stop ()
1179+ imgName := path .Join (repo , "cosign-e2e" )
1180+
1181+ _ , _ , cleanup := mkimage (t , imgName )
1182+ defer cleanup ()
1183+
1184+ ctx := context .Background ()
1185+
1186+ rootPath := filepath .Join (tufMirror , "1.root.json" )
1187+ must (initialize .DoInitialize (ctx , rootPath , mirror ), t )
1188+
1189+ ko := options.KeyOpts {
1190+ NewBundleFormat : true ,
1191+ SkipConfirmation : true ,
1192+ KeyRef : importKeyPath ,
1193+ PassFunc : passFunc ,
1194+ }
1195+ trustedMaterial , err := cosign .TrustedRoot ()
1196+ must (err , t )
1197+ ko .TrustedMaterial = trustedMaterial
1198+ signingConfig , err := cosign .SigningConfig ()
1199+ must (err , t )
1200+ ko .SigningConfig = signingConfig
1201+
1202+ // Sign image with cert in bundle format
1203+ so := options.SignOptions {
1204+ Upload : true ,
1205+ NewBundleFormat : true ,
1206+ Key : importKeyPath ,
1207+ Cert : certPath ,
1208+ TlogUpload : false ,
1209+ }
1210+ must (sign .SignCmd (ctx , ro , ko , so , []string {imgName }), t )
1211+
1212+ // Verify image
1213+ cmd := cliverify.VerifyCommand {
1214+ CertVerifyOptions : options.CertVerifyOptions {
1215+ CertOidcIssuerRegexp : ".*" ,
1216+ CertIdentity :
"[email protected] " ,
1217+ },
1218+ NewBundleFormat : true ,
1219+ IgnoreSCT : true ,
1220+ }
1221+ args := []string {imgName }
1222+ must (cmd .Exec (ctx , args ), t )
1223+ }
1224+
10971225func TestSignVerifyWithSigningConfigWithKey (t * testing.T ) {
10981226 tufLocalCache := t .TempDir ()
10991227 t .Setenv ("TUF_ROOT" , tufLocalCache )
@@ -4369,3 +4497,31 @@ func TestAttestVerifyUploadFalse(t *testing.T) {
43694497 must (err , t )
43704498 assert .Contains (t , out .String (), fmt .Sprintf ("sha256:%s" , hex .EncodeToString (h .Sum (nil ))))
43714499}
4500+
4501+ func selfSignedCertificate () (* x509.Certificate , * ecdsa.PrivateKey , error ) {
4502+ priv , err := ecdsa .GenerateKey (elliptic .P256 (), rand .Reader )
4503+ if err != nil {
4504+ return nil , nil , err
4505+ }
4506+ ct := & x509.Certificate {
4507+ SerialNumber : big .NewInt (1 ),
4508+ Subject : pkix.Name {
4509+ CommonName : "self.signed.cert" ,
4510+ Organization : []string {"dev" },
4511+ },
4512+ EmailAddresses : []
string {
"[email protected] " },
4513+ NotBefore : time .Now ().Add (- 1 * time .Minute ),
4514+ NotAfter : time .Now ().Add (24 * time .Hour ),
4515+ KeyUsage : x509 .KeyUsageDigitalSignature ,
4516+ ExtKeyUsage : []x509.ExtKeyUsage {x509 .ExtKeyUsageCodeSigning },
4517+ }
4518+ certBytes , err := x509 .CreateCertificate (rand .Reader , ct , ct , & priv .PublicKey , priv )
4519+ if err != nil {
4520+ return nil , nil , err
4521+ }
4522+ cert , err := x509 .ParseCertificate (certBytes )
4523+ if err != nil {
4524+ return nil , nil , err
4525+ }
4526+ return cert , priv , nil
4527+ }
0 commit comments