Skip to content

Commit

Permalink
Refactor the tuf client code. (#1252)
Browse files Browse the repository at this point in the history
This is my attempt at refactoring the TUF client code to better
support the configuration modes we've recently added.

This also adds support for SIGSTORE_NO_CACHE, and eliminates most
writes to disk from cosign outside of cosign initialize.

I think these tests are about equivalent to what we had before, if not
a bit better. The coverage is at 72% and hits most non-sporadic errors.

Signed-off-by: Dan Lorenc <[email protected]>
  • Loading branch information
dlorenc authored Dec 28, 2021
1 parent dfc0347 commit 2e99320
Show file tree
Hide file tree
Showing 6 changed files with 426 additions and 384 deletions.
33 changes: 20 additions & 13 deletions cmd/cosign/cli/fulcio/fulcioroots/fulcioroots.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
package fulcioroots

import (
"bytes"
"context"
"crypto/x509"
"fmt"
"os"
"sync"

"github.com/pkg/errors"
"github.com/sigstore/cosign/pkg/cosign/tuf"
)

Expand All @@ -43,39 +42,47 @@ const (

func Get() *x509.CertPool {
rootsOnce.Do(func() {
roots = initRoots()
var err error
roots, err = initRoots()
if err != nil {
panic(err)
}
})
return roots
}

func initRoots() *x509.CertPool {
func initRoots() (*x509.CertPool, error) {
cp := x509.NewCertPool()
rootEnv := os.Getenv(altRoot)
if rootEnv != "" {
raw, err := os.ReadFile(rootEnv)
if err != nil {
panic(fmt.Sprintf("error reading root PEM file: %s", err))
return nil, errors.Wrap(err, "error reading root PEM file")
}
if !cp.AppendCertsFromPEM(raw) {
panic("error creating root cert pool")
return nil, errors.New("error creating root cert pool")
}
} else {
tuf, err := tuf.NewFromEnv(context.Background())
if err != nil {
return nil, errors.Wrap(err, "initializing tuf")
}
defer tuf.Close()
// Retrieve from the embedded or cached TUF root. If expired, a network
// call is made to update the root.
ctx := context.Background() // TODO: pass in context?
rootFound := false
for _, fulcioTarget := range []string{fulcioTargetStr, fulcioV1TargetStr} {
buf := tuf.ByteDestination{Buffer: &bytes.Buffer{}}
if err := tuf.GetTarget(ctx, fulcioTarget, &buf); err == nil {
b, err := tuf.GetTarget(fulcioTarget)
if err == nil {
rootFound = true
if !cp.AppendCertsFromPEM(buf.Bytes()) {
panic("error creating root cert pool")
if !cp.AppendCertsFromPEM(b) {
return nil, errors.New("error creating root cert pool")
}
}
}
if !rootFound {
panic("none of the Fulcio roots have been found")
return nil, errors.New("none of the Fulcio roots have been found")
}
}
return cp
return cp, nil
}
25 changes: 11 additions & 14 deletions cmd/cosign/cli/fulcio/fulcioverifier/fulcioverifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package fulcioverifier

import (
"bytes"
"context"
"crypto"
"crypto/x509"
Expand Down Expand Up @@ -44,18 +43,6 @@ var ctPublicKeyStr = `ctfe.pub`
// the SCT coming back from Fulcio.
const altCTLogPublicKeyLocation = "SIGSTORE_CT_LOG_PUBLIC_KEY_FILE"

func getCTPub() string {
ctx := context.Background() // TODO: pass in context?
buf := tuf.ByteDestination{Buffer: &bytes.Buffer{}}
// Retrieves the CT public key from the embedded or cached TUF root. If expired, makes a
// network call to retrieve the updated target.
if err := tuf.GetTarget(ctx, ctPublicKeyStr, &buf); err != nil {
fmt.Fprintln(os.Stderr, err)
panic("error retrieving CT public key")
}
return buf.String()
}

// verifySCT verifies the SCT against the Fulcio CT log public key.
// By default this comes from TUF, but you can override this (for test)
// purposes by using an env variable `SIGSTORE_CT_LOG_PUBLIC_KEY_FILE`. If using
Expand All @@ -69,8 +56,18 @@ func verifySCT(certPEM, rawSCT []byte) error {
var err error
rootEnv := os.Getenv(altCTLogPublicKeyLocation)
if rootEnv == "" {
ctx := context.TODO()
tuf, err := tuf.NewFromEnv(ctx)
if err != nil {
return err
}
defer tuf.Close()
ctPub, err := tuf.GetTarget(ctPublicKeyStr)
if err != nil {
return err
}
// Is there a reason why this must be ECDSA key?
pubKey, err = cosign.PemToECDSAKey([]byte(getCTPub()))
pubKey, err = cosign.PemToECDSAKey(ctPub)
if err != nil {
return errors.Wrap(err, "converting Public CT to ECDSAKey")
}
Expand Down
3 changes: 1 addition & 2 deletions cmd/cosign/cli/initialize/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,5 @@ func DoInitialize(ctx context.Context, root, mirror string) error {
return err
}

// Initialize and update the local SigStore root.
return tuf.Init(ctx, rootFileBytes, remote)
return tuf.Initialize(remote, rootFileBytes)
}
8 changes: 4 additions & 4 deletions pkg/cosign/tlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package cosign

import (
"bytes"
"context"
"crypto/sha256"
"encoding/base64"
Expand Down Expand Up @@ -46,11 +45,12 @@ var rekorTargetStr = `rekor.pub`
// GetRekorPub retrieves the rekor public key from the embedded or cached TUF root. If expired, makes a
// network call to retrieve the updated target.
func GetRekorPub(ctx context.Context) ([]byte, error) {
buf := tuf.ByteDestination{Buffer: &bytes.Buffer{}}
if err := tuf.GetTarget(ctx, rekorTargetStr, &buf); err != nil {
tuf, err := tuf.NewFromEnv(ctx)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
defer tuf.Close()
return tuf.GetTarget(rekorTargetStr)
}

// TLogUpload will upload the signature, public key and payload to the transparency log.
Expand Down
Loading

0 comments on commit 2e99320

Please sign in to comment.