From 59921bb0d56be752a6399cccf1549f39fcdc29a8 Mon Sep 17 00:00:00 2001 From: Chris Burns <29541485+ChrisJBurns@users.noreply.github.com> Date: Mon, 2 Jan 2023 21:07:29 +0000 Subject: [PATCH] feat: allows custom name for keypair generation (#2561) - also adds contribution docs Signed-off-by: ChrisJBurns <29541485+ChrisJBurns@users.noreply.github.com> Signed-off-by: ChrisJBurns <29541485+ChrisJBurns@users.noreply.github.com> --- CONTRIBUTING.md | 41 ++++++++++++++++ README.md | 14 ++++-- cmd/cosign/cli/generate/generate_key_pair.go | 30 ++++++++---- .../cli/generate/generate_key_pair_test.go | 48 +++++++++++++++++-- cmd/cosign/cli/generate_key_pair.go | 5 +- cmd/cosign/cli/options/generate_key_pair.go | 5 +- doc/cosign_generate-key-pair.md | 8 +++- 7 files changed, 129 insertions(+), 22 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..076ae07d5f1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,41 @@ +# Contributing to `cosign` + +The following document will detail the steps needed in order to ensure all of the correct processes are followed when contributing to `cosign`. + +The following are needed to be completed before a Pull Request is raised: + +- unit tests written, run, and passing +- lint run +- document generation run + +## Building + +To build `cosign` locally, run the following: + +```shell +make cosign +``` + +## Running Unit Tests + +To run the unit tests, run the following: + +```shell +make test +``` + +## Running Lint + +To run linting, run the following: + +```shell +make lint +``` + +## Document Generation + +To document generation, run the following: + +```shell +make docgen +``` diff --git a/README.md b/README.md index e18ba444072..fc9f8030dc3 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,16 @@ For Linux and macOS binaries see the [GitHub release assets](https://github.com/ If you have Go 1.19+, you can setup a development environment: - $ git clone https://github.com/sigstore/cosign - $ cd cosign - $ go install ./cmd/cosign - $ $(go env GOPATH)/bin/cosign +```shell +$ git clone https://github.com/sigstore/cosign +$ cd cosign +$ go install ./cmd/cosign +$ $(go env GOPATH)/bin/cosign +``` + +## Contributing + +If you are interested in contributing to `cosign`, please read the [contributing documentation](./CONTRIBUTING.md). ## Dockerfile diff --git a/cmd/cosign/cli/generate/generate_key_pair.go b/cmd/cosign/cli/generate/generate_key_pair.go index daed2250854..82b9ff34d5f 100644 --- a/cmd/cosign/cli/generate/generate_key_pair.go +++ b/cmd/cosign/cli/generate/generate_key_pair.go @@ -43,7 +43,10 @@ var ( ) // nolint -func GenerateKeyPairCmd(ctx context.Context, kmsVal string, args []string) error { +func GenerateKeyPairCmd(ctx context.Context, kmsVal string, nameVal string, args []string) error { + privateKeyFileName := nameVal + ".key" + publicKeyFileName := nameVal + ".pub" + if kmsVal != "" { k, err := kms.Get(ctx, kmsVal, crypto.SHA256) if err != nil { @@ -57,10 +60,10 @@ func GenerateKeyPairCmd(ctx context.Context, kmsVal string, args []string) error if err != nil { return err } - if err := os.WriteFile("cosign.pub", pemBytes, 0600); err != nil { + if err := os.WriteFile(publicKeyFileName, pemBytes, 0600); err != nil { return err } - fmt.Fprintln(os.Stderr, "Public key written to cosign.pub") + fmt.Fprintln(os.Stderr, "Public key written to", publicKeyFileName) return nil } @@ -88,27 +91,34 @@ func GenerateKeyPairCmd(ctx context.Context, kmsVal string, args []string) error return err } - fileExists, err := icos.FileExists("cosign.key") + fileExists, err := icos.FileExists(privateKeyFileName) if err != nil { - return fmt.Errorf("failed checking if cosign.key exists: %w", err) + return fmt.Errorf("failed checking if %s exists: %w", privateKeyFileName, err) } if fileExists { - ui.Warn(ctx, "File import-cosign.key already exists. Overwrite?") + ui.Warn(ctx, "File %s already exists. Overwrite?", privateKeyFileName) if err := ui.ConfirmContinue(ctx); err != nil { return err } + return writeKeyFiles(privateKeyFileName, publicKeyFileName, keys) } + + return writeKeyFiles(privateKeyFileName, publicKeyFileName, keys) +} + +func writeKeyFiles(privateKeyFileName string, publicKeyFileName string, keys *cosign.KeysBytes) error { // TODO: make sure the perms are locked down first. - if err := os.WriteFile("cosign.key", keys.PrivateBytes, 0600); err != nil { + if err := os.WriteFile(privateKeyFileName, keys.PrivateBytes, 0600); err != nil { return err } - fmt.Fprintln(os.Stderr, "Private key written to cosign.key") + fmt.Fprintln(os.Stderr, "Private key written to", privateKeyFileName) - if err := os.WriteFile("cosign.pub", keys.PublicBytes, 0644); err != nil { + if err := os.WriteFile(publicKeyFileName, keys.PublicBytes, 0644); err != nil { return err } // #nosec G306 - fmt.Fprintln(os.Stderr, "Public key written to cosign.pub") + fmt.Fprintln(os.Stderr, "Public key written to", publicKeyFileName) + return nil } diff --git a/cmd/cosign/cli/generate/generate_key_pair_test.go b/cmd/cosign/cli/generate/generate_key_pair_test.go index 07d73d3c1b0..f860382ea4e 100644 --- a/cmd/cosign/cli/generate/generate_key_pair_test.go +++ b/cmd/cosign/cli/generate/generate_key_pair_test.go @@ -16,15 +16,16 @@ package generate import ( + "context" "os" "testing" "github.com/google/go-cmp/cmp" + icos "github.com/sigstore/cosign/v2/internal/pkg/cosign" ) func TestReadPasswordFn_env(t *testing.T) { - os.Setenv("COSIGN_PASSWORD", "foo") - defer os.Unsetenv("COSIGN_PASSWORD") + t.Setenv("COSIGN_PASSWORD", "foo") b, err := readPasswordFn(true)() if err != nil { t.Fatalf("unexpected error: %v", err) @@ -35,8 +36,7 @@ func TestReadPasswordFn_env(t *testing.T) { } func TestReadPasswordFn_envEmptyVal(t *testing.T) { - os.Setenv("COSIGN_PASSWORD", "") - defer os.Unsetenv("COSIGN_PASSWORD") + t.Setenv("COSIGN_PASSWORD", "") b, err := readPasswordFn(true)() if err != nil { t.Fatalf("unexpected error: %v", err) @@ -45,3 +45,43 @@ func TestReadPasswordFn_envEmptyVal(t *testing.T) { t.Fatalf("expected empty string; got %q", string(b)) } } + +func TestGenerationOfKeys(t *testing.T) { + var privateKeyName = "my-test.key" + var publicKeyName = "my-test.pub" + + t.Setenv("COSIGN_PASSWORD", "test") + + // we pass in a custom name `my-test` because the GenerateKeyPairCmd + // doesn't care where the value comes from, only that it has a value. + // be default it's set to `cosign`, but this is done by the CLI flag + // framework if there is no value set by the user when running the + // command. + GenerateKeyPairCmd(context.Background(), "", "my-test", nil) + + checkIfFileExistsThenDelete(privateKeyName, t) + checkIfFileExistsThenDelete(publicKeyName, t) +} + +func checkIfFileExistsThenDelete(fileName string, t *testing.T) { + fileExists, err := icos.FileExists(fileName) + if err != nil { + t.Fatalf("failed checking if %s exists: %v", fileName, err) + } + + if !fileExists { + t.Fatalf("key generation for key %s failed", fileName) + } + + t.Logf("key generation for key %s succeeded", fileName) + + deleteKeyFile(fileName, t) +} + +func deleteKeyFile(fileName string, t *testing.T) { + t.Cleanup(func() { + t.Logf("Removing keyfile %s...", fileName) + os.Remove(fileName) + t.Logf("Removed keyfile %s", fileName) + }) +} diff --git a/cmd/cosign/cli/generate_key_pair.go b/cmd/cosign/cli/generate_key_pair.go index 7e389938a66..61871308415 100644 --- a/cmd/cosign/cli/generate_key_pair.go +++ b/cmd/cosign/cli/generate_key_pair.go @@ -34,6 +34,9 @@ func GenerateKeyPair() *cobra.Command { # generate key-pair and write to cosign.key and cosign.pub files cosign generate-key-pair + # generate key-pair and write tog custom named my-name.key and my-name.pub files + cosign generate-key-pair --name my-name + # generate a key-pair in Azure Key Vault cosign generate-key-pair --kms azurekms://[VAULT_NAME][VAULT_URI]/[KEY] @@ -64,7 +67,7 @@ CAVEATS: PersistentPreRun: options.BindViper, RunE: func(cmd *cobra.Command, args []string) error { - return generate.GenerateKeyPairCmd(cmd.Context(), o.KMS, args) + return generate.GenerateKeyPairCmd(cmd.Context(), o.KMS, o.Name, args) }, } diff --git a/cmd/cosign/cli/options/generate_key_pair.go b/cmd/cosign/cli/options/generate_key_pair.go index 4b7312d772a..9bcbe28a4b4 100644 --- a/cmd/cosign/cli/options/generate_key_pair.go +++ b/cmd/cosign/cli/options/generate_key_pair.go @@ -22,7 +22,8 @@ import ( // GenerateKeyPairOptions is the top level wrapper for the generate-key-pair command. type GenerateKeyPairOptions struct { // KMS Key Management Service - KMS string + KMS string + Name string } var _ Interface = (*GenerateKeyPairOptions)(nil) @@ -31,4 +32,6 @@ var _ Interface = (*GenerateKeyPairOptions)(nil) func (o *GenerateKeyPairOptions) AddFlags(cmd *cobra.Command) { cmd.Flags().StringVar(&o.KMS, "kms", "", "create key pair in KMS service to use for signing") + cmd.Flags().StringVar(&o.Name, "name", "cosign", + "adds a chosen name to your .pub and .key files (defaults to `cosign`)") } diff --git a/doc/cosign_generate-key-pair.md b/doc/cosign_generate-key-pair.md index 040ffecb1f0..c45de4673cd 100644 --- a/doc/cosign_generate-key-pair.md +++ b/doc/cosign_generate-key-pair.md @@ -18,6 +18,9 @@ cosign generate-key-pair [flags] # generate key-pair and write to cosign.key and cosign.pub files cosign generate-key-pair + # generate key-pair and write tog custom named my-name.key and my-name.pub files + cosign generate-key-pair --name my-name + # generate a key-pair in Azure Key Vault cosign generate-key-pair --kms azurekms://[VAULT_NAME][VAULT_URI]/[KEY] @@ -50,8 +53,9 @@ CAVEATS: ### Options ``` - -h, --help help for generate-key-pair - --kms string create key pair in KMS service to use for signing + -h, --help help for generate-key-pair + --kms string create key pair in KMS service to use for signing + --name cosign adds a chosen name to your .pub and .key files (defaults to cosign) (default "cosign") ``` ### Options inherited from parent commands