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

Make changes to Sigstore initialize #747

Merged
merged 1 commit into from
Oct 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion .github/workflows/whitespace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
LINT_FILES=$(git ls-files |
git check-attr --stdin linguist-generated | grep -Ev ': (set|true)$' | cut -d: -f1 |
git check-attr --stdin linguist-vendored | grep -Ev ': (set|true)$' | cut -d: -f1 |
grep -Ev '^(vendor/|third_party/|.git)' |
grep -Ev '^(vendor/|third_party/|.git|pkg/cosign/tuf/repository/targets/)' |
grep -v '\.ai$')
for x in $LINT_FILES; do
# Based on https://stackoverflow.com/questions/34943632/linux-check-if-there-is-an-empty-line-at-the-end-of-a-file
Expand Down
13 changes: 0 additions & 13 deletions cmd/cosign/cli/fulcio/fulcioroots/fulcio.pem

This file was deleted.

29 changes: 10 additions & 19 deletions cmd/cosign/cli/fulcio/fulcioroots/fulcioroots.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ import (
"strings"
"sync"

_ "embed" // To enable the `go:embed` directive.

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

Expand All @@ -36,9 +35,6 @@ var (
)

// This is the root in the fulcio project.
//go:embed fulcio.pem
var rootPem string

var fulcioTargetStr = `fulcio.crt.pem`

const (
Expand All @@ -64,22 +60,17 @@ func initRoots() *x509.CertPool {
panic("error creating root cert pool")
}
} else {
// First try retrieving from TUF root. Otherwise use rootPem.
// 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?
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.Fprintln(os.Stderr, "No TUF root installed, using embedded CA certificate.")
if !cp.AppendCertsFromPEM([]byte(rootPem)) {
panic("error creating root cert pool")
}
} else {
// 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")
}
if err := tuf.GetTarget(ctx, fulcioTargetStr, &buf); err != nil {
panic(errors.Wrap(err, "creating root cert pool"))
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason why we're using panics instead of errors in this 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.

This really shouldn't happen, but I'm not sure -- kind of was following existing code. We really should be getting these targets for any cosign verification, most of the callers expect these targets to be available.

I can plumb through errors, but it'll touch a bit of code

}
// 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")
}
}
return cp
Expand Down
22 changes: 17 additions & 5 deletions cmd/cosign/cli/fulcio/fulcioverifier/fulcioverifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
package fulcioverifier

import (
"bytes"
"context"
_ "embed" // To enable the `go:embed` directive.
"encoding/json"
"fmt"
"os"
Expand All @@ -30,19 +30,31 @@ import (

"github.com/sigstore/cosign/cmd/cosign/cli/fulcio"
"github.com/sigstore/cosign/pkg/cosign"
"github.com/sigstore/cosign/pkg/cosign/tuf"
fulcioClient "github.com/sigstore/fulcio/pkg/generated/client"
)

// This is the CT log public key
//go:embed ctfe.pub
var ctPublicKey string
// This is the CT log public key target name
var ctPublicKeyStr = `ctfe.pub`

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
// The SCT is a `Signed Certificate Timestamp`, which promises that
// the certificate issued by Fulcio was also added to the public CT log within
// some defined time period
func verifySCT(certPEM, rawSCT []byte) error {
pubKey, err := cosign.PemToECDSAKey([]byte(ctPublicKey))
pubKey, err := cosign.PemToECDSAKey([]byte(getCTPub()))
if err != nil {
return err
}
Expand Down
21 changes: 11 additions & 10 deletions cmd/cosign/cli/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,27 @@ func addInitialize(topLevel *cobra.Command) {
Long: `Initializes SigStore root to retrieve trusted certificate and key targets for verification.

The following options are used by default:
- The initial 1.root.json is embedded inside cosign.
- SigStore current TUF repository is pulled from the GCS mirror at sigstore-tuf-root.
- The current trusted Sigstore TUF root is embedded inside cosign at the time of release.
- SigStore remote TUF repository is pulled from the GCS mirror at sigstore-tuf-root.
- A default threshold of 3 root signatures is used.

To provide an out-of-band trusted initial root.json, use the -root flag with a file or URL reference.
This will enable you to point cosign to a separate TUF root.

The resulting updated TUF repository will be written to $HOME/.sigstore/root/.
Any updated TUF repository will be written to $HOME/.sigstore/root/.

Trusted keys and certificate used in cosign verification (e.g. verifying Fulcio issued certificates
with Fulcio root CA) are pulled form the trusted metadata.`,
Example: ` cosign initialize -mirror <url> -out <file>
Example: `cosign initialize -mirror <url> -out <file>

# initialize root with distributed root keys, default mirror, and default out path.
cosign initialize
# initialize root with distributed root keys, default mirror, and default out path.
cosign initialize

# initialize with an out-of-band root key file.
cosign initialize
# initialize with an out-of-band root key file, using the default mirror.
cosign initialize -root <url>

# initialize with an out-of-band root key file and custom repository mirror.
cosign initialize -mirror <url> -root <url>`,
# initialize with an out-of-band root key file and custom repository mirror.
cosign initialize -mirror <url> -root <url>`,
RunE: func(cmd *cobra.Command, args []string) error {
return initialize.DoInitialize(cmd.Context(), o.Root, o.Mirror, o.Threshold)
},
Expand Down
20 changes: 10 additions & 10 deletions cmd/cosign/cli/initialize/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,31 @@ import (
_ "embed" // To enable the `go:embed` directive.

"github.com/sigstore/cosign/pkg/blob"
ctuf "github.com/sigstore/cosign/pkg/cosign/tuf"
"github.com/sigstore/cosign/pkg/cosign/tuf"
)

//go:embed 1.root.json
var initialRoot string

func DoInitialize(ctx context.Context, root, mirror string, threshold int) error {
// Get the initial trusted root contents.
var rootFileBytes []byte
if root == "" {
rootFileBytes = []byte(initialRoot)
} else {
var err error
var err error
if root != "" {
rootFileBytes, err = blob.LoadFileOrURL(root)
if err != nil {
return err
}
} else {
rootFileBytes, err = tuf.GetEmbeddedRoot()
if err != nil {
return err
}
}

// Initialize the remote repository.
remote, err := ctuf.GcsRemoteStore(ctx, mirror, nil, nil)
remote, err := tuf.GcsRemoteStore(ctx, mirror, nil, nil)
if err != nil {
return err
}

// Initialize and update the local SigStore root.
return ctuf.Init(ctx, rootFileBytes, remote, threshold)
return tuf.Init(ctx, rootFileBytes, remote, threshold)
}
21 changes: 11 additions & 10 deletions doc/cosign_initialize.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 5 additions & 12 deletions pkg/cosign/tlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,8 @@ import (
"encoding/base64"
"encoding/hex"
"fmt"
"os"
"strings"

_ "embed" // To enable the `go:embed` directive.

"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/google/trillian/merkle/logverifier"
Expand All @@ -41,20 +38,16 @@ import (
rekord_v001 "github.com/sigstore/rekor/pkg/types/rekord/v0.0.1"
)

// This is rekor's public key, via `curl -L rekor.sigstore.dev/api/ggcrv1/log/publicKey`
// 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
// This is the rekor public key target name
var rekorTargetStr = `rekor.pub`

func GetRekorPub() string {
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.Fprintln(os.Stderr, "No TUF root installed, using embedded rekor key")
return rekorPub
// Retrieves the rekor 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, rekorTargetStr, &buf); err != nil {
panic("error retrieving rekor public key")
}
return buf.String()
}
Expand Down
Loading