Skip to content

Commit

Permalink
'cosign init' minor enhancements (file or URL root, write to $HOME/.s…
Browse files Browse the repository at this point in the history
…igstore) (#530)

* make minor changes to cosign init

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

* use gcs root

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

* also pin sha

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

* embed initial root

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

* remove sha because of embedded root

Signed-off-by: Asra Ali <asraa@google.com>
  • Loading branch information
asraa committed Aug 11, 2021
1 parent a7aff49 commit 4c76ff3
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 105 deletions.
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,5 @@
*.libfuzzer
*fuzz.a

# Root metadata
*.sigstore/root/

bin*
dist/
57 changes: 0 additions & 57 deletions .sigstore/keys.json

This file was deleted.

130 changes: 130 additions & 0 deletions cmd/cosign/cli/1.root.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
{
"signatures": [
{
"keyid": "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97",
"sig": "30450221008a35d51da0f845301a5eac98ad0df00a934f59b709c1eaf81c86be734d9356f80220742942325599749800f52675f6efe124345980a2a636c0dc76f9caf9fc3123b0"
},
{
"keyid": "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62",
"sig": "3045022100ef9157ece2a09baec1eab80adfc00b04da20b1f9a0d1b47c5dabc4506719ef2c022074f72acd57398e4ddc8c2a5040df902961e9615dca48f3fbe38cbb506e500066"
},
{
"keyid": "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b",
"sig": "30450220420fdc9a09cd069b8b15fd8db9cedf7d0dee75871bd1cfee77c926d4120a770002210097553b5ad0d6b4a13902ed37509638bb63a9009f78230cd56c802909ffbfead7"
},
{
"keyid": "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb",
"sig": "304502202aaf32e66f90752f658672b085ecfe45cc1ad31ee6cf5c9ad05f3267685f8d88022100b5df02acdaa371123db9d7a42219553fe079b230b168833e951be7ee56ded347"
},
{
"keyid": "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209",
"sig": "304402205d420c7d05c58980c1c9f7d221f53b5334aae27a447d2a91c2ceddd685269749022039ec83e51f8e1779d7f0142dfa4a5bbecfe327fc0b91b7416090fea2416fd53a"
}
],
"signed": {
"_type": "root",
"consistent_snapshot": false,
"expires": "2021-12-18T13:28:12.99008-06:00",
"keys": {
"2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "04cbc5cab2684160323c25cd06c3307178a6b1d1c9b949328453ae473c5ba7527e35b13f298b41633382241f3fd8526c262d43b45adee5c618fa0642c82b8a9803"
},
"scheme": "ecdsa-sha2-nistp256"
},
"bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "04a71aacd835dc170ba6db3fa33a1a33dee751d4f8b0217b805b9bd3242921ee93672fdcfd840576c5bb0dc0ed815edf394c1ee48c2b5e02485e59bfc512f3adc7"
},
"scheme": "ecdsa-sha2-nistp256"
},
"eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "04117b33dd265715bf23315e368faa499728db8d1f0a377070a1c7b1aba2cc21be6ab1628e42f2cdd7a35479f2dce07b303a8ba646c55569a8d2a504ba7e86e447"
},
"scheme": "ecdsa-sha2-nistp256"
},
"f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "04cc1cd53a61c23e88cc54b488dfae168a257c34fac3e88811c55962b24cffbfecb724447999c54670e365883716302e49da57c79a33cd3e16f81fbc66f0bcdf48"
},
"scheme": "ecdsa-sha2-nistp256"
},
"f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209": {
"keyid_hash_algorithms": [
"sha256",
"sha512"
],
"keytype": "ecdsa-sha2-nistp256",
"keyval": {
"public": "048a78a44ac01099890d787e5e62afc29c8ccb69a70ec6549a6b04033b0a8acbfb42ab1ab9c713d225cdb52b858886cf46c8e90a7f3b9e6371882f370c259e1c5b"
},
"scheme": "ecdsa-sha2-nistp256"
}
},
"roles": {
"root": {
"keyids": [
"2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97",
"bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62",
"eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b",
"f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb",
"f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209"
],
"threshold": 3
},
"snapshot": {
"keyids": [
"2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97",
"bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62",
"eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b",
"f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb",
"f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209"
],
"threshold": 3
},
"targets": {
"keyids": [
"2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97",
"bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62",
"eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b",
"f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb",
"f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209"
],
"threshold": 3
},
"timestamp": {
"keyids": [
"2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97",
"bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62",
"eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b",
"f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb",
"f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209"
],
"threshold": 3
}
},
"spec_version": "1.0",
"version": 1
}
}
59 changes: 51 additions & 8 deletions cmd/cosign/cli/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,49 @@ package cli

import (
"context"
_ "embed" // To enable the `go:embed` directive.
"flag"
"io/ioutil"
"net/http"
"path/filepath"
"strings"

"github.com/peterbourgon/ff/v3/ffcli"
ctuf "github.com/sigstore/cosign/pkg/cosign/tuf"
)

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

func loadFileOrURL(fileRef string) ([]byte, error) {
var raw []byte
var err error
if strings.HasPrefix(fileRef, "http://") || strings.HasPrefix(fileRef, "https://") {
// #nosec G107
resp, err := http.Get(fileRef)
if err != nil {
return nil, err
}
defer resp.Body.Close()
raw, err = ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
} else {
raw, err = ioutil.ReadFile(filepath.Clean(fileRef))
if err != nil {
return nil, err
}
}
return raw, nil
}

func Init() *ffcli.Command {
var (
flagset = flag.NewFlagSet("cosign init", flag.ExitOnError)
// TODO: Support HTTP mirrors as well
mirror = flagset.String("mirror", "sigstore-tuf-root", "GCS bucket to a SigStore TUF repository.")
root = flagset.String("root", ".sigstore/keys.json", "path to trusted initial root.")
root = flagset.String("root", "", "path to trusted initial root. defaults to embedded root.")
threshold = flagset.Int("threshold", 3, "threshold of root key signers")
)
return &ffcli.Command{
Expand All @@ -38,13 +69,13 @@ func Init() *ffcli.Command {
LongHelp: `Initializes SigStore root to retrieve trusted certificate and key targets for verification.
The following options are used by default:
- Initial root keys are pulled from .sigstore/keys. If it does not exist, uses root keys provided in the release.
- SigStore current TUF repository is pulled from the GCS mirror at .
- Resulting trusted metadata is written to .sigstore/root.
- The initial 1.root.json is embedded inside cosign.
- SigStore current 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 root.json, copy the file into a directory named .sigstore/root/.
To provide an out-of-band trusted initial root.json, use the -root flag with a file or URL reference.
The resulting updated TUF repository will be written to .sigstore/root/.
The resulting 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.
Expand All @@ -57,18 +88,30 @@ EXAMPLES
cosign init
# initialize with an out-of-band root key file and custom repository mirror.
cosign init-mirror <>
cosign init -mirror <url> -root <url>
`,
FlagSet: flagset,
Exec: func(ctx context.Context, args []string) error {
// Get the initial trusted root contents.
var rootFileBytes []byte
if *root == "" {
rootFileBytes = []byte(initialRoot)
} else {
var err error
rootFileBytes, err = loadFileOrURL(*root)
if err != nil {
return err
}
}

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

// Initialize and update the local SigStore root.
return ctuf.Init(context.Background(), *root, remote, *threshold)
return ctuf.Init(context.Background(), rootFileBytes, remote, *threshold)
},
}
}
30 changes: 16 additions & 14 deletions pkg/cosign/tuf/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (

"github.com/pkg/errors"

"github.com/theupdateframework/go-tuf"
"github.com/theupdateframework/go-tuf/client"
tuf_leveldbstore "github.com/theupdateframework/go-tuf/client/leveldbstore"
"github.com/theupdateframework/go-tuf/data"
Expand All @@ -37,15 +38,19 @@ const (
defaultLocalStore = ".sigstore/root/"
)

// Global TUF client. Stores local targets in .sigstore/root.
// Global TUF client. Stores local targets in $HOME/.sigstore/root.
// Could be in memory local store, but that would mean re-download each time cosign is run.
var rootClient *client.Client
var rootClientMu = &sync.Mutex{}

func CosignRoot() string {
rootDir := os.Getenv(TufRootEnv)
if rootDir == "" {
return defaultLocalStore
home, err := os.UserHomeDir()
if err != nil {
home = ""
}
return path.Join(home, defaultLocalStore)
}
return rootDir
}
Expand Down Expand Up @@ -73,16 +78,13 @@ func (b *ByteDestination) Delete() error {
return nil
}

func getRootKeys(rootPath string) ([]*data.Key, error) {
rootFile, err := os.Open(rootPath)
func getRootKeys(rootFileBytes []byte) ([]*data.Key, error) {
store := tuf.MemoryStore(map[string]json.RawMessage{"root.json": rootFileBytes}, nil)
repo, err := tuf.NewRepo(store)
if err != nil {
return nil, err
}
var rootKeys []*data.Key
if err := json.NewDecoder(rootFile).Decode(&rootKeys); err != nil {
return nil, err
}
return rootKeys, nil
return repo.RootKeys()
}

// Gets the global TUF client if the directory exists.
Expand All @@ -102,7 +104,7 @@ func RootClient(ctx context.Context, local string, remote client.RemoteStore) (*
}

func updateMetadataAndDownloadTargets(c *client.Client) error {
// Download initial targets and store in .sigstore/root/targets/.
// Download initial targets and store in $HOME/.sigstore/root/targets/.
targetFiles, err := c.Update()
if err != nil && !client.IsLatestSnapshot(err) {
return errors.Wrap(err, "updating tuf metadata")
Expand Down Expand Up @@ -137,20 +139,20 @@ func downloadTarget(name string, c *client.Client, out client.Destination) error
return err
}

// Instantiates the global TUF client. Downloads all initial targets and stores in .sigstore/root/targets/.
func Init(ctx context.Context, rootFile string, remote client.RemoteStore, threshold int) error {
// Instantiates the global TUF client. Downloads all initial targets and stores in $HOME/.sigstore/root/targets/.
func Init(ctx context.Context, rootBytes []byte, remote client.RemoteStore, threshold int) error {
rootClient, err := RootClient(ctx, CosignRoot(), remote)
if err != nil {
return errors.Wrap(err, "initializing root client")
}
rootKeys, err := getRootKeys(rootFile)
rootKeys, err := getRootKeys(rootBytes)
if err != nil {
return errors.Wrap(err, "retrieving root keys")
}
if err := rootClient.Init(rootKeys, threshold); err != nil {
return errors.Wrap(err, "initializing tuf client")
}
// Download initial targets and store in .sigstore/root/targets/.
// Download initial targets and store in $HOME/.sigstore/root/targets/.
if err := os.MkdirAll(CosignRoot(), 0755); err != nil {
return errors.Wrap(err, "creating targets dir")
}
Expand Down

0 comments on commit 4c76ff3

Please sign in to comment.