def run_kubernetes_scan(): current_dir = os.path.dirname(os.path.realpath(__file__)) test_files_dir = os.path.join(current_dir, repo_name) runner_filter = RunnerFilter() runner_registry = RunnerRegistry(banner, runner_filter, k8_runner()) reports = runner_registry.run(root_folder=test_files_dir) assert len(reports) > 0
def test_multi_iac(self): current_dir = os.path.dirname(os.path.realpath(__file__)) test_files_dir = current_dir + "/example_multi_iac" runner_filter = RunnerFilter(framework=None, checks=None, skip_checks=None) runner_registry = RunnerRegistry( banner, runner_filter, tf_runner(), cfn_runner(), k8_runner() ) reports = runner_registry.run(root_folder=test_files_dir) for report in reports: self.assertGreater(len(report.passed_checks), 1)
def verify_empty_report(self, test_files_dir, files=None): runner_filter = RunnerFilter(framework=None, checks=None, skip_checks=None) runner_registry = RunnerRegistry( banner, runner_filter, tf_runner(), cfn_runner(), k8_runner() ) reports = runner_registry.run(root_folder=test_files_dir, files=files) for report in reports: self.assertEqual(report.failed_checks, []) self.assertEqual(report.skipped_checks, []) self.assertEqual(report.passed_checks, []) return runner_registry
def test_resource_counts(self): current_dir = os.path.dirname(os.path.realpath(__file__)) test_files_dir = current_dir + "/example_multi_iac" runner_filter = RunnerFilter(framework=None, checks=None, skip_checks=None) runner_registry = RunnerRegistry( banner, runner_filter, tf_runner(), cfn_runner(), k8_runner() ) reports = runner_registry.run(root_folder=test_files_dir) # The number of resources that will get scan results. Note that this may change if we add policies covering new resource types. counts_by_type = {"kubernetes": 10, "terraform": 3, "cloudformation": 4} for report in reports: self.assertEqual( counts_by_type[report.check_type], report.get_summary()["resource_count"], )
from checkov.secrets.runner import Runner as secrets_runner from checkov.serverless.runner import Runner as sls_runner from checkov.terraform.plan_runner import Runner as tf_plan_runner from checkov.terraform.runner import Runner as tf_graph_runner from checkov.version import version outer_registry = None logging_init() logger = logging.getLogger(__name__) checkov_runners = [ 'cloudformation', 'terraform', 'kubernetes', 'serverless', 'arm', 'terraform_plan', 'helm', 'dockerfile', 'secrets' ] DEFAULT_RUNNERS = (tf_graph_runner(), cfn_runner(), k8_runner(), sls_runner(), arm_runner(), tf_plan_runner(), helm_runner(), dockerfile_runner(), secrets_runner()) def run(banner=checkov_banner, argv=sys.argv[1:]): default_config_paths = get_default_config_paths(sys.argv[1:]) parser = ExtArgumentParser( description='Infrastructure as code static analysis', default_config_files=default_config_paths, config_file_parser_class=configargparse.YAMLConfigFileParser, add_env_var_help=True) add_parser_args(parser) config = parser.parse_args(argv) # bridgecrew uses both the urllib3 and requests libraries, while checkov uses the requests library. # Allow the user to specify a CA bundle to be used by both libraries.
def run(banner=checkov_banner, argv=sys.argv[1:]): parser = argparse.ArgumentParser( description='Infrastructure as code static analysis') add_parser_args(parser) args = parser.parse_args(argv) runner_filter = RunnerFilter( framework=args.framework, checks=args.check, skip_checks=args.skip_check, download_external_modules=convert_str_to_bool( args.download_external_modules), external_modules_download_path=args.external_modules_download_path, evaluate_variables=convert_str_to_bool(args.evaluate_variables)) if outer_registry: runner_registry = outer_registry runner_registry.runner_filter = runner_filter else: runner_registry = RunnerRegistry(banner, runner_filter, tf_runner(), cfn_runner(), k8_runner(), sls_runner(), arm_runner(), tf_plan_runner()) if args.version: print(version) return if args.bc_api_key: if args.repo_id is None: parser.error( "--repo-id argument is required when using --bc-api-key") if len(args.repo_id.split('/')) != 2: parser.error( "--repo-id argument format should be 'organization/repository_name' E.g " "bridgecrewio/checkov") bc_integration.setup_bridgecrew_credentials(bc_api_key=args.bc_api_key, repo_id=args.repo_id) guidelines = {} if not args.no_guide: guidelines = bc_integration.get_guidelines() if args.check and args.skip_check: parser.error( "--check and --skip-check can not be applied together. please use only one of them" ) return if args.list: print_checks(framework=args.framework) return external_checks_dir = get_external_checks_dir(args) if args.directory: for root_folder in args.directory: file = args.file scan_reports = runner_registry.run( root_folder=root_folder, external_checks_dir=external_checks_dir, files=file, guidelines=guidelines) if bc_integration.is_integration_configured(): bc_integration.persist_repository(root_folder) bc_integration.persist_scan_results(scan_reports) bc_integration.commit_repository(args.branch) runner_registry.print_reports(scan_reports, args) return elif args.file: scan_reports = runner_registry.run( external_checks_dir=external_checks_dir, files=args.file, guidelines=guidelines) if bc_integration.is_integration_configured(): files = [os.path.abspath(file) for file in args.file] root_folder = os.path.split(os.path.commonprefix(files))[0] bc_integration.persist_repository(root_folder) bc_integration.persist_scan_results(scan_reports) bc_integration.commit_repository(args.branch) runner_registry.print_reports(scan_reports, args) else: print(f"{banner}") bc_integration.onboarding()
def run(self, root_folder, external_checks_dir=None, files=None, runner_filter=RunnerFilter(), collect_skip_comments=True): if external_checks_dir: for directory in external_checks_dir: registry.load_external_checks(directory) chart_directories = self.find_chart_directories(root_folder, files, runner_filter.excluded_paths) report = Report(self.check_type) chart_dir_and_meta = parallel_runner.run_function( lambda cd: (cd, self.parse_helm_chart_details(cd)), chart_directories) for chart_dir, chart_meta in chart_dir_and_meta: # chart_name = os.path.basename(chart_dir) logging.info( f"Processing chart found at: {chart_dir}, name: {chart_meta['name']}, version: {chart_meta['version']}") with tempfile.TemporaryDirectory() as target_dir: # dependency list is nicer to parse than dependency update. proc = subprocess.Popen([self.helm_command, 'dependency', 'list', chart_dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE) # nosec o, e = proc.communicate() if e: if "Warning: Dependencies" in str(e, 'utf-8'): logging.info( f"V1 API chart without Chart.yaml dependancies. Skipping chart dependancy list for {chart_meta['name']} at dir: {chart_dir}. Working dir: {target_dir}. Error details: {str(e, 'utf-8')}") else: logging.info( f"Error processing helm dependancies for {chart_meta['name']} at source dir: {chart_dir}. Working dir: {target_dir}. Error details: {str(e, 'utf-8')}") self.parse_helm_dependency_output(o) try: # --dependency-update needed to pull in deps before templating. proc = subprocess.Popen([self.helm_command, 'template', '--dependency-update', chart_dir], stdout=subprocess.PIPE, stderr=subprocess.PIPE) # nosec o, e = proc.communicate() logging.debug( f"Ran helm command to template chart output. Chart: {chart_meta['name']}. dir: {target_dir}. Output: {str(o, 'utf-8')}") except Exception: logging.info( f"Error processing helm chart {chart_meta['name']} at dir: {chart_dir}. Working dir: {target_dir}. Error details: {str(e, 'utf-8')}") output = str(o, 'utf-8') reader = io.StringIO(output) cur_source_file = None cur_writer = None last_line_dashes = False line_num = 1 for s in reader: s = s.rstrip() if s == '---': last_line_dashes = True continue if last_line_dashes: # The next line should contain a "Source" comment saying the name of the file it came from # So we will close the old file, open a new file, and write the dashes from last iteration plus this line if not s.startswith('# Source: '): raise Exception(f'Line {line_num}: Expected line to start with # Source: {s}') source = s[10:] if source != cur_source_file: if cur_writer: cur_writer.close() file_path = os.path.join(target_dir, source) parent = os.path.dirname(file_path) os.makedirs(parent, exist_ok=True) cur_source_file = source cur_writer = open(os.path.join(target_dir, source), 'a') cur_writer.write('---' + os.linesep) cur_writer.write(s + os.linesep) last_line_dashes = False else: if s.startswith('# Source: '): raise Exception(f'Line {line_num}: Unexpected line starting with # Source: {s}') if not cur_writer: continue else: cur_writer.write(s + os.linesep) line_num += 1 if cur_writer: cur_writer.close() try: k8s_runner = k8_runner() chart_results = k8s_runner.run(target_dir, external_checks_dir=external_checks_dir, runner_filter=runner_filter, helmChart=chart_meta['name']) logging.debug(f"Sucessfully ran k8s scan on {chart_meta['name']}. Scan dir : {target_dir}") report.failed_checks += chart_results.failed_checks report.passed_checks += chart_results.passed_checks report.parsing_errors += chart_results.parsing_errors report.skipped_checks += chart_results.skipped_checks report.resources.update(chart_results.resources) except Exception as e: logging.warning(e, stack_info=True) with tempfile.TemporaryDirectory() as save_error_dir: logging.debug( f"Error running k8s scan on {chart_meta['name']}. Scan dir: {target_dir}. Saved context dir: {save_error_dir}") shutil.move(target_dir, save_error_dir) ## TODO: Export helm dependancies for the chart we've extracted in chart_dependencies return report
def run(banner=checkov_banner): parser = argparse.ArgumentParser( description='Infrastructure as code static analysis') parser.add_argument('-v', '--version', help='version', action='store_true') parser.add_argument( '-d', '--directory', action='append', help= 'IaC root directory (can not be used together with --file). Can be repeated' ) parser.add_argument( '-f', '--file', action='append', help='IaC file(can not be used together with --directory)') parser.add_argument( '--external-checks-dir', action='append', help='Directory for custom checks to be loaded. Can be repeated') parser.add_argument('-l', '--list', help='List checks', action='store_true') parser.add_argument( '-o', '--output', nargs='?', choices=['cli', 'json', 'junitxml', 'github_failed_only'], default='cli', help='Report output format') parser.add_argument( '--framework', help= 'filter scan to run only on a specific infrastructure code frameworks', choices=['cloudformation', 'terraform', 'kubernetes', 'all'], default='all') parser.add_argument( '-c', '--check', help= 'filter scan to run only on a specific check identifier(whitelist), You can ' 'specify multiple checks separated by comma delimiter', default=None) parser.add_argument( '--skip-check', help= 'filter scan to run on all check but a specific check identifier(blacklist), You can ' 'specify multiple checks separated by comma delimiter', default=None) parser.add_argument('-s', '--soft-fail', help='Runs checks but suppresses error code', action='store_true') parser.add_argument('--bc-api-key', help='Bridgecrew API key') parser.add_argument( '--repo-id', help= 'Identity string of the repository, with form <repo_owner>/<repo_name>' ) parser.add_argument( '-b', '--branch', help= "Selected branch of the persisted repository. Only has effect when using the --bc-api-key flag", default='master') args = parser.parse_args() bc_integration = BcPlatformIntegration() runner_filter = RunnerFilter(framework=args.framework, checks=args.check, skip_checks=args.skip_check) runner_registry = RunnerRegistry(banner, runner_filter, tf_runner(), cfn_runner(), k8_runner()) if args.version: print(version) return if args.bc_api_key: if args.repo_id is None: parser.error( "--repo-id argument is required when using --bc-api-key") if len(args.repo_id.split('/')) != 2: parser.error( "--repo-id argument format should be 'organization/repository_name' E.g " "bridgecrewio/checkov") bc_integration.setup_bridgecrew_credentials(bc_api_key=args.bc_api_key, repo_id=args.repo_id) if args.check and args.skip_check: parser.error( "--check and --skip-check can not be applied together. please use only one of them" ) return if args.list: print_checks() return if args.directory: for root_folder in args.directory: file = args.file scan_reports = runner_registry.run( root_folder=root_folder, external_checks_dir=args.external_checks_dir, files=file) if bc_integration.is_integration_configured(): bc_integration.persist_repository(root_folder) bc_integration.persist_scan_results(scan_reports) bc_integration.commit_repository(args.branch) runner_registry.print_reports(scan_reports, args) return elif args.file: scan_reports = runner_registry.run( external_checks_dir=args.external_checks_dir, files=args.file) if bc_integration.is_integration_configured(): files = [os.path.abspath(file) for file in args.file] root_folder = os.path.split(os.path.commonprefix(files))[0] bc_integration.persist_repository(root_folder) bc_integration.persist_scan_results(scan_reports) bc_integration.commit_repository(args.branch) runner_registry.print_reports(scan_reports, args) else: print("No argument given. Try ` --help` for further information")
def run(banner=checkov_banner, argv=sys.argv[1:]): parser = argparse.ArgumentParser( description='Infrastructure as code static analysis') add_parser_args(parser) args = parser.parse_args(argv) # Disable runners with missing system dependencies args.skip_framework = runnerDependencyHandler.disable_incompatible_runners( args.skip_framework) runner_filter = RunnerFilter( framework=args.framework, skip_framework=args.skip_framework, checks=args.check, skip_checks=args.skip_check, download_external_modules=convert_str_to_bool( args.download_external_modules), external_modules_download_path=args.external_modules_download_path, evaluate_variables=convert_str_to_bool(args.evaluate_variables), runners=checkov_runners) if outer_registry: runner_registry = outer_registry runner_registry.runner_filter = runner_filter else: runner_registry = RunnerRegistry(banner, runner_filter, tf_runner(), cfn_runner(), k8_runner(), sls_runner(), arm_runner(), tf_plan_runner(), helm_runner()) if args.version: print(version) return if args.bc_api_key: if args.repo_id is None: parser.error( "--repo-id argument is required when using --bc-api-key") if len(args.repo_id.split('/')) != 2: parser.error( "--repo-id argument format should be 'organization/repository_name' E.g " "bridgecrewio/checkov") source = os.getenv('BC_SOURCE', 'cli') source_version = os.getenv('BC_SOURCE_VERSION', version) logger.debug(f'BC_SOURCE = {source}, version = {source_version}') try: bc_integration.setup_bridgecrew_credentials( bc_api_key=args.bc_api_key, repo_id=args.repo_id, skip_fixes=args.skip_fixes, skip_suppressions=args.skip_suppressions, source=source, source_version=source_version) except Exception as e: logger.error( 'An error occurred setting up the Bridgecrew platform integration. Please check your API token and try again.', exc_info=True) return guidelines = {} if not args.no_guide: guidelines = bc_integration.get_guidelines() if args.check and args.skip_check: parser.error( "--check and --skip-check can not be applied together. please use only one of them" ) return if args.list: print_checks(framework=args.framework) return external_checks_dir = get_external_checks_dir(args) url = None if args.directory: for root_folder in args.directory: file = args.file scan_reports = runner_registry.run( root_folder=root_folder, external_checks_dir=external_checks_dir, files=file, guidelines=guidelines, bc_integration=bc_integration) if bc_integration.is_integration_configured(): bc_integration.persist_repository(root_folder) bc_integration.persist_scan_results(scan_reports) url = bc_integration.commit_repository(args.branch) runner_registry.print_reports(scan_reports, args, url) return elif args.file: scan_reports = runner_registry.run( external_checks_dir=external_checks_dir, files=args.file, guidelines=guidelines, bc_integration=bc_integration) if bc_integration.is_integration_configured(): files = [os.path.abspath(file) for file in args.file] root_folder = os.path.split(os.path.commonprefix(files))[0] bc_integration.persist_repository(root_folder) bc_integration.persist_scan_results(scan_reports) url = bc_integration.commit_repository(args.branch) runner_registry.print_reports(scan_reports, args, url) else: print(f"{banner}") bc_integration.onboarding()
def run(banner=checkov_banner, argv=sys.argv[1:]): parser = argparse.ArgumentParser(description='Infrastructure as code static analysis') add_parser_args(parser) args = parser.parse_args(argv) # bridgecrew uses both the urllib3 and requests libraries, while checkov uses the requests library. # Allow the user to specify a CA bundle to be used by both libraries. bc_integration.setup_http_manager(args.ca_certificate) # Disable runners with missing system dependencies args.skip_framework = runnerDependencyHandler.disable_incompatible_runners(args.skip_framework) runner_filter = RunnerFilter(framework=args.framework, skip_framework=args.skip_framework, checks=args.check, skip_checks=args.skip_check, download_external_modules=convert_str_to_bool(args.download_external_modules), external_modules_download_path=args.external_modules_download_path, evaluate_variables=convert_str_to_bool(args.evaluate_variables), runners=checkov_runners) if outer_registry: runner_registry = outer_registry runner_registry.runner_filter = runner_filter else: runner_registry = RunnerRegistry(banner, runner_filter, tf_graph_runner(), cfn_runner(), k8_runner(), sls_runner(), arm_runner(), tf_plan_runner(), helm_runner(),dockerfile_runner()) if args.version: print(version) return if args.bc_api_key == '': parser.error('The --bc-api-key flag was specified but the value was blank. If this value was passed as a secret, you may need to double check the mapping.') elif args.bc_api_key: logger.debug(f'Using API key ending with {args.bc_api_key[-8:]}') if args.repo_id is None: parser.error("--repo-id argument is required when using --bc-api-key") if len(args.repo_id.split('/')) != 2: parser.error("--repo-id argument format should be 'organization/repository_name' E.g " "bridgecrewio/checkov") source = os.getenv('BC_SOURCE', 'cli') source_version = os.getenv('BC_SOURCE_VERSION', version) logger.debug(f'BC_SOURCE = {source}, version = {source_version}') try: bc_integration.setup_bridgecrew_credentials(bc_api_key=args.bc_api_key, repo_id=args.repo_id, skip_fixes=args.skip_fixes, skip_suppressions=args.skip_suppressions, source=source, source_version=source_version, repo_branch=args.branch) except Exception as e: logger.error('An error occurred setting up the Bridgecrew platform integration. Please check your API token and try again.', exc_info=True) return else: logger.debug('No API key found. Scanning locally only.') guidelines = {} if not args.no_guide: guidelines = bc_integration.get_guidelines() if args.check and args.skip_check: parser.error("--check and --skip-check can not be applied together. please use only one of them") return if args.list: print_checks(framework=args.framework) return external_checks_dir = get_external_checks_dir(args) url = None if args.directory: exit_codes = [] for root_folder in args.directory: file = args.file scan_reports = runner_registry.run(root_folder=root_folder, external_checks_dir=external_checks_dir, files=file, guidelines=guidelines, bc_integration=bc_integration) if bc_integration.is_integration_configured(): bc_integration.persist_repository(root_folder) bc_integration.persist_scan_results(scan_reports) url = bc_integration.commit_repository(args.branch) exit_codes.append(runner_registry.print_reports(scan_reports, args, url)) exit_code = 1 if 1 in exit_codes else 0 return exit_code elif args.file: scan_reports = runner_registry.run(external_checks_dir=external_checks_dir, files=args.file, guidelines=guidelines, bc_integration=bc_integration) if bc_integration.is_integration_configured(): files = [os.path.abspath(file) for file in args.file] root_folder = os.path.split(os.path.commonprefix(files))[0] bc_integration.persist_repository(root_folder) bc_integration.persist_scan_results(scan_reports) url = bc_integration.commit_repository(args.branch) return runner_registry.print_reports(scan_reports, args, url) elif args.docker_image: if args.bc_api_key is None: parser.error("--bc-api-key argument is required when using --docker-image") return if args.dockerfile_path is None: parser.error("--dockerfile-path argument is required when using --docker-image") return if args.branch is None: parser.error("--branch argument is required when using --docker-image") return image_scanner.scan(args.docker_image, args.dockerfile_path) else: print(f"{banner}") bc_integration.onboarding()