Skip to content

Commit

Permalink
Upgrade to TUF v2 client
Browse files Browse the repository at this point in the history
Swap the use of the go-tuf v0.7.0 client from sigstore/sigstore to the
v2.0.0 client from sigstore/sigstore-go. Sigstore-go provides a way to
check for a trusted root and automatically use it if available, but can
also fetch individual targets as needed if the provided TUF mirror does
not supply a trusted_root.json.

This change is intended to be backwards compatible and transparent.

TODO:
- e2e tests
- deprecate `cosign initialize`

Signed-off-by: Colleen Murphy <[email protected]>
  • Loading branch information
cmurphy committed Aug 21, 2024
1 parent 182f64b commit 07e1c38
Show file tree
Hide file tree
Showing 19 changed files with 407 additions and 213 deletions.
2 changes: 1 addition & 1 deletion cmd/cosign/cli/fulcio/fulcioverifier/fulcioverifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func NewSigner(ctx context.Context, ko options.KeyOpts, signer signature.SignerV
}

// Grab the PublicKeys for the CTFE, either from tuf or env.
pubKeys, err := cosign.GetCTLogPubs(ctx)
pubKeys, err := cosign.GetCTLogPubs()
if err != nil {
return nil, fmt.Errorf("getting CTFE public keys: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/cosign/cli/sign/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ func signerFromKeyRef(ctx context.Context, certPath, certChainPath, keyRef strin
return nil, err
}
if contains {
pubKeys, err := cosign.GetCTLogPubs(ctx)
pubKeys, err := cosign.GetCTLogPubs()
if err != nil {
return nil, fmt.Errorf("getting CTLog public keys: %w", err)
}
Expand Down
10 changes: 5 additions & 5 deletions cmd/cosign/cli/verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ type VerifyCommand struct {
ExperimentalOCI11 bool
}

func (c *VerifyCommand) loadTSACertificates(ctx context.Context) (*cosign.TSACertificates, error) {
func (c *VerifyCommand) loadTSACertificates() (*cosign.TSACertificates, error) {
if c.TSACertChainPath == "" && !c.UseSignedTimestamps {
return nil, fmt.Errorf("TSA certificate chain path not provided and use-signed-timestamps not set")
}
tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets)
tsaCertificates, err := cosign.GetTSACerts(c.TSACertChainPath)
if err != nil {
return nil, fmt.Errorf("unable to load TSA certificates: %w", err)
}
Expand Down Expand Up @@ -150,7 +150,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
}

if c.TSACertChainPath != "" || c.UseSignedTimestamps {
tsaCertificates, err := c.loadTSACertificates(ctx)
tsaCertificates, err := c.loadTSACertificates()
if err != nil {
return fmt.Errorf("unable to load TSA certificates: %w", err)
}
Expand All @@ -169,7 +169,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
}
// This performs an online fetch of the Rekor public keys, but this is needed
// for verifying tlog entries (both online and offline).
co.RekorPubKeys, err = cosign.GetRekorPubs(ctx)
co.RekorPubKeys, err = cosign.GetRekorPubs()
if err != nil {
return fmt.Errorf("getting Rekor public keys: %w", err)
}
Expand All @@ -185,7 +185,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {

// Ignore Signed Certificate Timestamp if the flag is set or a key is provided
if shouldVerifySCT(c.IgnoreSCT, c.KeyRef, c.Sk) {
co.CTLogPubKeys, err = cosign.GetCTLogPubs(ctx)
co.CTLogPubKeys, err = cosign.GetCTLogPubs()
if err != nil {
return fmt.Errorf("getting ctlog public keys: %w", err)
}
Expand Down
10 changes: 5 additions & 5 deletions cmd/cosign/cli/verify/verify_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ type VerifyAttestationCommand struct {
UseSignedTimestamps bool
}

func (c *VerifyAttestationCommand) loadTSACertificates(ctx context.Context) (*cosign.TSACertificates, error) {
func (c *VerifyAttestationCommand) loadTSACertificates() (*cosign.TSACertificates, error) {
if c.TSACertChainPath == "" && !c.UseSignedTimestamps {
return nil, fmt.Errorf("TSA certificate chain path not provided and use-signed-timestamps not set")
}
tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets)
tsaCertificates, err := cosign.GetTSACerts(c.TSACertChainPath)
if err != nil {
return nil, fmt.Errorf("unable to load TSA certificates: %w", err)
}
Expand Down Expand Up @@ -125,14 +125,14 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (e
}
// Ignore Signed Certificate Timestamp if the flag is set or a key is provided
if shouldVerifySCT(c.IgnoreSCT, c.KeyRef, c.Sk) {
co.CTLogPubKeys, err = cosign.GetCTLogPubs(ctx)
co.CTLogPubKeys, err = cosign.GetCTLogPubs()
if err != nil {
return fmt.Errorf("getting ctlog public keys: %w", err)
}
}

if c.TSACertChainPath != "" || c.UseSignedTimestamps {
tsaCertificates, err := c.loadTSACertificates(ctx)
tsaCertificates, err := c.loadTSACertificates()
if err != nil {
return fmt.Errorf("unable to load TSA certificates: %w", err)
}
Expand All @@ -151,7 +151,7 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (e
}
// This performs an online fetch of the Rekor public keys, but this is needed
// for verifying tlog entries (both online and offline).
co.RekorPubKeys, err = cosign.GetRekorPubs(ctx)
co.RekorPubKeys, err = cosign.GetRekorPubs()
if err != nil {
return fmt.Errorf("getting Rekor public keys: %w", err)
}
Expand Down
10 changes: 5 additions & 5 deletions cmd/cosign/cli/verify/verify_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ type VerifyBlobCmd struct {
IgnoreTlog bool
}

func (c *VerifyBlobCmd) loadTSACertificates(ctx context.Context) (*cosign.TSACertificates, error) {
func (c *VerifyBlobCmd) loadTSACertificates() (*cosign.TSACertificates, error) {
if c.TSACertChainPath == "" && !c.UseSignedTimestamps {
return nil, fmt.Errorf("either TSA certificate chain path must be provided or use-signed-timestamps must be set")
}
tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets)
tsaCertificates, err := cosign.GetTSACerts(c.TSACertChainPath)
if err != nil {
return nil, fmt.Errorf("unable to load TSA certificates: %w", err)
}
Expand Down Expand Up @@ -142,7 +142,7 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
return fmt.Errorf("either TSA certificate chain path must be provided or use-signed-timestamps must be set when using RFC3161 timestamp path")
}
if c.TSACertChainPath != "" || c.UseSignedTimestamps {
tsaCertificates, err := c.loadTSACertificates(ctx)
tsaCertificates, err := c.loadTSACertificates()
if err != nil {
return err
}
Expand All @@ -161,7 +161,7 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
}
// This performs an online fetch of the Rekor public keys, but this is needed
// for verifying tlog entries (both online and offline).
co.RekorPubKeys, err = cosign.GetRekorPubs(ctx)
co.RekorPubKeys, err = cosign.GetRekorPubs()
if err != nil {
return fmt.Errorf("getting Rekor public keys: %w", err)
}
Expand Down Expand Up @@ -294,7 +294,7 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {

// Ignore Signed Certificate Timestamp if the flag is set or a key is provided
if shouldVerifySCT(c.IgnoreSCT, c.KeyRef, c.Sk) {
co.CTLogPubKeys, err = cosign.GetCTLogPubs(ctx)
co.CTLogPubKeys, err = cosign.GetCTLogPubs()
if err != nil {
return fmt.Errorf("getting ctlog public keys: %w", err)
}
Expand Down
6 changes: 3 additions & 3 deletions cmd/cosign/cli/verify/verify_blob_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st
}

if c.TSACertChainPath != "" || c.UseSignedTimestamps {
tsaCertificates, err := cosign.GetTSACerts(ctx, c.TSACertChainPath, cosign.GetTufTargets)
tsaCertificates, err := cosign.GetTSACerts(c.TSACertChainPath)
if err != nil {
return fmt.Errorf("unable to load or get TSA certificates: %w", err)
}
Expand All @@ -179,7 +179,7 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st
}
// This performs an online fetch of the Rekor public keys, but this is needed
// for verifying tlog entries (both online and offline).
co.RekorPubKeys, err = cosign.GetRekorPubs(ctx)
co.RekorPubKeys, err = cosign.GetRekorPubs()
if err != nil {
return fmt.Errorf("getting Rekor public keys: %w", err)
}
Expand All @@ -192,7 +192,7 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st

// Ignore Signed Certificate Timestamp if the flag is set or a key is provided
if shouldVerifySCT(c.IgnoreSCT, c.KeyRef, c.Sk) {
co.CTLogPubKeys, err = cosign.GetCTLogPubs(ctx)
co.CTLogPubKeys, err = cosign.GetCTLogPubs()
if err != nil {
return fmt.Errorf("getting ctlog public keys: %w", err)
}
Expand Down
45 changes: 2 additions & 43 deletions internal/pkg/cosign/fulcio/fulcioroots/fulcioroots.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,10 @@
package fulcioroots

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

"github.com/sigstore/cosign/v2/pkg/cosign/env"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/fulcioroots"
"github.com/sigstore/cosign/v2/pkg/cosign"
)

var (
Expand Down Expand Up @@ -64,41 +59,5 @@ func ReInit() error {
}

func initRoots() (*x509.CertPool, *x509.CertPool, error) {
rootPool := x509.NewCertPool()
// intermediatePool should be nil if no intermediates are found
var intermediatePool *x509.CertPool

rootEnv := env.Getenv(env.VariableSigstoreRootFile)
if rootEnv != "" {
raw, err := os.ReadFile(rootEnv)
if err != nil {
return nil, nil, fmt.Errorf("error reading root PEM file: %w", err)
}
certs, err := cryptoutils.UnmarshalCertificatesFromPEM(raw)
if err != nil {
return nil, nil, fmt.Errorf("error unmarshalling certificates: %w", err)
}
for _, cert := range certs {
// root certificates are self-signed
if bytes.Equal(cert.RawSubject, cert.RawIssuer) {
rootPool.AddCert(cert)
} else {
if intermediatePool == nil {
intermediatePool = x509.NewCertPool()
}
intermediatePool.AddCert(cert)
}
}
} else {
var err error
rootPool, err = fulcioroots.Get()
if err != nil {
return nil, nil, err
}
intermediatePool, err = fulcioroots.GetIntermediates()
if err != nil {
return nil, nil, err
}
}
return rootPool, intermediatePool, nil
return cosign.GetFulcioCerts()
}
47 changes: 22 additions & 25 deletions pkg/cosign/ctlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@
package cosign

import (
"context"
"errors"
"fmt"
"os"

"github.com/sigstore/cosign/v2/pkg/cosign/env"
"github.com/sigstore/sigstore/pkg/tuf"
"github.com/sigstore/sigstore-go/pkg/root"
)

// This is the CT log public key target name
Expand All @@ -32,37 +30,36 @@ var ctPublicKeyStr = `ctfe.pub`
// By default the public keys comes from TUF, but you can override this for test
// purposes by using an env variable `SIGSTORE_CT_LOG_PUBLIC_KEY_FILE`. If using
// an alternate, the file can be PEM, or DER format.
func GetCTLogPubs(ctx context.Context) (*TrustedTransparencyLogPubKeys, error) {
func GetCTLogPubs() (*TrustedTransparencyLogPubKeys, error) {
publicKeys := NewTrustedTransparencyLogPubKeys()
altCTLogPub := env.Getenv(env.VariableSigstoreCTLogPublicKeyFile)

if altCTLogPub != "" {
raw, err := os.ReadFile(altCTLogPub)
if err != nil {
return nil, fmt.Errorf("error reading alternate CTLog public key file: %w", err)
}
if err := publicKeys.AddTransparencyLogPubKey(raw, tuf.Active); err != nil {
return nil, fmt.Errorf("AddCTLogPubKey: %w", err)
}
} else {
tufClient, err := tuf.NewFromEnv(ctx)
if err != nil {
return nil, err
}
targets, err := tufClient.GetTargetsByMeta(tuf.CTFE, []string{ctPublicKeyStr})
if err != nil {
return nil, err
}
for _, t := range targets {
if err := publicKeys.AddTransparencyLogPubKey(t.Target, t.Status); err != nil {
return nil, fmt.Errorf("AddCTLogPubKey: %w", err)
}
return addKeyFromFile(&publicKeys, altCTLogPub, "CT log public key")
}

opts, err := setTUFOpts()
if err != nil {
return nil, err
}

// Try getting keys from trusted_root.json
trustedRoot, _ := root.NewLiveTrustedRoot(opts)
if trustedRoot == nil {
// The TUF repository didn't have a trusted_root.json, try getting the individual target
return addKeyFromTUF(&publicKeys, opts, ctPublicKeyStr, "CT log public key")
}

ctlogs := trustedRoot.CTLogs()
for _, ct := range ctlogs {
validity := checkValidityPeriod(ct.ValidityPeriodStart, ct.ValidityPeriodEnd)
if err := publicKeys.AddTransparencyLogPubKey(ct.PublicKey, validity); err != nil {
return nil, fmt.Errorf("error adding CT log public key: %w", err)
}
}

if len(publicKeys.Keys) == 0 {
return nil, errors.New("none of the CTLog public keys have been found")
}

return &publicKeys, nil
}
5 changes: 2 additions & 3 deletions pkg/cosign/ctlog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package cosign

import (
"context"
"os"
"testing"
)
Expand All @@ -31,7 +30,7 @@ Nmo7M3bN7+dQddw9Ibc2R3SV8tzBZw0rST8FKcn4apJepcKM4qUpYUeNfw==
)

func TestGetCTLogPubKeys(t *testing.T) {
keys, err := GetCTLogPubs(context.Background())
keys, err := GetCTLogPubs()
if err != nil {
t.Fatalf("Unexpected error calling GetCTLogPubs, expected nil: %v", err)
}
Expand Down Expand Up @@ -61,7 +60,7 @@ func TestGetCTLogPubKeysAlt(t *testing.T) {
}
t.Setenv("SIGSTORE_CT_LOG_PUBLIC_KEY_FILE", pkFile.Name())

keys, err := GetCTLogPubs(context.Background())
keys, err := GetCTLogPubs()
if err != nil {
t.Errorf("Unexpected error calling GetCTLogPubs, expected nil: %v", err)
}
Expand Down
Loading

0 comments on commit 07e1c38

Please sign in to comment.