示例#1
0
def test_non_matching_filters_are_reported_normally(
        invalid_security_group_range):
    mock_config = Config(
        rules=["EC2SecurityGroupOpenToWorldRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_config={
            "EC2SecurityGroupOpenToWorldRule":
            RuleConfig(filters=[
                Filter(rule_mode=RuleMode.WHITELISTED,
                       eval={
                           "eq": [{
                               "ref": "config.stack_name"
                           }, "anotherstack"]
                       })
            ], )
        },
    )
    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(invalid_security_group_range,
                                           mock_config)

    assert not result.valid
    assert result.failed_rules[0].rule == "EC2SecurityGroupOpenToWorldRule"
    assert (
        result.failed_rules[0].reason ==
        "Port(s) 0-79, 81-100 open to public IPs: (11.0.0.0/8) in security group 'SecurityGroup'"
    )
示例#2
0
def test_filter_do_not_report_anything(invalid_security_group_range):
    mock_config = Config(
        rules=["EC2SecurityGroupOpenToWorldRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_filters=[
            Filter(
                rule_mode=RuleMode.ALLOWED,
                eval={
                    "and": [
                        {
                            "eq": [{
                                "ref": "config.stack_name"
                            }, "mockstack"]
                        },
                        {
                            "eq": [{
                                "ref": "open_ports"
                            }, list(range(0, 101))]
                        },
                    ]
                },
                rules={"EC2SecurityGroupOpenToWorldRule"},
            )
        ],
    )
    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(invalid_security_group_range,
                                           mock_config)

    assert result.valid
    assert compare_lists_of_failures(result.failures, [])
def test_filter_works_as_expected(template_two_roles_dict, expected_result_two_roles):
    config = Config(
        rules=["CrossAccountTrustRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_config={
            "CrossAccountTrustRule": RuleConfig(
                filters=[
                    Filter(
                        rule_mode=RuleMode.WHITELISTED,
                        eval={
                            "and": [
                                {"eq": [{"ref": "config.stack_name"}, "mockstack"]},
                                {"eq": [{"ref": "logical_id"}, "RootRoleOne"]},
                            ]
                        },
                    )
                ],
            )
        },
    )
    rules = [DEFAULT_RULES.get(rule)(config) for rule in config.rules]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(template_two_roles_dict, config)

    assert not result.valid
    assert result.failed_rules[0] == expected_result_two_roles[-1]
def test_non_matching_filters_are_reported_normally(
        single_security_group_one_cidr_ingress):
    mock_config = Config(
        rules=["EC2SecurityGroupMissingEgressRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_config={
            "EC2SecurityGroupMissingEgressRule":
            RuleConfig(filters=[
                Filter(rule_mode=RuleMode.WHITELISTED,
                       eval={
                           "eq": [{
                               "ref": "config.stack_name"
                           }, "anotherstack"]
                       })
            ], )
        },
    )
    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(
        single_security_group_one_cidr_ingress, mock_config)

    assert result.valid
    assert len(result.failed_rules) == 0
    assert len(result.failed_monitored_rules) == 1
    assert result.failed_monitored_rules[
        0].rule == "EC2SecurityGroupMissingEgressRule"
    assert (
        result.failed_monitored_rules[0].reason ==
        "Missing egress rule in sg means all traffic is allowed outbound. Make this explicit if it is desired configuration"
    )
def test_filter_do_not_report_anything(bad_template):
    mock_config = Config(
        rules=["EC2SecurityGroupIngressOpenToWorldRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_config={
            "EC2SecurityGroupIngressOpenToWorldRule":
            RuleConfig(filters=[
                Filter(
                    rule_mode=RuleMode.WHITELISTED,
                    eval={
                        "and": [
                            {
                                "eq": [{
                                    "ref": "config.stack_name"
                                }, "mockstack"]
                            },
                            {
                                "eq": [{
                                    "ref": "ingress.FromPort"
                                }, 46]
                            },
                        ]
                    },
                )
            ], )
        },
    )
    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(bad_template, mock_config)

    assert result.valid
示例#6
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()),
            ),
        ],
    )
def test_filter_do_not_report_anything(single_security_group_one_cidr_ingress):
    mock_config = Config(
        rules=["EC2SecurityGroupMissingEgressRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_config={
            "EC2SecurityGroupMissingEgressRule":
            RuleConfig(filters=[
                Filter(
                    rule_mode=RuleMode.WHITELISTED,
                    eval={"eq": [{
                        "ref": "config.stack_name"
                    }, "mockstack"]},
                )
            ], )
        },
    )
    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(
        single_security_group_one_cidr_ingress, mock_config)

    assert result.valid
示例#8
0
def test_exist_function_and_property_exists(
        template_cross_account_role_with_name):
    mock_config = Config(
        rules=["CrossAccountTrustRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_config={
            "CrossAccountTrustRule":
            RuleConfig(filters=[
                Filter(
                    rule_mode=RuleMode.WHITELISTED,
                    eval={
                        "and": [
                            {
                                "and": [
                                    {
                                        "exists": {
                                            "ref":
                                            "resource.Properties.RoleName"
                                        }
                                    },
                                    {
                                        "regex": [
                                            "^prefix-.*$", {
                                                "ref":
                                                "resource.Properties.RoleName"
                                            }
                                        ]
                                    },
                                ]
                            },
                            {
                                "eq":
                                [{
                                    "ref": "principal"
                                },
                                 "arn:aws:iam::999999999:role/[email protected]"
                                 ]
                            },
                        ]
                    },
                ),
            ])
        },
    )

    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(
        template_cross_account_role_with_name, mock_config)
    assert result.valid
示例#9
0
def test_non_matching_filters_are_reported_normally(bad_template):
    mock_config = Config(
        rules=["EC2SecurityGroupIngressOpenToWorldRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_filters=[
            Filter(
                rule_mode=RuleMode.ALLOWED,
                eval={"eq": [{
                    "ref": "config.stack_name"
                }, "anotherstack"]},
                rules={"EC2SecurityGroupIngressOpenToWorldRule"},
            )
        ],
    )
    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(bad_template, mock_config)
    assert not result.valid
    assert compare_lists_of_failures(
        result.failures,
        [
            Failure(
                granularity=RuleGranularity.RESOURCE,
                reason=
                "Port(s) 46 open to public IPs: (11.0.0.0/8) in security group 'securityGroupIngress1'",
                risk_value=RuleRisk.MEDIUM,
                rule="EC2SecurityGroupIngressOpenToWorldRule",
                rule_mode=RuleMode.BLOCKING,
                actions=None,
                resource_ids={"securityGroupIngress1"},
                resource_types={"AWS::EC2::SecurityGroupIngress"},
            ),
            Failure(
                granularity=RuleGranularity.RESOURCE,
                reason=
                "Port(s) 46 open to public IPs: (::/0) in security group 'securityGroupIngress2'",
                risk_value=RuleRisk.MEDIUM,
                rule="EC2SecurityGroupIngressOpenToWorldRule",
                rule_mode=RuleMode.BLOCKING,
                actions=None,
                resource_ids={"securityGroupIngress2"},
                resource_types={"AWS::EC2::SecurityGroupIngress"},
            ),
        ],
    )
def test_non_matching_filters_are_reported_normally(template_two_roles_dict, expected_result_two_roles):
    mock_config = Config(
        rules=["CrossAccountTrustRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_config={
            "CrossAccountTrustRule": RuleConfig(
                filters=[
                    Filter(rule_mode=RuleMode.WHITELISTED, eval={"eq": [{"ref": "config.stack_name"}, "anotherstack"]})
                ],
            )
        },
    )
    rules = [DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(template_two_roles_dict, mock_config)
    assert not result.valid
    assert result.failed_rules == expected_result_two_roles
def test_filter_do_not_report_anything(template_two_roles_dict):
    mock_config = Config(
        rules=["CrossAccountTrustRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_config={
            "CrossAccountTrustRule": RuleConfig(
                filters=[
                    Filter(rule_mode=RuleMode.WHITELISTED, eval={"eq": [{"ref": "config.stack_name"}, "mockstack"]})
                ],
            )
        },
    )
    rules = [DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(template_two_roles_dict, mock_config)

    assert result.valid
示例#12
0
def test_filter_do_not_report_anything(filter_eval_object, bad_template):
    mock_config = Config(
        rules=["EC2SecurityGroupIngressOpenToWorldRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_filters=[
            Filter(
                rule_mode=RuleMode.ALLOWED,
                eval=filter_eval_object,
                rules={"EC2SecurityGroupIngressOpenToWorldRule"},
            )
        ],
    )
    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(bad_template, mock_config)

    assert result.valid
    assert compare_lists_of_failures(result.failures, [])
示例#13
0
def test_non_matching_filters_are_reported_normally(
        single_security_group_one_cidr_ingress):
    mock_config = Config(
        rules=["EC2SecurityGroupMissingEgressRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_filters=[
            Filter(
                rule_mode=RuleMode.ALLOWED,
                eval={"eq": [{
                    "ref": "config.stack_name"
                }, "anotherstack"]},
                rules={"EC2SecurityGroupMissingEgressRule"},
            )
        ],
    )
    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    result = processor.process_cf_template(
        single_security_group_one_cidr_ingress, mock_config)

    assert not result.valid
    assert compare_lists_of_failures(
        result.failures,
        [
            Failure(
                granularity=RuleGranularity.RESOURCE,
                reason=
                "Missing egress rule in sg means all traffic is allowed outbound. Make this explicit if it is desired configuration",
                risk_value=RuleRisk.MEDIUM,
                rule="EC2SecurityGroupMissingEgressRule",
                rule_mode=RuleMode.BLOCKING,
                actions=None,
                resource_ids={"sg"},
                resource_types={"AWS::EC2::SecurityGroup"},
            )
        ],
    )
示例#14
0
from cfripper.config.filter import Filter
from cfripper.model.enums import RuleMode

# FILTERS is here a single filter instead of list of filters
FILTERS = Filter(
    rule_mode=RuleMode.ALLOWED,
    eval={
        "and": [{
            "eq": [{
                "ref": "config.stack_name"
            }, "mockstack"]
        }, {
            "eq": [{
                "ref": "logical_id"
            }, "RootRoleOne"]
        }]
    },
    rules={"CrossAccountTrustRule"},
)
示例#15
0
@pytest.fixture()
def template_cross_account_role_no_name():
    return get_cfmodel_from("config/cross_account_role_no_name.json").resolve()


@pytest.fixture()
def template_cross_account_role_with_name():
    return get_cfmodel_from(
        "config/cross_account_role_with_name.json").resolve()


@pytest.mark.parametrize(
    "filter, args, expected_result",
    [
        (Filter(eval={"eq": ["string", "string"]}), {}, True),
        (Filter(eval={"eq": [1, 1]}), {}, True),
        (Filter(eval={"eq": [-1, -1]}), {}, True),
        (Filter(eval={"eq": [1.0, 1.0]}), {}, True),
        (Filter(eval={"eq": [-1.0, -1.0]}), {}, True),
        (Filter(eval={"eq": [True, True]}), {}, True),
        (Filter(eval={"eq": [False, False]}), {}, True),
        (Filter(eval={"eq": [[1, 2], [1, 2]]}), {}, True),
        (Filter(eval={"eq": ["string", "not_that_string"]}), {}, False),
        (Filter(eval={"eq": [1, 2]}), {}, False),
        (Filter(eval={"eq": [-1, 1]}), {}, False),
        (Filter(eval={"eq": [1.0, 2.0]}), {}, False),
        (Filter(eval={"eq": [1.0, -1.0]}), {}, False),
        (Filter(eval={"eq": [False, True]}), {}, False),
        (Filter(eval={"eq": [True, False]}), {}, False),
        (Filter(eval={"eq": [[1, 2], [2, 1]]}), {}, False),
示例#16
0
def test_debug_filter(template_cross_account_role_with_name, caplog):
    logging.disable(logging.NOTSET)
    caplog.set_level(logging.DEBUG)
    mock_config = Config(
        rules=["CrossAccountTrustRule"],
        aws_account_id="123456789",
        stack_name="mockstack",
        rules_filters=[
            Filter(
                reason="Test reason",
                rule_mode=RuleMode.ALLOWED,
                eval={
                    "and": [
                        {
                            "and": [
                                {
                                    "exists": {
                                        "ref": "resource.Properties.RoleName"
                                    }
                                },
                                {
                                    "regex": [
                                        "^prefix-.*$", {
                                            "ref":
                                            "resource.Properties.RoleName"
                                        }
                                    ]
                                },
                            ]
                        },
                        {
                            "eq": [{
                                "ref": "principal"
                            }, "arn:aws:iam::999999999:role/[email protected]"]
                        },
                    ]
                },
                rules={"CrossAccountTrustRule"},
                debug=True,
            ),
        ],
    )

    rules = [
        DEFAULT_RULES.get(rule)(mock_config) for rule in mock_config.rules
    ]
    processor = RuleProcessor(*rules)
    processor.process_cf_template(template_cross_account_role_with_name,
                                  mock_config)

    for line in [
            "Filter: Test reason",
            "ref(resource.Properties.RoleName) -> prefix-test-root-role",
            "exists(prefix-test-root-role) -> True",
            "ref(resource.Properties.RoleName) -> prefix-test-root-role",
            "regex(^prefix-.*$, prefix-test-root-role) -> True",
            "ref(principal) -> arn:aws:iam::999999999:role/[email protected]",
            "eq(arn:aws:iam::999999999:role/[email protected], arn:aws:iam::999999999:role/[email protected]) -> True",
            "Filter result: True",
    ]:
        assert line in caplog.text
示例#17
0
from cfripper.config.filter import Filter
from cfripper.config.rule_config import RuleConfig
from cfripper.model.enums import RuleMode

# RULES_CONFIG is here a list of RuleConfig instead of a dict with the rule names as keys
RULES_CONFIG = [
    RuleConfig(filters=[
        Filter(
            rule_mode=RuleMode.ALLOWED,
            eval={
                "and": [
                    {
                        "eq": [{
                            "ref": "config.stack_name"
                        }, "mockstack"]
                    },
                    {
                        "eq": [{
                            "ref": "logical_id"
                        }, "RootRoleOne"]
                    },
                ]
            },
        )
    ], )
]
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))


allow_http_ports_open_to_world_rules_config_filter = Filter(
    reason=
    "It can be acceptable to have Security Groups publicly available on ports 80 or 443.",
    rule_mode=RuleMode.ALLOWED,
    eval={
        "and": [
            {
                "exists": {
                    "ref": "open_ports"
                }
            },
            {
                "or": [{
                    "eq": [list(subset_allowed_ports), {
                        "ref": "open_ports"
                    }]
                } for subset_allowed_ports in powerset(ALLOWED_PORTS)
                       if subset_allowed_ports]
            },
        ]
    },
    rules={
        "EC2SecurityGroupOpenToWorldRule",
        "EC2SecurityGroupIngressOpenToWorldRule"
    },
)