From 534a993689196200fb76c05c97a0ba9a04f4e2a8 Mon Sep 17 00:00:00 2001 From: Stefano Arlandini Date: Tue, 19 Jul 2022 20:45:06 +0200 Subject: [PATCH] Change `hashFiles` template function to generate SHA256 hashes --- internal/plugin/plugin.go | 5 +++-- key/generator/hash.go | 32 +++++++++++++++++--------------- key/generator/hash_test.go | 3 ++- key/generator/metadata.go | 19 ++++++++++++++----- key/generator/metadata_test.go | 6 +++--- key/generator/util.go | 8 +++----- 6 files changed, 42 insertions(+), 31 deletions(-) diff --git a/internal/plugin/plugin.go b/internal/plugin/plugin.go index 2a19dcca..cf9919ee 100644 --- a/internal/plugin/plugin.go +++ b/internal/plugin/plugin.go @@ -2,6 +2,7 @@ package plugin import ( + "crypto/md5" // #nosec "errors" "fmt" "os" @@ -89,9 +90,9 @@ func (p *Plugin) Exec() error { // nolint: funlen,cyclop return fmt.Errorf("parse failed, falling back to default, %w", err) } - options = append(options, cache.WithFallbackGenerator(keygen.NewHash(p.Metadata.Commit.Branch))) + options = append(options, cache.WithFallbackGenerator(keygen.NewHash(md5.New, p.Metadata.Commit.Branch))) } else { - generator = keygen.NewHash(p.Metadata.Commit.Branch) + generator = keygen.NewHash(md5.New, p.Metadata.Commit.Branch) options = append(options, cache.WithFallbackGenerator(keygen.NewStatic(p.Metadata.Commit.Branch))) } diff --git a/key/generator/hash.go b/key/generator/hash.go index a35b9ef3..5e128ea5 100644 --- a/key/generator/hash.go +++ b/key/generator/hash.go @@ -2,23 +2,35 @@ package generator import ( "fmt" + hash2 "hash" "io" "strings" ) -// Hash implements a key generator with md5. +// Hash implements a key generator that uses the specified hash algorithm. type Hash struct { + hasher func() hash2.Hash defaultParts []string } -// NewHash creates a new hash kye generator. -func NewHash(defaultParts ...string) *Hash { - return &Hash{defaultParts: defaultParts} +// NewHash creates a new hash key generator. +func NewHash(hasher func() hash2.Hash, defaultParts ...string) *Hash { + return &Hash{ + hasher: hasher, + defaultParts: defaultParts, + } } // Generate generates key from given parts or templates as parameter. func (h *Hash) Generate(parts ...string) (string, error) { - key, err := hash(append(parts, h.defaultParts...)...) + parts = append(parts, h.defaultParts...) + readers := make([]io.Reader, len(parts)) + + for i, p := range parts { + readers[i] = strings.NewReader(p) + } + + key, err := readerHasher(h.hasher, readers...) if err != nil { return "", fmt.Errorf("generate hash key for mounted, %w", err) } @@ -28,13 +40,3 @@ func (h *Hash) Generate(parts ...string) (string, error) { // Check checks if generator functional. func (h *Hash) Check() error { return nil } - -// hash generates a key based on given strings (ie. filename paths and branch). -func hash(parts ...string) ([]byte, error) { - readers := make([]io.Reader, len(parts)) - for i, p := range parts { - readers[i] = strings.NewReader(p) - } - - return readerHasher(readers...) -} diff --git a/key/generator/hash_test.go b/key/generator/hash_test.go index de264d8a..879c715d 100644 --- a/key/generator/hash_test.go +++ b/key/generator/hash_test.go @@ -1,6 +1,7 @@ package generator import ( + "crypto/md5" "testing" "github.com/meltwater/drone-cache/test" @@ -9,7 +10,7 @@ import ( func TestGenerateHash(t *testing.T) { t.Parallel() - actual, err := NewHash().Generate("hash") + actual, err := NewHash(md5.New).Generate("hash") test.Ok(t, err) expected := "0800fc577294c34e0b28ad2839435945" diff --git a/key/generator/metadata.go b/key/generator/metadata.go index e665b339..c610b239 100644 --- a/key/generator/metadata.go +++ b/key/generator/metadata.go @@ -2,8 +2,11 @@ package generator import ( "bytes" + "crypto/md5" // #nosec + "crypto/sha256" "errors" "fmt" + hash2 "hash" "io" "os" "path/filepath" @@ -92,7 +95,7 @@ func (g *Metadata) parseTemplate() (*template.Template, error) { func checksumFunc(logger log.Logger) func(string) string { return func(p string) string { - return fmt.Sprintf("%x", fileHash(p, logger)) + return fmt.Sprintf("%x", fileHash(p, logger, md5.New)) } } @@ -104,24 +107,27 @@ func hashFilesFunc(logger log.Logger) func(...string) string { paths, err := filepath.Glob(pattern) if err != nil { level.Error(logger).Log("could not parse file path as a glob pattern") + continue } for _, p := range paths { - readers = append(readers, bytes.NewReader(fileHash(p, logger))) + readers = append(readers, bytes.NewReader(fileHash(p, logger, sha256.New))) } } if len(readers) == 0 { level.Debug(logger).Log("no matches found for glob") + return "" } level.Debug(logger).Log("found %d files to hash", len(readers)) - h, err := readerHasher(readers...) + h, err := readerHasher(sha256.New, readers...) if err != nil { level.Error(logger).Log("could not generate the hash of the input files: %s", err.Error()) + return "" } @@ -129,24 +135,27 @@ func hashFilesFunc(logger log.Logger) func(...string) string { } } -func fileHash(path string, logger log.Logger) []byte { +func fileHash(path string, logger log.Logger, hasher func() hash2.Hash) []byte { path, err := filepath.Abs(filepath.Clean(path)) if err != nil { level.Error(logger).Log("could not compute the absolute file path: %s", err.Error()) + return []byte{} } f, err := os.Open(path) if err != nil { level.Error(logger).Log("could not open the file: %s", err.Error()) + return []byte{} } defer internal.CloseWithErrLogf(logger, f, "checksum close defer") - h, err := readerHasher(f) + h, err := readerHasher(hasher, f) if err != nil { level.Error(logger).Log("could not generate the hash of the input file: %s", err.Error()) + return []byte{} } diff --git a/key/generator/metadata_test.go b/key/generator/metadata_test.go index 4c964a53..ab3bc481 100644 --- a/key/generator/metadata_test.go +++ b/key/generator/metadata_test.go @@ -23,9 +23,9 @@ func TestGenerate(t *testing.T) { {`{{ checksum "checksum_file_test.txt"}}`, "04a29c732ecbce101c1be44c948a50c6"}, {`{{ checksum "../../docs/drone_env_vars.md"}}`, "f8b5b7f96f3ffaa828e4890aab290e59"}, {`{{ hashFiles "" }}`, ""}, - {`{{ hashFiles "checksum_file_test.txt" }}`, "5c3544faf206777a2827f5db8fca3a9a"}, - {`{{ hashFiles "checksum_file_test.txt" "checksum_file_test.txt" }}`, "1ce4114d3f702eecca6de4fed10250f3"}, - {`{{ hashFiles "checksum_file_tes*.txt" }}`, "5c3544faf206777a2827f5db8fca3a9a"}, + {`{{ hashFiles "checksum_file_test.txt" }}`, "b9fff559e00dd879bdffee979ee73e08c67dee2117da071083d3b833cbff7bc8"}, + {`{{ hashFiles "checksum_file_test.txt" "checksum_file_test.txt" }}`, "fed16eb2e98f501968c74e261feb26a8776b2ae03b205ad7302f949e75ca455f"}, + {`{{ hashFiles "checksum_file_tes*.txt" }}`, "b9fff559e00dd879bdffee979ee73e08c67dee2117da071083d3b833cbff7bc8"}, {`{{ epoch }}`, "1550563151"}, {`{{ arch }}`, runtime.GOARCH}, {`{{ os }}`, runtime.GOOS}, diff --git a/key/generator/util.go b/key/generator/util.go index ca5654dc..2067cb90 100644 --- a/key/generator/util.go +++ b/key/generator/util.go @@ -1,15 +1,13 @@ package generator import ( - "crypto/md5" // #nosec "fmt" + hash2 "hash" "io" ) -// readerHasher generic md5 hash generater from io.Reader. -func readerHasher(readers ...io.Reader) ([]byte, error) { - // Use go1.14 new hashmap functions. - h := md5.New() // #nosec +func readerHasher(hasher func() hash2.Hash, readers ...io.Reader) ([]byte, error) { + h := hasher() for _, r := range readers { if _, err := io.Copy(h, r); err != nil {