Example #1
0
 def test_is_array(self):
     cases = (
         ([1, 2], True),
         ((1, 2), True),
         (CustomSequence(1, 2), True),
         ("abc", False),
         (b"abc", False),
         (1, False),
         ({
             "a": 1
         }, False),
     )
     for case_input, expected in cases:
         self.assertIs(is_array(case_input), expected)
Example #2
0
    def _condition_entries(self):
        """Extracts any ARNs, Account Numbers, UserIDs, Usernames, CIDRs, VPCs, and VPC Endpoints from a condition block.

        Ignores any negated condition operators like StringNotLike.
        Ignores weak condition keys like referer, date, etc.

        Reason: A condition is meant to limit the principal in a statement.  Often, resource policies use a wildcard principal
        and rely exclusively on the Condition block to limit access.

        We would want to alert if the Condition had no limitations (like a non-existent Condition block), or very weak limitations.  Any negation
        would be weak, and largely equivelant to having no condition block whatsoever.

        The alerting code that relies on this data must ensure the condition has at least one of the following:
        - A limiting ARN
        - Account Identifier
        - AWS Organization Principal Org ID
        - User ID
        - Source IP / CIDR
        - VPC
        - VPC Endpoint

        https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html
        """
        conditions = list()
        condition = self.statement.get("Condition")
        if not condition:
            return conditions

        key_mapping = {
            "aws:sourcearn": "arn",
            "aws:sourceowner": "account",
            "aws:sourceaccount": "account",
            "aws:principalorgid": "org-id",
            "kms:calleraccount": "account",
            "aws:userid": "userid",
            "aws:sourceip": "cidr",
            "aws:sourcevpc": "vpc",
            "aws:sourcevpce": "vpce",
            # a key for SAML Federation trust policy.
            # https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_saml.html
            # https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_assertions.html
            "saml:aud": "saml-endpoint",
        }

        relevant_condition_operators = [
            re.compile(
                "((ForAllValues|ForAnyValue):)?ARN(Equals|Like)(IfExists)?",
                re.IGNORECASE,
            ),
            re.compile(
                "((ForAllValues|ForAnyValue):)?String(Equals|Like)(IgnoreCase)?(IfExists)?",
                re.IGNORECASE,
            ),
            re.compile("((ForAllValues|ForAnyValue):)?IpAddress(IfExists)?",
                       re.IGNORECASE),
        ]

        for condition_operator in condition.keys():
            if any(
                    regex.match(condition_operator)
                    for regex in relevant_condition_operators):
                for key, value in condition[condition_operator].items():

                    # ForAllValues and ForAnyValue must be paired with a list.
                    # Otherwise, skip over entries.
                    if not is_array(value) and condition_operator.lower(
                    ).startswith("for"):
                        continue

                    if key.lower() in key_mapping:
                        if is_array(value):
                            for v in value:
                                conditions.append(
                                    ConditionTuple(
                                        value=v,
                                        category=key_mapping[key.lower()]))
                        else:
                            conditions.append(
                                ConditionTuple(
                                    value=value,
                                    category=key_mapping[key.lower()]))

        return conditions
Example #3
0
 def _add_or_extend(self, value, structure):
     if is_array(value):
         structure.update(set(value))
     else:
         structure.add(value)