From ead4e9bf4e9ca5577cef1b4589c4167712da887f Mon Sep 17 00:00:00 2001 From: Ramon Petgrave Date: Tue, 18 Jun 2024 20:23:24 +0000 Subject: [PATCH] use utility to parse envelope, docs, use keyID Signed-off-by: Ramon Petgrave --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- verifiers/internal/vsa/v1.0/vsa.go | 18 +++--------------- verifiers/internal/vsa/verifier.go | 18 ++++++++++-------- verifiers/utils/dsse.go | 7 ++++++- 5 files changed, 34 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 67c9666..6a13a71 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( require ( github.com/google/go-containerregistry v0.19.1 github.com/gorilla/mux v1.8.1 + github.com/in-toto/attestation v1.1.0 github.com/sigstore/cosign/v2 v2.2.4 github.com/sigstore/sigstore-go v0.2.0 github.com/slsa-framework/slsa-github-generator v1.9.0 @@ -33,7 +34,6 @@ require ( github.com/go-openapi/strfmt v0.23.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/in-toto/attestation v1.1.0 // indirect github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -108,13 +108,13 @@ require ( go.opentelemetry.io/otel/trace v1.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/crypto v0.23.0 // indirect golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 golang.org/x/net v0.22.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/term v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/term v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect google.golang.org/grpc v1.62.1 // indirect google.golang.org/protobuf v1.34.1 gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 3c9ad00..98b8e35 100644 --- a/go.sum +++ b/go.sum @@ -444,6 +444,8 @@ github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbm github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU= github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c= github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= github.com/sigstore/cosign/v2 v2.2.4 h1:iY4vtEacmu2hkNj1Fh+8EBqBwKs2DHM27/lbNWDFJro= @@ -561,8 +563,8 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mgGG96aqaPXaMifQU47w= golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -602,18 +604,18 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= -golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -644,8 +646,6 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/verifiers/internal/vsa/v1.0/vsa.go b/verifiers/internal/vsa/v1.0/vsa.go index 3f533d0..c20d7bd 100644 --- a/verifiers/internal/vsa/v1.0/vsa.go +++ b/verifiers/internal/vsa/v1.0/vsa.go @@ -5,7 +5,6 @@ import ( "fmt" "time" - intotoAttestattions "github.com/in-toto/attestation/go/v1" intotoGolang "github.com/in-toto/in-toto-golang/in_toto" intotoCommon "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common" serrors "github.com/slsa-framework/slsa-verifier/v2/errors" @@ -20,7 +19,7 @@ const vsaPredicateType = "https://slsa.dev/verification_summary/v1" type VSA struct { intotoGolang.StatementHeader // Predicate is the VSA predicate. - // Idealy, we use "github.com/in-toto/attestation/go/predicates/vsa/v1"'s VerfificationSummary, + // Ideally, we use "github.com/in-toto/attestation/go/predicates/vsa/v1"'s VerfificationSummary, // but it currently does not correctly implement some fields according to spec, such as VerifiedLevels Predicate Predicate `json:"predicate"` } @@ -46,8 +45,8 @@ type Verifier struct { // VSAFromStatement creates a VSA from a statement. func VSAFromStatement(statement *intotoGolang.Statement) (*VSA, error) { - if err := validateStatementTypes(statement); err != nil { - return nil, err + if statement.PredicateType != vsaPredicateType { + return nil, fmt.Errorf("%w: expected predicate type %q, got %q", serrors.ErrorInvalidDssePayload, vsaPredicateType, statement.PredicateType) } vsaBytes, err := json.Marshal(statement) if err != nil { @@ -59,14 +58,3 @@ func VSAFromStatement(statement *intotoGolang.Statement) (*VSA, error) { } return &vsa, nil } - -// validateStatementTypes validates the statement types. -func validateStatementTypes(statement *intotoGolang.Statement) error { - if statement.Type != intotoAttestattions.StatementTypeUri { - return fmt.Errorf("%w: expected statement type %q, got %q", serrors.ErrorInvalidDssePayload, intotoAttestattions.StatementTypeUri, statement.Type) - } - if statement.PredicateType != vsaPredicateType { - return fmt.Errorf("%w: expected predicate type %q, got %q", serrors.ErrorInvalidDssePayload, vsaPredicateType, statement.PredicateType) - } - return nil -} diff --git a/verifiers/internal/vsa/verifier.go b/verifiers/internal/vsa/verifier.go index 301bb92..7bb97e5 100644 --- a/verifiers/internal/vsa/verifier.go +++ b/verifiers/internal/vsa/verifier.go @@ -29,14 +29,6 @@ func VerifyVSA(ctx context.Context, sigstoreEnvelope := sigstoreBundle.Envelope{ Envelope: envelope, } - sigstoreStatement, err := sigstoreEnvelope.Statement() - if err != nil { - return nil, nil, err - } - vsa, err := vsa10.VSAFromStatement(sigstoreStatement) - if err != nil { - return nil, nil, err - } // verify the envelope. signature err = verifyEnvelopeSignature(ctx, &sigstoreEnvelope) @@ -46,6 +38,14 @@ func VerifyVSA(ctx context.Context, // TODO: // verify the metadata + statement, err := utils.StatementFromEnvelope(envelope) + if err != nil { + return nil, nil, err + } + vsa, err := vsa10.VSAFromStatement(statement) + if err != nil { + return nil, nil, err + } err = matchExpectedValues(vsa, vsaOpts) if err != nil { return nil, nil, err @@ -61,6 +61,7 @@ func verifyEnvelopeSignature(ctx context.Context, sigstoreEnvelope *sigstoreBund MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeGa6ZCZn0q6WpaUwJrSk+PPYEsca 3Xkk3UrxvbQtoZzTmq0zIYq+4QQl0YBedSyy+XcwAMaUWTouTrB05WhYtg== -----END PUBLIC KEY-----`) + keyID := "keystore://76574:prod:vsa_signing_public_key" pubKey, err := sigstoreCryptoUtils.UnmarshalPEMToPublicKey(pubKeyBytes) if err != nil { return fmt.Errorf("%w: %w", serrors.ErrorInvalidPublicKey, err) @@ -72,6 +73,7 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeGa6ZCZn0q6WpaUwJrSk+PPYEsca envelopeVerifier, err := dsse.NewEnvelopeVerifier(&sigstoreDSSE.VerifierAdapter{ SignatureVerifier: signatureVerifier, Pub: pubKey, + PubKeyID: keyID, // "keystore://76574:prod:vsa_signing_public_key" }) if err != nil { return fmt.Errorf("%w: creating verifier %w", serrors.ErrorInvalidPublicKey, err) diff --git a/verifiers/utils/dsse.go b/verifiers/utils/dsse.go index 91512c5..4fd1e0e 100644 --- a/verifiers/utils/dsse.go +++ b/verifiers/utils/dsse.go @@ -12,6 +12,7 @@ import ( "fmt" "math/big" + intotoAttestattions "github.com/in-toto/attestation/go/v1" intoto "github.com/in-toto/in-toto-golang/in_toto" dsselib "github.com/secure-systems-lab/go-securesystemslib/dsse" serrors "github.com/slsa-framework/slsa-verifier/v2/errors" @@ -42,13 +43,17 @@ func PayloadFromEnvelope(env *dsselib.Envelope) ([]byte, error) { return payload, nil } +// StatementFromBytes parses the provided byte slice as a JSON payload and returns an intoto.Statement. +// Ideally, we use the "V1" Statement in https://pkg.go.dev/github.com/in-toto/attestation/go/v1#pkg-constants, +// but it parses json fields in snake case, while the official spec uses camel case +// https://github.com/in-toto/attestation/blob/v1.0/spec/v1.0/statement.md. func StatementFromBytes(payload []byte) (*intoto.Statement, error) { var statement intoto.Statement if err := json.Unmarshal(payload, &statement); err != nil { return nil, fmt.Errorf("%w: %w", serrors.ErrorInvalidDssePayload, err) } - if statement.Type != intoto.StatementInTotoV01 { + if statement.Type != intoto.StatementInTotoV01 && statement.Type != intotoAttestattions.StatementTypeUri { return nil, fmt.Errorf("%w: invalid statement type: %q", serrors.ErrorInvalidDssePayload, statement.Type) } return &statement, nil