Skip to content

Commit

Permalink
added formatting to return payloads
Browse files Browse the repository at this point in the history
Signed-off-by: Tom Meadows <[email protected]>
  • Loading branch information
Tom Meadows committed Jan 12, 2022
1 parent 9353f2a commit 0368d29
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 6 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/minio/pkg v1.1.14
github.com/open-policy-agent/frameworks/constraint v0.0.0-20211029184625-8b4a99a9a65a
github.com/sigstore/cosign v1.4.1
github.com/sigstore/sigstore v1.0.2-0.20211203233310-c8e7f70eab4e
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

Expand Down Expand Up @@ -149,7 +150,6 @@ require (
github.com/shibumi/go-pathspec v1.2.0 // indirect
github.com/sigstore/fulcio v0.1.2-0.20211207184413-f4746cc4ff3d // indirect
github.com/sigstore/rekor v0.3.1-0.20211203233407-3278f72b78bd // indirect
github.com/sigstore/sigstore v1.0.2-0.20211203233310-c8e7f70eab4e // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
github.com/spf13/afero v1.6.0 // indirect
Expand Down
97 changes: 92 additions & 5 deletions provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ package main

import (
"context"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"

"github.com/google/go-containerregistry/pkg/name"
"github.com/in-toto/in-toto-golang/in_toto"
"github.com/open-policy-agent/frameworks/constraint/pkg/externaldata"

"github.com/minio/pkg/wildcard"
Expand All @@ -33,6 +37,7 @@ import (
"github.com/sigstore/cosign/pkg/cosign/pkcs11key"
"github.com/sigstore/cosign/pkg/oci"
sigs "github.com/sigstore/cosign/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature/payload"
)

const (
Expand Down Expand Up @@ -105,8 +110,8 @@ func validate(cfg *Config) func(w http.ResponseWriter, req *http.Request) {
}

type checkedMetadata struct {
ImageSignatures []oci.Signature `json:"imageSignatures"`
AttestationSignatures []oci.Signature `json:"attestationSignatures"`
ImageSignatures []payload.SimpleContainerImage `json:"imageSignatures"`
AttestationSignatures []in_toto.Statement `json:"attestationSignatures"`
}

func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier) (*checkedMetadata, error) {
Expand Down Expand Up @@ -148,7 +153,7 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
return nil, fmt.Errorf("parseReference: %v", err)
}

var metadata *checkedMetadata
metadata := &checkedMetadata{}

checkedSignatures, bundleVerified, err := cosign.VerifyImageSignatures(ctx, ref, co)
if err != nil {
Expand All @@ -163,7 +168,10 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
return nil, fmt.Errorf("no valid signatures found for %s", key)
}

metadata.ImageSignatures = checkedSignatures
metadata.ImageSignatures, err = formatSignaturePayloads(checkedSignatures)
if err != nil {
return nil, fmt.Errorf("formatSignaturePayloads: %v", err)
}

fmt.Println("signature verified for: ", key)
fmt.Printf("%d number of valid signatures found for %s, found signatures: %v\n", len(checkedSignatures), key, checkedSignatures)
Expand All @@ -179,7 +187,12 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
return nil, fmt.Errorf("no valid attestations found for: %s", key)
}

metadata.AttestationSignatures = checkedAttestations
AttestationPayloads, err := formatAttestations(checkedAttestations)
if err != nil {
return nil, fmt.Errorf("formatAttestations: %v", err)
}

metadata.AttestationSignatures = AttestationPayloads

fmt.Println("attestation verified for: ", key)
fmt.Printf("%d number of valid attestations found for %s, found attestations: %v\n", len(checkedAttestations), key, checkedAttestations)
Expand All @@ -191,6 +204,80 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
return nil, fmt.Errorf("no verifier found for: %s", key)
}

// formatAttestations takes the payload within an Attestation and base64 decodes it, returning it as an in-toto statement
func formatAttestations(verifiedAttestations []oci.Signature) ([]in_toto.Statement, error) {

decodedAttestations := make([]in_toto.Statement, len(verifiedAttestations))

for i, att := range verifiedAttestations {
p, err := att.Payload()
if err != nil {
fmt.Fprintf(os.Stderr, "error fetching payload: %v", err)
return nil, err
}

var pm map[string]interface{}
json.Unmarshal(p, &pm)

payload := strings.Trim(fmt.Sprintf("%v", pm["payload"]), "\"")

statementRaw, err := base64.StdEncoding.DecodeString(payload)
if err != nil {
fmt.Fprintf(os.Stderr, "error decoding payload: %v", err)
}

var statement in_toto.Statement
if err := json.Unmarshal(statementRaw, &statement); err != nil {
return nil, err
}

decodedAttestations[i] = statement
}

return decodedAttestations, nil

}

// formatPayload converts the signature into a payload to be sent back to gatekeeper
func formatSignaturePayloads(verifiedSignatures []oci.Signature) ([]payload.SimpleContainerImage, error) {

var outputKeys []payload.SimpleContainerImage

for _, sig := range verifiedSignatures {
p, err := sig.Payload()
if err != nil {
fmt.Fprintf(os.Stderr, "error fetching payload: %v", err)
return nil, err
}

ss := payload.SimpleContainerImage{}
if err := json.Unmarshal(p, &ss); err != nil {
fmt.Println("error decoding the payload:", err.Error())
return nil, err
}

if cert, err := sig.Cert(); err == nil && cert != nil {
if ss.Optional == nil {
ss.Optional = make(map[string]interface{})
}
ss.Optional["Subject"] = sigs.CertSubject(cert)
if issuerURL := sigs.CertIssuerExtension(cert); issuerURL != "" {
ss.Optional["Issuer"] = issuerURL
}
}
if bundle, err := sig.Bundle(); err == nil && bundle != nil {
if ss.Optional == nil {
ss.Optional = make(map[string]interface{})
}
ss.Optional["Bundle"] = bundle
}

outputKeys = append(outputKeys, ss)
}

return outputKeys, nil
}

// sendResponse sends back the response to Gatekeeper.
func sendResponse(results *[]externaldata.Item, systemErr string, w http.ResponseWriter) {
response := externaldata.ProviderResponse{
Expand Down

0 comments on commit 0368d29

Please sign in to comment.