diff --git a/docs/templating-language.md b/docs/templating-language.md index 960013832..66ddfaae1 100644 --- a/docs/templating-language.md +++ b/docs/templating-language.md @@ -74,6 +74,7 @@ provides the following functions: - [replaceAll](#replaceall) - [sha256Hex](#sha256hex) - [md5sum](#md5sum) + - [hmacSHA256Hex](#hmacSHA256hex) - [split](#split) - [splitToMap](#splitToMap) - [timestamp](#timestamp) @@ -1486,6 +1487,20 @@ Takes a string input as an argument, and returns the hex-encoded md5 hash of the {{ "myString" | md5sum }} ``` +### `hmacSHA256Hex` + +Takes a key and a message as string inputs. Returns a hex-encoded HMAC-SHA256 hash with the given parameters. + +```golang +{{ hmacSHA256Hex "somemessage" "somekey" }} +``` + +Or with a pipe function + +```golang +{{ "somekey" | hmacSHA256Hex "somemessage" }} +``` + ### `split` Splits the given string on the provided separator: diff --git a/template/funcs.go b/template/funcs.go index 530a77f64..3635d0b14 100644 --- a/template/funcs.go +++ b/template/funcs.go @@ -5,6 +5,7 @@ package template import ( "bytes" + "crypto/hmac" "crypto/md5" "crypto/sha256" "encoding/base64" @@ -1720,6 +1721,14 @@ func md5sum(item string) (string, error) { return fmt.Sprintf("%x", md5.Sum([]byte(item))), nil } +// hmacSHA256Hex returns the HMAC-SHA256 hash in hexadecimal format of the +// given message by using the provided key +func hmacSHA256Hex(message, key string) (string, error) { + h := hmac.New(sha256.New, []byte(key)) + h.Write([]byte(message)) + return hex.EncodeToString(h.Sum(nil)), nil +} + // writeToFile writes the content to a file with permissions, username (or UID), group name (or GID), // and optional flags to select appending mode or add a newline. // diff --git a/template/funcs_test.go b/template/funcs_test.go index 9d5a6b03a..20a47869c 100644 --- a/template/funcs_test.go +++ b/template/funcs_test.go @@ -268,3 +268,38 @@ func Test_md5sum(t *testing.T) { }) } } + +func Test_hmacSHA256Hex(t *testing.T) { + type args struct { + message string + key string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "Should return the proper string", + args: args{ + message: "bladibla", + key: "foobar", + }, + want: "82cd4c36fa45a1936e93d005ea2fd008350339bb9246a3ba0c8dfecb9d77155b", + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := hmacSHA256Hex(tt.args.message, tt.args.key) + if (err != nil) != tt.wantErr { + t.Errorf("hmacSHA256Hex() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("hmacSHA256Hex() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/template/template.go b/template/template.go index 50180b157..f43a62dd6 100644 --- a/template/template.go +++ b/template/template.go @@ -390,6 +390,7 @@ func funcMap(i *funcMapInput) template.FuncMap { "replaceAll": replaceAll, "sha256Hex": sha256Hex, "md5sum": md5sum, + "hmacSHA256Hex": hmacSHA256Hex, "timestamp": timestamp, "toLower": toLower, "toJSON": toJSON, diff --git a/template/template_test.go b/template/template_test.go index 419efaf0c..9e1839ab9 100644 --- a/template/template_test.go +++ b/template/template_test.go @@ -254,6 +254,15 @@ func TestTemplate_Execute(t *testing.T) { "dGVzdGluZzEyMw==", false, }, + { + "func_hmacSHA256Hex", + &NewTemplateInput{ + Contents: `{{ hmacSHA256Hex "somemessage" "somekey" }}`, + }, + nil, + "6116e95f2827172aa6ef8b22b883f6a77e966aefc129c6b8228ebd0aac74e98d", + false, + }, { "func_datacenters", &NewTemplateInput{