-
Notifications
You must be signed in to change notification settings - Fork 565
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
Importing RSA and EC keypairs #1050
Merged
Merged
Changes from 9 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
3b79cee
initial cmd structure
venafi-iw 28e8b78
import rsa and ec keypairs into cosign
venafi-iw c55d69e
added IMPORT.md for instructions
venafi-iw e899afd
whitespace fix
venafi-iw 34b5bec
PR #1050 fixes
venafi-iw db13da2
fixes and added more tests
venafi-iw ddb2235
fixes and test updates
venafi-iw b2f2056
lint updates
venafi-iw 4f21d45
importkeypair update
venafi-iw 1e0f967
TestImportPrivateKey update
venafi-iw 07ede86
Merge branch 'main' into rsa-import
venafi-iw 86c3ada
TestImportPrivateKey updates
venafi-iw 8cde326
Merge branch 'rsa-import' of https://github.com/venafi-iw/cosign into…
venafi-iw f38a372
Merge branch 'sigstore:main' into rsa-import
venafi-iw 2dfbb28
linting fixes
venafi-iw 660b394
E2E fix
venafi-iw a37d984
conflict fix
venafi-iw 6533f33
Merge branch 'main' into rsa-import
venafi-iw File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Import RSA and EC Keypairs | ||
* Currently only supports RSA and ECDSA private keys | ||
|
||
### Import a keypair | ||
|
||
```shell | ||
$ cosign import-key-pair --key opensslrsakey.pem | ||
Enter password for private key: | ||
Enter password for private key again: | ||
Private key written to import-cosign.key | ||
Public key written to import-cosign.pub | ||
``` | ||
### Sign a container with imported keypair | ||
|
||
```shell | ||
$ cosign sign --key import import-cosign.key dlorenc/demo | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// | ||
// Copyright 2021 The Sigstore Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package cli | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/sigstore/cosign/cmd/cosign/cli/importkeypair" | ||
"github.com/sigstore/cosign/cmd/cosign/cli/options" | ||
) | ||
|
||
func ImportKeyPair() *cobra.Command { | ||
o := &options.ImportKeyPairOptions{} | ||
|
||
cmd := &cobra.Command{ | ||
Use: "import-key-pair", | ||
Short: "Imports a PEM-encoded RSA or EC private key.", | ||
Long: "Imports a PEM-encoded RSA or EC private key for signing.", | ||
Example: ` cosign import-key-pair --key openssl.key | ||
|
||
# import PEM-encoded RSA or EC private key and write to import-cosign.key and import-cosign.pub files | ||
cosign import-key-pair --key <key path> | ||
|
||
CAVEATS: | ||
This command interactively prompts for a password. You can use | ||
the COSIGN_PASSWORD environment variable to provide one.`, | ||
|
||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return importkeypair.ImportKeyPairCmd(cmd.Context(), o.Key, args) | ||
}, | ||
} | ||
|
||
o.AddFlags(cmd) | ||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// | ||
// Copyright 2021 The Sigstore Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package importkeypair | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"os" | ||
|
||
"github.com/pkg/errors" | ||
"github.com/sigstore/cosign/pkg/cosign" | ||
"golang.org/x/term" | ||
) | ||
|
||
var ( | ||
// Read is for fuzzing | ||
Read = readPasswordFn | ||
) | ||
|
||
// nolint | ||
func ImportKeyPairCmd(ctx context.Context, keyVal string, args []string) error { | ||
|
||
keys, err := cosign.ImportKeyPair(keyVal, GetPass) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if fileExists("import-cosign.key") { | ||
var overwrite string | ||
fmt.Fprint(os.Stderr, "File import-cosign.key already exists. Overwrite (y/n)? ") | ||
fmt.Scanf("%s", &overwrite) | ||
switch overwrite { | ||
case "y", "Y": | ||
case "n", "N": | ||
return nil | ||
default: | ||
fmt.Fprintln(os.Stderr, "Invalid input") | ||
return nil | ||
} | ||
} | ||
// TODO: make sure the perms are locked down first. | ||
if err := os.WriteFile("import-cosign.key", keys.PrivateBytes, 0600); err != nil { | ||
return err | ||
} | ||
fmt.Fprintln(os.Stderr, "Private key written to import-cosign.key") | ||
|
||
if err := os.WriteFile("import-cosign.pub", keys.PublicBytes, 0644); err != nil { | ||
return err | ||
} // #nosec G306 | ||
fmt.Fprintln(os.Stderr, "Public key written to import-cosign.pub") | ||
return nil | ||
} | ||
|
||
func GetPass(confirm bool) ([]byte, error) { | ||
read := Read(confirm) | ||
return read() | ||
} | ||
|
||
func readPasswordFn(confirm bool) func() ([]byte, error) { | ||
pw, ok := os.LookupEnv("COSIGN_PASSWORD") | ||
switch { | ||
case ok: | ||
return func() ([]byte, error) { | ||
return []byte(pw), nil | ||
} | ||
case isTerminal(): | ||
return func() ([]byte, error) { | ||
return getPassFromTerm(confirm) | ||
} | ||
// Handle piped in passwords. | ||
default: | ||
return func() ([]byte, error) { | ||
return io.ReadAll(os.Stdin) | ||
} | ||
} | ||
} | ||
|
||
func isTerminal() bool { | ||
stat, _ := os.Stdin.Stat() | ||
return (stat.Mode() & os.ModeCharDevice) != 0 | ||
} | ||
|
||
// TODO centralize password prompt logic for code reuse across more use cases -> https://github.com/sigstore/cosign/issues/1078 | ||
func getPassFromTerm(confirm bool) ([]byte, error) { | ||
asraa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fmt.Fprint(os.Stderr, "Enter password for private key: ") | ||
pw1, err := term.ReadPassword(0) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if !confirm { | ||
return pw1, nil | ||
} | ||
fmt.Fprintln(os.Stderr) | ||
fmt.Fprint(os.Stderr, "Enter password for private key again: ") | ||
confirmpw, err := term.ReadPassword(0) | ||
fmt.Fprintln(os.Stderr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if string(pw1) != string(confirmpw) { | ||
return nil, errors.New("passwords do not match") | ||
} | ||
return pw1, nil | ||
} | ||
|
||
// TODO need to centralize this logic | ||
func fileExists(filename string) bool { | ||
asraa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
info, err := os.Stat(filename) | ||
if os.IsNotExist(err) { | ||
return false | ||
} | ||
return !info.IsDir() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// | ||
// Copyright 2021 The Sigstore Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package importkeypair | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
) | ||
|
||
func TestReadPasswordFn_env(t *testing.T) { | ||
os.Setenv("COSIGN_PASSWORD", "foo") | ||
defer os.Unsetenv("COSIGN_PASSWORD") | ||
b, err := readPasswordFn(true)() | ||
if err != nil { | ||
t.Fatalf("unexpected error: %v", err) | ||
} | ||
if diff := cmp.Diff("foo", string(b)); diff != "" { | ||
t.Fatal(diff) | ||
} | ||
} | ||
|
||
func TestReadPasswordFn_envEmptyVal(t *testing.T) { | ||
os.Setenv("COSIGN_PASSWORD", "") | ||
defer os.Unsetenv("COSIGN_PASSWORD") | ||
b, err := readPasswordFn(true)() | ||
if err != nil { | ||
t.Fatalf("unexpected error: %v", err) | ||
} | ||
if len(b) > 0 { | ||
t.Fatalf("expected empty string; got %q", string(b)) | ||
} | ||
} | ||
asraa marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// | ||
// Copyright 2021 The Sigstore Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package options | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// ImportKeyPairOptions is the top level wrapper for the import-key-pair command. | ||
type ImportKeyPairOptions struct { | ||
// Local key file generated by external program such as OpenSSL | ||
Key string | ||
} | ||
|
||
var _ Interface = (*ImportKeyPairOptions)(nil) | ||
|
||
// AddFlags implements Interface | ||
func (o *ImportKeyPairOptions) AddFlags(cmd *cobra.Command) { | ||
cmd.Flags().StringVar(&o.Key, "key", "", | ||
"import key pair to use for signing") | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this
import
is needed?or should be just
cosign sign --key import-cosign.key dlorenc/demo
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
documentation needs to be updated as it should be:
cosign sign --key import-cosign.key dlorenc/demo
#1290