crowdsec/pkg/acquisition/modules/syslog/internal/parser/rfc5424/parse_test.go

233 lines
9.5 KiB
Go
Raw Permalink Normal View History

package rfc5424
import (
"testing"
"time"
2023-01-12 16:03:25 +00:00
"github.com/crowdsecurity/go-cs-lib/pkg/cstest"
2023-01-12 16:03:25 +00:00
"github.com/stretchr/testify/require"
)
func TestPri(t *testing.T) {
tests := []struct {
input string
expected int
expectedErr string
}{
{"<0>", 0, ""},
{"<19>", 19, ""},
{"<200>", 200, ""},
{"<4999>", 0, "PRI must be up to 3 characters long"},
{"<123", 0, "PRI must end with '>'"},
{"123>", 0, "PRI must start with '<'"},
{"<abc>", 0, "PRI must be a number"},
}
for _, test := range tests {
test := test
t.Run(test.input, func(t *testing.T) {
r := &RFC5424{}
r.buf = []byte(test.input)
r.len = len(r.buf)
err := r.parsePRI()
2023-01-12 16:03:25 +00:00
cstest.RequireErrorMessage(t, err, test.expectedErr)
})
}
}
func TestHostname(t *testing.T) {
tests := []struct {
input string
expected string
expectedErr string
strictHostname bool
}{
{"127.0.0.1", "127.0.0.1", "", false},
{"::1", "::1", "", false},
{"-", "", "", false},
{"foo.-bar", "", "hostname is not valid", true},
{"foo-.bar", "", "hostname is not valid", true},
{"foo123.bar", "foo123.bar", "", true},
{"a..", "", "hostname is not valid", true},
{"foo.bar", "foo.bar", "", false},
{"foo,bar", "foo,bar", "", false},
{"foo,bar", "", "hostname is not valid", true},
{".", ".", "", true},
{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "", "hostname is not valid", true},
{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.bla", "", "hostname is not valid", true},
{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.bla", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.bla", "", false},
{"a.foo-", "", "hostname is not valid", true},
}
for _, test := range tests {
test := test
t.Run(test.input, func(t *testing.T) {
opts := []RFC5424Option{}
if test.strictHostname {
opts = append(opts, WithStrictHostname())
}
r := NewRFC5424Parser(opts...)
r.buf = []byte(test.input)
r.len = len(r.buf)
err := r.parseHostname()
2023-01-12 16:03:25 +00:00
cstest.RequireErrorMessage(t, err, test.expectedErr)
})
}
}
func TestParse(t *testing.T) {
type expected struct {
Timestamp time.Time
Hostname string
Tag string
PID string
Message string
PRI int
MsgID string
}
tests := []struct {
name string
input string
expected expected
expectedErr string
opts []RFC5424Option
}{
{
"valid msg",
`<13>1 2021-05-18T11:58:40.828081+02:42 mantis sshd 49340 - [timeQuality isSynced="0" tzKnown="1"] blabla`, expected{
Timestamp: time.Date(2021, 5, 18, 11, 58, 40, 828081000, time.FixedZone("+0242", 9720)),
Hostname: "mantis",
Tag: "sshd",
PID: "49340",
MsgID: "",
Message: "blabla",
PRI: 13,
}, "", []RFC5424Option{},
},
{
"valid msg with msgid",
`<13>1 2021-05-18T11:58:40.828081+02:42 mantis foobar 49340 123123 [timeQuality isSynced="0" tzKnown="1"] blabla`, expected{
Timestamp: time.Date(2021, 5, 18, 11, 58, 40, 828081000, time.FixedZone("+0242", 9720)),
Hostname: "mantis",
Tag: "foobar",
PID: "49340",
MsgID: "123123",
Message: "blabla",
PRI: 13,
}, "", []RFC5424Option{},
},
{
"valid msg with repeating SD",
`<13>1 2021-05-18T11:58:40.828081+02:42 mantis foobar 49340 123123 [timeQuality isSynced="0" tzKnown="1"][foo="bar][a] blabla`, expected{
Timestamp: time.Date(2021, 5, 18, 11, 58, 40, 828081000, time.FixedZone("+0242", 9720)),
Hostname: "mantis",
Tag: "foobar",
PID: "49340",
MsgID: "123123",
Message: "blabla",
PRI: 13,
}, "", []RFC5424Option{},
},
{
"invalid SD",
`<13>1 2021-05-18T11:58:40.828081+02:00 mantis foobar 49340 123123 [timeQuality asd`, expected{}, "structured data must end with ']'", []RFC5424Option{},
},
{
"invalid version",
`<13>42 2021-05-18T11:58:40.828081+02:00 mantis foobar 49340 123123 [timeQuality isSynced="0" tzKnown="1"] blabla`, expected{}, "version must be 1", []RFC5424Option{},
},
{
"invalid message",
`<13>1`, expected{}, "version must be followed by a space", []RFC5424Option{},
},
{
"valid msg with empty fields",
`<13>1 - foo - - - - blabla`, expected{
2023-01-12 16:03:25 +00:00
Timestamp: time.Now().UTC(),
Hostname: "foo",
PRI: 13,
Message: "blabla",
}, "", []RFC5424Option{},
},
{
"valid msg with empty fields",
`<13>1 - - - - - - blabla`, expected{
2023-01-12 16:03:25 +00:00
Timestamp: time.Now().UTC(),
PRI: 13,
Message: "blabla",
}, "", []RFC5424Option{},
},
{
"valid msg with escaped SD",
`<13>1 2022-05-24T10:57:39Z testhostname unknown - sn="msgid" [foo="\]" bar="a\""][a b="[\]" c] testmessage`,
expected{
PRI: 13,
Timestamp: time.Date(2022, 5, 24, 10, 57, 39, 0, time.UTC),
Tag: "unknown",
Hostname: "testhostname",
MsgID: `sn="msgid"`,
Message: `testmessage`,
}, "", []RFC5424Option{},
},
{
"valid complex msg",
`<13>1 2022-05-24T10:57:39Z myhostname unknown - sn="msgid" [all@0 request="/dist/precache-manifest.58b57debe6bc4f96698da0dc314461e9.js" src_ip_geo_country="DE" MONTH="May" COMMONAPACHELOG="1.1.1.1 - - [24/May/2022:10:57:37 +0200\] \"GET /dist/precache-manifest.58b57debe6bc4f96698da0dc314461e9.js HTTP/2.0\" 304 0" auth="-" HOUR="10" gl2_remote_ip="172.31.32.142" ident="-" gl2_remote_port="43375" BASE10NUM="[2.0, 304, 0\]" pid="-1" program="nginx" gl2_source_input="623ed3440183476d61cff974" INT="+0200" is_private_ip="false" YEAR="2022" src_ip_geo_city="Achern" clientip="1.1.1.1" USERNAME="-" src_ip_geo_location="48.6306,8.0743" gl2_source_node="8620c2bb-dbb7-4535-b1ce-83df223acd8d" MINUTE="57" timestamp="2022-05-24T08:57:37.000Z" src_ip_asn="3320" level="5" IP="1.1.1.1" IPV4="1.1.1.1" verb="GET" gl2_message_id="01G3TMJFAMFS4H60QSF7M029R0" TIME="10:57:37" USER="-" src_ip_asn_owner="Deutsche Telekom AG" response="304" bytes="0" SECOND="37" httpversion="2.0" _id="906ce155-db3f-11ec-b25f-0a189ba2c64e" facility="user" MONTHDAY="24"] source: sn="www.foobar.com" | message: 1.1.1.1 - - [24/May/2022:10:57:37 +0200] "GET /dist/precache-manifest.58b57debe6bc4f96698da0dc314461e9.js HTTP/2.0" 304 0 "https://www.foobar.com/sw.js" "Mozilla/5.0 (Linux; Android 9; ANE-LX1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36" "-" "www.foobar.com" sn="www.foobar.com" rt=0.000 ua="-" us="-" ut="-" ul="-" cs=HIT { request: /dist/precache-manifest.58b57debe6bc4f96698da0dc314461e9.js | src_ip_geo_country: DE | MONTH: May | COMMONAPACHELOG: 1.1.1.1 - - [24/May/2022:10:57:37 +0200] "GET /dist/precache-manifest.58b57debe6bc4f96698da0dc314461e9.js HTTP/2.0" 304 0 | auth: - | HOUR: 10 | gl2_remote_ip: 172.31.32.142 | ident: - | gl2_remote_port: 43375 | BASE10NUM: [2.0, 304, 0] | pid: -1 | program: nginx | gl2_source_input: 623ed3440183476d61cff974 | INT: +0200 | is_private_ip: false | YEAR: 2022 | src_ip_geo_city: Achern | clientip: 1.1.1.1 | USERNAME:`,
expected{
Timestamp: time.Date(2022, 5, 24, 10, 57, 39, 0, time.UTC),
Hostname: "myhostname",
Tag: "unknown",
PRI: 13,
MsgID: `sn="msgid"`,
Message: `source: sn="www.foobar.com" | message: 1.1.1.1 - - [24/May/2022:10:57:37 +0200] "GET /dist/precache-manifest.58b57debe6bc4f96698da0dc314461e9.js HTTP/2.0" 304 0 "https://www.foobar.com/sw.js" "Mozilla/5.0 (Linux; Android 9; ANE-LX1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.61 Mobile Safari/537.36" "-" "www.foobar.com" sn="www.foobar.com" rt=0.000 ua="-" us="-" ut="-" ul="-" cs=HIT { request: /dist/precache-manifest.58b57debe6bc4f96698da0dc314461e9.js | src_ip_geo_country: DE | MONTH: May | COMMONAPACHELOG: 1.1.1.1 - - [24/May/2022:10:57:37 +0200] "GET /dist/precache-manifest.58b57debe6bc4f96698da0dc314461e9.js HTTP/2.0" 304 0 | auth: - | HOUR: 10 | gl2_remote_ip: 172.31.32.142 | ident: - | gl2_remote_port: 43375 | BASE10NUM: [2.0, 304, 0] | pid: -1 | program: nginx | gl2_source_input: 623ed3440183476d61cff974 | INT: +0200 | is_private_ip: false | YEAR: 2022 | src_ip_geo_city: Achern | clientip: 1.1.1.1 | USERNAME:`,
}, "", []RFC5424Option{},
},
{
"partial message",
`<13>1 2022-05-24T10:57:39Z foo bar -`,
expected{},
"EOL after ProcID",
[]RFC5424Option{},
},
{
"partial message",
`<13>1 2022-05-24T10:57:39Z foo bar `,
expected{},
"EOL after appname",
[]RFC5424Option{},
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
r := NewRFC5424Parser(test.opts...)
err := r.Parse([]byte(test.input))
2023-01-12 16:03:25 +00:00
cstest.RequireErrorMessage(t, err, test.expectedErr)
if test.expectedErr != "" {
return
}
require.WithinDuration(t, test.expected.Timestamp, r.Timestamp, time.Second)
if r.Hostname != test.expected.Hostname {
t.Errorf("expected hostname '%s', got '%s'", test.expected.Hostname, r.Hostname)
}
if r.Tag != test.expected.Tag {
t.Errorf("expected tag '%s', got '%s'", test.expected.Tag, r.Tag)
}
if r.PID != test.expected.PID {
t.Errorf("expected pid '%s', got '%s'", test.expected.PID, r.PID)
}
if r.Message != test.expected.Message {
t.Errorf("expected message '%s', got '%s'", test.expected.Message, r.Message)
}
if r.PRI != test.expected.PRI {
t.Errorf("expected pri '%d', got '%d'", test.expected.PRI, r.PRI)
}
if r.MsgID != test.expected.MsgID {
t.Errorf("expected msgid '%s', got '%s'", test.expected.MsgID, r.MsgID)
}
})
}
}