Skip to content
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

feat(tasks): bbot integration #375

Merged
merged 15 commits into from
Oct 1, 2024
1 change: 1 addition & 0 deletions secator/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def decorator(f):
short = conf.pop('short', None)
conf.pop('internal', False)
conf.pop('prefix', None)
conf.pop('shlex', True)
long = f'--{opt_name}'
short = f'-{short}' if short else f'-{opt_name}'
f = click.option(long, short, **conf)(f)
Expand Down
12 changes: 11 additions & 1 deletion secator/output_types/_base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import logging
import re
from dataclasses import _MISSING_TYPE, dataclass, fields
from secator.definitions import DEBUG
from secator.rich import console

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -66,7 +68,15 @@ def load(cls, item, output_map={}):
if key in output_map:
mapped_key = output_map[key]
if callable(mapped_key):
mapped_val = mapped_key(item)
try:
mapped_val = mapped_key(item)
except Exception as e:
mapped_val = None
if DEBUG > 0:
console.print_exception(show_locals=True)
raise TypeError(
f'Fail to transform value for "{key}" using output_map function. Exception: '
f'{type(e).__name__}: {str(e)}')
else:
mapped_val = item.get(mapped_key)
new_item[key] = mapped_val
Expand Down
4 changes: 3 additions & 1 deletion secator/output_types/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ def __str__(self) -> str:
return self.name

def __repr__(self) -> str:
s = f'🎤 [bold white]{self.name}[/] \[[green]{self.type}[/]] \[[magenta]{self.host}[/]]'
s = f'🎤 [bold white]{self.name}[/] \[[green]{self.type}[/]]'
if self.host:
s += f' \[[magenta]{self.host}[/]]'
if self.extra_data:
s += ' \[[bold yellow]' + ','.join(f'{k}={v}' for k, v in self.extra_data.items()) + '[/]]'
return rich_to_ansi(s)
17 changes: 17 additions & 0 deletions secator/runners/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,23 @@ def _convert_item_schema(self, item):
new_item = None
output_types = getattr(self, 'output_types', [])
debug(f'Input item: {item}', sub='klass.load', level=5)

# Skip if already converted
if isinstance(item, DotMap) or isinstance(item, OutputType):
return item

# Use output discriminator to let user arbiter between output types to pick
output_discriminator = getattr(self, 'output_discriminator', None)
if output_discriminator:
result = output_discriminator(item)
if result:
debug(f'Discriminated output type: {result.__name__}', sub='klass.load', level=5)
output_types = [result]
else:
new_item = DotMap(item)
new_item._type = 'unknown'
return new_item

debug(f'Output types to try: {[o.__name__ for o in output_types]}', sub='klass.load', level=5)
for klass in output_types:
debug(f'Loading item as {klass.__name__}', sub='klass.load', level=5)
Expand Down
4 changes: 3 additions & 1 deletion secator/runners/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,8 +580,10 @@ def _process_opts(
# Append opt name + opt value to option string.
# Note: does not append opt value if value is True (flag)
opts_str += f' {opt_name}'
shlex_quote = opt_conf.get('shlex', True)
if opt_val is not True:
opt_val = shlex.quote(str(opt_val))
if shlex_quote:
opt_val = shlex.quote(str(opt_val))
opts_str += f' {opt_val}'

return opts_str.strip()
Expand Down
4 changes: 2 additions & 2 deletions secator/runners/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ def yielder(self):
'print_input_file': DEBUG > 0,
'print_item': True,
'print_item_count': not self.sync and not dry_run,
'print_line': True
# 'print_line': self.sync and not self.output_quiet,
# 'print_line': True
'print_line': self.sync and not self.output_quiet,
}
# self.print_item = not self.sync # enable print_item for base Task only if running remote
run_opts.update(fmt_opts)
Expand Down
12 changes: 10 additions & 2 deletions secator/serializers/regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,23 @@

class RegexSerializer:

def __init__(self, regex, fields=[]):
def __init__(self, regex, fields=[], findall=False):
self.regex = re.compile(regex)
self.fields = fields
self.findall = findall

def run(self, line):
match = self.regex.match(line)
if self.findall:
match = self.regex.findall(line)
yield from match
return
output = {}
match = self.regex.match(line)
if not match:
return
if not self.fields:
yield match.group(0)
return
for field in self.fields:
output[field] = match.group(field)
yield output
Loading
Loading