Skip to content

Commit

Permalink
feat: add file based signer and password (#1049)
Browse files Browse the repository at this point in the history
* feat: add file based signer and password

Signed-off-by: Asra Ali <asraa@google.com>

lint

Signed-off-by: Asra Ali <asraa@google.com>

fix go

Signed-off-by: Asra Ali <asraa@google.com>

* Add testing comment

Signed-off-by: Asra Ali <asraa@google.com>

Signed-off-by: Asra Ali <asraa@google.com>
  • Loading branch information
asraa committed Sep 15, 2022
1 parent f1b8bae commit 4bb6f44
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 8 deletions.
6 changes: 5 additions & 1 deletion cmd/rekor-server/app/root.go
Expand Up @@ -73,7 +73,11 @@ func init() {
}
rootCmd.PersistentFlags().String("rekor_server.hostname", hostname, "public hostname of instance")
rootCmd.PersistentFlags().String("rekor_server.address", "127.0.0.1", "Address to bind to")
rootCmd.PersistentFlags().String("rekor_server.signer", "memory", "Rekor signer to use. Current valid options include: [gcpkms, memory]")

rootCmd.PersistentFlags().String("rekor_server.signer", "memory",
`Rekor signer to use. Valid options are: [gcpkms, memory, filename containing PEM encoded private key].
Memory and file-based signers should only be used for testing.`)
rootCmd.PersistentFlags().String("rekor_server.signer-passwd", "", "Password to decrypt signer private key")

rootCmd.PersistentFlags().Uint16("port", 3000, "Port to bind to")

Expand Down
5 changes: 4 additions & 1 deletion go.mod
Expand Up @@ -56,6 +56,8 @@ require (

require golang.org/x/exp v0.0.0-20220823124025-807a23277127

require filippo.io/edwards25519 v1.0.0-rc.1 // indirect

require (
cloud.google.com/go v0.103.0 // indirect
cloud.google.com/go/compute v1.7.0 // indirect
Expand Down Expand Up @@ -116,12 +118,13 @@ require (
github.com/x448/float16 v0.8.4 // indirect
go.mongodb.org/mongo-driver v1.10.0 // indirect
go.opencensus.io v0.23.0 // indirect
go.step.sm/crypto v0.19.0
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 // indirect
golang.org/x/sys v0.0.0-20220907062415-87db552b00fd // indirect
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b // indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
google.golang.org/api v0.95.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
Expand Down
8 changes: 7 additions & 1 deletion go.sum
Expand Up @@ -80,6 +80,8 @@ contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod
contrib.go.opencensus.io/exporter/stackdriver v0.13.10/go.mod h1:I5htMbyta491eUxufwwZPQdcKvvgzMB4O9ni41YnIM8=
contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
github.com/Azure/azure-amqp-common-go/v3 v3.2.1/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
github.com/Azure/azure-amqp-common-go/v3 v3.2.2/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
Expand Down Expand Up @@ -715,6 +717,7 @@ github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
Expand Down Expand Up @@ -822,6 +825,8 @@ go.opentelemetry.io/contrib/propagators v0.19.0 h1:HrixVNZYFjUl/Db+Tr3DhqzLsVW9G
go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g=
go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.step.sm/crypto v0.19.0 h1:WxjUDeTDpuPZ1IR3v6c4jc6WdlQlS5IYYQBhfnG5uW0=
go.step.sm/crypto v0.19.0/go.mod h1:qZ+pNU1nV+THwP7TPTNCRMRr9xrRURhETTAK7U5psfw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
Expand Down Expand Up @@ -1107,8 +1112,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b h1:NXqSWXSRUSCaFuvitrWtU169I3876zRTalMRbfd6LL0=
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
3 changes: 2 additions & 1 deletion pkg/api/api.go
Expand Up @@ -90,7 +90,8 @@ func NewAPI(treeID uint) (*API, error) {
log.Logger.Infof("Starting Rekor server with active tree %v", tid)
ranges.SetActive(tid)

rekorSigner, err := signer.New(ctx, viper.GetString("rekor_server.signer"))
rekorSigner, err := signer.New(ctx, viper.GetString("rekor_server.signer"),
viper.GetString("rekor_server.signer-passwd"))
if err != nil {
return nil, fmt.Errorf("getting new signer: %w", err)
}
Expand Down
43 changes: 43 additions & 0 deletions pkg/signer/file.go
@@ -0,0 +1,43 @@
/*
Copyright The Rekor 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 signer

import (
"crypto"
"fmt"

"github.com/sigstore/sigstore/pkg/signature"
"go.step.sm/crypto/pemutil"
)

// returns an file based signer and verify, used for spinning up local instances
type File struct {
signature.SignerVerifier
}

func NewFile(keyPath, keyPass string) (*File, error) {
opaqueKey, err := pemutil.Read(keyPath, pemutil.WithPassword([]byte(keyPass)))
if err != nil {
return nil, fmt.Errorf("file: provide a valid signer, %s is not valid: %w", keyPath, err)
}

signer, err := signature.LoadSignerVerifier(opaqueKey, crypto.SHA256)
if err != nil {
return nil, fmt.Errorf(`file: loaded private key from %s can't be used to sign: %w`, keyPath, err)
}
return &File{signer}, nil
}
72 changes: 72 additions & 0 deletions pkg/signer/file_test.go
@@ -0,0 +1,72 @@
/*
Copyright The Rekor 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 signer

import (
"os"
"path/filepath"
"testing"
)

const testEcdsaKey = `
-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,1ee56fe067d83265fe430391edfa6586
W5NqqRe5rOVe4OvxehYKm6wscR1JFoyRyd8M+Rutp8Q2lxPuKFhR4FZ61b0yy6pr
LGJGQWOTIZxrNZ8g4JeS9I3huDWGloZRI2fbTg69HK4EiQQWUc1wS1TWAVoaf4fr
LclBWxp2UzqHDaNJ0/2DoGFZhaeMU84VA1O41lO+p5Cx4bms0yWeEHwOrf2AmnNY
l5Zm9zoPpXxaDEPSTs5c1loRmmxPHKgb68oZPxEnsCg=
-----END EC PRIVATE KEY-----`

func TestFile(t *testing.T) {
testKeyPass := `password123`
td := t.TempDir()
keyFile := filepath.Join(td, "ecdsa-key.pem")
if err := os.WriteFile(keyFile, []byte(testEcdsaKey), 0644); err != nil {
t.Fatal(err)
}

tests := []struct {
name string
keyPath string
keyPass string
wantErr bool
}{
{
name: "valid ecdsa",
keyPath: keyFile,
keyPass: testKeyPass,
wantErr: false,
},
{
name: "invalid pass",
keyPath: keyFile,
keyPass: "123",
wantErr: true,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
tc := tc
_, err := NewFile(tc.keyPath, tc.keyPass)
if tc.wantErr != (err != nil) {
t.Errorf("NewFile() expected %t, got err %s", tc.wantErr, err)
}
})
}
}
2 changes: 1 addition & 1 deletion pkg/signer/memory_test.go
Expand Up @@ -24,7 +24,7 @@ import (
func TestMemory(t *testing.T) {
ctx := context.Background()

m, err := New(ctx, "memory")
m, err := New(ctx, "memory", "")
if err != nil {
t.Fatalf("new memory: %v", err)
}
Expand Down
5 changes: 2 additions & 3 deletions pkg/signer/signer.go
Expand Up @@ -18,20 +18,19 @@ package signer

import (
"context"
"fmt"
"strings"

"github.com/sigstore/sigstore/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature/kms/gcp"
)

func New(ctx context.Context, signer string) (signature.Signer, error) {
func New(ctx context.Context, signer string, pass string) (signature.Signer, error) {
switch {
case strings.HasPrefix(signer, gcp.ReferenceScheme):
return gcp.LoadSignerVerifier(ctx, signer)
case signer == MemoryScheme:
return NewMemory()
default:
return nil, fmt.Errorf("please provide a valid signer, %v is not valid", signer)
return NewFile(signer, pass)
}
}

0 comments on commit 4bb6f44

Please sign in to comment.