Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cosign init to initialize the SigStore root metadata #520

Merged
merged 7 commits into from
Aug 9, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
use tuf root for rekor and fulcio data
Signed-off-by: Asra Ali <asraa@google.com>
  • Loading branch information
asraa committed Aug 4, 2021
commit ce731056db46c302d545b1679fcb977d072bb7ed
10 changes: 5 additions & 5 deletions cmd/cosign/cli/fulcio/fulcio.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ const (
// This is the root in the fulcio project.
//go:embed fulcio.pem
var rootPem string

var fulcioTargetStr = `fulcio.crt.pem`

type oidcConnector interface {
Expand Down Expand Up @@ -209,17 +208,18 @@ func initRoots() *x509.CertPool {
panic("error creating root cert pool")
}
} else {
// First try retrieving from TUF root. Requires running `cosign init`
// Otherwise use rootPem.
ctx := context.Background()
// First try retrieving from TUF root. Otherwise use rootPem.
ctx := context.Background() // TODO: pass in context?
buf := tuf.ByteDestination{Buffer: &bytes.Buffer{}}
err := tuf.GetTarget(ctx, fulcioTargetStr, &buf)
if err != nil {
// The user may not have initialized the local root metadata. Log the error and use the embedded root.
fmt.Println("using embedded fulcio certificate. did you run `cosign init`? error retrieving target: ", err)
if !cp.AppendCertsFromPEM([]byte(rootPem)) {
panic("error creating root cert pool")
}
} else {
// TODO: Remove this when re-signing the next Fulcio certificate.
// TODO: Remove the string replace when SigStore root is updated.
replaced := strings.ReplaceAll(buf.String(), "\n ", "\n")
if !cp.AppendCertsFromPEM([]byte(replaced)) {
panic("error creating root cert pool")
Expand Down
16 changes: 16 additions & 0 deletions pkg/cosign/tlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
package cosign

import (
"bytes"
"context"
"encoding/base64"
"encoding/hex"
"fmt"
Expand All @@ -29,6 +31,7 @@ import (
"github.com/pkg/errors"

cremote "github.com/sigstore/cosign/pkg/cosign/remote"
"github.com/sigstore/cosign/pkg/cosign/tuf"
"github.com/sigstore/rekor/pkg/generated/client"
"github.com/sigstore/rekor/pkg/generated/client/entries"
"github.com/sigstore/rekor/pkg/generated/client/pubkey"
Expand All @@ -41,6 +44,19 @@ import (
// rekor.pub should be updated whenever the Rekor public key is rotated & the bundle annotation should be up-versioned
//go:embed rekor.pub
var rekorPub string
var rekorTargetStr = `rekor.pub`

func GetRekorPub() string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO we should put this somewhere under cli/ in order to keep logging and cosign binary-specific out of package

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohhh hmmmm you mean keeping fmt.Println out? It's used elsewhere in this file as well

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hrm yeah

ctx := context.Background() // TODO: pass in context?
buf := tuf.ByteDestination{Buffer: &bytes.Buffer{}}
err := tuf.GetTarget(ctx, rekorTargetStr, &buf)
if err != nil {
// The user may not have initialized the local root metadata. Log the error and use the embedded root.
fmt.Println("using embedded rekor public key. did you run `cosign init`? error retrieving target: ", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fmt.Println("using embedded rekor public key. did you run `cosign init`? error retrieving target: ", err)
fmt.Fprintln(os.Stderr, "using embedded rekor public key. did you run `cosign init`? error retrieving target: ", err)

return rekorPub
}
return buf.String()
}

// TLogUpload will upload the signature, public key and payload to the transparency log.
func TLogUpload(rekorClient *client.Rekor, signature, payload []byte, pemBytes []byte) (*models.LogEntryAnon, error) {
Expand Down
40 changes: 19 additions & 21 deletions pkg/cosign/tuf/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ func getRootKeys() ([]*data.Key, error) {

// Gets the global TUF client if the directory exists.
func RootClient(ctx context.Context) (*client.Client, error) {
rootClientMu.Lock()
defer rootClientMu.Unlock()
if rootClient == nil {
// Instantiate the global TUF client.
// Instantiate the global TUF client from the local store. This does not do a download.
local, err := tuf_leveldbstore.FileLocalStore(TufLocalStore)
if err != nil {
return nil, errors.Wrap(err, "initializing local store")
Expand All @@ -86,23 +88,6 @@ func RootClient(ctx context.Context) (*client.Client, error) {
return nil, errors.Wrap(err, "initializing remote store")
}
rootClient = client.NewClient(local, remote)

rootKeys, err := getRootKeys()
if err != nil {
return nil, errors.Wrap(err, "retrieving root keys")
}
if err := rootClient.Init(rootKeys, TufThreshold); err != nil {
return nil, errors.Wrap(err, "initializing tuf client")
}

// Download initial targets and store in .sigstore/root/targets/.
if err := os.MkdirAll(TufLocalTargets, 0755); err != nil {
return nil, errors.Wrap(err, "creating targets dir")
}
if err := updateMetadataAndDownloadTargets(rootClient); err != nil {
return nil, errors.Wrap(err, "updating local metadata and targets")
}
return rootClient, nil
}
return rootClient, nil
}
Expand Down Expand Up @@ -142,10 +127,23 @@ func downloadTarget(name string, c *client.Client, out client.Destination) error

// Instantiates the global TUF client. Downloads all initial targets and stores in .sigstore/root/targets/.
func Init(ctx context.Context) error {
// Instantiate the global TUF client.
_, err := RootClient(ctx)
rootClient, err := RootClient(ctx)
if err != nil {
return errors.Wrap(err, "getting root client")
return errors.Wrap(err, "initializing root client")
}
rootKeys, err := getRootKeys()
if err != nil {
return errors.Wrap(err, "retrieving root keys")
}
if err := rootClient.Init(rootKeys, TufThreshold); err != nil {
return errors.Wrap(err, "initializing tuf client")
}
// Download initial targets and store in .sigstore/root/targets/.
if err := os.MkdirAll(TufLocalTargets, 0755); err != nil {
return errors.Wrap(err, "creating targets dir")
}
if err := updateMetadataAndDownloadTargets(rootClient); err != nil {
return errors.Wrap(err, "updating local metadata and targets")
}

return nil
Expand Down
3 changes: 2 additions & 1 deletion pkg/cosign/tuf/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ type gcsRemoteStore struct {
opts *GcsRemoteOptions
}

// A remote store for TUF metadata on GCS.
func GcsRemoteStore(ctx context.Context, bucket string, opts *GcsRemoteOptions, client *storage.Client) (client.RemoteStore, error) {
if opts == nil {
opts = &GcsRemoteOptions{}
}
if opts.TargetsPath == "" {
opts.TargetsPath = "targets"
}
store := gcsRemoteStore{ctx: ctx, bucket: bucket, opts: opts}
store := gcsRemoteStore{ctx: ctx, bucket: bucket, opts: opts, client: client}
if client == nil {
var err error
store.client, err = storage.NewClient(ctx)
Expand Down
2 changes: 1 addition & 1 deletion pkg/cosign/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ func (sp *SignedPayload) VerifyBundle() (bool, error) {
if sp.bundleVerified {
return true, nil
}
rekorPubKey, err := PemToECDSAKey([]byte(rekorPub))
rekorPubKey, err := PemToECDSAKey([]byte(GetRekorPub()))
if err != nil {
return false, errors.Wrap(err, "pem to ecdsa")
}
Expand Down