Skip to content

Commit

Permalink
Link attestor proposed changes (#204)
Browse files Browse the repository at this point in the history
* unmarshal the time in the attestation collection correctly (#203)
* add StepName to AttestorContext
* use CollectionAttestion to properly set start/end times
---------

Signed-off-by: John Kjell <[email protected]>
Co-authored-by: Cole Kennedy <[email protected]>
Co-authored-by: Cole <[email protected]>
Co-authored-by: John Kjell <[email protected]>
  • Loading branch information
4 people authored Apr 4, 2024
1 parent 74a58da commit 4d86ee9
Show file tree
Hide file tree
Showing 13 changed files with 43 additions and 56 deletions.
5 changes: 2 additions & 3 deletions attestation/aws-iid/aws-iid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,10 @@ func TestAttestor_Attest(t *testing.T) {
conf: conf,
}

ctx, err := attestation.NewContext([]attestation.Attestor{a})
ctx, err := attestation.NewContext("test", []attestation.Attestor{a})
require.NoError(t, err)
err = a.Attest(ctx)
require.NoError(t, err)

}

func TestAttestor_getIID(t *testing.T) {
Expand Down Expand Up @@ -154,7 +153,7 @@ func TestAttestor_Subjects(t *testing.T) {
conf: conf,
}

ctx, err := attestation.NewContext([]attestation.Attestor{a})
ctx, err := attestation.NewContext("test", []attestation.Attestor{a})
require.NoError(t, err)
err = a.Attest(ctx)
require.NoError(t, err)
Expand Down
4 changes: 4 additions & 0 deletions attestation/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ func (c *CollectionAttestation) UnmarshalJSON(data []byte) error {
proposed := struct {
Type string `json:"type"`
Attestation json.RawMessage `json:"attestation"`
StartTime time.Time `json:"starttime"`
EndTime time.Time `json:"endtime"`
}{}

if err := json.Unmarshal(data, &proposed); err != nil {
Expand All @@ -83,6 +85,8 @@ func (c *CollectionAttestation) UnmarshalJSON(data []byte) error {

c.Type = proposed.Type
c.Attestation = newAttest
c.StartTime = proposed.StartTime
c.EndTime = proposed.EndTime
return nil
}

Expand Down
8 changes: 7 additions & 1 deletion attestation/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,15 @@ type AttestationContext struct {
completedAttestors []CompletedAttestor
products map[string]Product
materials map[string]cryptoutil.DigestSet
stepName string
}

type Product struct {
MimeType string `json:"mime_type"`
Digest cryptoutil.DigestSet `json:"digest"`
}

func NewContext(attestors []Attestor, opts ...AttestationContextOption) (*AttestationContext, error) {
func NewContext(stepName string, attestors []Attestor, opts ...AttestationContextOption) (*AttestationContext, error) {
wd, err := os.Getwd()
if err != nil {
return nil, err
Expand All @@ -112,6 +113,7 @@ func NewContext(attestors []Attestor, opts ...AttestationContextOption) (*Attest
hashes: []cryptoutil.DigestValue{{Hash: crypto.SHA256}, {Hash: crypto.SHA256, GitOID: true}, {Hash: crypto.SHA1, GitOID: true}},
materials: make(map[string]cryptoutil.DigestSet),
products: make(map[string]Product),
stepName: stepName,
}

for _, opt := range opts {
Expand Down Expand Up @@ -209,6 +211,10 @@ func (ctx *AttestationContext) Products() map[string]Product {
return out
}

func (ctx *AttestationContext) StepName() string {
return ctx.stepName
}

func (ctx *AttestationContext) addMaterials(materialer Materialer) {
newMats := materialer.Materials()
for k, v := range newMats {
Expand Down
2 changes: 1 addition & 1 deletion attestation/environment/environment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (

func TestEnvironment(t *testing.T) {
attestor := New()
ctx, err := attestation.NewContext([]attestation.Attestor{attestor})
ctx, err := attestation.NewContext("test", []attestation.Attestor{attestor})
require.NoError(t, err)

t.Setenv("AWS_ACCESS_KEY_ID", "super secret")
Expand Down
5 changes: 5 additions & 0 deletions attestation/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ type Producer interface {
Products() map[string]Product
}

// Exporter allows attestors to export their attestations for separation from the collection.
type Exporter interface {
Export() bool
}

// BackReffer allows attestors to indicate which of their subjects are good candidates
// to find related attestations. For example the git attestor's commit hash subject
// is a good candidate to find all attestation collections that also refer to a specific
Expand Down
4 changes: 2 additions & 2 deletions attestation/git/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestRunWorksWithCommits(t *testing.T) {
_, dir, cleanup := createTestRepo(t, true)
defer cleanup()

ctx, err := attestation.NewContext([]attestation.Attestor{attestor}, attestation.WithWorkingDir(dir))
ctx, err := attestation.NewContext("test", []attestation.Attestor{attestor}, attestation.WithWorkingDir(dir))
require.NoError(t, err, "Expected no error from NewContext")

err = ctx.RunAttestors()
Expand Down Expand Up @@ -146,7 +146,7 @@ func TestRunWorksWithoutCommits(t *testing.T) {
_, dir, cleanup := createTestRepo(t, false)
defer cleanup()

ctx, err := attestation.NewContext([]attestation.Attestor{attestor}, attestation.WithWorkingDir(dir))
ctx, err := attestation.NewContext("test", []attestation.Attestor{attestor}, attestation.WithWorkingDir(dir))
require.NoError(t, err, "Expected no error from NewContext")

err = ctx.RunAttestors()
Expand Down
18 changes: 2 additions & 16 deletions attestation/link/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"github.com/in-toto/go-witness/attestation/material"
"github.com/in-toto/go-witness/attestation/product"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/in-toto/go-witness/registry"
"google.golang.org/protobuf/types/known/structpb"
)

Expand All @@ -48,19 +47,6 @@ var (
func init() {
attestation.RegisterAttestation(Name, Type, RunType,
func() attestation.Attestor { return New() },
registry.BoolConfigOption(
"export",
"Export the link attestation to its own file",
defaultExport,
func(a attestation.Attestor, export bool) (attestation.Attestor, error) {
linkAttestor, ok := a.(*Link)
if !ok {
return a, fmt.Errorf("unexpected attestor type: %T is not a link attestor", a)
}
WithExport(export)(linkAttestor)
return linkAttestor, nil
},
),
)
}

Expand Down Expand Up @@ -95,11 +81,11 @@ func (l *Link) RunType() attestation.RunType {
}

func (l *Link) Export() bool {
return l.export
return true
}

func (l *Link) Attest(ctx *attestation.AttestationContext) error {
l.PbLink.Name = "stepNameHere"
l.PbLink.Name = ctx.StepName()
for _, attestor := range ctx.CompletedAttestors() {
switch name := attestor.Attestor.Name(); name {
case commandrun.Name:
Expand Down
2 changes: 1 addition & 1 deletion attestation/maven/maven_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func TestMaven(t *testing.T) {
}

t.Run(test.name, func(t *testing.T) {
ctx, err := attestation.NewContext([]attestation.Attestor{}, attestation.WithWorkingDir(workingDir))
ctx, err := attestation.NewContext("test", []attestation.Attestor{}, attestation.WithWorkingDir(workingDir))
require.NoError(t, err)
a := New(WithPom(p))
require.NoError(t, a.Attest(ctx))
Expand Down
2 changes: 1 addition & 1 deletion attestation/oci/oci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func TestAttestor_Attest(t *testing.T) {
Digest: tarDigest,
}

ctx, err := attestation.NewContext([]attestation.Attestor{testProducter{testProductSet}, a})
ctx, err := attestation.NewContext("test", []attestation.Attestor{testProducter{testProductSet}, a})
if err != nil {
t.Fatal(err)
}
Expand Down
6 changes: 3 additions & 3 deletions attestation/product/product_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestAttestorAttest(t *testing.T) {
testDigestSet := make(map[string]cryptoutil.DigestSet)
testDigestSet["test"] = testDigest
a.baseArtifacts = testDigestSet
ctx, err := attestation.NewContext([]attestation.Attestor{a})
ctx, err := attestation.NewContext("test", []attestation.Attestor{a})
require.NoError(t, err)
require.NoError(t, a.Attest(ctx))
}
Expand Down Expand Up @@ -174,7 +174,7 @@ func TestIncludeExcludeGlobs(t *testing.T) {
}

t.Run("default include all", func(t *testing.T) {
ctx, err := attestation.NewContext([]attestation.Attestor{}, attestation.WithWorkingDir(workingDir))
ctx, err := attestation.NewContext("test", []attestation.Attestor{}, attestation.WithWorkingDir(workingDir))
require.NoError(t, err)
a := New()
require.NoError(t, a.Attest(ctx))
Expand All @@ -183,7 +183,7 @@ func TestIncludeExcludeGlobs(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctx, err := attestation.NewContext([]attestation.Attestor{}, attestation.WithWorkingDir(workingDir))
ctx, err := attestation.NewContext("test", []attestation.Attestor{}, attestation.WithWorkingDir(workingDir))
require.NoError(t, err)
a := New()
WithIncludeGlob(test.includeGlob)(a)
Expand Down
15 changes: 9 additions & 6 deletions attestation/slsa/slsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"encoding/json"
"fmt"
"strings"
"time"

prov "github.com/in-toto/attestation/go/predicates/provenance/v1"
v1 "github.com/in-toto/attestation/go/v1"
Expand Down Expand Up @@ -106,7 +105,7 @@ func (p *Provenance) RunType() attestation.RunType {
}

func (p *Provenance) Export() bool {
return p.export
return true
}

func (p *Provenance) Attest(ctx *attestation.AttestationContext) error {
Expand Down Expand Up @@ -196,13 +195,17 @@ func (p *Provenance) Attest(ctx *attestation.AttestationContext) error {
if err != nil {
return err
}
// We have start and finish time at the collection level, how do we access it here?
p.PbProvenance.RunDetails.Metadata.StartedOn = timestamppb.New(time.Now())
p.PbProvenance.RunDetails.Metadata.FinishedOn = timestamppb.New(time.Now())

p.PbProvenance.RunDetails.Metadata.StartedOn = timestamppb.New(attestor.StartTime)
p.PbProvenance.RunDetails.Metadata.FinishedOn = timestamppb.New(attestor.EndTime)

// Product Attestors
case product.ProductName:
maps.Copy(p.products, attestor.Attestor.(product.ProductAttestor).Products())
if p.products == nil {
p.products = ctx.Products()
} else {
maps.Copy(p.products, ctx.Products())
}

// Post Attestors
case oci.Name:
Expand Down
2 changes: 1 addition & 1 deletion attestation/slsa/slsa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func TestAttest(t *testing.T) {
p := attestors.NewTestProductAttestor()
s := New()

ctx, err := attestation.NewContext([]attestation.Attestor{g, gh, m, c, p, s})
ctx, err := attestation.NewContext("test", []attestation.Attestor{g, gh, m, c, p, s})
if err != nil {
t.Errorf("error creating attestation context: %s", err)
}
Expand Down
26 changes: 5 additions & 21 deletions run.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import (
"github.com/in-toto/go-witness/attestation"
"github.com/in-toto/go-witness/attestation/environment"
"github.com/in-toto/go-witness/attestation/git"
"github.com/in-toto/go-witness/attestation/link"
"github.com/in-toto/go-witness/attestation/slsa"
"github.com/in-toto/go-witness/cryptoutil"
"github.com/in-toto/go-witness/dsse"
"github.com/in-toto/go-witness/intoto"
Expand Down Expand Up @@ -95,7 +93,7 @@ func run(stepName string, signer cryptoutil.Signer, opts []RunOption) ([]RunResu
return result, err
}

runCtx, err := attestation.NewContext(ro.attestors, ro.attestationOpts...)
runCtx, err := attestation.NewContext(stepName, ro.attestors, ro.attestationOpts...)
if err != nil {
return result, fmt.Errorf("failed to create attestation context: %w", err)
}
Expand All @@ -108,29 +106,15 @@ func run(stepName string, signer cryptoutil.Signer, opts []RunOption) ([]RunResu
for _, r := range runCtx.CompletedAttestors() {
if r.Error != nil {
errs = append(errs, r.Error)
} else if r.Attestor.Name() == link.Name {
// TODO: Find a better way to set stepName
r.Attestor.(*link.Link).PbLink.Name = ro.stepName

// TODO: Add Exporter interface to attestors
if r.Attestor.(*link.Link).Export() {
if subjecter, ok := r.Attestor.(attestation.Subjecter); ok {
linkEnvelope, err := createAndSignEnvelope(r.Attestor, r.Attestor.Type(), subjecter.Subjects(), dsse.SignWithSigners(ro.signer), dsse.SignWithTimestampers(ro.timestampers...))
if err != nil {
return result, fmt.Errorf("failed to sign envelope: %w", err)
}
result = append(result, RunResult{SignedEnvelope: linkEnvelope, AttestorName: r.Attestor.Name()})
}
}
} else if r.Attestor.Name() == slsa.Name {
} else {
// TODO: Add Exporter interface to attestors
if r.Attestor.(*slsa.Provenance).Export() {
if _, ok := r.Attestor.(attestation.Exporter); ok {
if subjecter, ok := r.Attestor.(attestation.Subjecter); ok {
linkEnvelope, err := createAndSignEnvelope(r.Attestor, r.Attestor.Type(), subjecter.Subjects(), dsse.SignWithSigners(ro.signer), dsse.SignWithTimestampers(ro.timestampers...))
envelope, err := createAndSignEnvelope(r.Attestor, r.Attestor.Type(), subjecter.Subjects(), dsse.SignWithSigners(ro.signer), dsse.SignWithTimestampers(ro.timestampers...))
if err != nil {
return result, fmt.Errorf("failed to sign envelope: %w", err)
}
result = append(result, RunResult{SignedEnvelope: linkEnvelope, AttestorName: r.Attestor.Name()})
result = append(result, RunResult{SignedEnvelope: envelope, AttestorName: r.Attestor.Name()})
}
}
}
Expand Down

0 comments on commit 4d86ee9

Please sign in to comment.