Skip to content

Commit 3aec76f

Browse files
Add COSE support to Rekor (sigstore#867)
* WIP: Add COSE support to Rekor This commit adds COSE Sign1 support to rekor via a new data type. COSE is defined in RFC8152, and provides a signing message envelope. This is supported in rekor using the veraison/go-cose library. The new API type requires the signed content, the signature envelope, and the public key. The public key is in the standard rekor PKI format, at the moment only ECDSA P256 with SHA256 is supported. The signed message only supports in-line bodies (no URL fetching), and there is no support for pre-hashed entries. Signed-off-by: Dan Lorenc <lorenc.d@gmail.com> * Completed basic support for COSE records. This adds some more functionality related to COSE enveleopes. Features added are: - Support for specifying Additional Authentincated Data (AAD) - The entire CBOR envelope is stored as an attestation - If the payload type is an in-toto statement, subject is indexed What's not optimal is that the COSE envelope is using the regular `Attestion()` functionality, which means that rekor cli tries to print it during `rekor-cli get` and the response record from Rekor looks a bit awkward. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Updated the documentation for COSE envelopes. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Resolved merge conflicts with main. The biggest change is adapting the new interface where attestation func is split to two, one to get the key and a nother to get key/val. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Ran go mod tidy after resolving merge committs. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Added check to see that provided EC key uses the P256 curve. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Spelled out aad when printing the help message. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Updated copyright notice to have current (2022) year. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Removed direct dependency on github.com/pkg/errors and replaced with stdlib errors package. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Fixed a bug where nil was wrongfully returned instead of err. Also increas the general test coverage. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Changed aad in artifact properties struct to be []byte instead of string. This gives the caller the possibility to decide how to decode the data. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Fixed a warning from the linter. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * Added test case for malformed base64 aad parameter. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> * During signature validation, do not store any state until entire validation is done. Signed-off-by: Fredrik Skogman <kommendorkapten@github.com> Co-authored-by: Dan Lorenc <lorenc.d@gmail.com>
1 parent bd717e7 commit 3aec76f

25 files changed

+2253
-10
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ KO_PREFIX ?= gcr.io/projectsigstore
4747
export KO_DOCKER_REPO=$(KO_PREFIX)
4848
REKOR_YAML ?= rekor-$(GIT_TAG).yaml
4949
GHCR_PREFIX ?= ghcr.io/sigstore/rekor
50+
GOBIN ?= $(shell go env GOPATH)/bin
5051

5152
# Binaries
5253
SWAGGER := $(TOOLS_BIN_DIR)/swagger

cmd/rekor-cli/app/pflag_groups.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package app
1717

1818
import (
19+
"encoding/base64"
1920
"errors"
2021
"fmt"
2122
"net/url"
@@ -87,6 +88,11 @@ func addArtifactPFlags(cmd *cobra.Command) error {
8788
"path or URL to pre-formatted entry file",
8889
false,
8990
},
91+
"aad": {
92+
base64Flag,
93+
"base64 encoded additional authenticated data",
94+
false,
95+
},
9096
}
9197

9298
for flag, flagVal := range flags {
@@ -152,6 +158,10 @@ func CreatePropsFromPflags() *types.ArtifactProperties {
152158
}
153159

154160
props.PKIFormat = viper.GetString("pki-format")
161+
b64aad := viper.GetString("aad")
162+
if b64aad != "" {
163+
props.AdditionalAuthenticatedData, _ = base64.StdEncoding.DecodeString(b64aad)
164+
}
155165

156166
return props
157167
}

cmd/rekor-cli/app/pflags.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package app
1717

1818
import (
19+
"encoding/base64"
1920
"fmt"
2021
"log"
2122
"strconv"
@@ -46,6 +47,7 @@ const (
4647
oidFlag FlagType = "oid"
4748
formatFlag FlagType = "format"
4849
timeoutFlag FlagType = "timeout"
50+
base64Flag FlagType = "base64"
4951
)
5052

5153
type newPFlagValueFunc func() pflag.Value
@@ -105,6 +107,10 @@ func initializePFlagMap() {
105107
// this validates the timeout is >= 0
106108
return valueFactory(formatFlag, validateTimeout, "")
107109
},
110+
base64Flag: func() pflag.Value {
111+
// This validates the string is in base64 format
112+
return valueFactory(base64Flag, validateBase64, "")
113+
},
108114
}
109115
}
110116

@@ -239,6 +245,13 @@ func validateTimeout(v string) error {
239245
return useValidator(timeoutFlag, d)
240246
}
241247

248+
// validateBase64 ensures that the supplied string is valid base64 encoded data
249+
func validateBase64(v string) error {
250+
_, err := base64.StdEncoding.DecodeString(v)
251+
252+
return err
253+
}
254+
242255
// validateTypeFlag ensures that the string is in the format type(\.version)? and
243256
// that one of the types requested is implemented
244257
func validateTypeFlag(v string) error {

cmd/rekor-cli/app/pflags_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ func TestArtifactPFlags(t *testing.T) {
3838
signature string
3939
publicKey string
4040
uuid string
41+
aad string
4142
uuidRequired bool
4243
logIndex string
4344
logIndexRequired bool
@@ -346,6 +347,32 @@ func TestArtifactPFlags(t *testing.T) {
346347
expectParseSuccess: true,
347348
expectValidateSuccess: false,
348349
},
350+
{
351+
caseDesc: "valid cose, with aad",
352+
typeStr: "cose",
353+
artifact: "../../../tests/test_cose.cbor",
354+
publicKey: "../../../tests/test_cose.pub",
355+
expectParseSuccess: true,
356+
expectValidateSuccess: true,
357+
aad: "dGVzdCBhYWQ=",
358+
},
359+
{
360+
caseDesc: "valid cose, malformed base64 aad",
361+
typeStr: "cose",
362+
artifact: "../../../tests/test_cose.cbor",
363+
publicKey: "../../../tests/test_cose.pub",
364+
expectParseSuccess: false,
365+
expectValidateSuccess: true,
366+
aad: "dGVzdCBhYWQ]",
367+
},
368+
{
369+
caseDesc: "valid cose, missing aad",
370+
typeStr: "cose",
371+
artifact: "../../../tests/test_cose.cbor",
372+
publicKey: "../../../tests/test_cose.pub",
373+
expectParseSuccess: true,
374+
expectValidateSuccess: false,
375+
},
349376
}
350377

351378
for _, tc := range tests {
@@ -384,6 +411,9 @@ func TestArtifactPFlags(t *testing.T) {
384411
if tc.logIndex != "" {
385412
args = append(args, "--log-index", tc.logIndex)
386413
}
414+
if tc.aad != "" {
415+
args = append(args, "--aad", tc.aad)
416+
}
387417

388418
if err := blankCmd.ParseFlags(args); (err == nil) != tc.expectParseSuccess {
389419
t.Errorf("unexpected result parsing '%v': %v", tc.caseDesc, err)

cmd/rekor-cli/app/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828

2929
// these imports are to call the packages' init methods
3030
_ "github.com/sigstore/rekor/pkg/types/alpine/v0.0.1"
31+
_ "github.com/sigstore/rekor/pkg/types/cose/v0.0.1"
3132
_ "github.com/sigstore/rekor/pkg/types/hashedrekord/v0.0.1"
3233
_ "github.com/sigstore/rekor/pkg/types/helm/v0.0.1"
3334
_ "github.com/sigstore/rekor/pkg/types/intoto/v0.0.1"

cmd/rekor-server/app/serve.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import (
3131
"github.com/sigstore/rekor/pkg/log"
3232
"github.com/sigstore/rekor/pkg/types/alpine"
3333
alpine_v001 "github.com/sigstore/rekor/pkg/types/alpine/v0.0.1"
34+
"github.com/sigstore/rekor/pkg/types/cose"
35+
cose_v001 "github.com/sigstore/rekor/pkg/types/cose/v0.0.1"
3436
hashedrekord "github.com/sigstore/rekor/pkg/types/hashedrekord"
3537
hashedrekord_v001 "github.com/sigstore/rekor/pkg/types/hashedrekord/v0.0.1"
3638
"github.com/sigstore/rekor/pkg/types/helm"
@@ -87,6 +89,7 @@ var serveCmd = &cobra.Command{
8789
rpm.KIND: rpm_v001.APIVERSION,
8890
jar.KIND: jar_v001.APIVERSION,
8991
intoto.KIND: intoto_v001.APIVERSION,
92+
cose.KIND: cose_v001.APIVERSION,
9093
rfc3161.KIND: rfc3161_v001.APIVERSION,
9194
alpine.KIND: alpine_v001.APIVERSION,
9295
helm.KIND: helm_v001.APIVERSION,

go.mod

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ require (
2525
github.com/mediocregopher/radix/v4 v4.1.0
2626
github.com/mitchellh/go-homedir v1.1.0
2727
github.com/mitchellh/mapstructure v1.5.0
28+
github.com/pkg/errors v0.9.1 // indirect
2829
github.com/prometheus/client_golang v1.12.2
2930
github.com/rs/cors v1.8.2
3031
github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74
@@ -37,6 +38,8 @@ require (
3738
github.com/theupdateframework/go-tuf v0.3.0
3839
github.com/transparency-dev/merkle v0.0.1
3940
github.com/urfave/negroni v1.0.0
41+
github.com/veraison/go-cose v1.0.0-alpha.1
42+
github.com/zalando/go-keyring v0.1.1 // indirect
4043
go.uber.org/goleak v1.1.12
4144
go.uber.org/zap v1.21.0
4245
gocloud.dev v0.24.1-0.20211119014450-028788aaaa4c
@@ -66,6 +69,7 @@ require (
6669
github.com/danieljoos/wincred v1.1.1 // indirect
6770
github.com/docker/go-units v0.4.0 // indirect
6871
github.com/fsnotify/fsnotify v1.5.4 // indirect
72+
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
6973
github.com/go-openapi/analysis v0.21.2 // indirect
7074
github.com/go-openapi/jsonpointer v0.19.5 // indirect
7175
github.com/go-openapi/jsonreference v0.20.0 // indirect
@@ -95,7 +99,6 @@ require (
9599
github.com/opentracing/opentracing-go v1.2.0 // indirect
96100
github.com/pelletier/go-toml v1.9.5 // indirect
97101
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
98-
github.com/pkg/errors v0.9.1 // indirect
99102
github.com/prometheus/client_model v0.2.0 // indirect
100103
github.com/prometheus/common v0.34.0 // indirect
101104
github.com/prometheus/procfs v0.7.3 // indirect
@@ -108,7 +111,7 @@ require (
108111
github.com/tilinna/clock v1.1.0 // indirect
109112
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
110113
github.com/ulikunitz/xz v0.5.10 // indirect
111-
github.com/zalando/go-keyring v0.1.1 // indirect
114+
github.com/x448/float16 v0.8.4 // indirect
112115
go.mongodb.org/mongo-driver v1.8.3 // indirect
113116
go.opencensus.io v0.23.0 // indirect
114117
go.uber.org/atomic v1.9.0 // indirect

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,8 @@ github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3n
475475
github.com/fullstorydev/grpcurl v1.8.0/go.mod h1:Mn2jWbdMrQGJQ8UD62uNyMumT2acsZUCkZIqFxsQf1o=
476476
github.com/fullstorydev/grpcurl v1.8.1/go.mod h1:3BWhvHZwNO7iLXaQlojdg5NA6SxUDePli4ecpK1N7gw=
477477
github.com/fullstorydev/grpcurl v1.8.6/go.mod h1:WhP7fRQdhxz2TkL97u+TCb505sxfH78W1usyoB3tepw=
478+
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
479+
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
478480
github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E=
479481
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
480482
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
@@ -1582,13 +1584,17 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+
15821584
github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8=
15831585
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
15841586
github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI=
1587+
github.com/veraison/go-cose v1.0.0-alpha.1 h1:W5AhenQOS3ZDsJH2rdDMffLuuFOIoZw6VfIAkPatsRs=
1588+
github.com/veraison/go-cose v1.0.0-alpha.1/go.mod h1:7ziE85vSq4ScFTg6wyoMXjucIGOf4JkFEZi/an96Ct4=
15851589
github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE=
15861590
github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U=
15871591
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
15881592
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
15891593
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
15901594
github.com/weppos/publicsuffix-go v0.15.1-0.20210807195340-dc689ff0bb59/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE=
15911595
github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE=
1596+
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
1597+
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
15921598
github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
15931599
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
15941600
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=

openapi.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,23 @@ definitions:
378378
- spec
379379
additionalProperties: false
380380

381+
cose:
382+
type: object
383+
description: COSE object
384+
allOf:
385+
- $ref: '#/definitions/ProposedEntry'
386+
- properties:
387+
apiVersion:
388+
type: string
389+
pattern: ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
390+
spec:
391+
type: object
392+
$ref: 'pkg/types/cose/cose_schema.json'
393+
required:
394+
- apiVersion
395+
- spec
396+
additionalProperties: false
397+
381398
jar:
382399
type: object
383400
description: Java Archive (JAR)

0 commit comments

Comments
 (0)