Skip to content

Commit

Permalink
move cisco asa rfc5424 parse over to rfc 3164 parser
Browse files Browse the repository at this point in the history
  • Loading branch information
GLMONTER committed Apr 11, 2024
1 parent 98ee588 commit 229ff3f
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 79 deletions.
43 changes: 43 additions & 0 deletions internal/syslogparser/rfc3164/rfc3164.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ const FortiOSTimestampRePattern = `eventtime=(\d+)`

var fortiOSTimestampCaptureRe = regexp.MustCompile(FortiOSTimestampRePattern)

const ciscoASATimestampCapture = `^<\d+>(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z)`

var ciscoASATimestampRegexp = regexp.MustCompile(ciscoASATimestampCapture)

func (p *Parser) parseFortiOSHeader() (header, error) {
//FortiOS log, do a regex parse because it is not standard
//example log : <133>date=2024-01-31 time=13:36:54 devname="Y21FS1-101F" devid="FGUSI@#J%JI@I" eventtime=1706726214463347261 tz="-0500" logid="0000000011" type="traffic" subtype="forward" level="notice" vd="root" srcip=10.2.2.30 srcport=50295 srcintf="almi-f5s" srcintfrole="undefined" dstip=10.3.1.1 dstport=90 dstintf="sr929" dstintfrole="lan" srccountry="Reserved" dstcountry="Reserved" sessionid=1583922 proto=3 action="start" policyid=905 policytype="policy" poluuid="fjkdsljjlk-5u39582305-573289527358" policyname="FIREWALL_POLICY" user="USER_ADMIN" authserver="AGENT_FO" dstuser="SVC_USER" centralnatid=5 service="TESTSERV" trandisp="noop" duration=0 sentbyte=0 rcvdbyte=0 sentpkt=0 rcvdpkt=0 vpntype="ipsecvpn" appcat="unscanned"
Expand All @@ -170,6 +174,21 @@ func (p *Parser) parseFortiOSHeader() (header, error) {
}, nil
}

func (p *Parser) parseCiscoASA_RFC5424() (header, error) {
//example log : <166>2018-06-27T12:17:46Z asa : %ASA-6-110002: Failed to locate egress interface for protocol from src interface :src IP/src port to dest IP/dest port
match := ciscoASATimestampRegexp.FindStringSubmatch(string(p.buff))
if match != nil && len(match) > 1 {
timestampStr := match[1]
parsedTime, err := time.Parse(time.RFC3339, timestampStr)
if err != nil {
return header{}, fmt.Errorf("failed to parse cisco ASA RFC5424 timestamp: %v", err)
}
fixTimestampIfNeeded(&parsedTime)
return header{timestamp: parsedTime, hostname: ""}, nil
}
return header{}, fmt.Errorf("failed to parse cisco ASA RFC5424 timestamp: %v", "no match")
}

func (p *Parser) Parse() error {
tcursor := p.cursor
p.message = rfc3164message{content: string(p.buff)}
Expand Down Expand Up @@ -227,6 +246,14 @@ func (p *Parser) Parse() error {
setDefaultFail()
return err
}
} else if errors.Is(err, syslogparser.ErrCiscoASARFC5424) {
skipMessageParse = true

hdr, err = p.parseCiscoASA_RFC5424()
if err != nil {
setDefaultFail()
return err
}
} else {
setDefaultFail()

Expand Down Expand Up @@ -311,6 +338,18 @@ func (p *Parser) parsemessage() (rfc3164message, error) {
return msg, err
}

const ciscoASA_RFC5424Format = `^<\d+>(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z)`

var ciscoASA_RFC5424Regexp = regexp.MustCompile(ciscoASA_RFC5424Format)

func checkCiscoASA_RFC5424(buff []byte) bool {
if ciscoASA_RFC5424Regexp.MatchString(string(buff)) {
return true
}

return false
}

const ciscoASAPriorityFormat = `<\d+>:`

var ciscoASARegexp = regexp.MustCompile(ciscoASAPriorityFormat)
Expand Down Expand Up @@ -377,6 +416,10 @@ func (p *Parser) parseTimestamp() (time.Time, error) {
return ts, syslogparser.ErrFortiOSFormat
}

if checkCiscoASA_RFC5424(p.buff) {
return ts, syslogparser.ErrCiscoASARFC5424
}

return ts, fmt.Errorf("%v %s", syslogparser.ErrTimestampUnknownFormat, string(p.buff))
}

Expand Down
31 changes: 31 additions & 0 deletions internal/syslogparser/rfc3164/rfc3164_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,37 @@ var (
lastTriedTimestampLen = 15
)

func (s *Rfc3164TestSuite) TestParserCiscoASA_Valid_RFC5424(c *C) {
buff := []byte(`<166>2018-06-27T12:17:46Z asa : %ASA-6-110002: Failed to locate egress interface for protocol from src interface :src IP/src port to dest IP/dest port`)

p := NewParser(buff)
expectedP := &Parser{
buff: buff,
cursor: 0,
l: len(buff),
location: time.UTC,
}

c.Assert(p, DeepEquals, expectedP)

err := p.Parse()
c.Assert(err, IsNil)

obtained := p.Dump()

expected := syslogparser.LogParts{
"timestamp": time.Date(2018, time.June, 27, 12, 17, 46, 0, time.UTC),
"hostname": "",
"tag": "",
"content": `<166>2018-06-27T12:17:46Z asa : %ASA-6-110002: Failed to locate egress interface for protocol from src interface :src IP/src port to dest IP/dest port`,
"priority": 166,
"facility": 20,
"severity": 6,
}

c.Assert(obtained, DeepEquals, expected)
}

func (s *Rfc3164TestSuite) TestParserCiscoASA_NoTimestamp(c *C) {
buff := []byte(`<34>:%ASA-session-6-106100: access-list outside_access_in permitted tcp outside/155.138.247.97(58344) -> NEX-DMZ/10.90.3.239(443) hit-cnt 1 first hit [0x8fca8d4d, 0xf3808cf3]`)

Expand Down
46 changes: 1 addition & 45 deletions internal/syslogparser/rfc5424/rfc5424.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
package rfc5424

import (
"errors"
"fmt"
"math"
"regexp"
"strconv"
"time"

Expand All @@ -32,7 +30,6 @@ var (
ErrInvalidProcId = &syslogparser.ParserError{"Invalid proc ID"}
ErrInvalidMsgId = &syslogparser.ParserError{"Invalid msg ID"}
ErrNoStructuredData = &syslogparser.ParserError{"No structured data"}
ErrCiscoASARFC5424 = &syslogparser.ParserError{"Cisco ASA RFC5424"}
)

type Parser struct {
Expand Down Expand Up @@ -91,12 +88,6 @@ func (p *Parser) Parse() error {

hdr, err := p.parseHeader()
if err != nil {
if errors.Is(err, ErrCiscoASARFC5424) {
p.header = hdr
p.structuredData = "-"
p.header.version = 1
return nil
}
return err
}

Expand Down Expand Up @@ -155,10 +146,6 @@ func (p *Parser) parseHeader() (header, error) {

ts, err := p.parseTimestamp()
if err != nil {
if errors.Is(err, ErrCiscoASARFC5424) {
hdr.timestamp = ts
return hdr, ErrCiscoASARFC5424
}
return hdr, err
}

Expand Down Expand Up @@ -274,10 +261,6 @@ func parseUnixTimestamp(buff []byte, cursor *int, l int) (time.Time, error) {
return time.Unix(sec, nsec), nil
}

const ciscoASATimestampCapture = `^<\d+>(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z)`

var ciscoASATimestampRegexp = regexp.MustCompile(ciscoASATimestampCapture)

// https://tools.ietf.org/html/rfc5424#section-6.2.3
func (p *Parser) parseTimestamp() (time.Time, error) {
ts := time.Now().UTC()
Expand All @@ -303,19 +286,7 @@ func (p *Parser) parseTimestamp() (time.Time, error) {

fd, err := parseFullDate(p.buff, &p.cursor, p.l)
if err != nil {
if errors.Is(err, ErrCiscoASARFC5424) {
match := ciscoASATimestampRegexp.FindStringSubmatch(string(p.buff))
if match != nil && len(match) > 1 {
timestampStr := match[1]
parsedTime, err := time.Parse(time.RFC3339, timestampStr)
if err != nil {
return ts, fmt.Errorf("failed to parse cisco ASA RFC5424 timestamp: %v", err)
}
return parsedTime, ErrCiscoASARFC5424
}
} else {
return ts, err
}
return ts, err
}

if p.cursor >= p.l || p.buff[p.cursor] != 'T' {
Expand Down Expand Up @@ -418,18 +389,6 @@ func parseFullDate(buff []byte, cursor *int, l int) (fullDate, error) {
return fd, nil
}

const ciscoASA_RFC5424Format = `^<\d+>(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z)`

var ciscoASA_RFC5424Regexp = regexp.MustCompile(ciscoASA_RFC5424Format)

func checkCiscoASA_RFC5424(buff []byte) bool {
if ciscoASA_RFC5424Regexp.MatchString(string(buff)) {
return true
}

return false
}

// DATE-FULLYEAR = 4DIGIT
func parseYear(buff []byte, cursor *int, l int) (int, error) {
yearLen := 4
Expand All @@ -446,9 +405,6 @@ func parseYear(buff []byte, cursor *int, l int) (int, error) {

year, err := strconv.Atoi(sub)
if err != nil {
if checkCiscoASA_RFC5424(buff) {
return 0, ErrCiscoASARFC5424
}
return 0, ErrYearInvalid
}

Expand Down
34 changes: 0 additions & 34 deletions internal/syslogparser/rfc5424/rfc5424_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,6 @@ type Rfc5424TestSuite struct {

var _ = Suite(&Rfc5424TestSuite{})

func (s *Rfc5424TestSuite) TestParserCiscoASA_Valid_RFC5424(c *C) {
buff := []byte(`<166>2018-06-27T12:17:46Z asa : %ASA-6-110002: Failed to locate egress interface for protocol from src interface :src IP/src port to dest IP/dest port`)

p := NewParser(buff)
expectedP := &Parser{
buff: buff,
cursor: 0,
l: len(buff),
}

c.Assert(p, DeepEquals, expectedP)

err := p.Parse()
c.Assert(err, IsNil)

obtained := p.Dump()

expected := syslogparser.LogParts{
"priority": 166,
"facility": 20,
"severity": 6,
"version": 1,
"timestamp": time.Date(2018, time.June, 27, 12, 17, 46, 0, time.UTC),
"hostname": "",
"app_name": "",
"proc_id": "",
"msg_id": "",
"structured_data": "-",
"message": "<166>2018-06-27T12:17:46Z asa : %ASA-6-110002: Failed to locate egress interface for protocol from src interface :src IP/src port to dest IP/dest port",
}

c.Assert(obtained, DeepEquals, expected)
}

func (s *Rfc5424TestSuite) TestParser_Valid(c *C) {
fixtures := []string{
// no STRUCTURED-DATA
Expand Down
1 change: 1 addition & 0 deletions internal/syslogparser/syslogparser.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var (
ErrSonicOSFormat = &ParserError{"SonicOS Format"}
ErrFortiOSFormat = &ParserError{"FortiOS Format"}
ErrCiscoASAFormat = &ParserError{"Cisco ASA Format"}
ErrCiscoASARFC5424 = &ParserError{"Cisco ASA RFC5424"}

ErrHostnameTooShort = &ParserError{"Hostname field too short"}
)
Expand Down

0 comments on commit 229ff3f

Please sign in to comment.