Skip to content

Commit

Permalink
adding support for verifying attestations
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 11, 2022
1 parent 7307a7b commit 48085b9
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 13 deletions.
5 changes: 4 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ type Verifier struct {
// Supports '*' and '?' in the pattern string.
Image string `yaml:"image,omitempty"`

// AttestationPresent is a boolean to specify whether an attestation is expected to be present
AttestationPresent bool `yaml:"attestationPresent,omitempty"`

// Options defines verification options
Options *CheckOptions `yaml:"options,omitempty"`
}
Expand Down Expand Up @@ -89,5 +92,5 @@ type CheckOptions struct {
Key string `yaml:"key,omitempty"`

// RekorURL is the address of a rekor STL server
RekorURL string `yaml:"rekorURL,omitempty"`
RekorURL string `yaml:"rekor_url,omitempty"`
}
53 changes: 41 additions & 12 deletions provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/sigstore/cosign/cmd/cosign/cli/rekor"
"github.com/sigstore/cosign/pkg/cosign"
"github.com/sigstore/cosign/pkg/cosign/pkcs11key"
"github.com/sigstore/cosign/pkg/oci"
sigs "github.com/sigstore/cosign/pkg/signature"
)

Expand Down Expand Up @@ -91,17 +92,24 @@ func validate(cfg *Config) func(w http.ResponseWriter, req *http.Request) {
Key: key,
}
fmt.Println("verify signature for:", key)
if err := verifyImageSignatures(ctx, key, cfg.Verifiers); err != nil {
metadata, err := verifyImageSignatures(ctx, key, cfg.Verifiers)
if err != nil {
result.Error = err.Error()
}
result.Value = metadata
results = append(results, result)
}

sendResponse(&results, "", w)
}
}

func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier) error {
type CheckedMetadata struct {
ImageSignatures []oci.Signature `json:"imageSignatures"`
AttestationSignatures []oci.Signature `json:"attestationSignatures"`
}

func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier) (*CheckedMetadata, error) {
for _, o := range verifiers {
if !wildcard.Match(o.Image, key) {
continue
Expand All @@ -110,7 +118,7 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
ro := options.RegistryOptions{}
ociremoteOpts, err := ro.ClientOpts(ctx)
if err != nil {
return err
return nil, err
}
co := &cosign.CheckOpts{
RegistryClientOpts: ociremoteOpts,
Expand All @@ -119,14 +127,14 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier
if o.Options.RekorURL != "" {
rekorClient, err := rekor.NewClient(o.Options.RekorURL)
if err != nil {
return fmt.Errorf("rekor.NewClient: %v", err)
return nil, fmt.Errorf("rekor.NewClient: %v", err)
}
co.RekorClient = rekorClient
}
if o.Options.Key != "" {
pubKey, err := sigs.PublicKeyFromKeyRef(ctx, o.Options.Key)
if err != nil {
return fmt.Errorf("PublicKeyFromKeyRef: %v", err)
return nil, fmt.Errorf("PublicKeyFromKeyRef: %v", err)
}
pkcs11Key, ok := pubKey.(*pkcs11key.Key)
if ok {
Expand All @@ -137,29 +145,50 @@ func verifyImageSignatures(ctx context.Context, key string, verifiers []Verifier

ref, err := name.ParseReference(key)
if err != nil {
return fmt.Errorf("ParseReference: %v", err)
return nil, fmt.Errorf("ParseReference: %v", err)
}

var metadata *CheckedMetadata

checkedSignatures, bundleVerified, err := cosign.VerifyImageSignatures(ctx, ref, co)
if err != nil {
return fmt.Errorf("VerifyImageSignatures: %v", err)
return nil, fmt.Errorf("VerifyImageSignatures: %v", err)
}

if co.RekorClient != nil && !bundleVerified {
return fmt.Errorf("no valid signatures found for %s: %v", key, err)
return nil, fmt.Errorf("no valid signatures found for %s: %v", key, err)
}

if len(checkedSignatures) == 0 {
return fmt.Errorf("no valid signatures found for %s", key)
return nil, fmt.Errorf("no valid signatures found for %s", key)
}

fmt.Println("signature verified for:", key)
metadata.ImageSignatures = checkedSignatures

fmt.Println("signature verified for: ", key)
fmt.Printf("%d number of valid signatures found for %s, found signatures: %v\n", len(checkedSignatures), key, checkedSignatures)

return nil
if o.AttestationPresent {
fmt.Println("Verifying Attestations for image: ", key)

checkedAttestations, bundleVerified, err := cosign.VerifyImageAttestations(ctx, ref, co)
if err != nil {
return nil, fmt.Errorf("VerifyImageAttestations: %v", err)
}
if co.RekorClient != nil && !bundleVerified {
return nil, fmt.Errorf("no valid attestations found for: %s", key)
}

metadata.AttestationSignatures = checkedAttestations

fmt.Println("attestation verified for: ", key)
fmt.Printf("%d number of valid attestations found for %s, found attestations: %v\n", len(checkedAttestations), key, checkedAttestations)
}

return metadata, nil
}

return fmt.Errorf("no verifier found for: %s", key)
return nil, fmt.Errorf("no verifier found for: %s", key)
}

// sendResponse sends back the response to Gatekeeper.
Expand Down

0 comments on commit 48085b9

Please sign in to comment.