Skip to content
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

feat: add file based signer and password #1049

Merged
merged 2 commits into from Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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)
}
}