Skip to content

Commit

Permalink
feat: add algo hash list for digest calc in config (#292)
Browse files Browse the repository at this point in the history
Introduce cobra/config flag that allows for slice of string's indicating
hash algorithms to be used for digest calculation. Uses
go-witness.attestation.WithHashes to add the slice to attestation run
options. Will error if can't parse hash from its string value.

Add test for testing acceptable/unacceptable hash algorithms accepted.

Refs: #73
  • Loading branch information
DataDavD committed Dec 5, 2023
1 parent 81bdfce commit 0bca967
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 1 deletion.
12 changes: 11 additions & 1 deletion cmd/run.go
Expand Up @@ -16,6 +16,7 @@ package cmd

import (
"context"
"crypto"
"encoding/json"
"fmt"

Expand Down Expand Up @@ -102,12 +103,21 @@ func runRun(ctx context.Context, ro options.RunOptions, args []string, signers .
}
}

var roHashes []crypto.Hash
for _, hashStr := range ro.Hashes {
hash, err := cryptoutil.HashFromString(hashStr)
if err != nil {
return fmt.Errorf("failed to parse hash: %w", err)
}
roHashes = append(roHashes, hash)
}

defer out.Close()
result, err := witness.Run(
ro.StepName,
signers[0],
witness.RunWithAttestors(attestors),
witness.RunWithAttestationOpts(attestation.WithWorkingDir(ro.WorkingDir)),
witness.RunWithAttestationOpts(attestation.WithWorkingDir(ro.WorkingDir), attestation.WithHashes(roHashes)),
witness.RunWithTimestampers(timestampers...),
)

Expand Down
55 changes: 55 additions & 0 deletions cmd/run_test.go
Expand Up @@ -116,3 +116,58 @@ func Test_runRunRSACA(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, b, env.Signatures[0].Certificate)
}

func TestRunHashesOptions(t *testing.T) {
tests := []struct {
name string
hashesOption []string
expectErr bool
}{
{
name: "Valid RSA key pair",
hashesOption: []string{"sha256"},
expectErr: false,
},
{
name: "Invalid hashes option",
hashesOption: []string{"invalidHash"},
expectErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
privatekey, err := rsa.GenerateKey(rand.Reader, keybits)
require.NoError(t, err)
signer := cryptoutil.NewRSASigner(privatekey, crypto.SHA256)

workingDir := t.TempDir()
attestationPath := filepath.Join(workingDir, "outfile.txt")
runOptions := options.RunOptions{
WorkingDir: workingDir,
Attestations: []string{},
Hashes: tt.hashesOption,
OutFilePath: attestationPath,
StepName: "teststep",
Tracing: false,
}

args := []string{
"bash",
"-c",
"echo 'test' > test.txt",
}

err = runRun(context.Background(), runOptions, args, signer)
if tt.expectErr {
require.Error(t, err)
} else {
require.NoError(t, err)
attestationBytes, err := os.ReadFile(attestationPath)
require.NoError(t, err)
env := dsse.Envelope{}
require.NoError(t, json.Unmarshal(attestationBytes, &env))
}
})
}
}
1 change: 1 addition & 0 deletions docs/witness_run.md
Expand Up @@ -14,6 +14,7 @@ witness run [cmd] [flags]
--attestor-product-exclude-glob string Pattern to use when recording products. Files that match this pattern will be excluded as subjects on the attestation.
--attestor-product-include-glob string Pattern to use when recording products. Files that match this pattern will be included as subjects on the attestation. (default "*")
--enable-archivista Use Archivista to store or retrieve attestations
--hashes strings Hashes selected for digest calculation. Defaults to SHA256 (default [sha256])
-h, --help help for run
-o, --outfile string File to which to write signed data. Defaults to stdout
--signer-file-cert-path string Path to the file containing the certificate for the private key
Expand Down
2 changes: 2 additions & 0 deletions options/run.go
Expand Up @@ -25,6 +25,7 @@ type RunOptions struct {
ArchivistaOptions ArchivistaOptions
WorkingDir string
Attestations []string
Hashes []string
OutFilePath string
StepName string
Tracing bool
Expand All @@ -37,6 +38,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", []string{"environment", "git"}, "Attestations to record")
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")
cmd.Flags().BoolVar(&ro.Tracing, "trace", false, "Enable tracing for the command")
Expand Down

0 comments on commit 0bca967

Please sign in to comment.