add expr XML helpers (#1493)
This commit is contained in:
parent
392708a804
commit
64369b5c2b
3
go.mod
3
go.mod
|
@ -16,9 +16,9 @@ require (
|
||||||
github.com/confluentinc/bincover v0.2.0
|
github.com/confluentinc/bincover v0.2.0
|
||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||||
github.com/crowdsecurity/grokky v0.0.0-20220120093523-d5b3478363fa
|
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/davecgh/go-spew v1.1.1
|
||||||
github.com/denisbrodbeck/machineid v1.0.1
|
github.com/denisbrodbeck/machineid v1.0.1
|
||||||
github.com/crowdsecurity/machineid v1.0.1
|
|
||||||
github.com/dghubble/sling v1.3.0
|
github.com/dghubble/sling v1.3.0
|
||||||
github.com/docker/docker v20.10.2+incompatible
|
github.com/docker/docker v20.10.2+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
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/ahmetalpbalkan/dlog v0.0.0-20170105205344-4fb5f8204f26 // indirect
|
||||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||||
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // 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/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
github.com/containerd/containerd v1.6.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.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 h1:BbdvHAi+t9LRiaYUyd53noq9jcaAcfzOhSVbKfr6Avs=
|
||||||
github.com/aws/aws-sdk-go v1.42.25/go.mod h1:gyRszuZ/icHmHAVE4gc/r+cfCmhA1AD+vqfWbgI+eHs=
|
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 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.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
|
|
@ -55,6 +55,8 @@ func GetExprEnv(ctx map[string]interface{}) map[string]interface{} {
|
||||||
"QueryUnescape": QueryUnescape,
|
"QueryUnescape": QueryUnescape,
|
||||||
"PathEscape": PathEscape,
|
"PathEscape": PathEscape,
|
||||||
"QueryEscape": QueryEscape,
|
"QueryEscape": QueryEscape,
|
||||||
|
"XMLGetAttributeValue": XMLGetAttributeValue,
|
||||||
|
"XMLGetNodeValue": XMLGetNodeValue,
|
||||||
"IpToRange": IpToRange,
|
"IpToRange": IpToRange,
|
||||||
}
|
}
|
||||||
for k, v := range ctx {
|
for k, v := range ctx {
|
||||||
|
|
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