%PDF- %PDF-
Direktori : /proc/2/cwd/opt/imunify360/venv/lib64/python3.8/site-packages/defence360agent/utils/ |
Current File : //proc/2/cwd/opt/imunify360/venv/lib64/python3.8/site-packages/defence360agent/utils/cli.py |
""" This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. Copyright © 2019 Cloud Linux Software Inc. This software is also available under ImunifyAV commercial license, see <https://www.imunify360.com/legal/eula> """ from collections import defaultdict import json import os import subprocess import sys import time import yaml PRETTY_JSON_ARGS = {'sort_keys': True, 'indent': 2, 'separators': (',', ': ')} EXITCODE_NOT_FOUND = 2 EXITCODE_WARNING = 3 EXITCODE_GENERAL_ERROR = 11 PAGERS = ['/bin/less', '/bin/more'] SUCCESS, WARNING, ERROR = 'success', 'warnings', 'error' # see simple_rpc _CLI_MSG_PREFIX = { WARNING: 'WARNING', ERROR: 'ERROR' } EXIT_CODES = { SUCCESS: 0, WARNING: EXITCODE_WARNING, ERROR: EXITCODE_GENERAL_ERROR, } def pager(data): pager = os.environ.get( 'PAGER', next((p for p in PAGERS if os.path.isfile(p)), None)) if pager is None: print(data) else: subprocess.run([pager], input=data.encode(), stdout=sys.stdout) class TablePrinter(): def __init__(self): self._headers = {} self._mappers = defaultdict(list) self._right_aligned = {} self._widths = {} def set_field_properties(self, field, mappers=None, max_width=None, right_align=False, header=None): if mappers: self._mappers[field] = mappers if max_width: self._widths[field] = max_width self._right_aligned[field] = right_align self._headers[field] = header if header else field.upper() def print(self, fields, items, file=sys.stdout): headers = [self._headers.get(field, field.upper()) for field in fields] widths = [len(field) for field in headers] rows = [] for item in items: row = [] for i, field in enumerate(fields): v = item.get(field) for mapper in self._mappers[field]: v = mapper(v) v = str(v) if len(v) > widths[i]: max_width = self._widths.get(field) if max_width and len(v) > max_width: v = v[:max_width - 3] + '...' widths[i] = len(v) row.append(v) rows.append(row) print(self._format_row(headers, widths, False)) for row in rows: print(self._format_row(row, widths, self._right_aligned.get(field, False))) @staticmethod def _add_padding(value, width, right_align): if right_align: return value.rjust(width) return value.ljust(width) @staticmethod def _format_row(columns, widths, right_aligned): cols = [TablePrinter._add_padding(value, widths[i], right_aligned) for i, value in enumerate(columns)] return ' '.join(cols) def n_a(value): return value if value is not None else 'n/a' def to_int(value): return int(value) if value is not None else value def extract_field(field): def extractor(value): if isinstance(value, dict): return value.get(field) return value return extractor def print_table(data, field_props): table = TablePrinter() for props in field_props: table.set_field_properties(*props) table.print([item[0] for item in field_props], data) def print_incidents(data): field_props = ( ('timestamp', [to_int]), ('abuser', [n_a]), ('country', [extract_field('code')]), ('times', [n_a]), ('name', [n_a]), ('severity', [n_a]), ) print_table(data, field_props) def add_ttl(data): now = int(time.time()) for item in data: expiration = item.get('expiration', 0) if expiration > 0: item['ttl'] = expiration - now else: item['ttl'] = 0 def print_graylist(data): add_ttl(data) field_props = ( ('ip', ), ('ttl', ), ('country', [extract_field('code')]), ) print_table(data, field_props) def print_bwlist(data): add_ttl(data) field_props = ( ('ip', ), ('ttl', ), ('country', [extract_field('code')]), ('imported_from', ), ('comment', ), ) print_table(data, field_props) def guess_printer(data): if isinstance(data, (list, tuple)): if len(data): printer = TablePrinter() if isinstance(data[0], dict): keys = sorted(data[0].keys()) printer.set_field_properties( 'country', mappers=[extract_field('code')] ) printer.print(keys, data) else: for item in data: print(item) else: print(data) def yaml_printer(data): if isinstance(data, str): print(data) else: print(yaml.dump(data, default_flow_style=False)) def hook_printer(data): if isinstance(data, dict): print('Status: {}'.format(data['status'])) else: result = [] for hook in data: result.append('Event: {}, Path: {}{}' .format(hook['event'], hook['path'], ' native' if hook['native'] else '')) print('\n'.join(result)) PRINTERS = { ('eula', 'show'): pager, ('get', ): print_incidents, ('whitelist',): print_bwlist, ('whitelist', 'ip', 'list'): print_bwlist, ('blacklist',): print_bwlist, ('blacklist', 'ip', 'list'): print_bwlist, ('graylist',): print_graylist, ('graylist', 'ip', 'list'): print_graylist, ('malware', 'on-demand', 'status'): yaml_printer, ('feature-management', 'defaults'): yaml_printer, ('feature-management', 'show'): yaml_printer, ('feature-management', 'enable'): yaml_printer, ('feature-management', 'disable'): yaml_printer, ('feature-management', 'get'): yaml_printer, ('hook', 'add'): hook_printer, ('hook', 'delete'): hook_printer, ('hook', 'list'): hook_printer, ('hook', 'add-native'): hook_printer, } def print_response(method, result, is_json=False, is_verbose=False): if is_json: pretty_args = PRETTY_JSON_ARGS if is_verbose else {} print(json.dumps(result, **pretty_args)) else: print_fun = PRINTERS.get(method, guess_printer) print_fun(result['items'] if result.get('items') is not None else 'OK') def print_error( result, messages, is_json=False, is_verbose=False, *, file=sys.stderr ): if is_json: pretty_args = PRETTY_JSON_ARGS if is_verbose else {} print(json.dumps({result: messages}, **pretty_args)) else: if isinstance(messages, (list, tuple)): for msg in messages: print("%s: %s" % (_CLI_MSG_PREFIX[result], msg), file=file) else: print(messages, file=file)