def __init__(self, config=None, library=True, name=None, verbose=False): """ :type library: bool :param library: Toggle for command line features :type config: dict :param config: Client configuration """ self.name = name self.verbose = verbose self.cli = Cli() self.library = library if self.library is False: args = self.cli.parse_args(sys.argv[1:]) try: self.config = self.cli.configure(arguments=args) except Exception as ex: print("Error parsing config file: {0}".format(ex)) quit(1) if args.verbose is True: self.verbose = True else: if config is None: raise NoConfigurationError self.config = self.cli.configure(config=config) if self.verbose is True: margaritashotgun.set_stream_logger(name=self.name, level=logging.DEBUG) else: margaritashotgun.set_stream_logger(name=self.name, level=logging.INFO)
def test_args_server(): cli = Cli() args = ["--server", "app.example.com"] arguments = cli.parse_args(args) assert arguments.server == "app.example.com" args = ["-s", "app.example.com"] arguments = cli.parse_args(args) assert arguments.server == "app.example.com"
def test_args_config_file(): cli = Cli() args = ["--config", "config_file.yml"] arguments = cli.parse_args(args) assert arguments.config == "config_file.yml" args = ["-c", "config_file.yml"] arguments = cli.parse_args(args) assert arguments.config == "config_file.yml"
def test_check_directory_path(): passing_paths = ['bin', 'margaritashotgun', 'tests'] failing_paths = ['req.txt', '', None, '/root'] cli = Cli() for path in passing_paths: cli.check_directory_path(path) with pytest.raises(OSError): for path in failing_paths: cli.check_directory_path(path)
def test_check_file_path(): passing_paths = ['requirements.txt', 'setup.py', 'bin/margaritashotgun', 'margaritashotgun/client.py'] failing_paths = ['req.txt', '', None, '/root/.bashrc'] cli = Cli() for path in passing_paths: cli.check_file_path(path) with pytest.raises(OSError): for path in failing_paths: cli.check_file_path(path)
def test_configure_args(): cli = Cli() args = ["-c", "tests/files/validate_passing.yml"] arguments = cli.parse_args(args) cli.configure_args(arguments) args = ["-c", "tests/files/yml_failing.yml"] arguments = cli.parse_args(args) with pytest.raises(YAMLError): cli.configure_args(arguments) args = ["-c", "tests/files/validate_failing_aws.yml"] arguments = cli.parse_args(args) with pytest.raises(InvalidConfigurationError): cli.configure_args(arguments)
def test_args_optional(): cli = Cli() args = ["--server", "app.example.com", "--port", '2222', "--username", "ec2-user", "--module", "lime.ko", "--password", "hunter2", "--key", "rsa.key", "--filename", "mem.lime", "--workers", "auto", "--bucket", "marsho", "--log-dir", "logs", "--log-prefix", "case_num", "--repository-url", "https://www.example.com/repo"] arguments = cli.parse_args(args) assert arguments.server == "app.example.com" assert arguments.port == "2222" assert arguments.username == "ec2-user" assert arguments.module == "lime.ko" assert arguments.password == "hunter2" assert arguments.key == "rsa.key" assert arguments.filename == "mem.lime" assert arguments.workers == "auto" assert arguments.bucket == "marsho" assert arguments.log_dir == "logs" assert arguments.log_prefix == "case_num" assert arguments.repository_url == "https://www.example.com/repo"
def test_args_optional(): cli = Cli() args = [ "--server", "app.example.com", "--port", '2222', "--username", "ec2-user", "--module", "lime.ko", "--password", "hunter2", "--key", "rsa.key", "--filename", "mem.lime", "--workers", "auto", "--bucket", "marsho", "--log-dir", "logs", "--log-prefix", "case_num", "--repository-url", "https://www.example.com/repo" ] arguments = cli.parse_args(args) assert arguments.server == "app.example.com" assert arguments.port == "2222" assert arguments.username == "ec2-user" assert arguments.module == "lime.ko" assert arguments.password == "hunter2" assert arguments.key == "rsa.key" assert arguments.filename == "mem.lime" assert arguments.workers == "auto" assert arguments.bucket == "marsho" assert arguments.log_dir == "logs" assert arguments.log_prefix == "case_num" assert arguments.repository_url == "https://www.example.com/repo"
def test_args_optional(): cli = Cli() args = [ "-s", "app.example.com", "--port", '2222', "--username", "ec2-user", "--module", "lime.ko", "--password", "hunter2", "--key", "rsa.key", "--filename", "mem.lime", "--workers", "auto", "--bucket", "marsho", "--log_dir", "logs", "--log_prefix", "case_num" ] arguments = cli.parse_args(args) assert arguments.server == "app.example.com" assert arguments.port == "2222" assert arguments.username == "ec2-user" assert arguments.module == "lime.ko" assert arguments.password == "hunter2" assert arguments.key == "rsa.key" assert arguments.filename == "mem.lime" assert arguments.workers == "auto" assert arguments.bucket == "marsho" assert arguments.log_dir == "logs" assert arguments.log_prefix == "case_num" args = [ "-s", "app.example.com", "-P", '2222', "-u", "ec2-user", "-m", "lime.ko", "-p", "hunter2", "-k", "rsa.key", "-f", "mem.lime", "-w", "2", "-o", "dump", "-d", "logs", "--log_prefix", "case_num" ] arguments = cli.parse_args(args) assert arguments.server == "app.example.com" assert arguments.port == "2222" assert arguments.username == "ec2-user" assert arguments.module == "lime.ko" assert arguments.password == "hunter2" assert arguments.key == "rsa.key" assert arguments.filename == "mem.lime" assert arguments.workers == "2" assert arguments.output_dir == "dump" assert arguments.log_dir == "logs" assert arguments.log_prefix == "case_num"
def test_args_optional(): cli = Cli() args = ["-s", "app.example.com", "--port", '2222', "--username", "ec2-user", "--module", "lime.ko", "--password", "hunter2", "--key", "rsa.key", "--filename", "mem.lime", "--workers", "auto", "--bucket", "marsho", "--log_dir", "logs", "--log_prefix", "case_num"] arguments = cli.parse_args(args) assert arguments.server == "app.example.com" assert arguments.port == "2222" assert arguments.username == "ec2-user" assert arguments.module == "lime.ko" assert arguments.password == "hunter2" assert arguments.key == "rsa.key" assert arguments.filename == "mem.lime" assert arguments.workers == "auto" assert arguments.bucket == "marsho" assert arguments.log_dir == "logs" assert arguments.log_prefix == "case_num" args = ["-s", "app.example.com", "-P", '2222', "-u", "ec2-user", "-m", "lime.ko", "-p", "hunter2", "-k", "rsa.key", "-f", "mem.lime", "-w", "2", "-o", "dump", "-d", "logs", "--log_prefix", "case_num"] arguments = cli.parse_args(args) assert arguments.server == "app.example.com" assert arguments.port == "2222" assert arguments.username == "ec2-user" assert arguments.module == "lime.ko" assert arguments.password == "hunter2" assert arguments.key == "rsa.key" assert arguments.filename == "mem.lime" assert arguments.workers == "2" assert arguments.output_dir == "dump" assert arguments.log_dir == "logs" assert arguments.log_prefix == "case_num"
def test_jump_host_args(): cli = Cli() args = ["--server", "172.16.180.10", "--port", "22", "--username", "vagrant", "--password", "vagrant", "--jump-server", "172.16.180.20", "--jump-username", "vagrant", "--jump-password", "vagrant"] arguments = cli.parse_args(args) cli.configure_args(arguments) args = ["--server", "172.16.180.10", "--port", "22", "--username", "vagrant", "--password", "vagrant", "--jump-server", "172.16.180.20", "--jump-username", "vagrant", "--jump-password", "vagrant", "--jump-port", "22"] arguments = cli.parse_args(args) cli.configure_args(arguments)
def test_jump_host_args(): cli = Cli() args = [ "--server", "172.16.180.10", "--port", "22", "--username", "vagrant", "--password", "vagrant", "--jump-server", "172.16.180.20", "--jump-username", "vagrant", "--jump-password", "vagrant" ] arguments = cli.parse_args(args) cli.configure_args(arguments) args = [ "--server", "172.16.180.10", "--port", "22", "--username", "vagrant", "--password", "vagrant", "--jump-server", "172.16.180.20", "--jump-username", "vagrant", "--jump-password", "vagrant", "--jump-port", "22" ] arguments = cli.parse_args(args) cli.configure_args(arguments)
def test_check_file_path(): passing_paths = [ 'requirements.txt', 'setup.py', 'bin/margaritashotgun', 'margaritashotgun/client.py' ] failing_paths = ['req.txt', '', None, '/root/.bashrc'] cli = Cli() for path in passing_paths: cli.check_file_path(path) with pytest.raises(OSError): for path in failing_paths: cli.check_file_path(path)
def test_configure_args(): cli = Cli() args = ["-c", "tests/files/validate_passing.yml"] arguments = cli.parse_args(args) cli.configure_args(arguments) args = [ "--server", "tests/files/validate_passing.yml", "--repository-url", "https://www.example.com/repo" ] arguments = cli.parse_args(args) cli.configure_args(arguments) args = ["-c", "tests/files/yml_failing.yml"] arguments = cli.parse_args(args) with pytest.raises(YAMLError): cli.configure_args(arguments) args = ["-c", "tests/files/validate_failing_aws.yml"] arguments = cli.parse_args(args) with pytest.raises(InvalidConfigurationError): cli.configure_args(arguments)
class Client(): """ Client for parallel memory capture with LiME """ def __init__(self, config=None, library=True, name=None, verbose=False): """ :type library: bool :param library: Toggle for command line features :type config: dict :param config: Client configuration """ self.name = name self.verbose = verbose self.cli = Cli() self.library = library if self.library is False: args = self.cli.parse_args(sys.argv[1:]) self.config = self.cli.configure(arguments=args) if args.verbose is True: self.verbose = True else: if config is None: raise NoConfigurationError self.config = self.cli.configure(config=config) if self.verbose is True: margaritashotgun.set_stream_logger(name=self.name, level=logging.DEBUG) else: margaritashotgun.set_stream_logger(name=self.name, level=logging.INFO) def run(self): """ Captures remote hosts memory """ logger = logging.getLogger(__name__) try: conf = self.map_config() workers = Workers(conf, self.config['workers'], name=self.name, library=self.library) description = 'memory capture action' results = workers.spawn(description) self.statistics(results) if self.library is True: return dict([('total', self.total), ('completed', self.completed_addresses), ('failed', self.failed_addresses)]) else: logger.info(("{0} hosts processed. completed: {1} " "failed {2}".format(self.total, self.completed, self.failed))) logger.info("completed_hosts: {0}".format(self.completed_addresses)) logger.info("failed_hosts: {0}".format(self.failed_addresses)) quit() except KeyboardInterrupt: workers.cleanup(terminate=True) if self.library: raise else: quit(1) def map_config(self): config_list = [] keys = ['aws', 'host', 'logging', 'repository'] for host in self.config['hosts']: values = [self.config['aws'], host, self.config['logging'], self.config['repository']] conf = dict(zip(keys, values)) config_list.append(conf) return config_list def statistics(self, results): self.total = len(results) self.completed = 0 self.completed_addresses = [] self.failed = 0 self.failed_addresses = [] for result in results: if result[1] is False: self.failed += 1 self.failed_addresses.append(result[0]) else: self.completed += 1 self.completed_addresses.append(result[0])
def test_configure(): cli = Cli() config = cli.load_config('tests/files/validate_failing_aws.yml') with pytest.raises(InvalidConfigurationError): cli.configure(config=config)
def test_validate_config(): cli = Cli() passing_config = cli.load_config('tests/files/validate_passing.yml') failing_configs = list() failing_configs.append( cli.load_config('tests/files/validate_failing_aws.yml')) failing_configs.append( cli.load_config('tests/files/validate_failing_hosts.yml')) failing_configs.append( cli.load_config('tests/files/validate_failing_host.yml')) failing_configs.append( cli.load_config('tests/files/validate_failing_logging.yml')) failing_configs.append( cli.load_config('tests/files/validate_failing_output.yml')) failing_configs.append( cli.load_config('tests/files/validate_failing_root.yml')) cli.validate_config(passing_config) with pytest.raises(InvalidConfigurationError): for conf in failing_configs: cli.validate_config(conf)
def test_validate_config(): cli = Cli() passing_config = cli.load_config('tests/files/validate_passing.yml') failing_configs = list() failing_configs.append(cli.load_config('tests/files/validate_failing_aws.yml')) failing_configs.append(cli.load_config('tests/files/validate_failing_hosts.yml')) failing_configs.append(cli.load_config('tests/files/validate_failing_host.yml')) failing_configs.append(cli.load_config('tests/files/validate_failing_logging.yml')) failing_configs.append(cli.load_config('tests/files/validate_failing_output.yml')) failing_configs.append(cli.load_config('tests/files/validate_failing_root.yml')) cli.validate_config(passing_config) with pytest.raises(InvalidConfigurationError): for conf in failing_configs: cli.validate_config(conf)
def test_load_config(): cli = Cli() config = cli.load_config('tests/files/yml_passing.yml') with pytest.raises(YAMLError): config = cli.load_config('tests/files/yml_failing.yml')
class Client(): """ Client for parallel memory capture with LiME """ def __init__(self, config=None, library=True, name=None, verbose=False): """ :type library: bool :param library: Toggle for command line features :type config: dict :param config: Client configuration """ self.name = name self.verbose = verbose self.cli = Cli() self.library = library if self.library is False: args = self.cli.parse_args(sys.argv[1:]) try: self.config = self.cli.configure(arguments=args) except Exception as ex: print("Error parsing config file: {0}".format(ex)) quit(1) if args.verbose is True: self.verbose = True else: if config is None: raise NoConfigurationError self.config = self.cli.configure(config=config) if self.verbose is True: margaritashotgun.set_stream_logger(name=self.name, level=logging.DEBUG) else: margaritashotgun.set_stream_logger(name=self.name, level=logging.INFO) def run(self): """ Captures remote hosts memory """ logger = logging.getLogger(__name__) try: # Check repository GPG settings before starting workers # Handling this here prevents subprocesses from needing stdin access repo_conf = self.config['repository'] repo = None if repo_conf['enabled'] and repo_conf['gpg_verify']: try: repo = Repository(repo_conf['url'], repo_conf['gpg_verify']) repo.init_gpg() except Exception as ex: # Do not prompt to install gpg keys unless running interactively if repo is not None and self.library is False: if isinstance(ex, RepositoryUntrustedSigningKeyError): installed = repo.prompt_for_install() if installed is False: logger.critical(("repository signature not " "installed, install the " "signature manually or use " "the --gpg-no-verify flag " "to bypass this check")) quit(1) else: logger.critical(ex) quit(1) conf = self.map_config() workers = Workers(conf, self.config['workers'], name=self.name, library=self.library) description = 'memory capture action' results = workers.spawn(description) self.statistics(results) if self.library is True: return dict([('total', self.total), ('completed', self.completed_addresses), ('failed', self.failed_addresses)]) else: logger.info(("{0} hosts processed. completed: {1} " "failed {2}".format(self.total, self.completed, self.failed))) logger.info("completed_hosts: {0}".format(self.completed_addresses)) logger.info("failed_hosts: {0}".format(self.failed_addresses)) quit() except KeyboardInterrupt: workers.cleanup(terminate=True) if self.library: raise else: quit(1) def map_config(self): config_list = [] keys = ['aws', 'host', 'logging', 'repository'] for host in self.config['hosts']: values = [self.config['aws'], host, self.config['logging'], self.config['repository']] conf = dict(zip(keys, values)) config_list.append(conf) return config_list def statistics(self, results): self.total = len(results) self.completed = 0 self.completed_addresses = [] self.failed = 0 self.failed_addresses = [] for result in results: if result[1] is False: self.failed += 1 self.failed_addresses.append(result[0]) else: self.completed += 1 self.completed_addresses.append(result[0])
class Client(): """ Client for parallel memory capture with LiME """ def __init__(self, config=None, library=True, name=None, verbose=False): """ :type library: bool :param library: Toggle for command line features :type config: dict :param config: Client configuration """ self.name = name self.verbose = verbose self.cli = Cli() self.library = library if self.library is False: args = self.cli.parse_args(sys.argv[1:]) try: self.config = self.cli.configure(arguments=args) except Exception as ex: print("Error parsing config file: {0}".format(ex)) quit(1) if args.verbose is True: self.verbose = True else: if config is None: raise NoConfigurationError self.config = self.cli.configure(config=config) if self.verbose is True: margaritashotgun.set_stream_logger(name=self.name, level=logging.DEBUG) else: margaritashotgun.set_stream_logger(name=self.name, level=logging.INFO) def run(self): """ Captures remote hosts memory """ logger = logging.getLogger(__name__) try: # Check repository GPG settings before starting workers # Handling this here prevents subprocesses from needing stdin access repo_conf = self.config['repository'] repo = None if repo_conf['enabled'] and repo_conf['gpg_verify']: try: repo = Repository(repo_conf['url'], repo_conf['gpg_verify']) repo.init_gpg() except Exception as ex: # Do not prompt to install gpg keys unless running interactively if repo is not None and self.library is False: if isinstance(ex, RepositoryUntrustedSigningKeyError): installed = repo.prompt_for_install() if installed is False: logger.critical(("repository signature not " "installed, install the " "signature manually or use " "the --gpg-no-verify flag " "to bypass this check")) quit(1) else: logger.critical(ex) quit(1) conf = self.map_config() workers = Workers(conf, self.config['workers'], name=self.name, library=self.library) description = 'memory capture action' results = workers.spawn(description) self.statistics(results) if self.library is True: return dict([('total', self.total), ('completed', self.completed_addresses), ('failed', self.failed_addresses)]) else: logger.info(("{0} hosts processed. completed: {1} " "failed {2}".format(self.total, self.completed, self.failed))) logger.info("completed_hosts: {0}".format( self.completed_addresses)) logger.info("failed_hosts: {0}".format(self.failed_addresses)) quit() except KeyboardInterrupt: workers.cleanup(terminate=True) if self.library: raise else: quit(1) def map_config(self): config_list = [] keys = ['aws', 'host', 'logging', 'repository'] for host in self.config['hosts']: values = [ self.config['aws'], host, self.config['logging'], self.config['repository'] ] conf = dict(zip(keys, values)) config_list.append(conf) return config_list def statistics(self, results): self.total = len(results) self.completed = 0 self.completed_addresses = [] self.failed = 0 self.failed_addresses = [] for result in results: if result[1] is False: self.failed += 1 self.failed_addresses.append(result[0]) else: self.completed += 1 self.completed_addresses.append(result[0])
def test_check_file_paths(): cli = Cli() response = cli.check_file_paths('requirements.txt', 'setup.py') assert response == ('requirements.txt', 'setup.py') response = cli.check_file_paths('bin/margaritashotgun') assert response == ('bin/margaritashotgun',)
def test_environment_var_override(): cli = Cli() #TODO: set environment variable here os.environ['LIME_REPOSITORY'] = 'enabled' arguments = cli.parse_args(['-c', 'tests/files/validate_passing.yml']) cli.configure_args(arguments)
def test_configure_args(): cli = Cli() args = ["-c", "tests/files/validate_passing.yml"] arguments = cli.parse_args(args) cli.configure_args(arguments) args = ["--server", "tests/files/validate_passing.yml", "--repository-url", "https://www.example.com/repo"] arguments = cli.parse_args(args) cli.configure_args(arguments) args = ["-c", "tests/files/yml_failing.yml"] arguments = cli.parse_args(args) with pytest.raises(YAMLError): cli.configure_args(arguments) args = ["-c", "tests/files/validate_failing_aws.yml"] arguments = cli.parse_args(args) with pytest.raises(InvalidConfigurationError): cli.configure_args(arguments)
def test_check_directory_paths(): cli = Cli() response = cli.check_directory_paths('bin', 'margaritashotgun') assert response == ('bin', 'margaritashotgun') response = cli.check_directory_paths('tests') assert response == ('tests',)
def test_check_file_paths(): cli = Cli() response = cli.check_file_paths('requirements.txt', 'setup.py') assert response == ('requirements.txt', 'setup.py') response = cli.check_file_paths('bin/margaritashotgun') assert response == ('bin/margaritashotgun', )
def test_check_directory_paths(): cli = Cli() response = cli.check_directory_paths('bin', 'margaritashotgun') assert response == ('bin', 'margaritashotgun') response = cli.check_directory_paths('tests') assert response == ('tests', )