Skip to content

Commit 650dc80

Browse files
authored
test: create fake TUF test root and create test SETs for verification (#1750)
* wip Signed-off-by: Asra Ali <[email protected]> add fake SET test Signed-off-by: Asra Ali <[email protected]> fix Signed-off-by: Asra Ali <[email protected]> fix test Signed-off-by: Asra Ali <[email protected]> fix Signed-off-by: Asra Ali <[email protected]> * address haydentherapper comments Signed-off-by: Asra Ali <[email protected]>
1 parent ea74133 commit 650dc80

File tree

2 files changed

+192
-4
lines changed

2 files changed

+192
-4
lines changed

pkg/cosign/tuf/testutils.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//
2+
// Copyright 2021 The Sigstore Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
package tuf
17+
18+
import (
19+
"context"
20+
"crypto/x509"
21+
"encoding/json"
22+
"io/ioutil"
23+
"net/http"
24+
"net/http/httptest"
25+
"os"
26+
"path/filepath"
27+
"testing"
28+
29+
"github.com/sigstore/sigstore/pkg/cryptoutils"
30+
"github.com/sigstore/sigstore/pkg/signature"
31+
"github.com/sigstore/sigstore/pkg/signature/options"
32+
"github.com/theupdateframework/go-tuf"
33+
)
34+
35+
type TestSigstoreRoot struct {
36+
Rekor signature.Verifier
37+
FulcioCertificate *x509.Certificate
38+
// TODO: Include a CTFE key if/when cosign verifies SCT.
39+
}
40+
41+
// This creates a new sigstore TUF repo whose signers can be used to create dynamic
42+
// signed Rekor entries.
43+
func NewSigstoreTufRepo(t *testing.T, root TestSigstoreRoot) (tuf.LocalStore, *tuf.Repo) {
44+
td := t.TempDir()
45+
ctx := context.Background()
46+
remote := tuf.FileSystemStore(td, nil)
47+
r, err := tuf.NewRepo(remote)
48+
if err != nil {
49+
t.Error(err)
50+
}
51+
if err := r.Init(false); err != nil {
52+
t.Error(err)
53+
}
54+
55+
for _, role := range []string{"root", "targets", "snapshot", "timestamp"} {
56+
if _, err := r.GenKey(role); err != nil {
57+
t.Error(err)
58+
}
59+
}
60+
targetsPath := filepath.Join(td, "staged", "targets")
61+
if err := os.MkdirAll(filepath.Dir(targetsPath), 0755); err != nil {
62+
t.Error(err)
63+
}
64+
// Add the rekor key target
65+
pk, err := root.Rekor.PublicKey(options.WithContext(ctx))
66+
if err != nil {
67+
t.Error(err)
68+
}
69+
b, err := x509.MarshalPKIXPublicKey(pk)
70+
if err != nil {
71+
t.Error(err)
72+
}
73+
rekorPath := "rekor.pub"
74+
rekorData := cryptoutils.PEMEncode(cryptoutils.PublicKeyPEMType, b)
75+
if err := ioutil.WriteFile(filepath.Join(targetsPath, rekorPath), rekorData, 0600); err != nil {
76+
t.Error(err)
77+
}
78+
scmRekor, err := json.Marshal(&sigstoreCustomMetadata{Sigstore: customMetadata{Usage: Rekor, Status: Active}})
79+
if err != nil {
80+
t.Error(err)
81+
}
82+
if err := r.AddTarget("rekor.pub", scmRekor); err != nil {
83+
t.Error(err)
84+
}
85+
// Add Fulcio Certificate information.
86+
fulcioPath := "fulcio.crt.pem"
87+
fulcioData := cryptoutils.PEMEncode(cryptoutils.CertificatePEMType, root.FulcioCertificate.Raw)
88+
if err := ioutil.WriteFile(filepath.Join(targetsPath, fulcioPath), fulcioData, 0600); err != nil {
89+
t.Error(err)
90+
}
91+
scmFulcio, err := json.Marshal(&sigstoreCustomMetadata{Sigstore: customMetadata{Usage: Fulcio, Status: Active}})
92+
if err != nil {
93+
t.Error(err)
94+
}
95+
if err := r.AddTarget(fulcioPath, scmFulcio); err != nil {
96+
t.Error(err)
97+
}
98+
if err := r.Snapshot(); err != nil {
99+
t.Error(err)
100+
}
101+
if err := r.Timestamp(); err != nil {
102+
t.Error(err)
103+
}
104+
if err := r.Commit(); err != nil {
105+
t.Error(err)
106+
}
107+
// Serve remote repository.
108+
s := httptest.NewServer(http.FileServer(http.Dir(filepath.Join(td, "repository"))))
109+
defer s.Close()
110+
111+
// Initialize with custom root.
112+
tufRoot := t.TempDir()
113+
t.Setenv("TUF_ROOT", tufRoot)
114+
meta, err := remote.GetMeta()
115+
if err != nil {
116+
t.Error(err)
117+
}
118+
rootBytes, ok := meta["root.json"]
119+
if !ok {
120+
t.Error(err)
121+
}
122+
if err := Initialize(ctx, s.URL, rootBytes); err != nil {
123+
t.Error(err)
124+
}
125+
return remote, r
126+
}

pkg/cosign/verify_test.go

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
package cosign
1616

1717
import (
18+
"bytes"
1819
"context"
1920
"crypto"
21+
"crypto/elliptic"
2022
"crypto/rand"
2123
"crypto/sha256"
2224
"crypto/x509"
@@ -26,15 +28,22 @@ import (
2628
"io"
2729
"strings"
2830
"testing"
31+
"time"
2932

33+
"github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer"
34+
"github.com/go-openapi/strfmt"
3035
v1 "github.com/google/go-containerregistry/pkg/v1"
3136
"github.com/in-toto/in-toto-golang/in_toto"
3237
"github.com/pkg/errors"
3338
"github.com/secure-systems-lab/go-securesystemslib/dsse"
39+
"github.com/sigstore/cosign/pkg/cosign/bundle"
40+
ctuf "github.com/sigstore/cosign/pkg/cosign/tuf"
3441
"github.com/sigstore/cosign/pkg/oci/static"
3542
"github.com/sigstore/cosign/pkg/types"
3643
"github.com/sigstore/cosign/test"
44+
rtypes "github.com/sigstore/rekor/pkg/types"
3745
"github.com/sigstore/sigstore/pkg/signature"
46+
"github.com/sigstore/sigstore/pkg/signature/options"
3847
"github.com/stretchr/testify/require"
3948
)
4049

@@ -167,8 +176,54 @@ func TestVerifyImageSignatureMultipleSubs(t *testing.T) {
167176
}
168177
}
169178

179+
func signEntry(ctx context.Context, t *testing.T, signer signature.Signer, entry bundle.RekorPayload) []byte {
180+
payload, err := json.Marshal(entry)
181+
if err != nil {
182+
t.Fatalf("marshalling error: %v", err)
183+
}
184+
canonicalized, err := jsoncanonicalizer.Transform(payload)
185+
if err != nil {
186+
t.Fatalf("canonicalizing error: %v", err)
187+
}
188+
signature, err := signer.SignMessage(bytes.NewReader(canonicalized), options.WithContext(ctx))
189+
if err != nil {
190+
t.Fatalf("signing error: %v", err)
191+
}
192+
return signature
193+
}
194+
195+
func CreateTestBundle(ctx context.Context, t *testing.T, rekor signature.Signer, leaf []byte) *bundle.RekorBundle {
196+
// generate log ID according to rekor public key
197+
pk, _ := rekor.PublicKey(nil)
198+
keyID, _ := getLogID(pk)
199+
pyld := bundle.RekorPayload{
200+
Body: base64.StdEncoding.EncodeToString(leaf),
201+
IntegratedTime: time.Now().Unix(),
202+
LogIndex: 693591,
203+
LogID: keyID,
204+
}
205+
// Sign with root.
206+
signature := signEntry(ctx, t, rekor, pyld)
207+
b := &bundle.RekorBundle{
208+
SignedEntryTimestamp: strfmt.Base64(signature),
209+
Payload: pyld,
210+
}
211+
return b
212+
}
213+
170214
func TestVerifyImageSignatureWithNoChain(t *testing.T) {
215+
ctx := context.Background()
171216
rootCert, rootKey, _ := test.GenerateRootCa()
217+
sv, _, err := signature.NewECDSASignerVerifier(elliptic.P256(), rand.Reader, crypto.SHA256)
218+
if err != nil {
219+
t.Fatalf("creating signer: %v", err)
220+
}
221+
testSigstoreRoot := ctuf.TestSigstoreRoot{
222+
Rekor: sv,
223+
FulcioCertificate: rootCert,
224+
}
225+
_, _ = ctuf.NewSigstoreTufRepo(t, testSigstoreRoot)
226+
172227
leafCert, privKey, _ := test.GenerateLeafCert("subject", "oidc-issuer", rootCert, rootKey)
173228
pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
174229

@@ -179,14 +234,21 @@ func TestVerifyImageSignatureWithNoChain(t *testing.T) {
179234
h := sha256.Sum256(payload)
180235
signature, _ := privKey.Sign(rand.Reader, h[:], crypto.SHA256)
181236

182-
ociSig, _ := static.NewSignature(payload, base64.StdEncoding.EncodeToString(signature), static.WithCertChain(pemLeaf, []byte{}))
237+
// Create a fake bundle
238+
pe, _ := proposedEntry(base64.StdEncoding.EncodeToString(signature), payload, pemLeaf)
239+
entry, _ := rtypes.NewEntry(pe[0])
240+
leaf, _ := entry.Canonicalize(ctx)
241+
rekorBundle := CreateTestBundle(ctx, t, sv, leaf)
242+
243+
opts := []static.Option{static.WithCertChain(pemLeaf, []byte{}), static.WithBundle(rekorBundle)}
244+
ociSig, _ := static.NewSignature(payload, base64.StdEncoding.EncodeToString(signature), opts...)
245+
183246
verified, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{}, &CheckOpts{RootCerts: rootPool})
184247
if err != nil {
185248
t.Fatalf("unexpected error while verifying signature, expected no error, got %v", err)
186249
}
187-
// TODO: Create fake bundle and test verification
188-
if verified == true {
189-
t.Fatalf("expected verified=false, got verified=true")
250+
if verified == false {
251+
t.Fatalf("expected verified=true, got verified=false")
190252
}
191253
}
192254

0 commit comments

Comments
 (0)