add expr XML helpers (#1493)
This commit is contained in:
parent
392708a804
commit
64369b5c2b
5 changed files with 201 additions and 17 deletions
3
go.mod
3
go.mod
|
@ -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
2
go.sum
|
@ -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=
|
||||
|
|
|
@ -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
64
pkg/exprhelpers/xml.go
Normal 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
115
pkg/exprhelpers/xml_test.go
Normal 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)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue