Skip to content

Replace pynspect with ransack #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions pycommon/reporter_config/Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import copy
import logging

from pynspect.compilers import IDEAFilterCompiler
from pynspect.gparser import PynspectFilterParser
from ransack import Parser as RansackParser

from .actions.Drop import DropAction, DropMsg
from .actions.Action import Action
Expand Down Expand Up @@ -49,9 +48,7 @@ def __init__(self, path, dry = False, trap = None, wardenargs = None, module_nam
overrided the name by -n and only the module_name is used.
"""

self.compiler = IDEAFilterCompiler()
self.parser = PynspectFilterParser()
self.parser.build()
self.parser = RansackParser()
self.trap = trap
self.autoreload = autoreload
self.path = path
Expand Down Expand Up @@ -146,6 +143,7 @@ def loadConfig(self):
raise SyntaxError("Yaml parsing error: " + str(e))

addrGroups = dict()
parser_context = dict()
smtp_conns = dict()
actions = dict()
rules = list()
Expand All @@ -157,6 +155,9 @@ def loadConfig(self):
if "addressgroups" in conf:
for i in conf["addressgroups"]:
addrGroups[i["id"]] = AddressGroup(i)
parser_context[i["id"]] = addrGroups[i["id"]].content
# Pass address groups as a context for the parser
self.parser = RansackParser(parser_context)


# Check if "smtp_connections" exists when there is some "email" action in "custom_actions"
Expand Down Expand Up @@ -219,14 +220,12 @@ def loadConfig(self):

actions["drop"] = DropAction()

# Parse all rules and match them with actions and address groups
# Parse all rules and match them with actions
# There must be at least one rule (mandatory field)
if "rules" in conf:
if conf["rules"]:
for i in conf["rules"]:
r = Rule(i, actions, addrGroups,
parser = self.parser, compiler = self.compiler,
module_name = self.module_name)
r = Rule(i, actions, parser = self.parser, module_name = self.module_name)
rules.append(r)
if not rules:
raise SyntaxError("YAML file should contain at least one `rule` in `rules`.")
Expand Down
52 changes: 8 additions & 44 deletions pycommon/reporter_config/Rule.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import re
import logging
import redis
#from pynspect.rules import *
from pynspect.filters import DataObjectFilter
from pynspect.compilers import IDEAFilterCompiler
from pynspect.gparser import PynspectFilterParser
from ransack import Parser, Filter
from idea import lite

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -41,41 +38,33 @@ def clearCounters(prefix, module):
logging.error("redis: Could not update statistics.")

class Rule():
def __init__(self, rule, actions, addrGroups, parser=None, compiler=None, module_name=""):
def __init__(self, rule, actions, parser=None, module_name=""):

if not "condition" in rule:
raise SyntaxError("Missing 'condition' in the rule: " + str(rule))

if not "id" in rule:
raise SyntaxError("Missing 'id' in the rule: " + str(rule))

# Check is we got parser instance
# Check if we got parser instance
if parser is None:
self.parser = PynspectFilterParser()
self.parser.build()
self.parser = Parser()
else:
self.parser = parser

# Check is we got compiler instance
if compiler is None:
self.compiler = IDEAFilterCompiler()
else:
self.compiler = compiler

# Instantiate filter
self.__filter = DataObjectFilter()
self.__filter = Filter()


# Store rule condition in raw form
self.__conditionRaw = rule["condition"]

if not self.__matchvar(rule["condition"], addrGroups):
self.__condition = self.__conditionRaw

self.module_name = module_name
# Set inner rule ID
self.id = rule["id"]

# Store the parsed condition
self.__condition = self.__conditionRaw
if (self.__condition != None):
self.parseRule()

Expand Down Expand Up @@ -109,7 +98,6 @@ def parseRule(self):
else:
try:
self.__condition = self.parser.parse(self.__condition)
self.__condition = self.compiler.compile(self.__condition)
except Exception as e:
raise SyntaxError("Error while parsing condition: {0}\nOriginal exception: {1}".format(self.__condition, e))

Expand All @@ -136,7 +124,7 @@ def filter(self, record):
res = False
else:
# Match the record with non-empty rule's condition
res = self.__filter.filter(self.__condition, record)
res = self.__filter.eval(self.__condition, record)

logger.debug("RESULT: %s", res)

Expand Down Expand Up @@ -185,27 +173,3 @@ def __str__(self):
def rule(self):
return str(self.__condition)

def __matchvar(self, rule, addrGroups):
"""
Since pyncspect doesn't support variables yet we had to provide
a solution where every address group's name is matched against
the rule's condition and eventually replaced with address group's values
"""

matched = False

"""
Tautology - empty rule should always match
Don't try to match or replace any address group
"""
if rule is None or isinstance(rule, bool):
return False

for key in addrGroups:
if key in rule:
rule = re.sub(r"\b{0}\b".format(re.escape(key)), addrGroups[key].iplist(), rule)
matched = True
self.__condition = rule

return matched

8 changes: 4 additions & 4 deletions pycommon/test/rc_config/iprange_stdout.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@ custom_actions:
path: /dev/stdout
rules:
- id: 1
condition: Source.IP4 in [ "192.168.0.0/24" ]
condition: Source.IP4 in 192.168.0.0/24
actions:
- stdout

- id: 1
condition: Source.IP4 in [ "192.168.1.0/24" ]
condition: Source.IP4 in 192.168.1.0/24
actions:
- stdout

- id: 1
condition: Source.IP4 in [ "10.0.0.0/8" ]
condition: Source.IP4 in 10.0.0.0/8
actions:
- stdout

- id: 1
condition: Source.IP4 in [ "10.1.0.0/16" ]
condition: Source.IP4 in 10.1.0.0/16
actions:
- stdout