def _add_to_result(
     self,
     result: Result,
     logical_id: str,
     policy_name: Optional[str],
     action: Optional[str],
     statement: Statement,
     extras: Dict,
     warning: bool = False,
 ):
     add_to_result = self.add_warning_to_result if warning else self.add_failure_to_result
     add_to_result(
         result=result,
         reason=self._build_reason(logical_id, action, policy_name),
         granularity=RuleGranularity.ACTION,
         resource_ids={logical_id},
         actions=set(statement.get_action_list()),
         context={
             "config": self._config,
             "extras": extras,
             "logical_id": logical_id,
             "policy_name": policy_name,
             "statement": statement,
             "action": action,
         },
     )
 def _add_to_result(
     self,
     result: Result,
     logical_id: str,
     policy_name: Optional[str],
     action: Optional[str],
     statement: Statement,
     extras: Dict,
     resource_type: str,
     monitor: bool = False,
 ):
     self.add_failure_to_result(
         result=result,
         reason=self._build_reason(logical_id, action, policy_name),
         granularity=RuleGranularity.ACTION,
         resource_ids={logical_id},
         resource_types={resource_type},
         actions=set(statement.get_action_list()),
         rule_mode=RuleMode.MONITOR if monitor else None,
         context={
             "config": self._config,
             "extras": extras,
             "logical_id": logical_id,
             "policy_name": policy_name,
             "statement": statement,
             "action": action,
         },
     )
Example #3
0
def statement_principal_5():
    return Statement(
        **{
            "Principal": [
                "arn:aws:iam::AWS-account-ID:user/user-name-1",
                "arn:aws:iam::AWS-account-ID:user/UserName2"
            ]
        })
Example #4
0
def statement_4():
    return Statement(
        **{
            "Effect": "Allow",
            "Action": "action2",
            "Resource": "arn1",
            "NotResource": ["arn2"]
        })
Example #5
0
def statement_1():
    return Statement(
        **{
            "Effect": "Allow",
            "Action": ["action1"],
            "NotAction": "action2",
            "Resource": ["arn"]
        })
Example #6
0
def statement_not_principal_2():
    return Statement(
        **{
            "NotPrincipal": {
                "AWS": ["arn:aws:iam::AWS-account-ID:user/user-name-1", "arn:aws:iam::AWS-account-ID:user/UserName2"]
            }
        }
    )
    def _check_statement(self, result: Result, logical_id: str,
                         policy_name: Optional[str], statement: Statement,
                         extras: Dict):
        if statement.Effect and statement.Effect == "Deny":
            return

        if statement.actions_with(REGEX_IS_STAR):
            if statement.Condition:
                self._add_to_result(result,
                                    logical_id,
                                    policy_name,
                                    None,
                                    statement,
                                    extras,
                                    warning=True)
            else:
                self._add_to_result(result, logical_id, policy_name, None,
                                    statement, extras)
        else:
            for action in statement.get_expanded_action_list():
                if action in CLOUDFORMATION_ACTIONS_ONLY_ACCEPTS_WILDCARD:
                    logger.info(
                        f"Action {action} only accepts wildcard, ignoring...")
                elif action.lower().startswith("kms:"):
                    # When KMS Key policies use * in the resource, that * will only apply this policy to the KMS Key being created
                    # so we must not flag this
                    # Source: https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html
                    logger.info(
                        f"KMS Action {action} only accepts wildcard, ignoring..."
                    )
                elif statement.Condition:
                    self._add_to_result(result,
                                        logical_id,
                                        policy_name,
                                        action,
                                        statement,
                                        extras,
                                        warning=True)
                else:
                    self._add_to_result(result, logical_id, policy_name,
                                        action, statement, extras)
def test_can_obtain_policy_documents_from_inherited_method(valid_opensearch_domain_with_access_policies):
    assert len(valid_opensearch_domain_with_access_policies.policy_documents) == 1
    assert valid_opensearch_domain_with_access_policies.policy_documents == [
        OptionallyNamedPolicyDocument(
            policy_document=PolicyDocument(
                Statement=[
                    Statement(
                        Effect="Allow",
                        Action="es:*",
                        Resource="arn:aws:es:us-east-1:123456789012:domain/test/*",
                        Principal=Principal(AWS="arn:aws:iam::123456789012:user/opensearch-user"),
                    )
                ]
            ),
            name=None,
        ),
    ]
Example #9
0
 def _do_statement_check(self, result: Result, logical_id: str,
                         statement: Statement,
                         filters_available_context: Dict,
                         resource: Resource):
     if statement.Effect == "Allow":
         for principal in statement.get_principal_list():
             account_id = get_account_id_from_principal(principal)
             filters_available_context["principal"] = principal
             filters_available_context["account_id"] = account_id
             if (
                     # checks if principal is a canonical id and is allowed
                     principal not in self.valid_principals
                     # if it wasn't a canonical id and contains a valid account id
                     and account_id not in self.valid_principals
                     # if principal is an AWS service
                     and not principal.endswith(".amazonaws.com")):
                 if statement.Condition and statement.Condition.dict():
                     # Ignoring condition checks since they will get reviewed in other rules and future improvements
                     pass
                 elif not self._config.aws_account_id:
                     logger.warning(
                         f"Not adding {type(self).__name__} failure in {logical_id} "
                         f"because no AWS Account ID was found in the config."
                     )
                 elif principal.startswith(
                         "GETATT") or principal.startswith("UNDEFINED_"):
                     self.add_failure_to_result(
                         result,
                         self.REASON.format(logical_id, principal),
                         rule_mode=RuleMode.DEBUG,
                         resource_ids={logical_id},
                         context=filters_available_context,
                         resource_types={resource.Type},
                     )
                 else:
                     self.add_failure_to_result(
                         result,
                         self.REASON.format(logical_id, principal),
                         resource_ids={logical_id},
                         context=filters_available_context,
                         resource_types={resource.Type},
                     )
 def _do_statement_check(self, result: Result, logical_id: str,
                         statement: Statement,
                         filters_available_context: Dict):
     if statement.Effect == "Allow":
         for principal in statement.get_principal_list():
             account_id = get_account_id_from_principal(principal)
             filters_available_context["principal"] = principal
             filters_available_context["account_id"] = account_id
             if (
                     # checks if principal is a canonical id and is whitelisted
                     principal not in self.valid_principals
                     # if it wasn't a canonical id and contains a valid account id
                     and account_id not in self.valid_principals
                     # if principal is an AWS service
                     and not principal.endswith(".amazonaws.com")):
                 if statement.Condition and statement.Condition.dict():
                     logger.warning(
                         f"Not adding {type(self).__name__} failure in {logical_id} "
                         f"because there are conditions: {statement.Condition}"
                     )
                 elif not self._config.aws_account_id:
                     logger.warning(
                         f"Not adding {type(self).__name__} failure in {logical_id} "
                         f"because no AWS Account ID was found in the config."
                     )
                 elif "GETATT" in principal or "UNDEFINED_" in principal:
                     self.add_failure_to_result(
                         result,
                         self.REASON.format(logical_id, principal),
                         rule_mode=RuleMode.DEBUG,
                         resource_ids={logical_id},
                         context=filters_available_context,
                     )
                 else:
                     self.add_failure_to_result(
                         result,
                         self.REASON.format(logical_id, principal),
                         resource_ids={logical_id},
                         context=filters_available_context,
                     )
Example #11
0
                         "Statement": [{
                             "Effect": "Allow",
                             "Action": ["service:GetService"],
                             "Resource": "*",
                         }],
                     },
                 },
             }
         },
     },
     [
         OptionallyNamedPolicyDocument(
             policy_document=PolicyDocument(Statement=[
                 Statement(
                     Effect="Allow",
                     Action=["service:GetService"],
                     Resource="*",
                 )
             ]),
             name=None,
         )
     ],
     1,
 ),
 (
     {
         "AWSTemplateFormatVersion": "2010-09-09",
         "Description":
         "Test resolving a nonexistent resource to Resource class",
         "Resources": {
             "NonexistentResource": {
Example #12
0
def statement_principal_4():
    return Statement(**{"Principal": "arn:aws:iam::123456789012:root"})
Example #13
0
def statement_principal_3():
    return Statement(
        **{"Principal": {
            "Federated": "cognito-identity.amazonaws.com"
        }})
Example #14
0
def statement_not_principal_1():
    return Statement(
        **{"NotPrincipal": {
            "AWS": "arn:aws:iam::123456789012:root"
        }})
Example #15
0
def test_capitalize_effect():
    statement = Statement(**{"Effect": "allOw", "Action": ["action1"], "NotAction": "action2", "Resource": ["arn"]})
    assert statement.Effect == "Allow"
Example #16
0
    "statement, expected_output",
    [
        (statement_1(), ["action1", "action2"]),
        (statement_2(), ["action1", "action2"]),
        (statement_3(), ["action1"]),
        (statement_4(), ["action2"]),
    ],
)
def test_get_action_list(statement, expected_output):
    assert statement.get_action_list() == expected_output


@pytest.mark.parametrize(
    "statement, expected_output",
    [
        (Statement(**{"Effect": "Allow", "Action": "ec2:RunInstances", "Resource": ["arn"]}), ["ec2:RunInstances"]),
        (Statement(**{"Effect": "Allow", "Action": "ec2:Run?nstances", "Resource": ["arn"]}), ["ec2:RunInstances"]),
        (Statement(**{"Effect": "Allow", "Action": "ec?:RunInstances", "Resource": ["arn"]}), ["ec2:RunInstances"]),
        (
            Statement(**{"Effect": "Allow", "Action": "ec2:Run*", "Resource": ["arn"]}),
            ["ec2:RunInstances", "ec2:RunScheduledInstances"],
        ),
    ],
)
def test_get_expanded_action_list(statement, expected_output):
    assert statement.get_expanded_action_list() == expected_output


@pytest.mark.parametrize(
    "statement, expected_output",
    [