Skip to content

Commit

Permalink
Allow passing keys via environment variables (env:// refs) (#1794)
Browse files Browse the repository at this point in the history
* Bump github.com/sigstore/sigstore

Signed-off-by: Zachary Newman <[email protected]>

* test: add test for blob.LoadFileOrURL

Signed-off-by: Zachary Newman <[email protected]>

* refactor: break up LoadFileOrURL by scheme

Signed-off-by: Zachary Newman <[email protected]>

* feat: add "env://" scheme for blob load

Signed-off-by: Zachary Newman <[email protected]>

* feat: add "env://" scheme for key lookup

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]>

* test: skip test that flakes on Windows

Signed-off-by: Zachary Newman <[email protected]>
  • Loading branch information
znewman01 authored Apr 24, 2022
1 parent 683a6c0 commit 0c4cf2e
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 37 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
3 changes: 3 additions & 0 deletions doc/cosign_sign.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions doc/cosign_verify.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ require (
github.com/secure-systems-lab/go-securesystemslib v0.3.1
github.com/sigstore/fulcio v0.1.2-0.20220114150912-86a2036f9bc7
github.com/sigstore/rekor v0.4.1-0.20220114213500-23f583409af3
github.com/sigstore/sigstore v1.2.1-0.20220401110139-0e610e39782f
github.com/sigstore/sigstore v1.2.1-0.20220424143412-3d41663116d5
github.com/spf13/cobra v1.4.0
github.com/spf13/viper v1.11.0
github.com/spiffe/go-spiffe/v2 v2.0.0
Expand Down Expand Up @@ -113,9 +113,9 @@ require (
cloud.google.com/go/kms v1.4.0 // indirect
contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d // indirect
contrib.go.opencensus.io/exporter/prometheus v0.4.0 // indirect
github.com/Azure/azure-sdk-for-go v63.2.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go v63.3.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.25 // indirect
github.com/Azure/go-autorest/autorest v0.11.27 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
Expand All @@ -131,7 +131,7 @@ require (
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/ReneKroon/ttlcache/v2 v2.11.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
github.com/aws/aws-sdk-go v1.43.37 // indirect
github.com/aws/aws-sdk-go v1.43.45 // indirect
github.com/aws/aws-sdk-go-v2 v1.14.0 // indirect
github.com/aws/aws-sdk-go-v2/config v1.14.0 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.9.0 // indirect
Expand Down
34 changes: 16 additions & 18 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,8 @@ github.com/Azure/azure-sdk-for-go v59.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo
github.com/Azure/azure-sdk-for-go v60.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v60.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v62.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v63.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v63.2.0+incompatible h1:OIqkK/zTGqVUuzpEvY0B1YSYDRAFC/j+y0w2GovCggI=
github.com/Azure/azure-sdk-for-go v63.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v63.3.0+incompatible h1:INepVujzUrmArRZjDLHbtER+FkvCoEwyRCXGqOlmDII=
github.com/Azure/azure-sdk-for-go v63.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0=
github.com/Azure/azure-service-bus-go v0.11.5/go.mod h1:MI6ge2CuQWBVq+ly456MY7XqNLJip5LO1iSFodbNLbU=
github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0=
Expand All @@ -154,8 +153,8 @@ github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgq
github.com/Azure/go-autorest/autorest v0.11.19/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.22/go.mod h1:BAWYUWGPEtKPzjVkp0Q6an0MJcJDsoh5Z1BFAEFs4Xs=
github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
github.com/Azure/go-autorest/autorest v0.11.25 h1:yp+V8DGur2aIUE87ebP8twPLz6k68jtJTlg61mEoByA=
github.com/Azure/go-autorest/autorest v0.11.25/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A=
github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
github.com/Azure/go-autorest/autorest/adal v0.9.4/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
Expand Down Expand Up @@ -325,9 +324,8 @@ github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zK
github.com/aws/aws-sdk-go v1.42.8/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.42.22/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.42.25/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs=
github.com/aws/aws-sdk-go v1.43.30/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.43.37 h1:kyZ7UjaPZaCik+asF33UFOOYSwr9liDRr/UM/vuw8yY=
github.com/aws/aws-sdk-go v1.43.37/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go v1.43.45 h1:2708Bj4uV+ym62MOtBnErm/CDX61C4mFe9V2gXy1caE=
github.com/aws/aws-sdk-go v1.43.45/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.7.1/go.mod h1:L5LuPC1ZgDr2xQS7AmIec/Jlc7O/Y1u2KxJyNVab250=
github.com/aws/aws-sdk-go-v2 v1.11.0/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ=
Expand Down Expand Up @@ -951,8 +949,8 @@ github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8w
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-rod/rod v0.101.8/go.mod h1:N/zlT53CfSpq74nb6rOR0K8UF0SPUPBmzBnArrms+mY=
github.com/go-rod/rod v0.104.4 h1:sQR35AFo9ceR7ksh+Ld81bQzIbrXlQH/IO46iCWqxts=
github.com/go-rod/rod v0.104.4/go.mod h1:trmrxxg+qUodIIQiYeyJbW5ZMo0FSajmdEGw2tHzlM4=
github.com/go-rod/rod v0.106.1 h1:+9YdoTT56KI3KrFfWVr3I13wh0qbhm/Aq+7JvCBA6AQ=
github.com/go-rod/rod v0.106.1/go.mod h1:+YLe2X+nAuEGpYWs7rKPZr9SMX100FbxYZaeU1Dofpc=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
Expand Down Expand Up @@ -2034,8 +2032,8 @@ github.com/sigstore/rekor v0.4.1-0.20220114213500-23f583409af3 h1:mbqXrm8YZXN/cJ
github.com/sigstore/rekor v0.4.1-0.20220114213500-23f583409af3/go.mod h1:u9clLqaVjqV9pExVL1XkM37dGyMCOX/LMocS9nsnWDY=
github.com/sigstore/sigstore v1.0.2-0.20211210190220-04746d994282/go.mod h1:SuM+QIHtnnR9eGsURRLv5JfxM6KeaU0XKA1O7FmLs4Q=
github.com/sigstore/sigstore v1.1.0/go.mod h1:gDpcHw4VwpoL5C6N1Ud1YtBsc+ikRDwDelDlWRyYoE8=
github.com/sigstore/sigstore v1.2.1-0.20220401110139-0e610e39782f h1:JPD9q1718mub78ILVcTqOZ/q4ECKCQ7JQfUX/q+nEJ4=
github.com/sigstore/sigstore v1.2.1-0.20220401110139-0e610e39782f/go.mod h1:9wYagRiKz/8KgK/YFPM6FA8WrNjv3Y6rQUQWBLqJXs0=
github.com/sigstore/sigstore v1.2.1-0.20220424143412-3d41663116d5 h1:8OL06Knchax4CMtdfquC3ASWQPtYMJgyeQImWQPw6XE=
github.com/sigstore/sigstore v1.2.1-0.20220424143412-3d41663116d5/go.mod h1:OvpZniSE9oRPnW7+mhxljRt2RAQU+TwcnhYbqQsPwPc=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
Expand Down Expand Up @@ -2255,15 +2253,15 @@ github.com/yashtewari/glob-intersection v0.0.0-20180916065949-5c77d914dd0b/go.mo
github.com/yeya24/promlinter v0.1.0/go.mod h1:rs5vtZzeBHqqMwXqFScncpCF6u06lezhZepno9AB1Oc=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/ysmood/goob v0.3.0/go.mod h1:S3lq113Y91y1UBf1wj1pFOxeahvfKkCk6mTWTWbDdWs=
github.com/ysmood/goob v0.3.1 h1:qMp5364BGS1DLJVrAqUxTF6KOFt0YDot8GC70u/0jbI=
github.com/ysmood/goob v0.3.1/go.mod h1:S3lq113Y91y1UBf1wj1pFOxeahvfKkCk6mTWTWbDdWs=
github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ=
github.com/ysmood/goob v0.4.0/go.mod h1:u6yx7ZhS4Exf2MwciFr6nIM8knHQIE22lFpWHnfql18=
github.com/ysmood/got v0.15.1/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY=
github.com/ysmood/got v0.19.1/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY=
github.com/ysmood/got v0.23.3/go.mod h1:pE1l4LOwOBhQg6A/8IAatkGp7uZjnalzrZolnlhhMgY=
github.com/ysmood/gotrace v0.2.2/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM=
github.com/ysmood/gotrace v0.4.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM=
github.com/ysmood/gotrace v0.6.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM=
github.com/ysmood/gson v0.6.4/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg=
github.com/ysmood/gson v0.7.0 h1:oQhY2FQtfy3+bgaNeqopd7NGAB6Me+UpG0n7oO4VDko=
github.com/ysmood/gson v0.7.0/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg=
github.com/ysmood/gson v0.7.1 h1:zKL2MTGtynxdBdlZjyGsvEOZ7dkxaY5TH6QhAbTgz0Q=
github.com/ysmood/gson v0.7.1/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg=
github.com/ysmood/leakless v0.7.0 h1:XCGdaPExyoreoQd+H5qgxM3ReNbSPFsEXpSKwbXbwQw=
github.com/ysmood/leakless v0.7.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
Expand Down
37 changes: 27 additions & 10 deletions pkg/blob/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package blob

import (
"fmt"
"io"
"net/http"
"os"
Expand All @@ -25,16 +26,32 @@ import (
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 = io.ReadAll(resp.Body)
if err != nil {
return nil, err
parts := strings.SplitAfterN(fileRef, "://", 2)
if len(parts) == 2 {
scheme := parts[0]
switch scheme {
case "http://":
fallthrough
case "https://":
// #nosec G107
resp, err := http.Get(fileRef)
if err != nil {
return nil, err
}
defer resp.Body.Close()
raw, err = io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
case "env://":
envVar := parts[1]
value, found := os.LookupEnv(envVar)
if !found {
return nil, fmt.Errorf("loading URL: env var $%s not found", envVar)
}
raw = []byte(value)
default:
return nil, fmt.Errorf("loading URL: unrecognized scheme: %s", scheme)
}
} else {
raw, err = os.ReadFile(filepath.Clean(fileRef))
Expand Down
99 changes: 99 additions & 0 deletions pkg/blob/load_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// 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 blob

import (
"bytes"
"net/http"
"net/http/httptest"
"os"
"path"
"runtime"
"testing"
)

func TestLoadFile(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("Skipping on Windows due to https://github.com/golang/go/issues/51442")
}
temp := t.TempDir()
fname := "filename.txt"
path := path.Join(temp, fname)
data := []byte("test")
defer os.Remove(path)
os.WriteFile(path, data, 0400)

// absolute path
actual, err := LoadFileOrURL(path)
if err != nil {
t.Errorf("Reading from absolute path %s failed: %v", path, err)
} else if !bytes.Equal(actual, data) {
t.Errorf("LoadFileOrURL(absolute path) = '%s'; want '%s'", actual, data)
}

if err = os.Chdir(temp); err != nil {
t.Fatalf("Chdir('%s'): %v", temp, err)
}
actual, err = LoadFileOrURL(fname)
if err != nil {
t.Errorf("Reading from relative path %s failed: %v", fname, err)
} else if !bytes.Equal(actual, data) {
t.Errorf("LoadFileOrURL(relative path) = '%s'; want '%s'", actual, data)
}
}

func TestLoadURL(t *testing.T) {
data := []byte("test")

server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Write(data)
}))
defer server.Close()

actual, err := LoadFileOrURL(server.URL)
if err != nil {
t.Errorf("Reading from HTTP failed: %v", err)
} else if !bytes.Equal(actual, data) {
t.Errorf("LoadFileOrURL(HTTP) = '%s'; want '%s'", actual, data)
}

os.Setenv("MY_ENV_VAR", string(data))
actual, err = LoadFileOrURL("env://MY_ENV_VAR")
if err != nil {
t.Errorf("Reading from environment failed: %v", err)
} else if !bytes.Equal(actual, data) {
t.Errorf("LoadFileOrURL(env) = '%s'; want '%s'", actual, data)
}

os.Setenv("MY_ENV_VAR", "")
actual, err = LoadFileOrURL("env://MY_ENV_VAR")
if err != nil {
t.Errorf("Reading from environment failed: %v", err)
} else if !bytes.Equal(actual, make([]byte, 0)) {
t.Errorf("LoadFileOrURL(env) = '%s'; should be empty", actual)
}

os.Unsetenv("MY_ENV_VAR")
_, err = LoadFileOrURL("env://MY_ENV_VAR")
if err == nil {
t.Error("LoadFileOrURL(): expected error for unset env var")
}

_, err = LoadFileOrURL("invalid://url")
if err == nil {
t.Error("LoadFileOrURL(): expected error for invalid scheme")
}
}
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 0c4cf2e

Please sign in to comment.