Skip to content

Commit

Permalink
Allow for option in cosign attest and attest-blob to upload attestati…
Browse files Browse the repository at this point in the history
…on as supported in Rekor (#3466)

* adding conditional to upload intoto attestation if type equals intoto

Signed-off-by: Ahmed Alsabag <ahmed.alsabag@gmail.com>

* adding new store-attestation flag to upload attestation

Signed-off-by: Ahmed Alsabag <ahmed.alsabag@gmail.com>

* adding attest and attest-blob documentation for  store-attestation flag

Signed-off-by: Ahmed Alsabag <ahmed.alsabag@gmail.com>

* changing flag name to --rekor-entry-type

Signed-off-by: Ahmed Alsabag <ahmed.alsabag@gmail.com>

* fixing broken unit tests missing rekor-entry-type

Signed-off-by: Ahmed Alsabag <ahmed.alsabag@gmail.com>

* fixing rekor-entry-type e2e tests

Signed-off-by: Ahmed Alsabag <ahmed.alsabag@gmail.com>

* fixing rekor-entry-type e2e tests part 2

Signed-off-by: Ahmed Alsabag <ahmed.alsabag@gmail.com>

---------

Signed-off-by: Ahmed Alsabag <ahmed.alsabag@gmail.com>
  • Loading branch information
aalsabag committed Jan 13, 2024
1 parent 8586a28 commit 7b7304c
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 74 deletions.
1 change: 1 addition & 0 deletions cmd/cosign/cli/attest.go
Expand Up @@ -95,6 +95,7 @@ func Attest() *cobra.Command {
Replace: o.Replace,
Timeout: ro.Timeout,
TlogUpload: o.TlogUpload,
RekorEntryType: o.RekorEntryType,
}

for _, img := range args {
Expand Down
30 changes: 20 additions & 10 deletions cmd/cosign/cli/attest/attest.go
Expand Up @@ -71,15 +71,16 @@ func uploadToTlog(ctx context.Context, sv *sign.SignerVerifier, rekorURL string,
type AttestCommand struct {
options.KeyOpts
options.RegistryOptions
CertPath string
CertChainPath string
NoUpload bool
PredicatePath string
PredicateType string
Replace bool
Timeout time.Duration
TlogUpload bool
TSAServerURL string
CertPath string
CertChainPath string
NoUpload bool
PredicatePath string
PredicateType string
Replace bool
Timeout time.Duration
TlogUpload bool
TSAServerURL string
RekorEntryType string
}

// nolint
Expand All @@ -93,6 +94,10 @@ func (c *AttestCommand) Exec(ctx context.Context, imageRef string) error {
return fmt.Errorf("predicate cannot be empty")
}

if c.RekorEntryType != "dsse" && c.RekorEntryType != "intoto" {
return fmt.Errorf("unknown value for rekor-entry-type")
}

predicateURI, err := options.ParsePredicateType(c.PredicateType)
if err != nil {
return err
Expand Down Expand Up @@ -197,7 +202,12 @@ func (c *AttestCommand) Exec(ctx context.Context, imageRef string) error {
}
if shouldUpload {
bundle, err := uploadToTlog(ctx, sv, c.RekorURL, func(r *client.Rekor, b []byte) (*models.LogEntryAnon, error) {
return cosign.TLogUploadDSSEEnvelope(ctx, r, signedPayload, b)
if c.RekorEntryType == "intoto" {
return cosign.TLogUploadInTotoAttestation(ctx, r, signedPayload, b)
} else {
return cosign.TLogUploadDSSEEnvelope(ctx, r, signedPayload, b)
}

})
if err != nil {
return err
Expand Down
15 changes: 14 additions & 1 deletion cmd/cosign/cli/attest/attest_blob.go
Expand Up @@ -39,6 +39,7 @@ import (
"github.com/sigstore/cosign/v2/pkg/cosign/attestation"
cbundle "github.com/sigstore/cosign/v2/pkg/cosign/bundle"
"github.com/sigstore/cosign/v2/pkg/types"
"github.com/sigstore/rekor/pkg/generated/models"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature/dsse"
Expand All @@ -62,6 +63,8 @@ type AttestBlobCommand struct {
OutputSignature string
OutputAttestation string
OutputCertificate string

RekorEntryType string
}

// nolint
Expand All @@ -75,6 +78,10 @@ func (c *AttestBlobCommand) Exec(ctx context.Context, artifactPath string) error
return fmt.Errorf("predicate cannot be empty")
}

if c.RekorEntryType != "dsse" && c.RekorEntryType != "intoto" {
return fmt.Errorf("unknown value for rekor-entry-type")
}

if c.Timeout != 0 {
var cancelFn context.CancelFunc
ctx, cancelFn = context.WithTimeout(ctx, c.Timeout)
Expand Down Expand Up @@ -182,7 +189,13 @@ func (c *AttestBlobCommand) Exec(ctx context.Context, artifactPath string) error
if err != nil {
return err
}
entry, err := cosign.TLogUploadDSSEEnvelope(ctx, rekorClient, sig, rekorBytes)
var entry *models.LogEntryAnon
if c.RekorEntryType == "intoto" {
entry, err = cosign.TLogUploadInTotoAttestation(ctx, rekorClient, sig, rekorBytes)
} else {
entry, err = cosign.TLogUploadDSSEEnvelope(ctx, rekorClient, sig, rekorBytes)
}

if err != nil {
return err
}
Expand Down
44 changes: 39 additions & 5 deletions cmd/cosign/cli/attest/attest_blob_test.go
Expand Up @@ -161,11 +161,12 @@ func TestAttestBlobCmdLocalKeyAndCert(t *testing.T) {
} {
t.Run(tc.name, func(t *testing.T) {
at := AttestBlobCommand{
KeyOpts: options.KeyOpts{KeyRef: tc.keyref},
CertPath: tc.certref,
CertChainPath: tc.certchainref,
PredicatePath: predicatePath,
PredicateType: predicateType,
KeyOpts: options.KeyOpts{KeyRef: tc.keyref},
CertPath: tc.certref,
CertChainPath: tc.certchainref,
PredicatePath: predicatePath,
PredicateType: predicateType,
RekorEntryType: "dsse",
}
err := at.Exec(ctx, blob)
if err != nil {
Expand Down Expand Up @@ -213,6 +214,7 @@ func TestAttestBlob(t *testing.T) {
PredicatePath: predicatePath,
PredicateType: predicateType,
OutputSignature: dssePath,
RekorEntryType: "dsse",
}
err := at.Exec(ctx, blobPath)
if err != nil {
Expand Down Expand Up @@ -261,3 +263,35 @@ func TestAttestBlob(t *testing.T) {
})
}
}

func TestBadRekorEntryType(t *testing.T) {
ctx := context.Background()
td := t.TempDir()

keys, _ := cosign.GenerateKeyPair(nil)
keyRef := writeFile(t, td, string(keys.PrivateBytes), "key.pem")

blob := []byte("foo")
blobPath := writeFile(t, td, string(blob), "foo.txt")

predicates := map[string]string{}
predicates["slsaprovenance"] = makeSLSA02PredicateFile(t, td)
predicates["slsaprovenance1"] = makeSLSA1PredicateFile(t, td)

for predicateType, predicatePath := range predicates {
t.Run(predicateType, func(t *testing.T) {
dssePath := filepath.Join(td, "dsse.intoto.jsonl")
at := AttestBlobCommand{
KeyOpts: options.KeyOpts{KeyRef: keyRef},
PredicatePath: predicatePath,
PredicateType: predicateType,
OutputSignature: dssePath,
RekorEntryType: "badvalue",
}
err := at.Exec(ctx, blobPath)
if err == nil || err.Error() != "unknown value for rekor-entry-type" {
t.Fatal("expected an error due to unknown rekor entry type")
}
})
}
}
1 change: 1 addition & 0 deletions cmd/cosign/cli/attest_blob.go
Expand Up @@ -85,6 +85,7 @@ func AttestBlob() *cobra.Command {
OutputAttestation: o.OutputAttestation,
OutputCertificate: o.OutputCertificate,
Timeout: ro.Timeout,
RekorEntryType: o.RekorEntryType,
}
return v.Exec(cmd.Context(), args[0])
},
Expand Down
4 changes: 4 additions & 0 deletions cmd/cosign/cli/options/attest.go
Expand Up @@ -30,6 +30,7 @@ type AttestOptions struct {
SkipConfirmation bool
TlogUpload bool
TSAServerURL string
RekorEntryType string

Rekor RekorOptions
Fulcio FulcioOptions
Expand Down Expand Up @@ -80,6 +81,9 @@ func (o *AttestOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().BoolVar(&o.TlogUpload, "tlog-upload", true,
"whether or not to upload to the tlog")

cmd.Flags().StringVar(&o.RekorEntryType, "rekor-entry-type", "dsse",
"specifies the type to be used for a rekor entry upload. Options are intoto or dsse (default). ")

cmd.Flags().StringVar(&o.TSAServerURL, "timestamp-server-url", "",
"url to the Timestamp RFC3161 server, default none. Must be the path to the API to request timestamp responses, e.g. https://freetsa.org/tsr")
}
5 changes: 5 additions & 0 deletions cmd/cosign/cli/options/attest_blob.go
Expand Up @@ -37,6 +37,8 @@ type AttestBlobOptions struct {
OutputCertificate string
BundlePath string

RekorEntryType string

Rekor RekorOptions
Fulcio FulcioOptions
OIDC OIDCOptions
Expand Down Expand Up @@ -92,6 +94,9 @@ func (o *AttestBlobOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().BoolVar(&o.TlogUpload, "tlog-upload", true,
"whether or not to upload to the tlog")

cmd.Flags().StringVar(&o.RekorEntryType, "rekor-entry-type", "dsse",
"specifies the type to be used for a rekor entry upload. Options are intoto or dsse (default). ")

cmd.Flags().StringVar(&o.TSAServerURL, "timestamp-server-url", "",
"url to the Timestamp RFC3161 server, default none. Must be the path to the API to request timestamp responses, e.g. https://freetsa.org/tsr")

Expand Down
1 change: 1 addition & 0 deletions doc/cosign_attest-blob.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions doc/cosign_attest.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7b7304c

Please sign in to comment.