Exemple #1
0
def run(banner=checkov_banner):
    parser = argparse.ArgumentParser(description='Infrastructure as code static analysis')
    add_parser_args(parser)
    args = parser.parse_args()
    runner_filter = RunnerFilter(framework=args.framework, checks=args.check, skip_checks=args.skip_check)
    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 test_enrichment_of_plan_report_with_modules(self):
        allowed_checks = ["CKV_AWS_66", "CKV_AWS_158"]
        runner_registry = RunnerRegistry(
            banner,
            RunnerFilter(checks=allowed_checks, framework="terraform_plan"),
            tf_plan_runner())

        repo_root = Path(
            __file__).parent / "plan_with_tf_modules_for_enrichment"
        valid_plan_path = repo_root / "tfplan.json"

        report = runner_registry.run(repo_root_for_plan_enrichment=repo_root,
                                     files=[valid_plan_path])[0]

        failed_check_ids = [c.check_id for c in report.failed_checks]
        passed_check_ids = [c.check_id for c in report.passed_checks]
        skipped_check_ids = [c.check_id for c in report.skipped_checks]
        expected_failed_check_ids = ["CKV_AWS_158", "CKV_AWS_158"]
        expected_passed_check_ids = ["CKV_AWS_66", "CKV_AWS_66"]
        expected_skipped_check_ids = []

        enriched_data = set([(c.file_path, tuple(c.file_line_range),
                              tuple(c.code_block))
                             for c in report.failed_checks])
        expected_enriched_data = {
            (
                f"/{Path.relative_to(valid_plan_path, Path.cwd())}",
                (16, 16),
                (),
            ),
            (
                "log_group/main.tf",
                (1, 2),
                (
                    (1,
                     'resource "aws_cloudwatch_log_group" "not_encrypted" {\n'
                     ),
                    (2, "}\n"),
                ),
            ),
        }

        self.assertEqual(len(failed_check_ids), 2)
        self.assertEqual(failed_check_ids, expected_failed_check_ids)
        self.assertEqual(len(passed_check_ids), 2)
        self.assertEqual(passed_check_ids, expected_passed_check_ids)
        self.assertEqual(len(skipped_check_ids), 0)
        self.assertEqual(skipped_check_ids, expected_skipped_check_ids)
        self.assertEqual(enriched_data, expected_enriched_data)
    def test_valid_cyclonedx_bom(self):
        runners = (
            tf_graph_runner(),
            tf_plan_runner(),
        )
        registry = RunnerRegistry("", RunnerFilter(), *runners)
        scan_reports = registry.run(
            files=[join(dirname(__file__), 'fixtures/main.tf')])

        self.assertEqual(len(scan_reports), 2)
        r = scan_reports[0]

        cyclonedx_bom = r.get_cyclonedx_bom()
        # outputter = get_instance(bom=cyclonedx_bom)
        # outputter.output_to_file(filename='/tmp/test.xml', allow_overwrite=True)
        self.assertEqual(len(cyclonedx_bom.get_components()), 1)
        first_component = cyclonedx_bom.get_components()[0]
        self.assertEqual(len(first_component.get_vulnerabilities()), 5)
    def test_skip_check(self):
        allowed_checks = ["CKV_AWS_20", "CKV_AWS_28"]
        runner_registry = RunnerRegistry(
            banner,
            RunnerFilter(checks=allowed_checks, framework="terraform_plan"),
            tf_plan_runner())

        repo_root = Path(__file__).parent / "plan_with_hcl_for_enrichment"
        valid_plan_path = repo_root / "tfplan.json"

        report = runner_registry.run(repo_root_for_plan_enrichment=[repo_root],
                                     files=[valid_plan_path])[0]

        failed_check_ids = {c.check_id for c in report.failed_checks}
        skipped_check_ids = {c.check_id for c in report.skipped_checks}
        expected_skipped_check_ids = {"CKV_AWS_20", "CKV_AWS_28"}

        self.assertEqual(len(failed_check_ids), 0)
        self.assertEqual(len(skipped_check_ids), 2)
        self.assertEqual(skipped_check_ids, expected_skipped_check_ids)
Exemple #5
0
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.
    bc_integration.setup_http_manager(config.ca_certificate)
Exemple #6
0
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 test_enrichment_of_plan_report(self):
        allowed_checks = [
            "CKV_AWS_19", "CKV_AWS_20", "CKV_AWS_28", "CKV_AWS_63",
            "CKV_AWS_119"
        ]
        runner_registry = RunnerRegistry(
            banner,
            RunnerFilter(checks=allowed_checks, framework="terraform_plan"),
            tf_plan_runner())

        repo_root = Path(__file__).parent / "plan_with_hcl_for_enrichment"
        valid_plan_path = repo_root / "tfplan.json"

        report = runner_registry.run(repo_root_for_plan_enrichment=repo_root,
                                     files=[valid_plan_path])[0]

        failed_check_ids = {c.check_id for c in report.failed_checks}
        skipped_check_ids = {c.check_id for c in report.skipped_checks}
        expected_failed_check_ids = {"CKV_AWS_19", "CKV_AWS_63", "CKV_AWS_119"}
        expected_skipped_check_ids = {"CKV_AWS_20", "CKV_AWS_28"}

        enriched_data = {(c.file_path, tuple(c.file_line_range),
                          tuple(c.code_block))
                         for c in report.failed_checks}
        expected_enriched_data = {
            (
                "iam.tf",
                (1, 19),
                (
                    (1, 'resource "aws_iam_policy" "policy" {\n'),
                    (2, '  name        = "my_policy-123456789101"\n'),
                    (3, '  path        = "/"\n'),
                    (4, '  description = "My test policy"\n'),
                    (5, "  policy = <<EOF\n"),
                    (6, "{\n"),
                    (7, '  "Version": "2012-10-17",\n'),
                    (8, '  "Statement": [\n'),
                    (9, "    {\n"),
                    (10, '      "Action": [\n'),
                    (11, '        "*"\n'),
                    (12, "      ],\n"),
                    (13, '      "Effect": "Allow",\n'),
                    (14,
                     '      "Resource": "arn:aws:iam::${var.aws_account_id}:role/admin"\n'
                     ),
                    (15, "    }\n"),
                    (16, "  ]\n"),
                    (17, "}\n"),
                    (18, "EOF\n"),
                    (19, "}"),
                ),
            ),
            (
                "s3.tf",
                (1, 17),
                (
                    (1, 'resource "aws_s3_bucket" "test-bucket1" {\n'),
                    (2, '  bucket = "test-bucket1"\n'),
                    (3,
                     "  # checkov:skip=CKV_AWS_20: The bucket is a public static content "
                     "host\n"),
                    (4, '  acl    = "public-read"\n'),
                    (5, "  lifecycle_rule {\n"),
                    (6, '    id      = "90 Day Lifecycle"\n'),
                    (7, "    enabled = true\n"),
                    (8, "    expiration {\n"),
                    (9, "      days = 90\n"),
                    (10, "    }\n"),
                    (11, "    noncurrent_version_expiration {\n"),
                    (12, "      days = 90\n"),
                    (13, "    }\n"),
                    (14, "    abort_incomplete_multipart_upload_days = 90\n"),
                    (15, "  }\n"),
                    (16, "  provider = aws.current_region\n"),
                    (17, "}"),
                ),
            ),
            (
                "dynamodb.tf",
                (1, 12),
                (
                    (1,
                     'resource "aws_dynamodb_table" "cross-environment-violations" {\n'
                     ),
                    (2,
                     "  # checkov:skip=CKV_AWS_28: ignoring backups for now\n"
                     ),
                    (3, '  name           = "CrossEnvironmentViolations"\n'),
                    (4, "  read_capacity  = 20\n"),
                    (5, "  write_capacity = 20\n"),
                    (6, '  hash_key       = "id"\n'),
                    (7, "  attribute {\n"),
                    (8, '    name = "id"\n'),
                    (9, '    type = "S"\n'),
                    (10, "  }\n"),
                    (11, "  provider = aws.current_region\n"),
                    (12, "}"),
                ),
            ),
        }

        self.assertEqual(len(failed_check_ids), 3)
        self.assertEqual(failed_check_ids, expected_failed_check_ids)
        self.assertEqual(len(skipped_check_ids), 2)
        self.assertEqual(skipped_check_ids, expected_skipped_check_ids)
        self.assertEqual(enriched_data, expected_enriched_data)
Exemple #8
0
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()