Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for timestamps in the cosign custom predicate, and docume… #533

Merged
merged 1 commit into from Aug 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 19 additions & 8 deletions pkg/cosign/attestation/attestation.go
Expand Up @@ -22,6 +22,7 @@ import (
"path/filepath"
"reflect"
"strings"
"time"

"github.com/in-toto/in-toto-golang/in_toto"
"github.com/pkg/errors"
Expand All @@ -32,9 +33,10 @@ const (
CosignCustomProvenanceV01 = "cosign.sigstore.dev/attestation/v1"
)

// CosignAttestation specifies the format of the Custom Predicate.
type CosignAttestation struct {
Data string
// CosignPredicate specifies the format of the Custom Predicate.
type CosignPredicate struct {
Data string
Timestamp string
}

// GenerateOpts specifies the options of the Statement generator.
Expand All @@ -48,6 +50,9 @@ type GenerateOpts struct {
Digest string
// Repo context of the reference.
Repo string

// Function to return the time to set
Time func() time.Time
}

// GenerateStatement returns corresponding Predicate (custom|provenance|spdx|link)
Expand All @@ -59,7 +64,12 @@ func GenerateStatement(opts GenerateOpts) (interface{}, error) {
}
switch opts.Type {
case "custom":
return generateCustomStatement(rawPayload, opts.Digest, opts.Repo)
if opts.Time == nil {
opts.Time = time.Now
}
now := opts.Time()
stamp := now.UTC().Format(time.RFC3339)
return generateCustomStatement(rawPayload, opts.Digest, opts.Repo, stamp)
case "provenance":
return generateProvenanceStatement(rawPayload, opts.Digest, opts.Repo)
case "spdx":
Expand Down Expand Up @@ -87,11 +97,12 @@ func generateStatementHeader(digest, repo, predicateType string) in_toto.Stateme
}

//
func generateCustomStatement(rawPayload []byte, digest, repo string) (interface{}, error) {
func generateCustomStatement(rawPayload []byte, digest, repo, timestamp string) (interface{}, error) {
return in_toto.Statement{
StatementHeader: generateStatementHeader(digest, repo, CosignCustomProvenanceV01),
Predicate: CosignAttestation{
Data: string(rawPayload),
Predicate: CosignPredicate{
Data: string(rawPayload),
Timestamp: timestamp,
},
}, nil
}
Expand Down Expand Up @@ -131,7 +142,7 @@ func generateLinkStatement(rawPayload []byte, digest string, repo string) (inter
func generateSPDXStatement(rawPayload []byte, digest string, repo string) (interface{}, error) {
return in_toto.SPDXStatement{
StatementHeader: generateStatementHeader(digest, repo, in_toto.PredicateSPDX),
Predicate: CosignAttestation{
Predicate: CosignPredicate{
Data: string(rawPayload),
},
}, nil
Expand Down
31 changes: 31 additions & 0 deletions specs/COSIGN_PREDICATE_SPEC.md
@@ -0,0 +1,31 @@
# Cosign Generic Predicate Specification

`Cosign` supports working with [In-Toto Attestations](https://github.com/in-toto/attestation) using the predicate model.
Several well-known predicates are supported natively, but `cosign` also supports a simple, generic, format for data that
doesn't fit well into other types.

The format for this is defined as follows:

`data`: Raw data to place in the attestation. This is a base64-encoded string of bytes.
`timestamp`: The timestamp the attestion was generated at in the RFC3339 format in the UTC timezone.

Here is an example attestation containing a data file containing `foo`:

```json
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "cosign.sigstore.dev/attestation/v1",
"subject": [
{
"name": "us.gcr.io/dlorenc-vmtest2/demo",
"digest": {
"sha256": "124e1fdee94fe5c5f902bc94da2d6e2fea243934c74e76c2368acdc8d3ac7155"
}
}
],
"predicate": {
"Data": "foo\n",
"Timestamp": "2021-08-11T14:51:09Z"
}
}
```