add expr XML helpers (#1493)

This commit is contained in:
blotus 2022-04-29 13:52:23 +02:00 committed by GitHub
parent 392708a804
commit 64369b5c2b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 201 additions and 17 deletions

3
go.mod
View file

@ -16,9 +16,9 @@ require (
github.com/confluentinc/bincover v0.2.0
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/crowdsecurity/grokky v0.0.0-20220120093523-d5b3478363fa
github.com/crowdsecurity/machineid v1.0.1
github.com/davecgh/go-spew v1.1.1
github.com/denisbrodbeck/machineid v1.0.1
github.com/crowdsecurity/machineid v1.0.1
github.com/dghubble/sling v1.3.0
github.com/docker/docker v20.10.2+incompatible
github.com/docker/go-connections v0.4.0
@ -78,6 +78,7 @@ require (
github.com/ahmetalpbalkan/dlog v0.0.0-20170105205344-4fb5f8204f26 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect
github.com/beevik/etree v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/containerd/containerd v1.6.2 // indirect

2
go.sum
View file

@ -97,6 +97,8 @@ github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:W
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
github.com/aws/aws-sdk-go v1.42.25 h1:BbdvHAi+t9LRiaYUyd53noq9jcaAcfzOhSVbKfr6Avs=
github.com/aws/aws-sdk-go v1.42.25/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs=
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=

View file

@ -40,22 +40,24 @@ func Lower(s string) string {
func GetExprEnv(ctx map[string]interface{}) map[string]interface{} {
var ExprLib = map[string]interface{}{
"Atof": Atof,
"JsonExtract": JsonExtract,
"JsonExtractUnescape": JsonExtractUnescape,
"JsonExtractLib": JsonExtractLib,
"File": File,
"RegexpInFile": RegexpInFile,
"Upper": Upper,
"Lower": Lower,
"IpInRange": IpInRange,
"TimeNow": TimeNow,
"ParseUri": ParseUri,
"PathUnescape": PathUnescape,
"QueryUnescape": QueryUnescape,
"PathEscape": PathEscape,
"QueryEscape": QueryEscape,
"IpToRange": IpToRange,
"Atof": Atof,
"JsonExtract": JsonExtract,
"JsonExtractUnescape": JsonExtractUnescape,
"JsonExtractLib": JsonExtractLib,
"File": File,
"RegexpInFile": RegexpInFile,
"Upper": Upper,
"Lower": Lower,
"IpInRange": IpInRange,
"TimeNow": TimeNow,
"ParseUri": ParseUri,
"PathUnescape": PathUnescape,
"QueryUnescape": QueryUnescape,
"PathEscape": PathEscape,
"QueryEscape": QueryEscape,
"XMLGetAttributeValue": XMLGetAttributeValue,
"XMLGetNodeValue": XMLGetNodeValue,
"IpToRange": IpToRange,
}
for k, v := range ctx {
ExprLib[k] = v

64
pkg/exprhelpers/xml.go Normal file
View file

@ -0,0 +1,64 @@
package exprhelpers
import (
"github.com/beevik/etree"
log "github.com/sirupsen/logrus"
)
var pathCache = make(map[string]etree.Path)
func XMLGetAttributeValue(xmlString string, path string, attributeName string) string {
if _, ok := pathCache[path]; !ok {
compiledPath, err := etree.CompilePath(path)
if err != nil {
log.Errorf("Could not compile path %s: %s", path, err)
return ""
}
pathCache[path] = compiledPath
}
compiledPath := pathCache[path]
doc := etree.NewDocument()
err := doc.ReadFromString(xmlString)
if err != nil {
log.Tracef("Could not parse XML: %s", err)
return ""
}
elem := doc.FindElementPath(compiledPath)
if elem == nil {
log.Debugf("Could not find element %s", path)
return ""
}
attr := elem.SelectAttr(attributeName)
if attr == nil {
log.Debugf("Could not find attribute %s", attributeName)
return ""
}
return attr.Value
}
func XMLGetNodeValue(xmlString string, path string) string {
if _, ok := pathCache[path]; !ok {
compiledPath, err := etree.CompilePath(path)
if err != nil {
log.Errorf("Could not compile path %s: %s", path, err)
return ""
}
pathCache[path] = compiledPath
}
compiledPath := pathCache[path]
doc := etree.NewDocument()
err := doc.ReadFromString(xmlString)
if err != nil {
log.Tracef("Could not parse XML: %s", err)
return ""
}
elem := doc.FindElementPath(compiledPath)
if elem == nil {
log.Debugf("Could not find element %s", path)
return ""
}
return elem.Text()
}

115
pkg/exprhelpers/xml_test.go Normal file
View file

@ -0,0 +1,115 @@
package exprhelpers
import (
"log"
"testing"
"github.com/stretchr/testify/assert"
)
func TestXMLGetAttributeValue(t *testing.T) {
if err := Init(); err != nil {
log.Fatalf(err.Error())
}
tests := []struct {
name string
xmlString string
path string
attribute string
expectResult string
}{
{
name: "XMLGetAttributeValue",
xmlString: `<root><child attr="value"/></root>`,
path: "/root/child",
attribute: "attr",
expectResult: "value",
},
{
name: "Non existing attribute for XMLGetAttributeValue",
xmlString: `<root><child attr="value"/></root>`,
path: "/root/child",
attribute: "asdasd",
expectResult: "",
},
{
name: "Non existing path for XMLGetAttributeValue",
xmlString: `<root><child attr="value"/></root>`,
path: "/foo/bar",
attribute: "asdasd",
expectResult: "",
},
{
name: "Invalid XML for XMLGetAttributeValue",
xmlString: `<root><`,
path: "/foo/bar",
attribute: "asdasd",
expectResult: "",
},
{
name: "Invalid path for XMLGetAttributeValue",
xmlString: `<root><child attr="value"/></root>`,
path: "/foo/bar[@",
attribute: "asdasd",
expectResult: "",
},
}
for _, test := range tests {
result := XMLGetAttributeValue(test.xmlString, test.path, test.attribute)
isOk := assert.Equal(t, test.expectResult, result)
if !isOk {
t.Fatalf("test '%s' failed", test.name)
}
log.Printf("test '%s' : OK", test.name)
}
}
func TestXMLGetNodeValue(t *testing.T) {
if err := Init(); err != nil {
log.Fatalf(err.Error())
}
tests := []struct {
name string
xmlString string
path string
expectResult string
}{
{
name: "XMLGetNodeValue",
xmlString: `<root><child>foobar</child></root>`,
path: "/root/child",
expectResult: "foobar",
},
{
name: "Non existing path for XMLGetNodeValue",
xmlString: `<root><child>foobar</child></root>`,
path: "/foo/bar",
expectResult: "",
},
{
name: "Invalid XML for XMLGetNodeValue",
xmlString: `<root><`,
path: "/foo/bar",
expectResult: "",
},
{
name: "Invalid path for XMLGetNodeValue",
xmlString: `<root><child>foobar</child></root>`,
path: "/foo/bar[@",
expectResult: "",
},
}
for _, test := range tests {
result := XMLGetNodeValue(test.xmlString, test.path)
isOk := assert.Equal(t, test.expectResult, result)
if !isOk {
t.Fatalf("test '%s' failed", test.name)
}
log.Printf("test '%s' : OK", test.name)
}
}