From d3c66398c5f6d36223f3915434b0897876532a24 Mon Sep 17 00:00:00 2001 From: Ville Aikas Date: Fri, 21 Oct 2022 23:22:18 -0700 Subject: [PATCH 1/2] plumb ways to add metadata about targets. Signed-off-by: Ville Aikas --- pkg/repo/repo.go | 84 +++++++++++++++++++++++++++++++++---------- pkg/repo/repo_test.go | 1 - 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/pkg/repo/repo.go b/pkg/repo/repo.go index 742e4763..1a95d32f 100644 --- a/pkg/repo/repo.go +++ b/pkg/repo/repo.go @@ -18,6 +18,7 @@ import ( "archive/tar" "compress/gzip" "context" + "encoding/json" "fmt" "io" "io/fs" @@ -31,13 +32,26 @@ import ( "knative.dev/pkg/logging" ) -// CreateRepo creates and initializes a Tuf repo for Sigstore by adding -// keys to bytes. keys are typically for a basic setup like: -// "fulcio_v1.crt.pem" - Fulcio root cert in PEM format -// "ctfe.pub" - CTLog public key in PEM format -// "rekor.pub" - Rekor public key in PEM format -// but additional keys can be added here. -func CreateRepo(ctx context.Context, files map[string][]byte) (tuf.LocalStore, string, error) { +// TargetWithMetadata describes a TUF target with the given Name, Bytes, and +// CustomMetadata +type TargetWithMetadata struct { + Name string + Bytes []byte + CustomMetadata []byte +} + +type CustomMetadata struct { + Usage string `json:"usage"` + Status string `json:"status"` +} + +type sigstoreCustomMetadata struct { + Sigstore CustomMetadata `json:"sigstore"` +} + +// CreateRepoWithMetadata will create a TUF repo for Sigstore by adding targets +// to the Root with custom metadata. +func CreateRepoWithMetadata(ctx context.Context, targets []TargetWithMetadata) (tuf.LocalStore, string, error) { // TODO: Make this an in-memory fileystem. tmpDir := os.TempDir() dir := tmpDir + "tuf" @@ -56,7 +70,6 @@ func CreateRepo(ctx context.Context, files map[string][]byte) (tuf.LocalStore, s return nil, "", fmt.Errorf("failed to NewRepoIndent: %w", err) } - // Added by vaikas if err := r.Init(false); err != nil { return nil, "", fmt.Errorf("failed to Init repo: %w", err) } @@ -71,17 +84,15 @@ func CreateRepo(ctx context.Context, files map[string][]byte) (tuf.LocalStore, s } } - targets := make([]string, 0, len(files)) - for k, v := range files { - logging.FromContext(ctx).Infof("Adding %s file", k) - if err := writeStagedTarget(dir, k, v); err != nil { - return nil, "", fmt.Errorf("failed to write staged target %s: %w", k, err) + for _, t := range targets { + logging.FromContext(ctx).Infof("Adding file: %s", t.Name) + if err := writeStagedTarget(dir, t.Name, t.Bytes); err != nil { + return nil, "", fmt.Errorf("failed to write staged target %s: %w", t.Name, err) + } + err = r.AddTargetWithExpires(t.Name, t.CustomMetadata, expires) + if err != nil { + return nil, "", fmt.Errorf("failed to add AddTargetWithExpires: %w", err) } - targets = append(targets, k) - } - err = r.AddTargetsWithExpires(targets, nil, expires) - if err != nil { - return nil, "", fmt.Errorf("failed to add AddTargetsWithExpires: %w", err) } // Snapshot, Timestamp, and Publish the repository. @@ -97,6 +108,43 @@ func CreateRepo(ctx context.Context, files map[string][]byte) (tuf.LocalStore, s return local, dir, nil } +// CreateRepo creates and initializes a Tuf repo for Sigstore by adding +// keys to bytes. keys are typically for a basic setup like: +// "fulcio_v1.crt.pem" - Fulcio root cert in PEM format +// "ctfe.pub" - CTLog public key in PEM format +// "rekor.pub" - Rekor public key in PEM format +// but additional keys can be added here. +// +// This will also deduce the Usage for the keys based off the filename: +// if the filename contains: +// - `fulcio` = it will get Usage set to `Fulcio` +// - `ctfe` = it will get Usage set to `CTFE` +// - Anything else will get set to `Rekor` +func CreateRepo(ctx context.Context, files map[string][]byte) (tuf.LocalStore, string, error) { + targets := make([]TargetWithMetadata, 0, len(files)) + for name, bytes := range files { + usage := "" + if strings.Contains(name, "fulcio") { + usage = "Fulcio" + } else if strings.Contains(name, "ctfe") { + usage = "CTFE" + } else { + usage = "Rekor" + } + scmActive, err := json.Marshal(&sigstoreCustomMetadata{Sigstore: CustomMetadata{Usage: usage, Status: "Active"}}) + if err != nil { + return nil, "", fmt.Errorf("failed to marshal custom metadata for %s: %w", name, err) + } + targets = append(targets, TargetWithMetadata{ + Name: name, + Bytes: bytes, + CustomMetadata: scmActive, + }) + } + + return CreateRepoWithMetadata(ctx, targets) +} + func writeStagedTarget(dir, path string, data []byte) error { path = filepath.Join(dir, "staged", "targets", path) if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { diff --git a/pkg/repo/repo_test.go b/pkg/repo/repo_test.go index 44771715..fb4f74b8 100644 --- a/pkg/repo/repo_test.go +++ b/pkg/repo/repo_test.go @@ -122,5 +122,4 @@ func TestCompressUncompressFS(t *testing.T) { if bytes.Compare(files["rekor.pub"], rtRekor) != 0 { t.Errorf("Roundtripped rekor differs:\n%s\n%s", rekorPublicKey, string(rtRekor)) } - } From 03415a7e2af91dff56d439a054759413d5eac5ef Mon Sep 17 00:00:00 2001 From: Ville Aikas Date: Mon, 31 Oct 2022 14:39:00 -0700 Subject: [PATCH 2/2] Address PR Feedback. Add URI to CustomMetadata Signed-off-by: Ville Aikas --- pkg/repo/repo.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/repo/repo.go b/pkg/repo/repo.go index 1a95d32f..4398c6b8 100644 --- a/pkg/repo/repo.go +++ b/pkg/repo/repo.go @@ -43,6 +43,7 @@ type TargetWithMetadata struct { type CustomMetadata struct { Usage string `json:"usage"` Status string `json:"status"` + URI string `json:"uri"` } type sigstoreCustomMetadata struct { @@ -108,7 +109,7 @@ func CreateRepoWithMetadata(ctx context.Context, targets []TargetWithMetadata) ( return local, dir, nil } -// CreateRepo creates and initializes a Tuf repo for Sigstore by adding +// CreateRepo creates and initializes a TUF repo for Sigstore by adding // keys to bytes. keys are typically for a basic setup like: // "fulcio_v1.crt.pem" - Fulcio root cert in PEM format // "ctfe.pub" - CTLog public key in PEM format @@ -119,7 +120,8 @@ func CreateRepoWithMetadata(ctx context.Context, targets []TargetWithMetadata) ( // if the filename contains: // - `fulcio` = it will get Usage set to `Fulcio` // - `ctfe` = it will get Usage set to `CTFE` -// - Anything else will get set to `Rekor` +// - `rekor` = it will get Usage set to `Rekor` +// - Anything else will get set to `Unknown` func CreateRepo(ctx context.Context, files map[string][]byte) (tuf.LocalStore, string, error) { targets := make([]TargetWithMetadata, 0, len(files)) for name, bytes := range files { @@ -128,8 +130,10 @@ func CreateRepo(ctx context.Context, files map[string][]byte) (tuf.LocalStore, s usage = "Fulcio" } else if strings.Contains(name, "ctfe") { usage = "CTFE" - } else { + } else if strings.Contains(name, "rekor") { usage = "Rekor" + } else { + usage = "Unknown" } scmActive, err := json.Marshal(&sigstoreCustomMetadata{Sigstore: CustomMetadata{Usage: usage, Status: "Active"}}) if err != nil {