diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 1623aa903c5..d8cd4c6f863 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -867,6 +867,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Add new template functions and `value_type` parameter to `httpjson` transforms. {pull}26847[26847] - Add support to merge registry updates in the filestream input across multiple ACKed batches in case of backpressure in the registry or disk. {pull}25976[25976] - Update Elasticsearch module's ingest pipeline for parsing new deprecation logs {issue}26857[26857] {pull}26880[26880] +- Add new `hmac` template function for httpjson input {pull}27168[27168] *Heartbeat* diff --git a/x-pack/filebeat/docs/inputs/input-httpjson.asciidoc b/x-pack/filebeat/docs/inputs/input-httpjson.asciidoc index 24e1a610ada..b9da841f721 100644 --- a/x-pack/filebeat/docs/inputs/input-httpjson.asciidoc +++ b/x-pack/filebeat/docs/inputs/input-httpjson.asciidoc @@ -203,6 +203,7 @@ Some built-in helper functions are provided to work with the input state inside - `add`: adds a list of integers and returns their sum. - `mul`: multiplies two integers. - `div`: does the integer division of two integer values. +- `hmac`: calculates the hmac signature of a list of strings concatenated together. Supports sha1 or sha256. Example `[[hmac "sha256" "secret" "string1" "string2" (formatDate (now) "RFC1123")]]` In addition to the provided functions, any of the native functions for https://golang.org/pkg/time/#Time[`time.Time`], https://golang.org/pkg/net/http/#Header[`http.Header`], and https://golang.org/pkg/net/url/#Values[`url.Values`] types can be used on the corresponding objects. Examples: `[[(now).Day]]`, `[[.last_response.header.Get "key"]]` diff --git a/x-pack/filebeat/input/httpjson/internal/v2/value_tpl.go b/x-pack/filebeat/input/httpjson/internal/v2/value_tpl.go index 828a6c36c41..0dd4f10e36a 100644 --- a/x-pack/filebeat/input/httpjson/internal/v2/value_tpl.go +++ b/x-pack/filebeat/input/httpjson/internal/v2/value_tpl.go @@ -6,7 +6,12 @@ package v2 import ( "bytes" + "crypto/hmac" + "crypto/sha1" + "crypto/sha256" + "encoding/hex" "errors" + "hash" "reflect" "regexp" "strconv" @@ -48,6 +53,7 @@ func (t *valueTpl) Unpack(in string) error { "add": add, "mul": mul, "div": div, + "hmac": hmacString, }). Delims(leftDelim, rightDelim). Parse(in) @@ -236,3 +242,26 @@ func mul(a, b int64) int64 { func div(a, b int64) int64 { return a / b } + +func hmacString(hmacType string, hmacKey string, values ...string) string { + data := strings.Join(values[:], "") + if data == "" { + return "" + } + // Create a new HMAC by defining the hash type and the key (as byte array) + var mac hash.Hash + switch hmacType { + case "sha256": + mac = hmac.New(sha256.New, []byte(hmacKey)) + case "sha1": + mac = hmac.New(sha1.New, []byte(hmacKey)) + default: + // Upstream config validation prevents this from happening. + return "" + } + // Write Data to it + mac.Write([]byte(data)) + + // Get result and encode as hexadecimal string + return hex.EncodeToString(mac.Sum(nil)) +} diff --git a/x-pack/filebeat/input/httpjson/internal/v2/value_tpl_test.go b/x-pack/filebeat/input/httpjson/internal/v2/value_tpl_test.go index eb24cb9fdaa..2274a25614a 100644 --- a/x-pack/filebeat/input/httpjson/internal/v2/value_tpl_test.go +++ b/x-pack/filebeat/input/httpjson/internal/v2/value_tpl_test.go @@ -252,6 +252,30 @@ func TestValueTpl(t *testing.T) { paramTr: transformable{}, expectedVal: "4", }, + { + name: "func sha1 hmac", + value: `[[hmac "sha1" "secret" "string1" "string2"]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: "87eca1e7cba012b2dd4a907c2ad4345a252a38f4", + }, + { + name: "func sha256 hmac", + setup: func() { timeNow = func() time.Time { return time.Unix(1627697597, 0).UTC() } }, + teardown: func() { timeNow = time.Now }, + value: `[[hmac "sha256" "secret" "string1" "string2" (formatDate (now) "RFC1123")]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: "adc61cd206e146f2d1337504e760ea70f3d2e34bedf28d07802e0e776568a06b", + }, + { + name: "func invalid hmac", + value: `[[hmac "md5" "secret" "string1" "string2"]]`, + paramCtx: emptyTransformContext(), + paramTr: transformable{}, + expectedVal: "", + expectedError: errEmptyTemplateResult.Error(), + }, } for _, tc := range cases {