Skip to content

Commit

Permalink
Fix a few bugs with attestation summary and use it in tape view
Browse files Browse the repository at this point in the history
  • Loading branch information
errordeveloper committed Sep 28, 2023
1 parent 30df3be commit 6e42331
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 18 deletions.
21 changes: 20 additions & 1 deletion attest/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,26 @@ func (s Subjects) Export() []toto.Subject {

func (s Subjects) MarshalJSON() ([]byte, error) { return json.Marshal(s.Export()) }

//func (s *Subjects) UnmarshalJSON(data []byte) error { return json.Unmarshal(data, s) }
func (s *Subjects) UnmarshalJSON(data []byte) error {
subjects := []toto.Subject{}
if err := json.Unmarshal(data, &subjects); err != nil {
return err
}
if len(subjects) == 0 {
return fmt.Errorf("invalid subject: zero entries")
}
for i := range subjects {
digestValue, ok := subjects[i].Digest["sha256"]
if !ok {
return fmt.Errorf("invalid subject: missing sha256 digest")
}
*s = append(*s, Subject{
Name: subjects[i].Name,
Digest: digest.SHA256(digestValue),
})
}
return nil
}

func MakePathCheckSummaryCollection(entries ...PathChecker) (*PathCheckSummaryCollection, error) {
numEntries := len(entries)
Expand Down
30 changes: 15 additions & 15 deletions oci/artefact.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const (
ContentInterpreterAnnotation = mediaTypePrefix + ".content-interpreter.v1alpha1"
ContentInterpreterKubectlApply = mediaTypePrefix + ".kubectl-apply.v1alpha1.tar+gzip"

AttestationsSummaryAnnotations = mediaTypePrefix + ".attestations-summary.v1alpha1"
AttestationsSummaryAnnotation = mediaTypePrefix + ".attestations-summary.v1alpha1"

// TODO: content interpreter invocation with an image

Expand Down Expand Up @@ -101,7 +101,7 @@ func (c *Client) FetchFromIndexOrImage(ctx context.Context, imageIndex ImageInde
continue
}

info, err := newArtifcatInfoFromLayerDescriptor(image, layerDescriptor)
info, err := newArtifcatInfoFromLayerDescriptor(image, layerDescriptor, manifest.Annotations)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -131,7 +131,7 @@ func (c *Client) FetchFromIndexOrImage(ctx context.Context, imageIndex ImageInde
return nil, nil, fmt.Errorf("media type mismatch between manifest and layer: %s != %s", manifestDescriptor.MediaType, layerDescriptor.MediaType)
}

info, err := newArtifcatInfoFromLayerDescriptor(image, layerDescriptor)
info, err := newArtifcatInfoFromLayerDescriptor(image, layerDescriptor, manifest.Annotations)
if err != nil {
return nil, nil, err
}
Expand All @@ -143,17 +143,17 @@ func (c *Client) FetchFromIndexOrImage(ctx context.Context, imageIndex ImageInde
}

func (c *Client) GetSingleArtefact(ctx context.Context, ref string) (*ArtefactInfo, error) {
image, layers, err := c.getFlatArtefactLayers(ctx, ref)
image, layers, annotations, err := c.getFlatArtefactLayers(ctx, ref)
if err != nil {
return nil, err
}
if len(layers) != 1 {
return nil, fmt.Errorf("multiple layers found in image %q", ref)
}
return newArtifcatInfoFromLayerDescriptor(image, layers[0])
return newArtifcatInfoFromLayerDescriptor(image, layers[0], annotations)
}

func newArtifcatInfoFromLayerDescriptor(image Image, layerDecriptor Descriptor) (*ArtefactInfo, error) {
func newArtifcatInfoFromLayerDescriptor(image Image, layerDecriptor Descriptor, annotations map[string]string) (*ArtefactInfo, error) {
layer, err := image.LayerByDigest(layerDecriptor.Digest)
if err != nil {
return nil, fmt.Errorf("fetching artefact image failed: %w", err)
Expand All @@ -166,41 +166,41 @@ func newArtifcatInfoFromLayerDescriptor(image Image, layerDecriptor Descriptor)
info := &ArtefactInfo{
ReadCloser: blob,
MediaType: layerDecriptor.MediaType,
Annotations: layerDecriptor.Annotations,
Annotations: annotations,
Digest: layerDecriptor.Digest.String(),
}
return info, nil
}

func (c *Client) getFlatArtefactLayers(ctx context.Context, ref string) (Image, []Descriptor, error) {
func (c *Client) getFlatArtefactLayers(ctx context.Context, ref string) (Image, []Descriptor, map[string]string, error) {
imageIndex, indexManifest, image, err := c.GetIndexOrImage(ctx, ref)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}

var manifest *Manifest

if indexManifest != nil {
if len(indexManifest.Manifests) != 1 {
return nil, nil, fmt.Errorf("multiple manifests found in image %q", ref)
return nil, nil, nil, fmt.Errorf("multiple manifests found in image %q", ref)
}

image, manifest, err = c.getImage(ctx, imageIndex, indexManifest.Manifests[0].Digest)
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
} else {
manifest, err = image.Manifest()
if err != nil {
return nil, nil, fmt.Errorf("failed to get manifest for %q: %w", ref, err)
return nil, nil, nil, fmt.Errorf("failed to get manifest for %q: %w", ref, err)
}
}

if len(manifest.Layers) < 1 {
return nil, nil, fmt.Errorf("no layers found in image %q", ref)
return nil, nil, nil, fmt.Errorf("no layers found in image %q", ref)
}

return image, manifest.Layers, nil
return image, manifest.Layers, manifest.Annotations, nil
}

func (c *Client) getImage(ctx context.Context, imageIndex ImageIndex, digest Hash) (Image, *Manifest, error) {
Expand Down Expand Up @@ -307,7 +307,7 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str
if err != nil {
return "", err
}
attestAnnotations[AttestationsSummaryAnnotations] = summary
attestAnnotations[AttestationsSummaryAnnotation] = summary

attest := mutate.Annotations(
mutate.ConfigMediaType(
Expand Down
19 changes: 17 additions & 2 deletions tape/app/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

toto "github.com/in-toto/in-toto-golang/in_toto"

//attestTypes "github.com/docker/labs-brown-tape/attest/types"
attestTypes "github.com/docker/labs-brown-tape/attest/types"

"github.com/docker/labs-brown-tape/oci"
)
Expand All @@ -29,7 +29,8 @@ type artefactInfo struct {
Content rawManifest[oci.Manifest] `json:"content"`
Attest rawManifest[oci.Manifest] `json:"attest"`
} `json:"rawManifests"`
Attestations []toto.Statement `json:"attestations"`
Attestations []toto.Statement `json:"attestations"`
AttestationsSummary *attestTypes.SummaryAnnotation `json:"attestationsSummary,omitempty"`
}

type rawManifest[T oci.Manifest | oci.IndexManifest] struct {
Expand Down Expand Up @@ -96,6 +97,14 @@ func (c *TapeViewCommand) CollectInfo(ctx context.Context, client *oci.Client) (
switch info.MediaType {
case oci.ContentMediaType:
case oci.AttestMediaType:
if annotation, ok := info.Annotations[oci.AttestationsSummaryAnnotation]; ok {
summary, err := attestTypes.UnmarshalSummaryAnnotation(annotation)
if err != nil {
return nil, err
}
artefactInfo.AttestationsSummary = summary
}

gr, err := gzip.NewReader(info)
if err != nil {
return nil, err
Expand Down Expand Up @@ -149,6 +158,12 @@ func (c *TapeViewCommand) PrintInfo(ctx context.Context, outputInfo *artefactInf
fmt.Printf(" %s %s\n", outputInfo.RawManifests.Attest.Digest,
outputInfo.RawManifests.Attest.Manifest.Config.MediaType)

if outputInfo.AttestationsSummary != nil {
fmt.Printf(" Attestations Summary:\n")
fmt.Printf(" Number of Statements: %v\n", outputInfo.AttestationsSummary.NumStamentes)
fmt.Printf(" Predicate Types: %v\n", outputInfo.AttestationsSummary.PredicateTypes)
fmt.Printf(" Subjects: %v\n", outputInfo.AttestationsSummary.Subjects)
}
}
return nil
}

0 comments on commit 6e42331

Please sign in to comment.