123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- package rfc5424
- import (
- "testing"
- "time"
- "github.com/stretchr/testify/require"
- "github.com/crowdsecurity/crowdsec/pkg/cstest"
- )
- 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()
- 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()
- 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{
- Timestamp: time.Now().UTC(),
- Hostname: "foo",
- PRI: 13,
- Message: "blabla",
- }, "", []RFC5424Option{},
- },
- {
- "valid msg with empty fields",
- `<13>1 - - - - - - blabla`, expected{
- 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))
- 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)
- }
- })
- }
- }
|