Skip to content

Commit

Permalink
Handle and provide better filter processing errors
Browse files Browse the repository at this point in the history
  • Loading branch information
nbrownus committed Aug 7, 2017
1 parent e194f88 commit 3d18640
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 15 deletions.
44 changes: 29 additions & 15 deletions audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,26 +231,26 @@ func createStdOutOutput(config *viper.Viper) (*AuditWriter, error) {
return NewAuditWriter(os.Stdout, attempts), nil
}

func createFilters(config *viper.Viper) []AuditFilter {
func createFilters(config *viper.Viper) ([]AuditFilter, error) {
var err error
var ok bool

fs := config.Get("filters")
filters := []AuditFilter{}

if fs == nil {
return filters
return filters, nil
}

ft, ok := fs.([]interface{})
if !ok {
return filters
return filters, fmt.Errorf("Could not parse filters object")
}

for i, f := range ft {
f2, ok := f.(map[interface{}]interface{})
if !ok {
el.Fatal("Could not parse filter ", i+1, f)
return filters, fmt.Errorf("Could not parse filter %d; '%+v'", i+1, f)
}

af := AuditFilter{}
Expand All @@ -260,28 +260,25 @@ func createFilters(config *viper.Viper) []AuditFilter {
if ev, ok := v.(string); ok {
fv, err := strconv.ParseUint(ev, 10, 64)
if err != nil {
el.Fatal("`message_type` in filter ", i+1, " could not be parsed ", v, " ", err)
return filters, fmt.Errorf("`message_type` in filter %d could not be parsed; Value: `%+v`; Error: %s", i+1, v, err)
}
af.messageType = uint16(fv)

} else if ev, ok := v.(int); ok {
if !ok {
el.Fatal("`message_type` in filter ", i+1, " could not be parsed ", v)
}
af.messageType = uint16(ev)

} else {
el.Fatal("`message_type` in filter ", i+1, " could not be parsed ", v)
return filters, fmt.Errorf("`message_type` in filter %d could not be parsed; Value: `%+v`", i+1, v)
}

case "regex":
re, ok := v.(string)
if !ok {
el.Fatal("`regex` in filter ", i+1, " could not be parsed ", v)
return filters, fmt.Errorf("`regex` in filter %d could not be parsed; Value: `%+v`", i+1, v)
}

if af.regex, err = regexp.Compile(re); err != nil {
el.Fatal("`regex` in filter ", i+1, " could not be parsed ", v, " ", err)
return filters, fmt.Errorf("`regex` in filter %d could not be parsed; Value: `%+v`; Error: %s", i+1, v, err)
}

case "syscall":
Expand All @@ -290,16 +287,28 @@ func createFilters(config *viper.Viper) []AuditFilter {
} else if ev, ok := v.(int); ok {
af.syscall = strconv.Itoa(ev)
} else {
el.Fatal("`syscall` in filter ", i+1, " could not be parsed ", v)
return filters, fmt.Errorf("`syscall` in filter %d could not be parsed; Value: `%+v`", i+1, v)
}
}
}

if af.regex == nil {
return filters, fmt.Errorf("Filter %d is missing the `regex` entry", i+1)
}

if af.syscall == "" {
return filters, fmt.Errorf("Filter %d is missing the `syscall` entry", i+1)
}

if af.messageType == 0 {
return filters, fmt.Errorf("Filter %d is missing the `message_type` entry", i+1)
}

filters = append(filters, af)
l.Printf("Ignoring syscall `%v` containing message type `%v` matching string `%s`\n", af.syscall, af.messageType, af.regex.String())
l.Printf("Ignoring syscall `%v` containing message type `%v` matching string `%s`\n", af.syscall, af.messageType, af.regex.String())
}

return filters
return filters, nil
}

func main() {
Expand Down Expand Up @@ -328,6 +337,11 @@ func main() {
el.Fatal(err)
}

filters, err := createFilters(config)
if err != nil {
el.Fatal(err)
}

nlClient := NewNetlinkClient(config.GetInt("socket_buffer.receive"))
marshaller := NewAuditMarshaller(
writer,
Expand All @@ -336,7 +350,7 @@ func main() {
config.GetBool("message_tracking.enabled"),
config.GetBool("message_tracking.log_out_of_order"),
config.GetInt("message_tracking.max_out_of_order"),
createFilters(config),
filters,
)

l.Printf("Started processing events in the range [%d, %d]\n", config.GetInt("events.min"), config.GetInt("events.max"))
Expand Down
129 changes: 129 additions & 0 deletions audit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,135 @@ func Test_createOutput(t *testing.T) {
assert.Nil(t, err)
}

func Test_createFilters(t *testing.T) {
lb, elb := hookLogger()
defer resetLogger()

// no filters
c := viper.New()
f, err := createFilters(c)
assert.Nil(t, err)
assert.Empty(t, f)

// Bad outer filter value
c = viper.New()
c.Set("filters", 1)
f, err = createFilters(c)
assert.EqualError(t, err, "Could not parse filters object")
assert.Empty(t, f)

// Bad inner filter value
c = viper.New()
rf := make([]interface{}, 0)
rf = append(rf, "bad filter definition")
c.Set("filters", rf)
f, err = createFilters(c)
assert.EqualError(t, err, "Could not parse filter 1; 'bad filter definition'")
assert.Empty(t, f)

// Bad message type - string
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"message_type": "bad message type"})
c.Set("filters", rf)
f, err = createFilters(c)
assert.EqualError(t, err, "`message_type` in filter 1 could not be parsed; Value: `bad message type`; Error: strconv.ParseUint: parsing \"bad message type\": invalid syntax")
assert.Empty(t, f)

// Bad message type - unknown
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"message_type": false})
c.Set("filters", rf)
f, err = createFilters(c)
assert.EqualError(t, err, "`message_type` in filter 1 could not be parsed; Value: `false`")
assert.Empty(t, f)

// Bad regex - not string
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"regex": false})
c.Set("filters", rf)
f, err = createFilters(c)
assert.EqualError(t, err, "`regex` in filter 1 could not be parsed; Value: `false`")
assert.Empty(t, f)

// Bad regex - un-parse-able
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"regex": "["})
c.Set("filters", rf)
f, err = createFilters(c)
assert.EqualError(t, err, "`regex` in filter 1 could not be parsed; Value: `[`; Error: error parsing regexp: missing closing ]: `[`")
assert.Empty(t, f)

// Bad syscall - not string or int
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"syscall": []string{}})
c.Set("filters", rf)
f, err = createFilters(c)
assert.EqualError(t, err, "`syscall` in filter 1 could not be parsed; Value: `[]`")
assert.Empty(t, f)

// Missing regex
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"syscall": "1", "message_type": "1"})
c.Set("filters", rf)
f, err = createFilters(c)
assert.EqualError(t, err, "Filter 1 is missing the `regex` entry")
assert.Empty(t, f)

// Missing message_type
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"syscall": "1", "regex": "1"})
c.Set("filters", rf)
f, err = createFilters(c)
assert.EqualError(t, err, "Filter 1 is missing the `message_type` entry")
assert.Empty(t, f)

// Missing message_type
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"message_type": "1", "regex": "1"})
c.Set("filters", rf)
f, err = createFilters(c)
assert.EqualError(t, err, "Filter 1 is missing the `syscall` entry")
assert.Empty(t, f)

// Good with strings
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"message_type": "1", "regex": "1", "syscall": "1"})
c.Set("filters", rf)
f, err = createFilters(c)
assert.Nil(t, err)
assert.NotEmpty(t, f)
assert.Equal(t, "1", f[0].syscall)
assert.Equal(t, uint16(1), f[0].messageType)
assert.Equal(t, "1", f[0].regex.String())
assert.Empty(t, elb.String())
assert.Equal(t, "Ignoring syscall `1` containing message type `1` matching string `1`\n", lb.String())

// Good with ints
lb.Reset()
elb.Reset()
c = viper.New()
rf = make([]interface{}, 0)
rf = append(rf, map[interface{}]interface{}{"message_type": 1, "regex": "1", "syscall": 1})
c.Set("filters", rf)
f, err = createFilters(c)
assert.Nil(t, err)
assert.NotEmpty(t, f)
assert.Equal(t, "1", f[0].syscall)
assert.Equal(t, uint16(1), f[0].messageType)
assert.Equal(t, "1", f[0].regex.String())
assert.Empty(t, elb.String())
assert.Equal(t, "Ignoring syscall `1` containing message type `1` matching string `1`\n", lb.String())
}

func Benchmark_MultiPacketMessage(b *testing.B) {
marshaller := NewAuditMarshaller(NewAuditWriter(&noopWriter{}, 1), uint16(1300), uint16(1399), false, false, 1, []AuditFilter{})

Expand Down

0 comments on commit 3d18640

Please sign in to comment.