diff --git a/cmd/run.go b/cmd/run.go index 0a51073f..4bb50707 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -18,7 +18,9 @@ import ( "context" "encoding/json" "fmt" + "strings" + "github.com/gobwas/glob" witness "github.com/in-toto/go-witness" "github.com/in-toto/go-witness/archivista" "github.com/in-toto/go-witness/attestation" @@ -132,12 +134,23 @@ func runRun(ctx context.Context, ro options.RunOptions, args []string, signers . roHashes = append(roHashes, cryptoutil.DigestValue{Hash: hash, GitOID: false}) } + for _, dirHashGlobItem := range ro.DirHashGlobs { + if strings.Contains(dirHashGlobItem, "**") { + return fmt.Errorf("failed to parse dirhash-glob: can not contain deep (**) glob matches.") + } + + _, err := glob.Compile(dirHashGlobItem) + if err != nil { + return fmt.Errorf("failed to compile glob: %v", err) + } + } + defer out.Close() result, err := witness.Run( ro.StepName, signers[0], witness.RunWithAttestors(attestors), - witness.RunWithAttestationOpts(attestation.WithWorkingDir(ro.WorkingDir), attestation.WithHashes(roHashes)), + witness.RunWithAttestationOpts(attestation.WithWorkingDir(ro.WorkingDir), attestation.WithHashes(roHashes), attestation.WithDirHashGlob(ro.DirHashGlobs)), witness.RunWithTimestampers(timestampers...), ) if err != nil { diff --git a/options/run.go b/options/run.go index 00f38ace..530c194f 100644 --- a/options/run.go +++ b/options/run.go @@ -28,6 +28,7 @@ type RunOptions struct { ArchivistaOptions ArchivistaOptions WorkingDir string Attestations []string + DirHashGlobs []string Hashes []string OutFilePath string StepName string @@ -41,6 +42,7 @@ func (ro *RunOptions) AddFlags(cmd *cobra.Command) { ro.ArchivistaOptions.AddFlags(cmd) cmd.Flags().StringVarP(&ro.WorkingDir, "workingdir", "d", "", "Directory from which commands will run") cmd.Flags().StringSliceVarP(&ro.Attestations, "attestations", "a", DefaultAttestors, "Attestations to record ('product' and 'material' are always recorded)") + cmd.Flags().StringSliceVar(&ro.DirHashGlobs, "dirhash-glob", []string{}, "Dirhash glob can be used to collapse material and product hashes on matching directory matches.") cmd.Flags().StringSliceVar(&ro.Hashes, "hashes", []string{"sha256"}, "Hashes selected for digest calculation. Defaults to SHA256") cmd.Flags().StringVarP(&ro.OutFilePath, "outfile", "o", "", "File to which to write signed data. Defaults to stdout") cmd.Flags().StringVarP(&ro.StepName, "step", "s", "", "Name of the step being run")