def run(self): edn_pid = os.fork() if edn_pid == 0: try: while True: item = InternalServer.get_dagda_edn().get() if item['msg'] == 'init_db': self._init_or_update_db() elif item['msg'] == 'check_image': self._check_docker_by_image_name(item) elif item['msg'] == 'check_container': self._check_docker_by_container_id(item) except KeyboardInterrupt: # Pressed CTRL+C to quit, so nothing to do pass else: sysdig_falco_monitor_pid = os.fork() if sysdig_falco_monitor_pid == 0: try: self.sysdig_falco_monitor.pre_check() self.sysdig_falco_monitor.run() except DagdaError as e: DagdaLogger.get_logger().error(e.get_message()) DagdaLogger.get_logger().warning( 'Runtime behaviour monitor disabled.') except KeyboardInterrupt: # Pressed CTRL+C to quit InternalServer.get_docker_driver().docker_stop( self.sysdig_falco_monitor.get_running_container_id()) InternalServer.get_docker_driver().docker_remove_container( self.sysdig_falco_monitor.get_running_container_id()) else: DagdaServer.app.run(debug=False, host=self.dagda_server_host, port=self.dagda_server_port)
def _init_or_update_db(): try: InternalServer.get_mongodb_driver().insert_init_db_process_status({ 'status': 'Initializing', 'timestamp': datetime.datetime.now().timestamp() }) # Init db db_composer = DBComposer() db_composer.compose_vuln_db() InternalServer.get_mongodb_driver().insert_init_db_process_status({ 'status': 'Updated', 'timestamp': datetime.datetime.now().timestamp() }) except Exception as ex: message = "Unexpected exception of type {0} occurred: {1!r}".format( type(ex).__name__, ex.args) DagdaLogger.get_logger().error(message) if InternalServer.is_debug_logging_enabled(): traceback.print_exc() InternalServer.get_mongodb_driver().insert_init_db_process_status({ 'status': message, 'timestamp': datetime.datetime.now().timestamp() })
def verify_args(args): if args.server_port and args.server_port not in range(1, 65536): DagdaLogger.get_logger().error( 'Argument -p/--server_port: The port must be between 1 and 65535.' ) return 1 elif args.mongodb_port and args.mongodb_port not in range(1, 65536): DagdaLogger.get_logger().error( 'Argument -mp/--mongodb_port: The port must be between 1 and 65535.' ) return 2 elif args.mongodb_user and not args.mongodb_pass: DagdaLogger.get_logger().error( 'Argument --mongodb_pass: this argument should not be empty if you set ' '"--mongodb_user".') return 3 elif args.mongodb_pass and not args.mongodb_user: DagdaLogger.get_logger().error( 'Argument --mongodb_user: this argument should not be empty if you set ' '"--mongodb_pass".') return 4 elif args.falco_rules_file: with args.falco_rules_file as content_file: try: yaml.safe_load(content_file.read()) except: DagdaLogger.get_logger().error( 'Argument --falco_rules_file: Malformed yaml file.') return 5 # Else return 0
def check_docker_by_container_id(container_id): # -- Check input if not container_id: return json.dumps({'err': 400, 'msg': 'Bad container id'}, sort_keys=True), 400 # -- Retrieves docker image name try: image_name = InternalServer.get_docker_driver().get_docker_image_name_by_container_id(container_id) except Exception as ex: message = "Unexpected exception of type {0} occurred while getting the docker image name: {1!r}" \ .format(type(ex).__name__, ex.get_message() if type(ex).__name__ == 'DagdaError' else ex.args) DagdaLogger.get_logger().error(message) return json.dumps({'err': 404, 'msg': 'Container Id not found'}, sort_keys=True), 404 # -- Process request data = {} data['image_name'] = image_name data['timestamp'] = datetime.datetime.now().timestamp() data['status'] = 'Analyzing' id = InternalServer.get_mongodb_driver().insert_docker_image_scan_result_to_history(data) InternalServer.get_dagda_edn().put({'msg': 'check_container', 'container_id': container_id, '_id': str(id)}) # -- Return output = {} output['id'] = str(id) output['msg'] = 'Accepted the analysis of <' + image_name + '> with id: ' + container_id return json.dumps(output, sort_keys=True), 202
def __init__(self): super(DockerDriver, self).__init__() try: # Return a client configured from environment variables. The environment variables used are the same as # those used by the Docker command-line client. self.cli = docker.from_env(version="auto", timeout=3600).api except DockerException: DagdaLogger.get_logger().error('Error while fetching Docker server API version: Assuming Travis CI tests.') self.cli = None
def verify_args(args): if not args.start and not args.stop: DagdaLogger.get_logger().error('Missing arguments.') return 1 elif args.start and args.stop: DagdaLogger.get_logger().error('Arguments --start & --stop: Both arguments can not be together.') return 2 # Else return 0
def evaluate_image(self, image_name, container_id): # Init data = {} # -- Static analysis image_name = self.dockerDriver.get_docker_image_name_by_container_id(container_id) if container_id \ else image_name os_packages = [] malware_binaries = [] dependencies = None temp_dir = None try: # Get OS packages if container_id is None: # Scans the docker image os_packages = os_info_extractor.get_soft_from_docker_image( docker_driver=self.dockerDriver, image_name=image_name) temp_dir = extract_filesystem_bundle( docker_driver=self.dockerDriver, image_name=image_name) else: # Scans the docker container os_packages = os_info_extractor.get_soft_from_docker_container_id( docker_driver=self.dockerDriver, container_id=container_id) temp_dir = extract_filesystem_bundle( docker_driver=self.dockerDriver, container_id=container_id) # Get malware binaries malware_binaries = malware_extractor.get_malware_included_in_docker_image( docker_driver=self.dockerDriver, temp_dir=temp_dir) # Get programming language dependencies dependencies = dep_info_extractor.get_dependencies_from_docker_image( docker_driver=self.dockerDriver, image_name=image_name, temp_dir=temp_dir) except Exception as ex: message = "Unexpected exception of type {0} occured: {1!r}"\ .format(type(ex).__name__, ex.get_message() if type(ex).__name__ == 'DagdaError' else ex.args) DagdaLogger.get_logger().error(message) data['status'] = message # -- Cleanup if temp_dir is not None: clean_up(temporary_dir=temp_dir) # -- Prepare output if dependencies is not None: data['status'] = 'Completed' else: dependencies = [] data['image_name'] = image_name data['timestamp'] = datetime.datetime.now().timestamp() data['static_analysis'] = self.generate_static_analysis( image_name, os_packages, dependencies, malware_binaries) # -- Return return data
def check_docker_by_image_name(image_name): # -- Check input if not image_name: return json.dumps({ 'err': 400, 'msg': 'Bad image name' }, sort_keys=True), 400 # -- Docker pull from remote registry if it is necessary try: pulled = False if not InternalServer.get_docker_driver().is_docker_image(image_name): if ':' in image_name: tmp = image_name.split(':')[0] tag = image_name.split(':')[1] msg = 'Error: image library/' + image_name + ':' + tag + ' not found' output = InternalServer.get_docker_driver().docker_pull( tmp, tag=tag) else: msg = 'Error: image library/' + image_name + ':latest not found' output = InternalServer.get_docker_driver().docker_pull( image_name) if 'errorDetail' in output: DagdaLogger.get_logger().error(msg) raise DagdaError(msg) pulled = True except Exception as ex: message = "Unexpected exception of type {0} occurred while pulling the docker image: {1!r}" \ .format(type(ex).__name__, ex.get_message() if type(ex).__name__ == 'DagdaError' else ex.args) DagdaLogger.get_logger().error(message) return json.dumps({ 'err': 404, 'msg': 'Image name not found' }, sort_keys=True), 404 # -- Process request data = {} data['image_name'] = image_name data['timestamp'] = datetime.datetime.now().timestamp() data['status'] = 'Analyzing' id = InternalServer.get_mongodb_driver( ).insert_docker_image_scan_result_to_history(data) InternalServer.get_dagda_edn().put({ 'msg': 'check_image', 'image_name': image_name, '_id': str(id), 'pulled': pulled }) # -- Return output = {} output['id'] = str(id) output['msg'] = 'Accepted the analysis of <' + image_name + '>' return json.dumps(output, sort_keys=True), 202
def pre_check(self): # Init linux_distro = platform.linux_distribution()[0] uname_r = os.uname().release # Check requirements if not os.path.isfile('/.dockerenv'): # I'm living in real world! if 'Red Hat' == linux_distro or 'CentOS' == linux_distro or 'Fedora' == linux_distro \ or 'openSUSE' == linux_distro: # Red Hat/CentOS/Fedora/openSUSE return_code = subprocess.call( ["rpm", "-q", "kernel-devel-" + uname_r], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) elif 'Debian' == linux_distro or 'Ubuntu' == linux_distro: # Debian/Ubuntu return_code = subprocess.call( ["dpkg", "-l", "linux-headers-" + uname_r], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) else: raise DagdaError('Linux distribution not supported yet.') if return_code != 0: raise DagdaError( 'The kernel headers are not installed in the host operating system.' ) else: # I'm running inside a docker container DagdaLogger.get_logger().warning( "I'm running inside a docker container, so I can't check if the kernel " "headers are installed in the host operating system. Please, review it!!" ) # Docker pull for ensuring the sysdig/falco image self.docker_driver.docker_pull('sysdig/falco') # Stops sysdig/falco containers if there are any container_ids = self.docker_driver.get_docker_container_ids_by_image_name( 'sysdig/falco') if len(container_ids) > 0: for container_id in container_ids: self.docker_driver.docker_stop(container_id) # Cleans mongodb falco_events collection self.mongodb_driver.delete_falco_events_collection() # Starts sysdig running container without custom entrypoint for avoiding: # --> Runtime error: error opening device /host/dev/sysdig0 self.running_container_id = self._start_container() time.sleep(30) logs = self.docker_driver.docker_logs(self.running_container_id, True, True, False) if "Runtime error: error opening device /host/dev/sysdig0" not in logs: self.docker_driver.docker_stop(self.running_container_id) else: raise DagdaError('Runtime error opening device /host/dev/sysdig0.')
def _threaded_malware(dockerDriver, temp_dir, malware_binaries): # Get malware binaries if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Retrieving malware files from the docker image ...') malware_binaries.extend(malware_extractor.get_malware_included_in_docker_image(docker_driver=dockerDriver, temp_dir=temp_dir)) if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Malware files from the docker image retrieved')
def verify_args(args): if not args.container_id and not args.docker_image: DagdaLogger.get_logger().error('Missing arguments.') return 1 elif args.container_id and args.docker_image: DagdaLogger.get_logger().error('Arguments --docker_image/--container_id: Both arguments ' 'can not be together.') return 2 # Else return 0
def verify_args(args, sys_argv): if sys_argv[2] not in ['containers', 'images', 'events']: DagdaLogger.get_logger().error('Missing arguments.') return 1 elif (args.command == 'containers' or args.command == 'images') and \ (args.event_action or args.event_from or args.event_type): DagdaLogger.get_logger().error('Command <' + args.command + '>: this command must be alone.') return 2 # Else return 0
def _threaded_malware(dockerDriver, temp_dir, malware_binaries): # Get malware binaries if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Retrieving malware files from the docker image ...') malware_binaries.extend(malware_extractor.get_malware_included_in_docker_image(docker_driver=dockerDriver, temp_dir=temp_dir)) if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Malware files from the docker image retrieved')
def verify_args(args, sys_argv): if sys_argv[2] not in ['containers', 'images', 'events']: DagdaLogger.get_logger().error('Missing arguments.') return 1 elif (args.command == 'containers' or args.command == 'images') and \ (args.event_action or args.event_from or args.event_type): DagdaLogger.get_logger().error('Command <' + args.command + '>: this command must be alone.') return 2 # Else return 0
def _threaded_dependencies(dockerDriver, image_name, temp_dir, dependencies): # Get programming language dependencies if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Retrieving dependencies from the docker image ...') dependencies.extend(dep_info_extractor.get_dependencies_from_docker_image(docker_driver=dockerDriver, image_name=image_name, temp_dir=temp_dir)) if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Dependencies from the docker image retrieved')
def _threaded_cve_gathering(mongoDbDriver, i): if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('... Including CVEs - ' + str(i)) compressed_content = get_http_resource_content( "https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-" + str(i) + ".json.gz") cve_list, cve_ext_info_list = get_cve_list_from_file(compressed_content, i) if len(cve_list) > 0: mongoDbDriver.bulk_insert_cves(cve_list) if len(cve_ext_info_list) > 0: mongoDbDriver.bulk_insert_cves_info(cve_ext_info_list)
def verify_args(args): if not args.container_id and not args.docker_image: DagdaLogger.get_logger().error('Missing arguments.') return 1 elif args.container_id and args.docker_image: DagdaLogger.get_logger().error( 'Arguments --docker_image/--container_id: Both arguments ' 'can not be together.') return 2 # Else return 0
def pre_check(self): if not InternalServer.is_external_falco(): # Init linux_distro = SysdigFalcoMonitor._get_linux_distro() uname_r = os.uname().release # Check requirements if not os.path.isfile('/.dockerenv'): # I'm living in real world! if 'Red Hat' in linux_distro or 'CentOS' in linux_distro or 'Fedora' in linux_distro \ or 'openSUSE' in linux_distro: # Red Hat/CentOS/Fedora/openSUSE return_code = subprocess.call(["rpm", "-q", "kernel-devel-" + uname_r], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) elif 'Debian' in linux_distro or 'Ubuntu' in linux_distro: # Debian/Ubuntu return_code = subprocess.call(["dpkg", "-l", "linux-headers-" + uname_r], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) else: raise DagdaError('Linux distribution not supported yet.') if return_code != 0: raise DagdaError('The kernel headers are not installed in the host operating system.') else: # I'm running inside a docker container DagdaLogger.get_logger().warning("I'm running inside a docker container, so I can't check if the kernel " "headers are installed in the host operating system. Please, review it!!") # Check Docker driver if self.docker_driver.get_docker_client() is None: raise DagdaError('Error while fetching Docker server API version.') # Docker pull for ensuring the sysdig/falco image self.docker_driver.docker_pull('sysdig/falco') # Stops sysdig/falco containers if there are any container_ids = self.docker_driver.get_docker_container_ids_by_image_name('sysdig/falco') if len(container_ids) > 0: for container_id in container_ids: self.docker_driver.docker_stop(container_id) self.docker_driver.docker_remove_container(container_id) # Cleans mongodb falco_events collection self.mongodb_driver.delete_falco_events_collection() # Starts sysdig running container without custom entrypoint for avoiding: # --> Runtime error: error opening device /host/dev/sysdig0 self.running_container_id = self._start_container() time.sleep(30) logs = self.docker_driver.docker_logs(self.running_container_id, True, True, False) if "Runtime error: error opening device /host/dev/sysdig0" not in logs: self.docker_driver.docker_stop(self.running_container_id) else: raise DagdaError('Runtime error opening device /host/dev/sysdig0.') # Clean up self.docker_driver.docker_remove_container(self.running_container_id)
def __init__(self): super(DockerDriver, self).__init__() try: # Return a client configured from environment variables. The environment variables used are the same as # those used by the Docker command-line client. self.cli = docker.from_env(version="auto", timeout=3600).api except DockerException: DagdaLogger.get_logger().error( 'Error while fetching Docker server API version: Assumming Travis CI tests.' ) self.cli = None
def _threaded_dependencies(dockerDriver, image_name, temp_dir, dependencies): # Get programming language dependencies if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Retrieving dependencies from the docker image ...') dependencies.extend(dep_info_extractor.get_dependencies_from_docker_image(docker_driver=dockerDriver, image_name=image_name, temp_dir=temp_dir)) if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Dependencies from the docker image retrieved')
def verify_args(args): if not args.start and not args.stop: DagdaLogger.get_logger().error('Missing arguments.') return 1 elif args.start and args.stop: DagdaLogger.get_logger().error( 'Arguments --start & --stop: Both arguments can not be together.' ) return 2 # Else return 0
def __init__(self): super(DockerDriver, self).__init__() try: self.cli = docker.Client(base_url='unix://var/run/docker.sock', version="auto", timeout=3600) except docker.errors.DockerException: DagdaLogger.get_logger().error( 'Error while fetching Docker server API version: Assumming Travis CI tests.' ) self.cli = None
def _parse_log_and_show_dagda_warnings(sysdig_falco_logs): date_prefix = datetime.datetime.now().strftime("%A")[:3] + ' ' lines = sysdig_falco_logs.split("\n") warning = '' for line in lines: if line.startswith(date_prefix) is not True: line = line.strip() if line.startswith('Rule '): if warning: DagdaLogger.get_logger().warning(warning.strip()) warning = '' warning+=' ' + line
def _parse_log_and_show_dagda_warnings(sysdig_falco_logs): date_prefix = datetime.datetime.now().strftime("%A")[:3] + ' ' lines = sysdig_falco_logs.split("\n") warning = '' for line in lines: if line.startswith(date_prefix) is not True: line = line.strip() if line.startswith('Rule '): if warning: DagdaLogger.get_logger().warning(warning.strip()) warning = '' warning += ' ' + line
def get_os_software_packages_blind_mode(docker_driver, container_id): supported_distributions = [{'cmd': 'rpm -aqi', 'parser': parse_rpm_output_list}, {'cmd': 'dpkg -l', 'parser': parse_dpkg_output_list}, {'cmd': 'apk -v info', 'parser': parse_apk_output_list}] for supported_distribution in supported_distributions: packages_info = docker_driver.docker_exec(container_id, supported_distribution['cmd'], True, False) if packages_info is not None and 'exec failed' not in packages_info: return supported_distribution['parser'](packages_info) # The linux image has not a supported distribution or the image has not a package manager DagdaLogger.get_logger().warn('Linux image distribution not found. The OS packages report is empty.') # Return empty list return []
def docker_logs(self, container_id, show_stdout, show_stderr, follow): try: return (self.cli.logs(container=container_id, stdout=show_stdout, stderr=show_stderr, follow=follow))\ .decode('utf-8') except docker.errors.APIError as ex: if "configured logging reader does not support reading" in str(ex): message = "Docker logging driver is not set to be 'json-file' or 'journald'" DagdaLogger.get_logger().error(message) raise DagdaError(message) else: message = "Unexpected exception of type {0} occurred: {1!r}" \ .format(type(ex).__name__, str(ex)) DagdaLogger.get_logger().error(message) raise ex
def docker_logs(self, container_id, show_stdout, show_stderr, follow): try: return (self.cli.logs(container=container_id, stdout=show_stdout, stderr=show_stderr, follow=follow))\ .decode('utf-8') except docker.errors.APIError as ex: if "configured logging reader does not support reading" in str(ex): message = "Docker logging driver is not set to be 'json-file' or 'journald'" DagdaLogger.get_logger().error(message) raise DagdaError(message) else: message = "Unexpected exception of type {0} occurred: {1!r}" \ .format(type(ex).__name__, str(ex)) DagdaLogger.get_logger().error(message) raise ex
def _init_or_update_db(): try: InternalServer.get_mongodb_driver().insert_init_db_process_status( {'status': 'Initializing', 'timestamp': datetime.datetime.now().timestamp()}) # Init db db_composer = DBComposer() db_composer.compose_vuln_db() InternalServer.get_mongodb_driver().insert_init_db_process_status( {'status': 'Updated', 'timestamp': datetime.datetime.now().timestamp()}) except Exception as ex: message = "Unexpected exception of type {0} occurred: {1!r}".format(type(ex).__name__, ex.args) DagdaLogger.get_logger().error(message) if InternalServer.is_debug_logging_enabled(): traceback.print_exc() InternalServer.get_mongodb_driver().insert_init_db_process_status( {'status': message, 'timestamp': datetime.datetime.now().timestamp()})
def _get_dagda_base_url(): # -- Load env variables try: dagda_host = os.environ['DAGDA_HOST'] except KeyError: DagdaLogger.get_logger().error('DAGDA_HOST environment variable is not set.') exit(1) try: dagda_port = os.environ['DAGDA_PORT'] except KeyError: DagdaLogger.get_logger().error('DAGDA_PORT environment variable is not set.') exit(1) # -- Return Dagda server base url return 'http://' + dagda_host + ':' + dagda_port + '/v1'
def check_docker_by_image_name(image_name): # -- Check input if not image_name: return json.dumps({ 'err': 400, 'msg': 'Bad image name' }, sort_keys=True), 400 # -- Docker pull from remote registry if it is necessary try: pulled = False if not InternalServer.get_docker_driver().is_docker_image(image_name): output = InternalServer.get_docker_driver().docker_pull(image_name) if 'errorDetail' in output: msg = 'Error: image library/' + image_name + ':latest not found' DagdaLogger.get_logger().error(msg) raise DagdaError(msg) pulled = True except: return json.dumps({ 'err': 404, 'msg': 'Image name not found' }, sort_keys=True), 404 # -- Process request data = {} data['image_name'] = image_name data['timestamp'] = datetime.datetime.now().timestamp() data['status'] = 'Analyzing' id = InternalServer.get_mongodb_driver( ).insert_docker_image_scan_result_to_history(data) InternalServer.get_dagda_edn().put({ 'msg': 'check_image', 'image_name': image_name, '_id': str(id), 'pulled': pulled }) # -- Return output = {} output['id'] = str(id) output['msg'] = 'Accepted the analysis of <' + image_name + '>' return json.dumps(output, sort_keys=True), 202
def get_dagda_base_url(): # -- Load env variables try: dagda_host = os.environ['DAGDA_HOST'] except KeyError: DagdaLogger.get_logger().error( 'DAGDA_HOST environment variable is not set.') exit(1) try: dagda_port = os.environ['DAGDA_PORT'] except KeyError: DagdaLogger.get_logger().error( 'DAGDA_PORT environment variable is not set.') exit(1) # -- Return Dagda server base url return 'http://' + dagda_host + ':' + dagda_port + '/v1'
def get_rhsa_and_rhba_bz2_archive_files(): if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug( "Collecting RHSA and RHBA .bz2 archive files...") feed_json_file = get_http_resource_content( "https://www.redhat.com/security/data/oval/v2/feed.json") bz2_archive_files = [] for entry in json.loads(feed_json_file)["feed"]["entry"]: if entry["link"][0]["length"] > 850: if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug("Collected " + entry["content"]["src"]) bz2_archive_files.append( get_http_resource_content(entry["content"]["src"])) return bz2_archive_files
def run(self): edn_pid = os.fork() if edn_pid == 0: try: while True: item = InternalServer.get_dagda_edn().get() if item['msg'] == 'init_db': self._init_or_update_db() elif item['msg'] == 'check_image': self._check_docker_by_image_name(item) elif item['msg'] == 'check_container': self._check_docker_by_container_id(item) except KeyboardInterrupt: # Pressed CTRL+C to quit, so nothing to do pass else: docker_events_monitor_pid = os.fork() if docker_events_monitor_pid == 0: try: docker_daemon_events_monitor = DockerDaemonEventsMonitor(InternalServer.get_docker_driver(), InternalServer.get_mongodb_driver()) docker_daemon_events_monitor.run() except KeyboardInterrupt: # Pressed CTRL+C to quit, so nothing to do pass else: sysdig_falco_monitor_pid = os.fork() if sysdig_falco_monitor_pid == 0: try: self.sysdig_falco_monitor.pre_check() self.sysdig_falco_monitor.run() except DagdaError as e: DagdaLogger.get_logger().error(e.get_message()) DagdaLogger.get_logger().warning('Runtime behaviour monitor disabled.') except KeyboardInterrupt: # Pressed CTRL+C to quit if not InternalServer.is_external_falco(): InternalServer.get_docker_driver().docker_stop(self.sysdig_falco_monitor.get_running_container_id()) InternalServer.get_docker_driver().docker_remove_container( self.sysdig_falco_monitor.get_running_container_id()) else: DagdaServer.app.run(debug=False, host=self.dagda_server_host, port=self.dagda_server_port)
def check_docker_by_container_id(container_id): # -- Check input if not container_id: return json.dumps({ 'err': 400, 'msg': 'Bad container id' }, sort_keys=True), 400 # -- Retrieves docker image name try: image_name = InternalServer.get_docker_driver( ).get_docker_image_name_by_container_id(container_id) except Exception as ex: message = "Unexpected exception of type {0} occurred while getting the docker image name: {1!r}" \ .format(type(ex).__name__, ex.get_message() if type(ex).__name__ == 'DagdaError' else ex.args) DagdaLogger.get_logger().error(message) return json.dumps({ 'err': 404, 'msg': 'Container Id not found' }, sort_keys=True), 404 # -- Process request data = {} data['image_name'] = image_name data['timestamp'] = datetime.datetime.now().timestamp() data['status'] = 'Analyzing' id = InternalServer.get_mongodb_driver( ).insert_docker_image_scan_result_to_history(data) InternalServer.get_dagda_edn().put({ 'msg': 'check_container', 'container_id': container_id, '_id': str(id) }) # -- Return output = {} output['id'] = str(id) output[ 'msg'] = 'Accepted the analysis of <' + image_name + '> with id: ' + container_id return json.dumps(output, sort_keys=True), 202
def check_docker_by_image_name(image_name): # -- Check input if not image_name: return json.dumps({'err': 400, 'msg': 'Bad image name'}, sort_keys=True), 400 # -- Docker pull from remote registry if it is necessary try: pulled = False if not InternalServer.get_docker_driver().is_docker_image(image_name): if ':' in image_name: tmp = image_name.split(':')[0] tag = image_name.split(':')[1] msg = 'Error: image library/' + image_name + ':' + tag + ' not found' output = InternalServer.get_docker_driver().docker_pull(tmp, tag=tag) else: msg = 'Error: image library/' + image_name + ':latest not found' output = InternalServer.get_docker_driver().docker_pull(image_name) if 'errorDetail' in output: DagdaLogger.get_logger().error(msg) raise DagdaError(msg) pulled = True except Exception as ex: message = "Unexpected exception of type {0} occurred while pulling the docker image: {1!r}" \ .format(type(ex).__name__, ex.get_message() if type(ex).__name__ == 'DagdaError' else ex.args) DagdaLogger.get_logger().error(message) return json.dumps({'err': 404, 'msg': 'Image name not found'}, sort_keys=True), 404 # -- Process request data = {} data['image_name'] = image_name data['timestamp'] = datetime.datetime.now().timestamp() data['status'] = 'Analyzing' id = InternalServer.get_mongodb_driver().insert_docker_image_scan_result_to_history(data) InternalServer.get_dagda_edn().put({'msg': 'check_image', 'image_name': image_name, '_id': str(id), 'pulled': pulled}) # -- Return output = {} output['id'] = str(id) output['msg'] = 'Accepted the analysis of <' + image_name + '>' return json.dumps(output, sort_keys=True), 202
def _untar_layers(dir, layers): output = {} # Untar layer filesystem bundle for layer in layers: tarfile = TarFile(dir + "/" + layer) for member in tarfile.getmembers(): try: tarfile.extract(member, path=dir, set_attrs=False) except (ValueError, ReadError) as ex: if InternalServer.is_debug_logging_enabled(): message = "Unexpected exception of type {0} occurred while untaring the docker image: {1!r}" \ .format(type(ex).__name__, ex.get_message() if type(ex).__name__ == 'DagdaError' else ex.args) DagdaLogger.get_logger().debug(message) except PermissionError as ex: message = "Unexpected error occurred while untaring the docker image: " + \ "Operation not permitted on {0!r}".format(member.name) DagdaLogger.get_logger().warn(message) # Clean up for layer in layers: clean_up(dir + "/" + layer[:-10])
def verify_args(args): if args.fp and (args.id or args.is_fp): DagdaLogger.get_logger().error('Argument --fp: this argument must be alone.') return 1 elif args.fp and not args.docker_image_name: DagdaLogger.get_logger().error('Argument --fp: IMAGE_NAME argument is mandatory.') return 2 elif args.is_fp and args.id: DagdaLogger.get_logger().error('Argument --is_fp: this argument must be alone.') return 3 elif args.is_fp and not args.docker_image_name: DagdaLogger.get_logger().error('Argument --is_fp: IMAGE_NAME argument is mandatory.') return 4 return 0
def run(self): # Read docker daemon events while True: try: for event in self.docker_driver.docker_events(): e = json.loads(event.decode('UTF-8').replace("\n", "")) if 'Actor' in e and 'Attributes' in e['Actor']: iter = list(e['Actor']['Attributes']) for key in iter: if '.' in key: del e['Actor']['Attributes'][key] # Bulk insert self.mongodb_driver.bulk_insert_docker_daemon_events([e]) except requests.packages.urllib3.exceptions.ReadTimeoutError: # Nothing to do pass except bson.errors.InvalidDocument as ex: message = "Unexpected exception of type {0} occurred: {1!r}" \ .format(type(ex).__name__, ex.get_message() if type(ex).__name__ == 'DagdaError' else ex.args) DagdaLogger.get_logger().error(message) if InternalServer.is_debug_logging_enabled(): traceback.print_exc()
def get_soft_from_docker_container_id(docker_driver, container_id): # Extract Linux image distribution response = get_os_name(docker_driver.docker_exec(container_id, 'cat /etc/os-release', True, False)) if response is None: DagdaLogger.get_logger().info('Linux image distribution has not the "/etc/os-release" file. Starting the task ' 'for linux distribution identification in a blind mode ...') products = get_os_software_packages_blind_mode(docker_driver, container_id) else: # Get all installed packages if 'Red Hat' in response or 'CentOS' in response or 'Fedora' in response or 'openSUSE' in response: # Red Hat/CentOS/Fedora/openSUSE products = get_os_software_packages(docker_driver, container_id, 'rpm -aqi', parse_rpm_output_list) elif 'Debian' in response or 'Ubuntu' in response: # Debian/Ubuntu products = get_os_software_packages(docker_driver, container_id, 'dpkg -l', parse_dpkg_output_list) elif 'Alpine' in response: # Alpine products = get_os_software_packages(docker_driver, container_id, 'apk -v info', parse_apk_output_list) else: raise DagdaError('Linux image distribution not supported yet.') # Return packages return products
def run(self): # Read docker daemon events while True: try: for event in self.docker_driver.docker_events(): e = json.loads(event.decode('UTF-8').replace("\n", "")) if 'Actor' in e and 'Attributes' in e['Actor']: iter = list(e['Actor']['Attributes']) for key in iter: if '.' in key: del e['Actor']['Attributes'][key] # Bulk insert self.mongodb_driver.bulk_insert_docker_daemon_events([e]) except requests.packages.urllib3.exceptions.ReadTimeoutError: # Nothing to do pass except bson.errors.InvalidDocument as ex: message = "Unexpected exception of type {0} occurred: {1!r}" \ .format(type(ex).__name__, ex.get_message() if type(ex).__name__ == 'DagdaError' else ex.args) DagdaLogger.get_logger().error(message) if InternalServer.is_debug_logging_enabled(): traceback.print_exc()
def _threaded_cve_gathering(mongoDbDriver, i): if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('... Including CVEs - ' + str(i)) compressed_content = get_http_resource_content( "https://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-" + str(i) + ".xml.gz") cve_list = get_cve_list_from_file(compressed_content, i) if len(cve_list) > 0: mongoDbDriver.bulk_insert_cves(cve_list) # Add CVE info collection with additional info like score compressed_content_info = get_http_resource_content( "https://nvd.nist.gov/download/nvdcve-" + str(i) + ".xml.zip") cve_info_list = get_cve_description_from_file(compressed_content_info) compressed_ext_content_info = \ get_http_resource_content("https://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-" + str(i) + ".xml.zip") cve_ext_info_list = get_cve_cweid_from_file( compressed_ext_content_info, cve_info_list) if len(cve_ext_info_list) > 0: mongoDbDriver.bulk_insert_cves_info(cve_ext_info_list)
def evaluate_image(self, image_name, container_id): # Init data = {} # -- Static analysis # Get OS packages if image_name: # Scans the docker image os_packages = os_info_extractor.get_soft_from_docker_image( self.dockerDriver, image_name) else: # Scans the docker container os_packages = os_info_extractor.get_soft_from_docker_container_id( self.dockerDriver, container_id) image_name = self.dockerDriver.get_docker_image_name_by_container_id( container_id) # Get programming language dependencies dependencies = None try: dependencies = dep_info_extractor.get_dependencies_from_docker_image( self.dockerDriver, image_name) except Exception as ex: message = "Unexpected exception of type {0} occured: {1!r}".format( type(ex).__name__, ex.args) DagdaLogger.get_logger().error(message) data['status'] = message # -- Prepare output if dependencies is not None: data['status'] = 'Completed' else: dependencies = [] data['image_name'] = image_name data['timestamp'] = datetime.datetime.now().timestamp() data['static_analysis'] = self.generate_static_analysis( os_packages, dependencies) # -- Return return data
def get_bid(bugtraq_id): url = "http://www.securityfocus.com/bid/" + str(bugtraq_id) try: r = requests.get(url) if r.status_code == 200: try: body = r.content.decode("utf-8") body = body[body.index('<div id="vulnerability">'): body.index('<span class="label">Not Vulnerable:</span>')] title = get_title(body) clazz = get_info_by_label(body, 'Class') linked_cves = get_linked_CVEs(body) is_local = get_info_by_label(body, 'Local') is_remote = get_info_by_label(body, 'Remote') vuln_products = get_vulnerable_products(body) except: vuln_products = [] if len(vuln_products) > 0: return json.dumps(prepare_output(title, bugtraq_id, clazz, linked_cves, is_local, is_remote, vuln_products), sort_keys=True) except requests.ConnectionError: DagdaLogger.get_logger().warning('Connection error occurred with: "' + url + '"') return None
def get_rhsa_and_rhba_lists_from_files(bz2_files): if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug("Processing vulnerabilities...") rhsa_list = [] rhba_list = [] rhsa_info_list = [] rhba_info_list = [] count = 0 for bz2_file in bz2_files: _rhsa_list, _rhba_list, _rhsa_info_list, _rhba_info_list = get_rhsa_and_rhba_lists_from_file( bz2_file) rhsa_list.extend(_rhsa_list) rhba_list.extend(_rhba_list) rhsa_info_list.extend(_rhsa_info_list) rhba_info_list.extend(_rhba_info_list) count = count + 1 if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug("Processed: " + str(count) + "/" + str(len(bz2_files))) return rhsa_list, rhba_list, rhsa_info_list, rhba_info_list
def verify_args(args): if args.fp and (args.id or args.is_fp): DagdaLogger.get_logger().error( 'Argument --fp: this argument must be alone.') return 1 elif args.fp and not args.docker_image_name: DagdaLogger.get_logger().error( 'Argument --fp: IMAGE_NAME argument is mandatory.') return 2 elif args.is_fp and args.id: DagdaLogger.get_logger().error( 'Argument --is_fp: this argument must be alone.') return 3 elif args.is_fp and not args.docker_image_name: DagdaLogger.get_logger().error( 'Argument --is_fp: IMAGE_NAME argument is mandatory.') return 4 return 0
def verify_args(args): if args.server_port and args.server_port not in range(1, 65536): DagdaLogger.get_logger().error('Argument -p/--server_port: The port must be between 1 and 65535.') return 1 elif args.mongodb_port and args.mongodb_port not in range(1, 65536): DagdaLogger.get_logger().error('Argument -mp/--mongodb_port: The port must be between 1 and 65535.') return 2 elif args.falco_rules_file: with args.falco_rules_file as content_file: try: yaml.load(content_file.read()) except: DagdaLogger.get_logger().error('Argument --falco_rules_file: Malformed yaml file.') return 3 # Else return 0
def main(parsed_args): # -- Init cmd = parsed_args.get_command() parsed_args = parsed_args.get_extra_args() try: # Execute Dagda command r = execute_dagda_cmd(cmd=cmd, args=parsed_args) # -- Print cmd output if r is not None and r.content: output = r.content.decode('utf-8') try: print(json.dumps(json.loads(output), sort_keys=True, indent=4)) except json.decoder.JSONDecodeError as err: DagdaLogger.get_logger().error('JSONDecodeError with the received response: "' + output + '"') DagdaLogger.get_logger().error(str(err)) except BaseException as err: DagdaLogger.get_logger().error(str(err)) traceback.print_exc()
def compose_vuln_db(self): if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('ENTRY to the method for composing VulnDB') # -- CVE # Adding or updating CVEs if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Updating CVE collection ...') first_year = self.mongoDbDriver.remove_only_cve_for_update() for i in range(first_year, next_year): if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('... Including CVEs - ' + str(i)) compressed_content = get_http_resource_content( "https://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-" + str(i) + ".xml.gz") cve_list = get_cve_list_from_file(compressed_content, i) if len(cve_list) > 0: self.mongoDbDriver.bulk_insert_cves(cve_list) # Add CVE info collection with additional info like score compressed_content_info = get_http_resource_content("https://nvd.nist.gov/download/nvdcve-" + str(i) + ".xml.zip") cve_info_list = get_cve_description_from_file(compressed_content_info) compressed_ext_content_info = \ get_http_resource_content("https://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-" + str(i) + ".xml.zip") cve_ext_info_list = get_cve_cweid_from_file(compressed_ext_content_info, cve_info_list) if len(cve_ext_info_list) > 0: self.mongoDbDriver.bulk_insert_cves_info(cve_ext_info_list) if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('CVE collection updated') # -- Exploit DB # Adding or updating Exploit_db and Exploit_db info if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Updating Exploit DB collection ...') self.mongoDbDriver.delete_exploit_db_collection() self.mongoDbDriver.delete_exploit_db_info_collection() csv_content = get_http_resource_content( 'https://raw.githubusercontent.com/offensive-security/exploit-database/master/files_exploits.csv') exploit_db_list, exploit_db_info_list = get_exploit_db_list_from_csv(csv_content.decode("utf-8")) self.mongoDbDriver.bulk_insert_exploit_db_ids(exploit_db_list) self.mongoDbDriver.bulk_insert_exploit_db_info(exploit_db_info_list) if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Exploit DB collection updated') # -- BID # Adding BugTraqs from 20180328_sf_db.json.gz, where 103525 is the max bid in the gz file if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Updating BugTraqs Id collection ...') max_bid = self.mongoDbDriver.get_max_bid_inserted() if max_bid < 103525: # Clean if max_bid != 0: self.mongoDbDriver.delete_bid_collection() self.mongoDbDriver.delete_bid_info_collection() # Adding BIDs compressed_file = io.BytesIO(get_http_resource_content( "https://github.com/eliasgranderubio/bidDB_downloader/raw/master/bonus_track/20180328_sf_db.json.gz")) bid_items_array, bid_detail_array = get_bug_traqs_lists_from_file(compressed_file) # Insert BIDs for bid_items_list in bid_items_array: self.mongoDbDriver.bulk_insert_bids(bid_items_list) bid_items_list.clear() # Insert BID details self.mongoDbDriver.bulk_insert_bid_info(bid_detail_array) bid_detail_array.clear() # Set the new max bid max_bid = 103525 # Updating BugTraqs from http://www.securityfocus.com/ bid_items_array, bid_detail_array = get_bug_traqs_lists_from_online_mode(bid_downloader(first_bid=max_bid+1, last_bid=104000)) # Insert BIDs if len(bid_items_array) > 0: for bid_items_list in bid_items_array: self.mongoDbDriver.bulk_insert_bids(bid_items_list) bid_items_list.clear() # Insert BID details if len(bid_detail_array) > 0: self.mongoDbDriver.bulk_insert_bid_info(bid_detail_array) bid_detail_array.clear() if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('BugTraqs Id collection updated') # -- RHSA (Red Hat Security Advisory) and RHBA (Red Hat Bug Advisory) # Adding or updating rhsa and rhba collections if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Updating RHSA & RHBA collections ...') self.mongoDbDriver.delete_rhba_collection() self.mongoDbDriver.delete_rhba_info_collection() self.mongoDbDriver.delete_rhsa_collection() self.mongoDbDriver.delete_rhsa_info_collection() bz2_file = get_http_resource_content('https://www.redhat.com/security/data/oval/rhsa.tar.bz2') rhsa_list, rhba_list, rhsa_info_list, rhba_info_list = get_rhsa_and_rhba_lists_from_file(bz2_file) self.mongoDbDriver.bulk_insert_rhsa(rhsa_list) self.mongoDbDriver.bulk_insert_rhba(rhba_list) self.mongoDbDriver.bulk_insert_rhsa_info(rhsa_info_list) self.mongoDbDriver.bulk_insert_rhba_info(rhba_info_list) if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('RHSA & RHBA collections updated') if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('EXIT from the method for composing VulnDB')
def evaluate_image(self, image_name, container_id): if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('ENTRY to the method for analyzing a docker image') # Init data = {} # -- Static analysis image_name = self.dockerDriver.get_docker_image_name_by_container_id(container_id) if container_id \ else image_name os_packages = [] malware_binaries = [] dependencies = [] temp_dir = None try: # Get OS packages if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Retrieving OS packages from the docker image ...') if container_id is None: # Scans the docker image os_packages = os_info_extractor.get_soft_from_docker_image(docker_driver=self.dockerDriver, image_name=image_name) temp_dir = extract_filesystem_bundle(docker_driver=self.dockerDriver, image_name=image_name) else: # Scans the docker container os_packages = os_info_extractor.get_soft_from_docker_container_id(docker_driver=self.dockerDriver, container_id=container_id) temp_dir = extract_filesystem_bundle(docker_driver=self.dockerDriver, container_id=container_id) if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('OS packages from the docker image retrieved') # Get malware binaries in a parallel way malware_thread = Thread(target=Analyzer._threaded_malware, args=(self.dockerDriver, temp_dir, malware_binaries)) malware_thread.start() # Get programming language dependencies in a parallel way dependencies_thread = Thread(target=Analyzer._threaded_dependencies, args=(self.dockerDriver, image_name, temp_dir, dependencies)) dependencies_thread.start() # Waiting for the threads malware_thread.join() dependencies_thread.join() except Exception as ex: message = "Unexpected exception of type {0} occurred: {1!r}"\ .format(type(ex).__name__, ex.get_message() if type(ex).__name__ == 'DagdaError' else ex.args) DagdaLogger.get_logger().error(message) if InternalServer.is_debug_logging_enabled(): traceback.print_exc() data['status'] = message # -- Cleanup if temp_dir is not None: clean_up(temporary_dir=temp_dir) # -- Prepare output if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Preparing analysis output ...') if 'status' not in data or data['status'] is None: data['status'] = 'Completed' data['image_name'] = image_name data['timestamp'] = datetime.datetime.now().timestamp() data['static_analysis'] = self.generate_static_analysis(image_name, os_packages, dependencies, malware_binaries) if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('Analysis output completed') # -- Return if InternalServer.is_debug_logging_enabled(): DagdaLogger.get_logger().debug('EXIT from the method for analyzing a docker image') return data
def verify_args(args): if not args.init and not args.cve and not args.cve_info and not args.product and not args.product_version \ and not args.bid and not args.bid_info and not args.exploit_db and not args.exploit_db_info \ and not args.init_status and not args.rhba and not args.rhsa and not args.rhba_info \ and not args.rhsa_info: DagdaLogger.get_logger().error('Missing arguments.') return 1 elif args.init and (args.cve or args.product or args.product_version or args.bid or args.bid_info \ or args.exploit_db or args.exploit_db_info or args.init_status or args.rhba or args.rhsa \ or args.rhba_info or args.rhsa_info): DagdaLogger.get_logger().error('Argument --init: this argument must be alone.') return 2 elif args.init_status and (args.cve or args.product or args.product_version or args.bid or args.cve \ or args.cve_info or args.bid_info or args.exploit_db or args.exploit_db_info \ or args.init or args.rhba or args.rhsa or args.rhba_info or args.rhsa_info): DagdaLogger.get_logger().error('Argument --init_status: this argument must be alone.') return 3 elif args.cve: if args.init or args.init_status or args.product or args.product_version or args.bid or args.cve_info \ or args.exploit_db or args.bid_info or args.exploit_db_info or args.rhba or args.rhsa \ or args.rhba_info or args.rhsa_info: DagdaLogger.get_logger().error('Argument --cve: this argument must be alone.') return 4 else: regex = r"(CVE-[0-9]{4}-[0-9]{4,5})" search_obj = re.search(regex, args.cve) if not search_obj or len(search_obj.group(0)) != len(args.cve): DagdaLogger.get_logger().error('Argument --cve: The cve format must look like to CVE-2002-1234.') return 5 elif args.cve_info: if args.init or args.init_status or args.product or args.product_version or args.bid or args.cve \ or args.exploit_db or args.bid_info or args.exploit_db_info or args.rhba or args.rhsa \ or args.rhba_info or args.rhsa_info: DagdaLogger.get_logger().error('Argument --cve_info: this argument must be alone.') return 6 else: regex = r"(CVE-[0-9]{4}-[0-9]{4,5})" search_obj = re.search(regex, args.cve_info) if not search_obj or len(search_obj.group(0)) != len(args.cve_info): DagdaLogger.get_logger().error('Argument --cve_info: The cve format must look like to ' 'CVE-2002-1234.') return 7 elif args.bid: if args.init or args.init_status or args.product or args.product_version or args.cve or args.cve_info \ or args.exploit_db or args.bid_info or args.exploit_db_info or args.rhba or args.rhsa \ or args.rhba_info or args.rhsa_info: DagdaLogger.get_logger().error('Argument --bid: this argument must be alone.') return 8 else: if args.bid <= 0: DagdaLogger.get_logger().error('Argument --bid: The bid argument must be greater than zero.') return 9 elif args.bid_info: if args.init or args.init_status or args.product or args.product_version or args.cve or args.cve_info \ or args.exploit_db or args.bid or args.exploit_db_info or args.rhba or args.rhsa \ or args.rhba_info or args.rhsa_info: DagdaLogger.get_logger().error('Argument --bid_info: this argument must be alone.') return 10 else: if args.bid_info <= 0: DagdaLogger.get_logger().error( 'Argument --bid_info: The bid argument must be greater than zero.') return 11 elif args.exploit_db: if args.init or args.init_status or args.product or args.product_version or args.cve or args.cve_info \ or args.bid or args.bid_info or args.exploit_db_info or args.rhba or args.rhsa \ or args.rhba_info or args.rhsa_info: DagdaLogger.get_logger().error('Argument --exploit_db: this argument must be alone.') return 12 else: if args.exploit_db <= 0: DagdaLogger.get_logger().error('Argument --exploit_db: The exploit_db argument must be ' 'greater than zero.') return 13 elif args.exploit_db_info: if args.init or args.init_status or args.product or args.product_version or args.cve or args.cve_info \ or args.bid or args.bid_info or args.exploit_db or args.rhba or args.rhsa \ or args.rhba_info or args.rhsa_info: DagdaLogger.get_logger().error('Argument --exploit_db_info: this argument must be alone.') return 14 else: if args.exploit_db_info <= 0: DagdaLogger.get_logger().error('Argument --exploit_db_info: The exploit_db_info argument ' 'must be greater than zero.') return 15 elif args.product_version and not args.product: DagdaLogger.get_logger().error('Argument --product_version: this argument requires the --product argument.') return 16 elif args.rhba: if args.init or args.init_status or args.product or args.product_version or args.bid or args.cve_info \ or args.exploit_db or args.bid_info or args.exploit_db_info or args.cve or args.rhsa \ or args.rhba_info or args.rhsa_info: DagdaLogger.get_logger().error('Argument --rhba: this argument must be alone.') return 17 else: regex = r"(RHBA-[0-9]{4}:[0-9]+)" search_obj = re.search(regex, args.rhba) if not search_obj or len(search_obj.group(0)) != len(args.rhba): DagdaLogger.get_logger().error('Argument --rhba: The rhba format must look like to RHBA-2012:234.') return 18 elif args.rhba_info: if args.init or args.init_status or args.product or args.product_version or args.bid or args.cve_info \ or args.exploit_db or args.bid_info or args.exploit_db_info or args.cve or args.rhsa \ or args.rhba or args.rhsa_info: DagdaLogger.get_logger().error('Argument --rhba_info: this argument must be alone.') return 19 else: regex = r"(RHBA-[0-9]{4}:[0-9]+)" search_obj = re.search(regex, args.rhba_info) if not search_obj or len(search_obj.group(0)) != len(args.rhba_info): DagdaLogger.get_logger().error( 'Argument --rhba_info: The rhba format must look like to RHBA-2012:234.') return 20 elif args.rhsa: if args.init or args.init_status or args.product or args.product_version or args.bid or args.cve_info \ or args.exploit_db or args.bid_info or args.exploit_db_info or args.cve or args.rhba \ or args.rhba_info or args.rhsa_info: DagdaLogger.get_logger().error('Argument --rhsa: this argument must be alone.') return 21 else: regex = r"(RHSA-[0-9]{4}:[0-9]+)" search_obj = re.search(regex, args.rhsa) if not search_obj or len(search_obj.group(0)) != len(args.rhsa): DagdaLogger.get_logger().error( 'Argument --rhsa: The rhba format must look like to RHSA-2012:234.') return 22 elif args.rhsa_info: if args.init or args.init_status or args.product or args.product_version or args.bid or args.cve_info \ or args.exploit_db or args.bid_info or args.exploit_db_info or args.cve or args.rhsa \ or args.rhba or args.rhba_info: DagdaLogger.get_logger().error('Argument --rhsa_info: this argument must be alone.') return 23 else: regex = r"(RHSA-[0-9]{4}:[0-9]+)" search_obj = re.search(regex, args.rhsa_info) if not search_obj or len(search_obj.group(0)) != len(args.rhsa_info): DagdaLogger.get_logger().error( 'Argument --rhsa_info: The rhsa format must look like to RHSA-2012:234.') return 24 # Else return 0
def verify_args(args): if not args.dagda_server: DagdaLogger.get_logger().error('Wrong Dagda server endpoint.') return 1 else: splitted_info = args.dagda_server.split(':') if len(splitted_info) != 2: DagdaLogger.get_logger().error('Wrong Dagda server endpoint.') return 1 try: port = int(splitted_info[1]) if port not in range(1, 65536): DagdaLogger.get_logger().error('Wrong Dagda server endpoint.') return 1 except ValueError: DagdaLogger.get_logger().error('Wrong Dagda server endpoint.') return 1 if not args.container_id and not args.docker_image: DagdaLogger.get_logger().error('Missing arguments.') return 2 elif args.container_id and args.docker_image: DagdaLogger.get_logger().error('Arguments --docker_image/--container_id: Both arguments ' 'can not be together.') return 3 # Else return 0