diff --git a/cmd/slsa-provenance/cli/files.go b/cmd/slsa-provenance/cli/files.go index 09f1450c..d9371877 100644 --- a/cmd/slsa-provenance/cli/files.go +++ b/cmd/slsa-provenance/cli/files.go @@ -46,13 +46,11 @@ func Files() *cobra.Command { Runner: runner, } - stmt, err := env.GenerateProvenanceStatement(cmd.Context(), artifactPath) + stmt, err := env.GenerateProvenanceStatement(cmd.Context(), artifactPath, materials...) if err != nil { return fmt.Errorf("failed to generate provenance: %w", err) } - stmt.Predicate.Materials = append(stmt.Predicate.Materials, materials...) - fmt.Fprintf(cmd.OutOrStdout(), "Saving provenance to %s\n", outputPath) return env.PersistProvenanceStatement(cmd.Context(), stmt, outputPath) diff --git a/lib/github/provenance.go b/lib/github/provenance.go index 94420b8f..381417cc 100644 --- a/lib/github/provenance.go +++ b/lib/github/provenance.go @@ -15,7 +15,7 @@ import ( // GenerateProvenanceStatement generates provenance from the provided artifactPath // // The artifactPath can be a file or a directory. -func (e *Environment) GenerateProvenanceStatement(ctx context.Context, artifactPath string) (*intoto.Statement, error) { +func (e *Environment) GenerateProvenanceStatement(ctx context.Context, artifactPath string, materials ...intoto.Item) (*intoto.Statement, error) { subjects, err := intoto.Subjects(artifactPath) if os.IsNotExist(err) { return nil, fmt.Errorf("resource path not found: [provided=%s]", artifactPath) @@ -45,7 +45,9 @@ func (e *Environment) GenerateProvenanceStatement(ctx context.Context, artifactP []intoto.Item{ {URI: "git+" + repoURI, Digest: intoto.DigestSet{"sha1": e.Context.SHA}}, }, - )) + ), + intoto.WithMaterials(materials), + ) return stmt, nil } @@ -92,7 +94,7 @@ func NewReleaseEnvironment(gh Context, runner RunnerContext, tagName string, rc // Release assets will be downloaded to the given artifactPath // // The artifactPath has to be a directory. -func (e *ReleaseEnvironment) GenerateProvenanceStatement(ctx context.Context, artifactPath string) (*intoto.Statement, error) { +func (e *ReleaseEnvironment) GenerateProvenanceStatement(ctx context.Context, artifactPath string, materials ...intoto.Item) (*intoto.Statement, error) { err := os.MkdirAll(artifactPath, 0755) if err != nil { return nil, err @@ -117,7 +119,7 @@ func (e *ReleaseEnvironment) GenerateProvenanceStatement(ctx context.Context, ar return nil, err } - return e.Environment.GenerateProvenanceStatement(ctx, artifactPath) + return e.Environment.GenerateProvenanceStatement(ctx, artifactPath, materials...) } // PersistProvenanceStatement writes the provenance statement at the given path and uploads it to the GitHub release diff --git a/lib/intoto/intoto.go b/lib/intoto/intoto.go index 6a82f76e..2f5dd7a8 100644 --- a/lib/intoto/intoto.go +++ b/lib/intoto/intoto.go @@ -85,6 +85,13 @@ func WithInvocation(buildType, entryPoint string, environment json.RawMessage, p } } +// WithMaterials adds additional materials to the predicate +func WithMaterials(materials []Item) StatementOption { + return func(s *Statement) { + s.Predicate.Materials = append(s.Predicate.Materials, materials...) + } +} + // Statement The Statement is the middle layer of the attestation, binding it to a particular subject and unambiguously identifying the types of the predicate. type Statement struct { Type string `json:"_type"`