Skip to content

Commit

Permalink
feat: add "env://" scheme for key lookup
Browse files Browse the repository at this point in the history
Tested manually as well:

```shell
$ export COSIGN_PASSWORD=foo
$ cosign generate-key-pair
Enter password for private key:
Enter password for private key again:
Private key written to cosign.key
Public key written to cosign.pub
$ export MYPRIVKEY="$(cat cosign.key)"
$ export MYPUBKEY="$(cat cosign.pub)"
$ cosign verify-blob --key env://MYPUBKEY /dev/null --signature <(cosign sign-blob --key env://MYPRIVKEY /dev/null)
Using payload from: /dev/null
tlog entry created with index: 2095539
tlog entry verified with uuid: dd55086556d7ac0cded8f50961b68f7740e1435fbc5bb47460a8d78321313c7d index: 2095539
Verified OK
```

Signed-off-by: Zachary Newman <[email protected]>
  • Loading branch information
znewman01 committed Apr 23, 2022
1 parent 8ab0a70 commit 52de4c1
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 5 deletions.
3 changes: 3 additions & 0 deletions cmd/cosign/cli/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ func Sign() *cobra.Command {
# sign a container image and add annotations
cosign sign --key cosign.key -a key1=value1 -a key2=value2 <IMAGE>
# sign a container image with a key stored in an environment variable
cosign sign --key env://[ENV_VAR] <IMAGE>
# sign a container image with a key pair stored in Azure Key Vault
cosign sign --key azurekms://[VAULT_NAME][VAULT_URI]/[KEY] <IMAGE>
Expand Down
3 changes: 3 additions & 0 deletions cmd/cosign/cli/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ against the transparency log.`,
# verify image with public key provided by URL
cosign verify --key https://host.for/[FILE] <IMAGE>
# verify image with a key stored in an environment variable
cosign verify --key env://[ENV_VAR] <IMAGE>
# verify image with public key stored in Google Cloud KMS
cosign verify --key gcpkms://projects/[PROJECT]/locations/global/keyRings/[KEYRING]/cryptoKeys/[KEY] <IMAGE>
Expand Down
12 changes: 7 additions & 5 deletions pkg/signature/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import (
"crypto"
"crypto/x509"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/pkg/errors"
Expand Down Expand Up @@ -86,7 +84,7 @@ func VerifierForKeyRef(ctx context.Context, keyRef string, hashAlgorithm crypto.
}

func loadKey(keyPath string, pf cosign.PassFunc) (signature.SignerVerifier, error) {
kb, err := os.ReadFile(filepath.Clean(keyPath))
kb, err := blob.LoadFileOrURL(keyPath)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -169,10 +167,14 @@ func SignerVerifierFromKeyRef(ctx context.Context, keyRef string, pf cosign.Pass

if strings.Contains(keyRef, "://") {
sv, err := kms.Get(ctx, keyRef, crypto.SHA256)
if err != nil {
if err == nil {
return sv, nil
}
var e *kms.ProviderNotFoundError
if !errors.As(err, &e) {
return nil, fmt.Errorf("kms get: %w", err)
}
return sv, nil
// ProviderNotFoundError is okay; loadKey handles other URL schemes
}

return loadKey(keyRef, pf)
Expand Down
29 changes: 29 additions & 0 deletions pkg/signature/keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,35 @@ func TestPublicKeyFromFileRef(t *testing.T) {
}
}

func TestPublicKeyFromEnvVar(t *testing.T) {
keys, err := cosign.GenerateKeyPair(pass("whatever"))
if err != nil {
t.Fatalf("failed to generate keypair: %v", err)
}
ctx := context.Background()

os.Setenv("MY_ENV_VAR", string(keys.PublicBytes))
defer os.Unsetenv("MY_ENV_VAR")
if _, err := PublicKeyFromKeyRef(ctx, "env://MY_ENV_VAR"); err != nil {
t.Fatalf("PublicKeyFromKeyRef returned error: %v", err)
}
}

func TestSignerVerifierFromEnvVar(t *testing.T) {
passFunc := pass("whatever")
keys, err := cosign.GenerateKeyPair(passFunc)
if err != nil {
t.Fatalf("failed to generate keypair: %v", err)
}
ctx := context.Background()

os.Setenv("MY_ENV_VAR", string(keys.PrivateBytes))
defer os.Unsetenv("MY_ENV_VAR")
if _, err := SignerVerifierFromKeyRef(ctx, "env://MY_ENV_VAR", passFunc); err != nil {
t.Fatalf("SignerVerifierFromKeyRef returned error: %v", err)
}
}

func pass(s string) cosign.PassFunc {
return func(_ bool) ([]byte, error) {
return []byte(s), nil
Expand Down

0 comments on commit 52de4c1

Please sign in to comment.