Skip to content

Commit

Permalink
feat: Add support for DSSE Rekor type (#742)
Browse files Browse the repository at this point in the history
This is in preparation for switching over the Rekor entry type in the
slsa github generator to be the newer DSSE type. This adds support for
searching for both intoto v001 and dsse v001 entries.

Signed-off-by: Hayden Blauzvern <hblauzvern@google.com>
  • Loading branch information
haydentherapper committed Mar 4, 2024
1 parent bb41cb6 commit 52c099b
Showing 1 changed file with 41 additions and 23 deletions.
64 changes: 41 additions & 23 deletions verifiers/internal/gha/rekor.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,21 @@ import (

cjson "github.com/docker/go/canonical/json"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/sigstore/cosign/v2/pkg/cosign"
"github.com/sigstore/rekor/pkg/generated/client"
"github.com/sigstore/rekor/pkg/generated/client/entries"
"github.com/sigstore/rekor/pkg/generated/client/index"
"github.com/sigstore/rekor/pkg/generated/models"
"github.com/sigstore/rekor/pkg/sharding"
"github.com/sigstore/rekor/pkg/types"
intotod "github.com/sigstore/rekor/pkg/types/intoto/v0.0.1"
"github.com/sigstore/rekor/pkg/types/dsse"
dsse_v001 "github.com/sigstore/rekor/pkg/types/dsse/v0.0.1"
"github.com/sigstore/rekor/pkg/types/intoto"
intoto_v001 "github.com/sigstore/rekor/pkg/types/intoto/v0.0.1"
rverify "github.com/sigstore/rekor/pkg/verify"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature/dsse"
dsseverifier "github.com/sigstore/sigstore/pkg/signature/dsse"
"github.com/slsa-framework/slsa-github-generator/signing/envelope"

serrors "github.com/slsa-framework/slsa-verifier/v2/errors"
Expand Down Expand Up @@ -123,14 +124,19 @@ func extractCert(e *models.LogEntryAnon) (*x509.Certificate, error) {

var publicKeyB64 []byte
switch e := eimpl.(type) {
case *intotod.V001Entry:
case *intoto_v001.V001Entry:
publicKeyB64, err = e.IntotoObj.PublicKey.MarshalText()
if err != nil {
return nil, err
case *dsse_v001.V001Entry:
if len(e.DSSEObj.Signatures) > 1 {
return nil, errors.New("multiple signatures on DSSE envelopes are not currently supported")
}
publicKeyB64, err = e.DSSEObj.Signatures[0].Verifier.MarshalText()
default:
return nil, errors.New("unexpected tlog entry type")
}
if err != nil {
return nil, err
}

publicKey, err := base64.StdEncoding.DecodeString(string(publicKeyB64))
if err != nil {
Expand All @@ -149,19 +155,31 @@ func extractCert(e *models.LogEntryAnon) (*x509.Certificate, error) {
return certs[0], err
}

func intotoEntry(certPem, provenance []byte) (*intotod.V001Entry, error) {
func intotoEntry(certPem, provenance []byte) (models.ProposedEntry, error) {
if len(certPem) == 0 {
return nil, fmt.Errorf("no signing certificate found in intoto envelope")
}
cert := strfmt.Base64(certPem)
return &intotod.V001Entry{
IntotoObj: models.IntotoV001Schema{
Content: &models.IntotoV001SchemaContent{
Envelope: string(provenance),
},
PublicKey: &cert,
},
}, nil
var pubKeyBytes [][]byte
pubKeyBytes = append(pubKeyBytes, certPem)

return types.NewProposedEntry(context.Background(), intoto.KIND, intoto_v001.APIVERSION, types.ArtifactProperties{
ArtifactBytes: provenance,
PublicKeyBytes: pubKeyBytes,
})
}

func dsseEntry(certPem, provenance []byte) (models.ProposedEntry, error) {
if len(certPem) == 0 {
return nil, fmt.Errorf("no signing certificate found in intoto envelope")
}

var pubKeyBytes [][]byte
pubKeyBytes = append(pubKeyBytes, certPem)

return types.NewProposedEntry(context.Background(), dsse.KIND, dsse_v001.APIVERSION, types.ArtifactProperties{
ArtifactBytes: provenance,
PublicKeyBytes: pubKeyBytes,
})
}

// getUUIDsByArtifactDigest finds all entry UUIDs by the digest of the artifact binary.
Expand Down Expand Up @@ -195,15 +213,15 @@ func GetValidSignedAttestationWithCert(rClient *client.Rekor,
return nil, fmt.Errorf("error getting certificate from provenance: %w", err)
}

e, err := intotoEntry(certPem, provenance)
intotoEntry, err := intotoEntry(certPem, provenance)
if err != nil {
return nil, fmt.Errorf("error creating intoto entry: %w", err)
}
entry := models.Intoto{
APIVersion: swag.String(e.APIVersion()),
Spec: e.IntotoObj,
dsseEntry, err := dsseEntry(certPem, provenance)
if err != nil {
return nil, err
}
searchLogQuery.SetEntries([]models.ProposedEntry{&entry})
searchLogQuery.SetEntries([]models.ProposedEntry{intotoEntry, dsseEntry})

params.SetEntry(&searchLogQuery)
resp, err := rClient.Entries.SearchLogQuery(params)
Expand Down Expand Up @@ -347,7 +365,7 @@ func verifySignedAttestation(signedAtt *SignedAttestation, trustedRoot *TrustedR
}

// 2. Verify signature using validated certificate.
verifier = dsse.WrapVerifier(verifier)
verifier = dsseverifier.WrapVerifier(verifier)
if err := verifier.VerifySignature(bytes.NewReader(attBytes), bytes.NewReader(attBytes)); err != nil {
return fmt.Errorf("%w: %s", serrors.ErrorInvalidSignature, err)
}
Expand Down

0 comments on commit 52c099b

Please sign in to comment.