Skip to content

Commit

Permalink
test: create fake TUF test root and create test SETs for verification (
Browse files Browse the repository at this point in the history
…sigstore#1750)

* wip

Signed-off-by: Asra Ali <asraa@google.com>

add fake SET test

Signed-off-by: Asra Ali <asraa@google.com>

fix

Signed-off-by: Asra Ali <asraa@google.com>

fix test

Signed-off-by: Asra Ali <asraa@google.com>

fix

Signed-off-by: Asra Ali <asraa@google.com>

* address haydentherapper comments

Signed-off-by: Asra Ali <asraa@google.com>
  • Loading branch information
asraa authored and mlieberman85 committed May 6, 2022
1 parent 1491442 commit afde6ce
Show file tree
Hide file tree
Showing 2 changed files with 192 additions and 4 deletions.
126 changes: 126 additions & 0 deletions pkg/cosign/tuf/testutils.go
@@ -0,0 +1,126 @@
//
// Copyright 2021 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.

package tuf

import (
"context"
"crypto/x509"
"encoding/json"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"

"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature/options"
"github.com/theupdateframework/go-tuf"
)

type TestSigstoreRoot struct {
Rekor signature.Verifier
FulcioCertificate *x509.Certificate
// TODO: Include a CTFE key if/when cosign verifies SCT.
}

// This creates a new sigstore TUF repo whose signers can be used to create dynamic
// signed Rekor entries.
func NewSigstoreTufRepo(t *testing.T, root TestSigstoreRoot) (tuf.LocalStore, *tuf.Repo) {
td := t.TempDir()
ctx := context.Background()
remote := tuf.FileSystemStore(td, nil)
r, err := tuf.NewRepo(remote)
if err != nil {
t.Error(err)
}
if err := r.Init(false); err != nil {
t.Error(err)
}

for _, role := range []string{"root", "targets", "snapshot", "timestamp"} {
if _, err := r.GenKey(role); err != nil {
t.Error(err)
}
}
targetsPath := filepath.Join(td, "staged", "targets")
if err := os.MkdirAll(filepath.Dir(targetsPath), 0755); err != nil {
t.Error(err)
}
// Add the rekor key target
pk, err := root.Rekor.PublicKey(options.WithContext(ctx))
if err != nil {
t.Error(err)
}
b, err := x509.MarshalPKIXPublicKey(pk)
if err != nil {
t.Error(err)
}
rekorPath := "rekor.pub"
rekorData := cryptoutils.PEMEncode(cryptoutils.PublicKeyPEMType, b)
if err := ioutil.WriteFile(filepath.Join(targetsPath, rekorPath), rekorData, 0600); err != nil {
t.Error(err)
}
scmRekor, err := json.Marshal(&sigstoreCustomMetadata{Sigstore: customMetadata{Usage: Rekor, Status: Active}})
if err != nil {
t.Error(err)
}
if err := r.AddTarget("rekor.pub", scmRekor); err != nil {
t.Error(err)
}
// Add Fulcio Certificate information.
fulcioPath := "fulcio.crt.pem"
fulcioData := cryptoutils.PEMEncode(cryptoutils.CertificatePEMType, root.FulcioCertificate.Raw)
if err := ioutil.WriteFile(filepath.Join(targetsPath, fulcioPath), fulcioData, 0600); err != nil {
t.Error(err)
}
scmFulcio, err := json.Marshal(&sigstoreCustomMetadata{Sigstore: customMetadata{Usage: Fulcio, Status: Active}})
if err != nil {
t.Error(err)
}
if err := r.AddTarget(fulcioPath, scmFulcio); err != nil {
t.Error(err)
}
if err := r.Snapshot(); err != nil {
t.Error(err)
}
if err := r.Timestamp(); err != nil {
t.Error(err)
}
if err := r.Commit(); err != nil {
t.Error(err)
}
// Serve remote repository.
s := httptest.NewServer(http.FileServer(http.Dir(filepath.Join(td, "repository"))))
defer s.Close()

// Initialize with custom root.
tufRoot := t.TempDir()
t.Setenv("TUF_ROOT", tufRoot)
meta, err := remote.GetMeta()
if err != nil {
t.Error(err)
}
rootBytes, ok := meta["root.json"]
if !ok {
t.Error(err)
}
if err := Initialize(ctx, s.URL, rootBytes); err != nil {
t.Error(err)
}
return remote, r
}
70 changes: 66 additions & 4 deletions pkg/cosign/verify_test.go
Expand Up @@ -15,8 +15,10 @@
package cosign

import (
"bytes"
"context"
"crypto"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
Expand All @@ -26,15 +28,22 @@ import (
"io"
"strings"
"testing"
"time"

"github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer"
"github.com/go-openapi/strfmt"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/in-toto/in-toto-golang/in_toto"
"github.com/pkg/errors"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
"github.com/sigstore/cosign/pkg/cosign/bundle"
ctuf "github.com/sigstore/cosign/pkg/cosign/tuf"
"github.com/sigstore/cosign/pkg/oci/static"
"github.com/sigstore/cosign/pkg/types"
"github.com/sigstore/cosign/test"
rtypes "github.com/sigstore/rekor/pkg/types"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature/options"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -167,8 +176,54 @@ func TestVerifyImageSignatureMultipleSubs(t *testing.T) {
}
}

func signEntry(ctx context.Context, t *testing.T, signer signature.Signer, entry bundle.RekorPayload) []byte {
payload, err := json.Marshal(entry)
if err != nil {
t.Fatalf("marshalling error: %v", err)
}
canonicalized, err := jsoncanonicalizer.Transform(payload)
if err != nil {
t.Fatalf("canonicalizing error: %v", err)
}
signature, err := signer.SignMessage(bytes.NewReader(canonicalized), options.WithContext(ctx))
if err != nil {
t.Fatalf("signing error: %v", err)
}
return signature
}

func CreateTestBundle(ctx context.Context, t *testing.T, rekor signature.Signer, leaf []byte) *bundle.RekorBundle {
// generate log ID according to rekor public key
pk, _ := rekor.PublicKey(nil)
keyID, _ := getLogID(pk)
pyld := bundle.RekorPayload{
Body: base64.StdEncoding.EncodeToString(leaf),
IntegratedTime: time.Now().Unix(),
LogIndex: 693591,
LogID: keyID,
}
// Sign with root.
signature := signEntry(ctx, t, rekor, pyld)
b := &bundle.RekorBundle{
SignedEntryTimestamp: strfmt.Base64(signature),
Payload: pyld,
}
return b
}

func TestVerifyImageSignatureWithNoChain(t *testing.T) {
ctx := context.Background()
rootCert, rootKey, _ := test.GenerateRootCa()
sv, _, err := signature.NewECDSASignerVerifier(elliptic.P256(), rand.Reader, crypto.SHA256)
if err != nil {
t.Fatalf("creating signer: %v", err)
}
testSigstoreRoot := ctuf.TestSigstoreRoot{
Rekor: sv,
FulcioCertificate: rootCert,
}
_, _ = ctuf.NewSigstoreTufRepo(t, testSigstoreRoot)

leafCert, privKey, _ := test.GenerateLeafCert("subject", "oidc-issuer", rootCert, rootKey)
pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})

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

ociSig, _ := static.NewSignature(payload, base64.StdEncoding.EncodeToString(signature), static.WithCertChain(pemLeaf, []byte{}))
// Create a fake bundle
pe, _ := proposedEntry(base64.StdEncoding.EncodeToString(signature), payload, pemLeaf)
entry, _ := rtypes.NewEntry(pe[0])
leaf, _ := entry.Canonicalize(ctx)
rekorBundle := CreateTestBundle(ctx, t, sv, leaf)

opts := []static.Option{static.WithCertChain(pemLeaf, []byte{}), static.WithBundle(rekorBundle)}
ociSig, _ := static.NewSignature(payload, base64.StdEncoding.EncodeToString(signature), opts...)

verified, err := VerifyImageSignature(context.TODO(), ociSig, v1.Hash{}, &CheckOpts{RootCerts: rootPool})
if err != nil {
t.Fatalf("unexpected error while verifying signature, expected no error, got %v", err)
}
// TODO: Create fake bundle and test verification
if verified == true {
t.Fatalf("expected verified=false, got verified=true")
if verified == false {
t.Fatalf("expected verified=true, got verified=false")
}
}

Expand Down

0 comments on commit afde6ce

Please sign in to comment.