Esempio n. 1
0
def default_allow_all_config():
    return Config(
        rules=DEFAULT_RULES,
        aws_account_id="123456789012",
        stack_name="mockstack",
        rules_filters=[
            Filter(
                rule_mode=RuleMode.ALLOWED,
                eval={
                    "and": [
                        {
                            "exists": {
                                "ref": "config.stack_name"
                            }
                        },
                        {
                            "eq": [{
                                "ref": "config.stack_name"
                            }, "mockstack"]
                        },
                    ]
                },
                rules=set(DEFAULT_RULES.keys()),
            ),
        ],
    )
Esempio n. 2
0
    def test_stack_whitelist_joins_all_whitelisted_matching_stack_names(self):
        mock_whitelist = {
            "stackname": [
                "S3CrossAccountTrustRule",
            ],
            "notstackname": [
                "IAMRolesOverprivilegedRule",
            ],
            "stackname_withmorethings": [
                "CrossAccountTrustRule",
                "ManagedPolicyOnUserRule",
            ]

        }

        config = Config(
            project_name="project_mock",
            service_name="service_mock",
            stack_name="stackname_withmorethings",
            stack_whitelist=mock_whitelist,
            rules=DEFAULT_RULES.keys(),
        )

        whitelisted_rules = config.get_whitelisted_rules()

        assert set(whitelisted_rules) == {
            "CrossAccountTrustRule",
            "ManagedPolicyOnUserRule",
            "S3CrossAccountTrustRule",
        }
Esempio n. 3
0
def test_with_templates(cf_path):
    with open(cf_path) as cf_script:
        cf_template = convert_json_or_yaml_to_dict(cf_script.read())

    config = Config(project_name=cf_path,
                    service_name=cf_path,
                    stack_name=cf_path,
                    rules=DEFAULT_RULES.keys())

    # Scan result

    cfmodel = pycfmodel.parse(cf_template).resolve()

    rules = [DEFAULT_RULES.get(rule)(config) for rule in config.rules]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(cfmodel, config)

    # Use this to print the stack if there is an IAMManagedPolicyWildcardActionRule an error
    if len(result.exceptions):
        print(cf_path)
        traceback.print_tb(result.exceptions[0].__traceback__)

    assert len(result.exceptions) == 0
Esempio n. 4
0
def handler(event, context):
    """
    Main entry point of the Lambda function.

    :param event: {
        "stack_template_url": String,
        "project": String,
        "stack": {
            "name": String,
        },
        "event": String,
        "region": String,
        "account": {
            "name": String,
            "id": String,
        },
        "user_agent": String,
    }
    :param context:
    :return:
    """

    setup_logging()
    if not event.get("stack_template_url") and not event.get("stack",
                                                             {}).get("name"):
        raise ValueError(
            "Invalid event type: no parameter 'stack_template_url' or 'stack::name' in request."
        )

    result = Result()
    template = get_template(event)

    if not template:
        # In case of an invalid script log a warning and return early
        result.add_exception(
            TypeError(
                f"Malformed Event - could not parse!! Event: {str(event)}"))
        logger.exception(
            f"Malformed Event - could not parse!! Event: {str(event)}")
        return {
            "valid": True,
            "reason": "",
            "failed_rules": [],
            "exceptions": [x.args[0] for x in result.exceptions]
        }

    # Process Rules
    config = Config(
        project_name=event.get("project"),
        service_name=event.get("serviceName"),
        stack_name=event.get("stack", {}).get("name"),
        rules=DEFAULT_RULES.keys(),
        event=event.get("event"),
        template_url=event.get("stack_template_url", "N/A"),
        aws_region=event.get("region", "N/A"),
        aws_account_name=event.get("account", {}).get("name", "N/A"),
        aws_account_id=event.get("account", {}).get("id", "N/A"),
        aws_user_agent=event.get("user_agent", "N/A"),
    )

    logger.info("Scan started for: {}; {}; {};".format(config.project_name,
                                                       config.service_name,
                                                       config.stack_name))

    rules = [DEFAULT_RULES.get(rule)(config, result) for rule in config.rules]
    processor = RuleProcessor(*rules)

    processor.process_cf_template(template, config, result)

    perform_logging(result, config, event)

    return {
        "valid":
        result.valid,
        "reason":
        ",".join([
            "{}-{}".format(r["rule"], r["reason"]) for r in result.failed_rules
        ]),
        "failed_rules":
        RuleProcessor.remove_debug_rules(rules=result.failed_rules),
        "exceptions": [x.args[0] for x in result.exceptions],
        "warnings":
        RuleProcessor.remove_debug_rules(rules=result.failed_monitored_rules),
    }
Esempio n. 5
0
def init_cfripper() -> Tuple[Config, RuleProcessor]:
    config = Config(rules=DEFAULT_RULES.keys())
    rule_processor = RuleProcessor(
        *[DEFAULT_RULES.get(rule)(config) for rule in config.rules])
    return config, rule_processor
Esempio n. 6
0
    def test_with_templates(self):
        dir_path = os.path.dirname(os.path.realpath(__file__))

        test_templates = glob.glob(f"{dir_path}/test_templates/*.*")
        for template in test_templates:
            with open(template) as cf_script:
                cf_template = convert_json_or_yaml_to_dict(cf_script.read())

            config = Config(
                project_name=template, service_name=template, stack_name=template, rules=DEFAULT_RULES.keys()
            )

            # Scan result
            result = Result()

            rules = [DEFAULT_RULES.get(rule)(config, result) for rule in config.rules]
            processor = RuleProcessor(*rules)
            processor.process_cf_template(cf_template, config, result)

            # Use this to print the stack if there's an error
            if len(result.exceptions):
                print(template)
                traceback.print_tb(result.exceptions[0].__traceback__)

            no_resource_templates = ["vulgar_bad_syntax.yml", "rubbish.json"]

            if template.split("/")[-1] in no_resource_templates:
                assert len(result.exceptions) == 1
            else:
                assert len(result.exceptions) == 0