Skip to content

Commit c323013

Browse files
legoguy1000marc-gr
authored andcommitted
[Filebeat] Add Base64 encoded HMAC & UUID template functions to httpjson input (#27873)
* Init commit * Update docs and tests * Add Base64 HMAC * Remove EdgeGrid Library * Add UUID and Base64 HMAC template functions * don't upgrade google/uuid library * Format value_tpl.go Co-authored-by: Marc Guasch <marc.guasch@elastic.co> (cherry picked from commit 942d537)
1 parent 8e272a1 commit c323013

4 files changed

Lines changed: 69 additions & 10 deletions

File tree

CHANGELOG.next.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
434434
- Add `ignore_empty_value` flag to `httpjson` `split` processor. {pull}27880[27880]
435435
- Update Cisco ASA/FTD ingest pipeline grok/dissect patterns for multiple message IDs. {issue}26869[26869] {pull}26879[26879]
436436
- Add write access to `url.value` from `request.transforms` in `httpjson` input. {pull}27937[27937]
437+
- Add Base64 encoded HMAC and UUID template functions to `httpjson` input {pull}27873[27873]
437438

438439
*Heartbeat*
439440

x-pack/filebeat/docs/inputs/input-httpjson.asciidoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,13 @@ Some built-in helper functions are provided to work with the input state inside
202202
- `add`: adds a list of integers and returns their sum.
203203
- `mul`: multiplies two integers.
204204
- `div`: does the integer division of two integer values.
205-
- `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")]]`
205+
- `hmac`: calculates the hmac signature of a list of strings concatenated together. Returns a hex encoded signature. Supports sha1 or sha256. Example `[[hmac "sha256" "secret" "string1" "string2" (formatDate (now) "RFC1123")]]`
206206
- `base64Encode`: Joins and base64 encodes all supplied strings. Example `[[base64Encode "string1" "string2"]]`
207207
- `base64EncodeNoPad`: Joins and base64 encodes all supplied strings without padding. Example `[[base64EncodeNoPad "string1" "string2"]]`
208208
- `join`: joins a list of strings using the specified separator. Example: `[[join .body.arr ","]]`
209209
- `sprintf`: formats according to a format specifier and returns the resulting string. Refer to https://pkg.go.dev/fmt#Sprintf[the Go docs] for usage. Example: `[[sprintf "%d:%q" 34 "quote this"]]`
210+
- `hmacBase64`: calculates the hmac signature of a list of strings concatenated together. Returns a base64 encoded signature. Supports sha1 or sha256. Example `[[hmac "sha256" "secret" "string1" "string2" (formatDate (now) "RFC1123")]]`
211+
- `uuid`: returns a random UUID such as `a11e8780-e3e7-46d0-8e76-f66e75acf019` Example: `[[ uuid ]]`
210212

211213
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"]]`
212214

x-pack/filebeat/input/httpjson/internal/v2/value_tpl.go

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"text/template"
2222
"time"
2323

24+
"github.com/google/uuid"
25+
2426
"github.com/elastic/beats/v7/libbeat/logp"
2527
)
2628

@@ -55,11 +57,13 @@ func (t *valueTpl) Unpack(in string) error {
5557
"add": add,
5658
"mul": mul,
5759
"div": div,
58-
"hmac": hmacString,
60+
"hmac": hmacStringHex,
5961
"base64Encode": base64Encode,
6062
"base64EncodeNoPad": base64EncodeNoPad,
6163
"join": strings.Join,
6264
"sprintf": fmt.Sprintf,
65+
"hmacBase64": hmacStringBase64,
66+
"uuid": uuidString,
6367
}).
6468
Delims(leftDelim, rightDelim).
6569
Parse(in)
@@ -267,10 +271,9 @@ func base64EncodeNoPad(values ...string) string {
267271
return base64.RawStdEncoding.EncodeToString([]byte(data))
268272
}
269273

270-
func hmacString(hmacType string, hmacKey string, values ...string) string {
271-
data := strings.Join(values[:], "")
274+
func hmacString(hmacType string, hmacKey string, data string) []byte {
272275
if data == "" {
273-
return ""
276+
return nil
274277
}
275278
// Create a new HMAC by defining the hash type and the key (as byte array)
276279
var mac hash.Hash
@@ -281,11 +284,40 @@ func hmacString(hmacType string, hmacKey string, values ...string) string {
281284
mac = hmac.New(sha1.New, []byte(hmacKey))
282285
default:
283286
// Upstream config validation prevents this from happening.
284-
return ""
287+
return nil
285288
}
286289
// Write Data to it
287290
mac.Write([]byte(data))
288291

292+
// Get result and encode as bytes
293+
return mac.Sum(nil)
294+
}
295+
296+
func hmacStringHex(hmacType string, hmacKey string, values ...string) string {
297+
data := strings.Join(values[:], "")
298+
if data == "" {
299+
return ""
300+
}
301+
bytes := hmacString(hmacType, hmacKey, data)
289302
// Get result and encode as hexadecimal string
290-
return hex.EncodeToString(mac.Sum(nil))
303+
return hex.EncodeToString(bytes)
304+
}
305+
306+
func hmacStringBase64(hmacType string, hmacKey string, values ...string) string {
307+
data := strings.Join(values[:], "")
308+
if data == "" {
309+
return ""
310+
}
311+
bytes := hmacString(hmacType, hmacKey, data)
312+
313+
// Get result and encode as hexadecimal string
314+
return base64.StdEncoding.EncodeToString(bytes)
315+
}
316+
317+
func uuidString() string {
318+
uuid, err := uuid.NewRandom()
319+
if err != nil {
320+
return ""
321+
}
322+
return uuid.String()
291323
}

x-pack/filebeat/input/httpjson/internal/v2/value_tpl_test.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,14 @@ func TestValueTpl(t *testing.T) {
253253
expectedVal: "4",
254254
},
255255
{
256-
name: "func sha1 hmac",
256+
name: "func sha1 hmac Hex",
257257
value: `[[hmac "sha1" "secret" "string1" "string2"]]`,
258258
paramCtx: emptyTransformContext(),
259259
paramTr: transformable{},
260260
expectedVal: "87eca1e7cba012b2dd4a907c2ad4345a252a38f4",
261261
},
262262
{
263-
name: "func sha256 hmac",
263+
name: "func sha256 hmac Hex",
264264
setup: func() { timeNow = func() time.Time { return time.Unix(1627697597, 0).UTC() } },
265265
teardown: func() { timeNow = time.Now },
266266
value: `[[hmac "sha256" "secret" "string1" "string2" (formatDate (now) "RFC1123")]]`,
@@ -269,7 +269,7 @@ func TestValueTpl(t *testing.T) {
269269
expectedVal: "adc61cd206e146f2d1337504e760ea70f3d2e34bedf28d07802e0e776568a06b",
270270
},
271271
{
272-
name: "func invalid hmac",
272+
name: "func invalid hmac Hex",
273273
value: `[[hmac "md5" "secret" "string1" "string2"]]`,
274274
paramCtx: emptyTransformContext(),
275275
paramTr: transformable{},
@@ -331,6 +331,30 @@ func TestValueTpl(t *testing.T) {
331331
paramTr: transformable{},
332332
expectedVal: `"foo,bar":1`,
333333
},
334+
{
335+
name: "func sha1 hmac Base64",
336+
value: `[[hmacBase64 "sha1" "secret" "string1" "string2"]]`,
337+
paramCtx: emptyTransformContext(),
338+
paramTr: transformable{},
339+
expectedVal: "h+yh58ugErLdSpB8KtQ0WiUqOPQ=",
340+
},
341+
{
342+
name: "func sha256 hmac Base64",
343+
setup: func() { timeNow = func() time.Time { return time.Unix(1627697597, 0).UTC() } },
344+
teardown: func() { timeNow = time.Now },
345+
value: `[[hmacBase64 "sha256" "secret" "string1" "string2"]]`,
346+
paramCtx: emptyTransformContext(),
347+
paramTr: transformable{},
348+
expectedVal: "HlglO6yRZs0Ts3MjmgnRKtTJk3fr9nt8LmeliVKZyAA=",
349+
},
350+
{
351+
name: "func invalid hmac Base64",
352+
value: `[[hmacBase64 "md5" "secret" "string1" "string2"]]`,
353+
paramCtx: emptyTransformContext(),
354+
paramTr: transformable{},
355+
expectedVal: "",
356+
expectedError: errEmptyTemplateResult.Error(),
357+
},
334358
}
335359

336360
for _, tc := range cases {

0 commit comments

Comments
 (0)