Skip to content

Commit 4bb6f44

Browse files
authored
feat: add file based signer and password (sigstore#1049)
* 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>
1 parent f1b8bae commit 4bb6f44

File tree

8 files changed

+136
-8
lines changed

8 files changed

+136
-8
lines changed

cmd/rekor-server/app/root.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ func init() {
7373
}
7474
rootCmd.PersistentFlags().String("rekor_server.hostname", hostname, "public hostname of instance")
7575
rootCmd.PersistentFlags().String("rekor_server.address", "127.0.0.1", "Address to bind to")
76-
rootCmd.PersistentFlags().String("rekor_server.signer", "memory", "Rekor signer to use. Current valid options include: [gcpkms, memory]")
76+
77+
rootCmd.PersistentFlags().String("rekor_server.signer", "memory",
78+
`Rekor signer to use. Valid options are: [gcpkms, memory, filename containing PEM encoded private key].
79+
Memory and file-based signers should only be used for testing.`)
80+
rootCmd.PersistentFlags().String("rekor_server.signer-passwd", "", "Password to decrypt signer private key")
7781

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

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ require (
5656

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

59+
require filippo.io/edwards25519 v1.0.0-rc.1 // indirect
60+
5961
require (
6062
cloud.google.com/go v0.103.0 // indirect
6163
cloud.google.com/go/compute v1.7.0 // indirect
@@ -116,12 +118,13 @@ require (
116118
github.com/x448/float16 v0.8.4 // indirect
117119
go.mongodb.org/mongo-driver v1.10.0 // indirect
118120
go.opencensus.io v0.23.0 // indirect
121+
go.step.sm/crypto v0.19.0
119122
go.uber.org/atomic v1.9.0 // indirect
120123
go.uber.org/multierr v1.8.0 // indirect
121124
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 // indirect
122125
golang.org/x/sys v0.0.0-20220907062415-87db552b00fd // indirect
123126
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
124-
golang.org/x/text v0.3.7 // indirect
127+
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b // indirect
125128
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
126129
google.golang.org/api v0.95.0 // indirect
127130
google.golang.org/appengine v1.6.7 // indirect

go.sum

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod
8080
contrib.go.opencensus.io/exporter/stackdriver v0.13.10/go.mod h1:I5htMbyta491eUxufwwZPQdcKvvgzMB4O9ni41YnIM8=
8181
contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
8282
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
83+
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
84+
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
8385
github.com/Azure/azure-amqp-common-go/v3 v3.2.1/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
8486
github.com/Azure/azure-amqp-common-go/v3 v3.2.2/go.mod h1:O6X1iYHP7s2x7NjUKsXVhkwWrQhxrd+d8/3rRadj4CI=
8587
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
@@ -715,6 +717,7 @@ github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
715717
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
716718
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
717719
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
720+
github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY=
718721
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
719722
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
720723
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
@@ -822,6 +825,8 @@ go.opentelemetry.io/contrib/propagators v0.19.0 h1:HrixVNZYFjUl/Db+Tr3DhqzLsVW9G
822825
go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g=
823826
go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw=
824827
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
828+
go.step.sm/crypto v0.19.0 h1:WxjUDeTDpuPZ1IR3v6c4jc6WdlQlS5IYYQBhfnG5uW0=
829+
go.step.sm/crypto v0.19.0/go.mod h1:qZ+pNU1nV+THwP7TPTNCRMRr9xrRURhETTAK7U5psfw=
825830
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
826831
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
827832
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
@@ -1107,8 +1112,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
11071112
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
11081113
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
11091114
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
1110-
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
11111115
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
1116+
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b h1:NXqSWXSRUSCaFuvitrWtU169I3876zRTalMRbfd6LL0=
1117+
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
11121118
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
11131119
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
11141120
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

pkg/api/api.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ func NewAPI(treeID uint) (*API, error) {
9090
log.Logger.Infof("Starting Rekor server with active tree %v", tid)
9191
ranges.SetActive(tid)
9292

93-
rekorSigner, err := signer.New(ctx, viper.GetString("rekor_server.signer"))
93+
rekorSigner, err := signer.New(ctx, viper.GetString("rekor_server.signer"),
94+
viper.GetString("rekor_server.signer-passwd"))
9495
if err != nil {
9596
return nil, fmt.Errorf("getting new signer: %w", err)
9697
}

pkg/signer/file.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
Copyright The Rekor Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package signer
18+
19+
import (
20+
"crypto"
21+
"fmt"
22+
23+
"github.com/sigstore/sigstore/pkg/signature"
24+
"go.step.sm/crypto/pemutil"
25+
)
26+
27+
// returns an file based signer and verify, used for spinning up local instances
28+
type File struct {
29+
signature.SignerVerifier
30+
}
31+
32+
func NewFile(keyPath, keyPass string) (*File, error) {
33+
opaqueKey, err := pemutil.Read(keyPath, pemutil.WithPassword([]byte(keyPass)))
34+
if err != nil {
35+
return nil, fmt.Errorf("file: provide a valid signer, %s is not valid: %w", keyPath, err)
36+
}
37+
38+
signer, err := signature.LoadSignerVerifier(opaqueKey, crypto.SHA256)
39+
if err != nil {
40+
return nil, fmt.Errorf(`file: loaded private key from %s can't be used to sign: %w`, keyPath, err)
41+
}
42+
return &File{signer}, nil
43+
}

pkg/signer/file_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
Copyright The Rekor Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package signer
18+
19+
import (
20+
"os"
21+
"path/filepath"
22+
"testing"
23+
)
24+
25+
const testEcdsaKey = `
26+
-----BEGIN EC PRIVATE KEY-----
27+
Proc-Type: 4,ENCRYPTED
28+
DEK-Info: AES-256-CBC,1ee56fe067d83265fe430391edfa6586
29+
30+
W5NqqRe5rOVe4OvxehYKm6wscR1JFoyRyd8M+Rutp8Q2lxPuKFhR4FZ61b0yy6pr
31+
LGJGQWOTIZxrNZ8g4JeS9I3huDWGloZRI2fbTg69HK4EiQQWUc1wS1TWAVoaf4fr
32+
LclBWxp2UzqHDaNJ0/2DoGFZhaeMU84VA1O41lO+p5Cx4bms0yWeEHwOrf2AmnNY
33+
l5Zm9zoPpXxaDEPSTs5c1loRmmxPHKgb68oZPxEnsCg=
34+
-----END EC PRIVATE KEY-----`
35+
36+
func TestFile(t *testing.T) {
37+
testKeyPass := `password123`
38+
td := t.TempDir()
39+
keyFile := filepath.Join(td, "ecdsa-key.pem")
40+
if err := os.WriteFile(keyFile, []byte(testEcdsaKey), 0644); err != nil {
41+
t.Fatal(err)
42+
}
43+
44+
tests := []struct {
45+
name string
46+
keyPath string
47+
keyPass string
48+
wantErr bool
49+
}{
50+
{
51+
name: "valid ecdsa",
52+
keyPath: keyFile,
53+
keyPass: testKeyPass,
54+
wantErr: false,
55+
},
56+
{
57+
name: "invalid pass",
58+
keyPath: keyFile,
59+
keyPass: "123",
60+
wantErr: true,
61+
},
62+
}
63+
for _, tc := range tests {
64+
t.Run(tc.name, func(t *testing.T) {
65+
tc := tc
66+
_, err := NewFile(tc.keyPath, tc.keyPass)
67+
if tc.wantErr != (err != nil) {
68+
t.Errorf("NewFile() expected %t, got err %s", tc.wantErr, err)
69+
}
70+
})
71+
}
72+
}

pkg/signer/memory_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
func TestMemory(t *testing.T) {
2525
ctx := context.Background()
2626

27-
m, err := New(ctx, "memory")
27+
m, err := New(ctx, "memory", "")
2828
if err != nil {
2929
t.Fatalf("new memory: %v", err)
3030
}

pkg/signer/signer.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,19 @@ package signer
1818

1919
import (
2020
"context"
21-
"fmt"
2221
"strings"
2322

2423
"github.com/sigstore/sigstore/pkg/signature"
2524
"github.com/sigstore/sigstore/pkg/signature/kms/gcp"
2625
)
2726

28-
func New(ctx context.Context, signer string) (signature.Signer, error) {
27+
func New(ctx context.Context, signer string, pass string) (signature.Signer, error) {
2928
switch {
3029
case strings.HasPrefix(signer, gcp.ReferenceScheme):
3130
return gcp.LoadSignerVerifier(ctx, signer)
3231
case signer == MemoryScheme:
3332
return NewMemory()
3433
default:
35-
return nil, fmt.Errorf("please provide a valid signer, %v is not valid", signer)
34+
return NewFile(signer, pass)
3635
}
3736
}

0 commit comments

Comments
 (0)