Skip to content

Commit

Permalink
Fix some bugs in the attestation support and add a formal spec. (#561)
Browse files Browse the repository at this point in the history
Signed-off-by: Dan Lorenc <dlorenc@google.com>
  • Loading branch information
dlorenc committed Aug 23, 2021
1 parent 9479578 commit 92ce88e
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 4 deletions.
6 changes: 5 additions & 1 deletion cmd/cosign/cli/attest.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ EXAMPLES
}
}

const intotoPayloadType = "application/vnd.in-toto+json"
const (
intotoPayloadType = "application/vnd.in-toto+json"
dssePayloadType = "application/vnd.dsse.envelope.v1+json"
)

func AttestCmd(ctx context.Context, ko KeyOpts, imageRef string, certPath string,
upload bool, predicatePath string, force bool, predicateType string) error {
Expand Down Expand Up @@ -179,6 +182,7 @@ func AttestCmd(ctx context.Context, ko KeyOpts, imageRef string, certPath string
Chain: sv.Chain,
DupeDetector: sv,
RemoteOpts: remoteOpts,
MediaType: dssePayloadType,
}

uploadTLog, err := shouldUploadToTlog(ref, force, ko.RekorURL)
Expand Down
4 changes: 2 additions & 2 deletions cmd/cosign/cli/verify_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ func applyVerifyAttestationFlags(cmd *VerifyAttestationCommand, flagset *flag.Fl
flagset.BoolVar(&cmd.Sk, "sk", false, "whether to use a hardware security key")
flagset.StringVar(&cmd.Slot, "slot", "", "security key slot to use for generated key (default: signature) (authentication|signature|card-authentication|key-management)")
flagset.BoolVar(&cmd.CheckClaims, "check-claims", true, "whether to check the claims found")
flagset.StringVar(&cmd.Output, "output", "json", "output format for the signing image information (default JSON) (json|text)")
flagset.StringVar(&cmd.FulcioURL, "fulcio-url", "https://fulcio.sigstore.dev", "[EXPERIMENTAL] address of sigstore PKI server")
flagset.StringVar(&cmd.RekorURL, "rekor-url", "https://rekor.sigstore.dev", "[EXPERIMENTAL] address of rekor STL server")
}
Expand Down Expand Up @@ -155,7 +154,8 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, args []string) (err
return err
}

PrintVerification(imageRef, verified, co, c.Output)
// The attestations are always JSON, so use the raw "text" mode for outputting them instead of conversion
PrintVerification(imageRef, verified, co, "text")
}

return nil
Expand Down
7 changes: 6 additions & 1 deletion pkg/cosign/remote/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,17 @@ type UploadOpts struct {
Bundle *Bundle
AdditionalAnnotations map[string]string
RemoteOpts []remote.Option
MediaType string
}

func UploadSignature(signature, payload []byte, dst name.Reference, opts UploadOpts) (uploadedSig []byte, err error) {
// Preserve the default
if opts.MediaType == "" {
opts.MediaType = SimpleSigningMediaType
}
l := &staticLayer{
b: payload,
mt: SimpleSigningMediaType,
mt: types.MediaType(opts.MediaType),
}

base, err := SignatureImage(dst, opts.RemoteOpts...)
Expand Down
54 changes: 54 additions & 0 deletions specs/ATTESTATION_SPEC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Cosign Attestation Specifications

This document aims to describe how `cosign` attaches `Attestations` to container images.

The goal is to specify the behavior well enough to promote other implementations and enable interoperability.
Attestations attached with `cosign` should be retrievable in other tools, and vice-versa.

This document focuses on the layout of attestations within an [OCI Image Manifest V1](https://github.com/opencontainers/image-spec/blob/master/manifest.md) object.

This document assumes you are using the In-Toto [Attestation](https://github.com/in-toto/attestation) format, serialized as a `DSSE` envelope
Other formats can be used, and the `mediaType` property should describe the format of a particular attestation, but implementations may not understand them.
The DSSE envelope format is defined [here](https://github.com/secure-systems-lab/dsse/blob/master/envelope.md#dsse-envelope) and uses the `mediaType`: `application/vnd.dsse.envelope.v1+json`.

Multiple Attestations may be "attached" to one image.
Each Attestation may refer to the entire image, or to a specific part of that image.
This is indicated via the `subject` field of the `Statement` inside the `Attestation`.

Attestations attached to a container image are generally assumed to refer to that image in some way.

## Overall Layout

An `Attestation` object is represented as an [OCI Image Manifest V1](https://github.com/opencontainers/image-spec/blob/master/manifest.md).

Each individual `Attestation` is represented as a `layer`, using a standard `descriptor`.
The `layers` list is ordered, but no order is assumed or important for the `Attestations`.

Here is an example manifest containing one `Attestation`:

```json
{
"schemaVersion": 2,
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 233,
"digest": "sha256:83bd5fb5b39f65f28e50a86d48fa79c07880befc292d92eebdc18531054b070c"
},
"layers": [
{
"mediaType": "application/vnd.dsse.envelope.v1+json",
"size": 246,
"digest": "sha256:ed3ad03d3b87843b5419d7dce9d50a3e0f45554b2ba93bf378611cae6b450cff",
}
]
}
```

## Subject Verification

`Attestations` MAY refer to multiple `subjects`.

When verifying an attestation for a container image, implementations MUST verify the relationship between the `subject` field and the container image.
Attestations MAY reference the entire container image or a portion of it.

Implementations MUST support `Attestations` that reference the entire container image, other relationship types are optional.

0 comments on commit 92ce88e

Please sign in to comment.