return better errors if a regexp rule fails to compile

If a regexp rule fails to compile, return the reason instead of a
generic error. It'll help to debug problems.
This commit is contained in:
Gustavo Iñiguez Goia 2020-06-19 18:02:09 +02:00
parent 23d5f87dd7
commit fc2212f073
4 changed files with 29 additions and 19 deletions

View file

@ -46,7 +46,7 @@ type Operator struct {
re *regexp.Regexp
}
func NewOperator(t Type, o Operand, data string, list []Operator) *Operator {
func NewOperator(t Type, o Operand, data string, list []Operator) (*Operator, error) {
op := Operator{
Type: t,
Operand: o,
@ -54,9 +54,10 @@ func NewOperator(t Type, o Operand, data string, list []Operator) *Operator {
List: list,
}
if err := op.Compile(); err != nil {
return nil
log.Error("NewOperator() failed to compile:", err)
return nil, err
}
return &op
return &op, nil
}
func (o *Operator) Compile() error {
@ -64,11 +65,11 @@ func (o *Operator) Compile() error {
o.cb = o.simpleCmp
} else if o.Type == Regexp {
o.cb = o.reCmp
if re, err := regexp.Compile(o.Data); err == nil {
o.re = re
} else {
re, err := regexp.Compile(o.Data)
if err != nil {
return err
}
o.re = re
} else if o.Type == List {
o.Operand = OpList
}

View file

@ -5,6 +5,7 @@ import (
"time"
"github.com/gustavo-iniguez-goya/opensnitch/daemon/conman"
"github.com/gustavo-iniguez-goya/opensnitch/daemon/log"
"github.com/gustavo-iniguez-goya/opensnitch/daemon/ui/protocol"
)
@ -59,18 +60,20 @@ func (r *Rule) Match(con *conman.Connection) bool {
return r.Operator.Match(con)
}
func Deserialize(reply *protocol.Rule) *Rule {
func Deserialize(reply *protocol.Rule) (*Rule, error) {
if reply.Operator == nil {
return nil
log.Warning("Deserialize rule, Operator nil")
return nil, fmt.Errorf("invalid operator")
}
operator := NewOperator(
operator, err := NewOperator(
Type(reply.Operator.Type),
Operand(reply.Operator.Operand),
reply.Operator.Data,
make([]Operator, 0),
)
if operator == nil {
return nil
if err != nil {
log.Warning("Deserialize rule, NewOperator() error:", err)
return nil, err
}
return Create(
@ -79,7 +82,7 @@ func Deserialize(reply *protocol.Rule) *Rule {
Action(reply.Action),
Duration(reply.Duration),
operator,
)
), nil
}
func (r *Rule) Serialize() *protocol.Rule {

View file

@ -21,8 +21,9 @@ import (
var (
configFile = "/etc/opensnitchd/default-config.json"
clientDisconnectedRule = rule.Create("ui.client.disconnected", true, rule.Allow, rule.Once, rule.NewOperator(rule.Simple, rule.OpTrue, "", make([]rule.Operator, 0)))
clientErrorRule = rule.Create("ui.client.error", true, rule.Allow, rule.Once, rule.NewOperator(rule.Simple, rule.OpTrue, "", make([]rule.Operator, 0)))
dummyOperator, _ = rule.NewOperator(rule.Simple, rule.OpTrue, "", make([]rule.Operator, 0))
clientDisconnectedRule = rule.Create("ui.client.disconnected", true, rule.Allow, rule.Once, dummyOperator)
clientErrorRule = rule.Create("ui.client.error", true, rule.Allow, rule.Once, dummyOperator)
config Config
)
@ -234,7 +235,11 @@ func (c *Client) Ask(con *conman.Connection) (*rule.Rule, bool) {
return nil, false
}
return rule.Deserialize(reply), true
r, err := rule.Deserialize(reply)
if err != nil {
return nil, false
}
return r, true
}
func (c *Client) monitorConfigWorker() {

View file

@ -77,7 +77,7 @@ func (c *Client) handleNotification(stream protocol.UI_NotificationsClient, noti
for _, rul := range notification.Rules {
log.Info("[notification] enable rule: ", rul.Name)
// protocol.Rule(protobuf) != rule.Rule(json)
r := rule.Deserialize(rul)
r, _ := rule.Deserialize(rul)
r.Enabled = true
// save to disk only if the duration is rule.Always
if err := c.rules.Replace(r, r.Duration == rule.Always); err != nil {
@ -90,7 +90,7 @@ func (c *Client) handleNotification(stream protocol.UI_NotificationsClient, noti
var rErr error
for _, rul := range notification.Rules {
log.Info("[notification] disable: ", rul)
r := rule.Deserialize(rul)
r, _ := rule.Deserialize(rul)
r.Enabled = false
if err := c.rules.Replace(r, r.Duration == rule.Always); err != nil {
rErr = err
@ -113,9 +113,10 @@ func (c *Client) handleNotification(stream protocol.UI_NotificationsClient, noti
case notification.Type == protocol.Action_CHANGE_RULE:
var rErr error
for _, rul := range notification.Rules {
r := rule.Deserialize(rul)
log.Info("CHANGE_RULE: ", rul)
r, err := rule.Deserialize(rul)
if r == nil {
rErr = fmt.Errorf("Invalid rule")
rErr = fmt.Errorf("Invalid rule, %s", err)
continue
}
log.Info("[notification] change rule: ", r, notification.Id)