예제 #1
0
 def __init__(self, banner, runner_filter, *runners):
     self.logger = logging.getLogger(__name__)
     self.runner_filter = runner_filter
     self.runners = runners
     self.banner = banner
     self.scan_reports = []
     self.filter_runner_framework()
     self.bc_platform = BcPlatformIntegration()
예제 #2
0
 def test_overriding_pc_api_url(self):
     instance = BcPlatformIntegration()
     instance.setup_bridgecrew_credentials(
         repo_id="bridgecrewio/checkov",
         prisma_api_url="https://api0.prismacloud.io",
         source=get_source_type('disabled'))
     self.assertEqual(instance.api_url,
                      "https://api0.prismacloud.io/bridgecrew")
     self.assertEqual(instance.prisma_api_url,
                      "https://api0.prismacloud.io")
    def test_pre_scan_with_cloned_checks(self):
        instance = BcPlatformIntegration()
        instance.skip_policy_download = False
        instance.platform_integration_configured = True
        custom_policies_integration = CustomPoliciesIntegration(instance)

        # mock _get_policies_from_platform method
        custom_policies_integration._get_policies_from_platform = types.MethodType(_get_policies_from_platform,
                                                                                   custom_policies_integration)

        custom_policies_integration.pre_scan()
        self.assertEqual(1, len(custom_policies_integration.policies))
        self.assertEqual(1, len(custom_policies_integration.bc_cloned_checks))
예제 #4
0
def mock_bc_integration() -> BcPlatformIntegration:
    bc_integration = BcPlatformIntegration()
    bc_integration.bc_api_key = "abcd1234-abcd-1234-abcd-1234abcd1234"
    bc_integration.setup_bridgecrew_credentials(
        repo_id="bridgecrewio/checkov",
        skip_fixes=True,
        skip_suppressions=True,
        skip_policy_download=True,
        source=SourceType("Github", False),
        source_version="1.0",
        repo_branch="master",
    )
    return bc_integration
    def test_repo_match(self):
        integration = BcPlatformIntegration()
        integration.repo_id = 'org/repo'
        suppressions_integration = SuppressionsIntegration(integration)
        suppressions_integration._init_repo_regex()

        self.assertTrue(suppressions_integration._repo_matches('org/repo'))
        self.assertTrue(suppressions_integration._repo_matches('xyz_org/repo'))
        self.assertTrue(
            suppressions_integration._repo_matches('80001234_org/repo'))
        self.assertFalse(suppressions_integration._repo_matches('org/repo1'))
        self.assertFalse(
            suppressions_integration._repo_matches('xyz_org/repo1'))
        self.assertFalse(
            suppressions_integration._repo_matches('80001234_org/repo1'))
    def test_policy_suppression(self):
        instance = BcPlatformIntegration()

        suppressions_integration = SuppressionsIntegration(instance)

        suppression = {
            "suppressionType": "Policy",
            "id": "7caab873-7400-47f9-8b3f-82b33d0463ed",
            "policyId": "BC_AWS_GENERAL_31",
            "comment": "No justification comment provided.",
            "checkovPolicyId": "CKV_AWS_79",
        }

        record1 = Record(check_id='CKV_AWS_79', check_name=None, check_result=None,
                         code_block=None, file_path=None,
                         file_line_range=None,
                         resource=None, evaluations=None,
                         check_class=None, file_abs_path='.', entity_tags=None)
        record2 = Record(check_id='CKV_AWS_1', check_name=None, check_result=None,
                         code_block=None, file_path=None,
                         file_line_range=None,
                         resource=None, evaluations=None,
                         check_class=None, file_abs_path='.', entity_tags=None)

        self.assertTrue(suppressions_integration._check_suppression(record1, suppression))
        self.assertFalse(suppressions_integration._check_suppression(record2, suppression))
예제 #7
0
    def test_policy_id_regex(self):
        suppressions_integration = SuppressionsIntegration(
            BcPlatformIntegration())

        matching_ids = [
            'bcorg_aws_1234567891011', 'bcORrg_aws_1234567891011',
            'bcORrg_AWS_1234567891011', 'bcorg12_aws_1234567891011',
            'bcorgabcdefgh_azure_1234567891011'
        ]

        non_matching_ids = [
            'bcorg_aws_123456789101',
            'bcorg_aws123_1234567891011',
            'bcorg_1234567891011',
            'bcorgabcdefghazure_1234567891011',
            '_bcorg_aws_1234567891011',
        ]

        for id in matching_ids:
            self.assertIsNotNone(
                suppressions_integration.custom_policy_id_regex.match(id))

        for id in non_matching_ids:
            self.assertIsNone(
                suppressions_integration.custom_policy_id_regex.match(id))
    def test_account_suppression_cli_repo(self):
        instance = BcPlatformIntegration()
        instance.repo_id = 'org/repo'
        suppressions_integration = SuppressionsIntegration(instance)
        suppressions_integration._init_repo_regex()
        suppression = {
            "suppressionType": "Accounts",
            "policyId": "BC_AWS_S3_13",
            "comment": "testing checkov",
            "accountIds": ["bcorg_org/repo", "bcorg_not/valid"],
            "checkovPolicyId": "CKV_AWS_18",
        }

        record1 = Record(check_id='CKV_AWS_18',
                         check_name=None,
                         check_result=None,
                         code_block=None,
                         file_path=None,
                         file_line_range=None,
                         resource=None,
                         evaluations=None,
                         check_class=None,
                         file_abs_path='.',
                         entity_tags=None)
        record2 = Record(check_id='CKV_AWS_1',
                         check_name=None,
                         check_result=None,
                         code_block=None,
                         file_path=None,
                         file_line_range=None,
                         resource=None,
                         evaluations=None,
                         check_class=None,
                         file_abs_path='.',
                         entity_tags=None)

        self.assertTrue(
            suppressions_integration._check_suppression(record1, suppression))
        self.assertFalse(
            suppressions_integration._check_suppression(record2, suppression))
    def test_resource_suppression(self):
        instance = BcPlatformIntegration()
        instance.repo_id = 'org/repo'
        suppressions_integration = SuppressionsIntegration(instance)
        suppression = {
            "suppressionType": "Resources",
            "policyId": "BC_AWS_S3_13",
            "comment": "No justification comment provided.",
            "resources": [
                {
                    "accountId": "org/repo",
                    "resourceId": "/terraform/aws/s3.tf:aws_s3_bucket.operations",
                }
            ],
            "checkovPolicyId": "CKV_AWS_18",
        }

        record1 = Record(check_id='CKV_AWS_18', check_name=None, check_result=None,
                         code_block=None, file_path=None,
                         file_line_range=None,
                         resource='aws_s3_bucket.operations', evaluations=None,
                         check_class=None, file_abs_path=',.', entity_tags=None)
        record1.repo_file_path = '/terraform/aws/s3.tf'
        record2 = Record(check_id='CKV_AWS_13', check_name=None, check_result=None,
                         code_block=None, file_path=None,
                         file_line_range=None,
                         resource='aws_s3_bucket.no', evaluations=None,
                         check_class=None, file_abs_path='.', entity_tags=None)
        record2.repo_file_path = '/terraform/aws/s3.tf'
        record3 = Record(check_id='CKV_AWS_1', check_name=None, check_result=None,
                         code_block=None, file_path=None,
                         file_line_range=None,
                         resource='aws_s3_bucket.operations', evaluations=None,
                         check_class=None, file_abs_path='.', entity_tags=None)
        record3.repo_file_path = '/terraform/aws/s3.tf'

        self.assertTrue(suppressions_integration._check_suppression(record1, suppression))
        self.assertFalse(suppressions_integration._check_suppression(record2, suppression))
        self.assertFalse(suppressions_integration._check_suppression(record3, suppression))
예제 #10
0
    def test_guidelines_received(self):
        guideline1 = 'https://some.guideline.com/111'
        guideline2 = 'https://another.guideline.com/AWS/asdasd'

        def request_callback(_):
            resp_body = {'guidelines': {'CKV_AWS_1': guideline1, 'CKV_AWS_2': guideline2}}
            headers = {'Content-Type': 'application/json'}
            return 200, headers, json.dumps(resp_body)

        responses.add_callback('GET', '/guidelines',
                               callback=request_callback,
                               content_type='application/json')
        guidelines = BcPlatformIntegration().get_guidelines()
        self.assertTrue(isinstance(guidelines, dict))
        self.assertEqual(len(guidelines), 2)
        self.assertEqual(guidelines['CKV_AWS_1'], guideline1)
        self.assertEqual(guidelines['CKV_AWS_2'], guideline2)
예제 #11
0
    def test_integration_valid(self):
        instance = BcPlatformIntegration()
        instance.skip_suppressions = False
        instance.platform_integration_configured = True

        suppressions_integration = SuppressionsIntegration(instance)

        self.assertTrue(suppressions_integration.is_valid())

        instance.skip_suppressions = True
        self.assertFalse(suppressions_integration.is_valid())

        instance.platform_integration_configured = False
        self.assertFalse(suppressions_integration.is_valid())

        instance.skip_suppressions = False
        self.assertFalse(suppressions_integration.is_valid())
    def test_integration_valid(self):
        instance = BcPlatformIntegration()
        instance.skip_policy_download = False
        instance.platform_integration_configured = True

        custom_policies_integration = CustomPoliciesIntegration(instance)

        self.assertTrue(custom_policies_integration.is_valid())

        instance.skip_policy_download = True
        self.assertFalse(custom_policies_integration.is_valid())

        instance.platform_integration_configured = False
        self.assertFalse(custom_policies_integration.is_valid())

        instance.skip_policy_download = False
        self.assertFalse(custom_policies_integration.is_valid())
예제 #13
0
    def test_integration_valid(self):
        instance = BcPlatformIntegration()
        instance.skip_fixes = False
        instance.platform_integration_configured = True

        fixes_integration = FixesIntegration(instance)

        self.assertTrue(fixes_integration.is_valid())

        instance.skip_fixes = True
        self.assertFalse(fixes_integration.is_valid())

        instance.platform_integration_configured = False
        self.assertFalse(fixes_integration.is_valid())

        instance.skip_fixes = False
        self.assertFalse(fixes_integration.is_valid())
예제 #14
0
 def test_overriding_bc_source(self):
     instance = BcPlatformIntegration()
     self.assertEqual(instance.bc_source, "foo")
예제 #15
0
 def test_overriding_bc_api_url(self):
     instance = BcPlatformIntegration()
     self.assertEqual(instance.bc_api_url, "foo")
예제 #16
0
def run(banner=checkov_banner):
    parser = argparse.ArgumentParser(
        description='Infrastructure as code static analysis')
    add_parser_args(parser)
    args = parser.parse_args()
    bc_integration = BcPlatformIntegration()
    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())
    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("No argument given. Try ` --help` for further information")
예제 #17
0
 def test_real_guidelines(self):
     guidelines = BcPlatformIntegration().get_guidelines()
     self.assertGreater(len(guidelines.keys()), 0)
예제 #18
0
 def test_guidelines_not_received(self):
     guidelines = BcPlatformIntegration().get_guidelines()
     self.assertEqual(guidelines, {})
예제 #19
0
 def test_no_overriding_api_url(self):
     instance = BcPlatformIntegration()
     self.assertEqual(instance.api_url, "https://www.bridgecrew.cloud")
예제 #20
0
    def test_suppression_valid(self):
        instance = BcPlatformIntegration()
        instance.repo_id = 'org/repo'
        instance.bc_id_mapping = {'BC_AWS_1': 'CKV_AWS_20'}

        suppressions_integration = SuppressionsIntegration(instance)

        suppression = {
            "suppressionType": "Accounts",
            "policyId": "BC_AWS_1",
            "creationDate": 1608816140086,
            "comment": "No justification comment provided.",
            "accountIds": ["org/repo"]
        }

        self.assertTrue(
            suppressions_integration._suppression_valid_for_run(suppression))

        suppression = {
            "suppressionType": "Resources",
            "policyId": "BC_AWS_1",
            "creationDate": 1608816140086,
            "comment": "No justification comment provided.",
            "resources": {
                "accountId": "org/repo",
                "resourceId": "/s3.tf"
            }
        }

        self.assertTrue(
            suppressions_integration._suppression_valid_for_run(suppression))

        suppression = {
            "suppressionType": "Tags",
            "policyId": "BC_AWS_1",
            "creationDate": 1610035761349,
            "comment": "No justification comment provided.",
            "tags": [{
                "value": "test_1",
                "key": "test_num"
            }]
        }

        self.assertTrue(
            suppressions_integration._suppression_valid_for_run(suppression))

        suppression = {
            "suppressionType": "Policy",
            "policyId": "BC_AWS_1",
            "creationDate": 1602670330384,
            "comment": "No justification comment provided."
        }

        self.assertTrue(
            suppressions_integration._suppression_valid_for_run(suppression))

        suppression = {
            "suppressionType": "Accounts",
            "policyId": "BC_AWS_1",
            "creationDate": 1608816140086,
            "comment": "No justification comment provided.",
            "accountIds": ["other/repo"]
        }

        self.assertFalse(
            suppressions_integration._suppression_valid_for_run(suppression))

        suppression = {
            "suppressionType": "Tags",
            "policyId": "NOT_A_POLICY",
            "creationDate": 1610035761349,
            "comment": "No justification comment provided.",
            "tags": [{
                "value": "test_1",
                "key": "test_num"
            }]
        }

        self.assertFalse(
            suppressions_integration._suppression_valid_for_run(suppression))

        # custom policy
        suppression = {
            "suppressionType": "Tags",
            "policyId": "bcorg_aws_1234567891011",
            "creationDate": 1610035761349,
            "comment": "No justification comment provided.",
            "tags": [{
                "value": "test_1",
                "key": "test_num"
            }]
        }

        self.assertTrue(
            suppressions_integration._suppression_valid_for_run(suppression))
예제 #21
0
    def test_tag_suppression(self):
        instance = BcPlatformIntegration()
        suppressions_integration = SuppressionsIntegration(instance)
        suppression = {
            "suppressionType":
            "Tags",
            "policyId":
            "BC_AWS_S3_16",
            "comment":
            "No justification comment provided.",
            "tags": [{
                "value": "value1",
                "key": "tag1"
            }, {
                "value": "value2",
                "key": "tag2"
            }],
            "checkovPolicyId":
            "CKV_AWS_21",
        }

        record1 = Record(check_id='CKV_AWS_21',
                         check_name=None,
                         check_result=None,
                         code_block=None,
                         file_path=None,
                         file_line_range=None,
                         resource='aws_s3_bucket.operations',
                         evaluations=None,
                         check_class=None,
                         file_abs_path=',.',
                         entity_tags={'tag1': 'value1'})
        record2 = Record(check_id='CKV_AWS_1',
                         check_name=None,
                         check_result=None,
                         code_block=None,
                         file_path=None,
                         file_line_range=None,
                         resource='aws_s3_bucket.no',
                         evaluations=None,
                         check_class=None,
                         file_abs_path='.',
                         entity_tags={'tag1': 'value1'})
        record3 = Record(check_id='CKV_AWS_21',
                         check_name=None,
                         check_result=None,
                         code_block=None,
                         file_path=None,
                         file_line_range=None,
                         resource='aws_s3_bucket.operations',
                         evaluations=None,
                         check_class=None,
                         file_abs_path='.',
                         entity_tags={
                             'tag1': 'value2222',
                             'tag2': 'value2'
                         })
        record4 = Record(check_id='CKV_AWS_21',
                         check_name=None,
                         check_result=None,
                         code_block=None,
                         file_path=None,
                         file_line_range=None,
                         resource='aws_s3_bucket.operations',
                         evaluations=None,
                         check_class=None,
                         file_abs_path='.',
                         entity_tags={
                             'tag1': 'value2222',
                             'tag2': 'value1111'
                         })
        record5 = Record(check_id='CKV_AWS_21',
                         check_name=None,
                         check_result=None,
                         code_block=None,
                         file_path=None,
                         file_line_range=None,
                         resource='aws_s3_bucket.operations',
                         evaluations=None,
                         check_class=None,
                         file_abs_path='.',
                         entity_tags=None)

        self.assertTrue(
            suppressions_integration._check_suppression(record1, suppression))
        self.assertFalse(
            suppressions_integration._check_suppression(record2, suppression))
        self.assertTrue(
            suppressions_integration._check_suppression(record3, suppression))
        self.assertFalse(
            suppressions_integration._check_suppression(record4, suppression))
        self.assertFalse(
            suppressions_integration._check_suppression(record5, suppression))
예제 #22
0
 def test_overriding_pc_api_url(self):
     instance = BcPlatformIntegration()
     self.assertEqual(instance.api_url, "prisma/bridgecrew")
     self.assertEqual(instance.prisma_url, "prisma")
예제 #23
0
 def test_default_bc_source(self):
     instance = BcPlatformIntegration()
     self.assertEqual(instance.bc_source, "cli")
예제 #24
0
파일: main.py 프로젝트: honza1a/checkov
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")
예제 #25
0
    def test_skip_mapping_false(self):
        instance = BcPlatformIntegration()
        instance.get_id_mapping()

        self.assertNotEquals(None, instance.ckv_to_bc_id_mapping)
예제 #26
0
 def test_skip_mapping(self):
     instance = BcPlatformIntegration()
     instance.setup_http_manager()
     instance.get_id_mapping()
     self.assertEqual(None,instance.ckv_to_bc_id_mapping)
예제 #27
0
 def test_skip_mapping_true(self):
     instance = BcPlatformIntegration()
     instance.bc_skip_mapping = True
     instance.setup_http_manager()
     instance.get_id_mapping()
     self.assertDictEqual({}, instance.ckv_to_bc_id_mapping)
예제 #28
0
 def test_skip_mapping_default(self):
     # Default is False so mapping is obtained
     instance = BcPlatformIntegration()
     instance.setup_http_manager()
     instance.get_id_mapping()
     self.assertIsNotNone(instance.ckv_to_bc_id_mapping)
예제 #29
0
 def test_skip_mapping_false(self):
     instance = BcPlatformIntegration()
     instance.setup_http_manager()
     instance.get_id_mapping()
     self.assertIsNotNone(instance.ckv_to_bc_id_mapping)
예제 #30
0
class RunnerRegistry(object):
    runners = []
    scan_reports = []
    banner = ""

    def __init__(self, banner, runner_filter, *runners):
        self.logger = logging.getLogger(__name__)
        self.runner_filter = runner_filter
        self.runners = runners
        self.banner = banner
        self.scan_reports = []
        self.filter_runner_framework()
        self.bc_platform = BcPlatformIntegration()

    @abstractmethod
    def extract_entity_details(self, entity):
        raise NotImplementedError()

    def run(self,
            root_folder=None,
            external_checks_dir=None,
            files=None,
            guidelines=None,
            collect_skip_comments=True,
            bc_integration=None):
        for runner in self.runners:
            integration_feature_registry.run_pre_scan()
            scan_report = runner.run(
                root_folder,
                external_checks_dir=external_checks_dir,
                files=files,
                runner_filter=self.runner_filter,
                collect_skip_comments=collect_skip_comments)
            integration_feature_registry.run_post_scan(scan_report)
            if guidelines:
                RunnerRegistry.enrich_report_with_guidelines(
                    scan_report, guidelines)
            self.scan_reports.append(scan_report)
        return self.scan_reports

    def print_reports(self, scan_reports, args, url=None):
        if args.output == 'cli':
            print(f"{self.banner}\n")
        exit_codes = []
        report_jsons = []
        junit_reports = []
        for report in scan_reports:
            if not report.is_empty():
                if args.output == "json":
                    report_jsons.append(report.get_dict(is_quiet=args.quiet))
                elif args.output == "junitxml":
                    junit_reports.append(report)
                    # report.print_junit_xml()
                elif args.output == 'github_failed_only':
                    report.print_failed_github_md()
                else:
                    report.print_console(is_quiet=args.quiet,
                                         is_compact=args.compact)
                    if url:
                        print("More details: {}".format(url))
            exit_codes.append(report.get_exit_code(args.soft_fail))
        if args.output == "junitxml":
            if len(junit_reports) == 1:
                junit_reports[0].print_junit_xml()
            else:
                master_report = Report(None)
                for report in junit_reports:
                    master_report.skipped_checks += report.skipped_checks
                    master_report.passed_checks += report.passed_checks
                    master_report.failed_checks += report.failed_checks
                master_report.print_junit_xml()
        if args.output == "json":
            if len(report_jsons) == 1:
                print(json.dumps(report_jsons[0], indent=4))
            else:
                print(json.dumps(report_jsons, indent=4))
        if args.output == "cli":
            self.bc_platform.get_report_to_platform(args, scan_reports)

        exit_code = 1 if 1 in exit_codes else 0
        exit(exit_code)

    def filter_runner_framework(self):
        if not self.runner_filter:
            return
        if self.runner_filter.framework is None:
            return
        if self.runner_filter.framework == 'all':
            return
        filtered_runners = []
        for runner in self.runners:
            if runner.check_type in self.runner_filter.framework:
                filtered_runners.append(runner)
        self.runners = filtered_runners
        return

    @staticmethod
    def enrich_report_with_guidelines(scan_report, guidelines):
        for record in scan_report.failed_checks + scan_report.passed_checks + scan_report.skipped_checks:
            if record.check_id in guidelines:
                record.set_guideline(guidelines[record.check_id])