diff --git a/attest/manifest/manifest.go b/attest/manifest/manifest.go index c5fa33c..6a88285 100644 --- a/attest/manifest/manifest.go +++ b/attest/manifest/manifest.go @@ -42,6 +42,14 @@ func MakeDirContentsStatement(dir string, entries *types.PathCheckSummaryCollect } } +func MakeDirContentsStatementFrom(statement types.Statement) DirContents { + dirContents := DirContents{ + GenericStatement: attestTypes.GenericStatement[SourceDirectory]{}, + } + dirContents.ConvertFrom(statement) + return dirContents +} + func (a SourceDirectory) Compare(b SourceDirectory) types.Cmp { if cmp := cmp.Compare(a.Path, b.Path); cmp != 0 { return &cmp diff --git a/attest/types/types.go b/attest/types/types.go index f3daeb8..1d57926 100644 --- a/attest/types/types.go +++ b/attest/types/types.go @@ -119,6 +119,30 @@ func Export(s ExportableStatement) toto.Statement { } } +func FilterByPredicateType(t string, s Statements) Statements { + results := Statements{} + for i := range s { + if s[i].GetType() == t { + results = append(results, s[i]) + } + } + return results +} + +type StamentConverter[T any] struct { + Statement +} + +func (s *GenericStatement[T]) ConvertFrom(statement Statement) error { + predicate, ok := s.GetPredicate().(ComparablePredicate[T]) + if !ok { + return fmt.Errorf("cannot convert statement with predicte of type %T into %T", s.GetPredicate(), GenericStatement[T]{}) + } + + *s = MakeStatement[T](s.GetType(), predicate, s.GetSubject()...) + return nil +} + func (s Statements) Export() []toto.Statement { statements := make([]toto.Statement, len(s)) for i := range s { diff --git a/oci/artefact.go b/oci/artefact.go index 0630e85..4ee82b2 100644 --- a/oci/artefact.go +++ b/oci/artefact.go @@ -23,6 +23,7 @@ import ( "github.com/google/go-containerregistry/pkg/v1/tarball" typesv1 "github.com/google/go-containerregistry/pkg/v1/types" + "github.com/docker/labs-brown-tape/attest/manifest" attestTypes "github.com/docker/labs-brown-tape/attest/types" manifestTypes "github.com/docker/labs-brown-tape/manifest/types" ) @@ -223,6 +224,10 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str } defer os.RemoveAll(tmpDir) + _, err = SemVerFromAttestations(ctx, sourceAttestations...) + if err != nil { + return "", err + } tmpFile := filepath.Join(tmpDir, "artefact.tgz") outputFile, err := os.OpenFile(tmpFile, os.O_RDWR|os.O_CREATE|os.O_EXCL, regularFileMode) @@ -348,6 +353,20 @@ func (c *Client) PushArtefact(ctx context.Context, destinationRef, sourceDir str return tagAlias.String() + "@" + digest.String(), err } +func SemVerFromAttestations(ctx context.Context, sourceAttestations ...attestTypes.Statement) (string, error) { + statements := attestTypes.FilterByPredicateType(manifest.ManifestDirPredicateType, sourceAttestations) + if len(statements) == 0 { + return "", fmt.Errorf("VCS provinance attestion (%q) not found", manifest.ManifestDirPredicateType) + } + if len(statements) > 1 { + return "", fmt.Errorf("too many attestations of type %q found, expected 1", manifest.ManifestDirPredicateType) + } + + _ = manifest.MakeDirContentsStatementFrom(statements[0]) + + return "", nil +} + func makeDescriptorWithPlatform() Descriptor { return Descriptor{ Platform: &Platform{