Ejemplo n.º 1
0
    def resource_invoke(self,
                        resource: S3BucketPolicy,
                        logical_id: str,
                        extras: Optional[Dict] = None) -> Result:
        result = Result()

        for statement in resource.Properties.PolicyDocument._statement_as_list(
        ):
            for principal in statement.get_principal_list():
                account_id = get_account_id_from_principal(principal)
                if not account_id:
                    continue
                if account_id not in self.valid_principals:
                    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}"
                        )
                    else:
                        self.add_failure_to_result(
                            result,
                            self.REASON.format(logical_id, account_id),
                            resource_ids={logical_id},
                            context={
                                "config": self._config,
                                "extras": extras,
                                "logical_id": logical_id,
                                "resource": resource,
                                "statement": statement,
                                "principal": principal,
                                "account_id": account_id,
                            },
                        )
        return result
Ejemplo n.º 2
0
    def _do_statement_check(self, logical_id, statement):

        if statement.Effect == "Allow":
            for principal in statement.get_principal_list():
                account_id = get_account_id_from_principal(principal)
                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(
                            type(self).__name__,
                            self.REASON.format(logical_id, principal),
                            rule_mode=RuleMode.DEBUG,
                            resource_ids={logical_id},
                        )
                    else:
                        self.add_failure(type(self).__name__,
                                         self.REASON.format(
                                             logical_id, principal),
                                         resource_ids={logical_id})
Ejemplo n.º 3
0
 def invoke(self,
            cfmodel: CFModel,
            extras: Optional[Dict] = None) -> Result:
     result = Result()
     for logical_id, resource in cfmodel.Resources.items():
         if isinstance(resource, S3BucketPolicy):
             for statement in resource.Properties.PolicyDocument._statement_as_list(
             ):
                 for principal in statement.get_principal_list():
                     account_id = get_account_id_from_principal(principal)
                     if not account_id:
                         continue
                     if account_id not in self.valid_principals:
                         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}"
                             )
                         else:
                             self.add_failure_to_result(
                                 result,
                                 self.REASON.format(logical_id, account_id),
                                 resource_ids={logical_id},
                             )
     return result
Ejemplo n.º 4
0
    def resource_invoke(self,
                        resource: S3BucketPolicy,
                        logical_id: str,
                        extras: Optional[Dict] = None) -> Result:
        result = Result()

        for statement in resource.Properties.PolicyDocument._statement_as_list(
        ):
            for principal in statement.get_principal_list():
                account_id = get_account_id_from_principal(principal)
                if not account_id:
                    continue
                if account_id not in self.valid_principals:
                    if statement.Condition and statement.Condition.dict():
                        # Ignoring condition checks since they will get reviewed in other rules and future improvements
                        pass
                    else:
                        self.add_failure_to_result(
                            result,
                            self.REASON.format(logical_id, account_id),
                            resource_ids={logical_id},
                            resource_types={resource.Type},
                            context={
                                "config": self._config,
                                "extras": extras,
                                "logical_id": logical_id,
                                "resource": resource,
                                "statement": statement,
                                "principal": principal,
                                "account_id": account_id,
                            },
                        )
        return result
Ejemplo n.º 5
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},
                     )
Ejemplo n.º 6
0
    def check_for_wildcards(
        self,
        result: Result,
        logical_id: str,
        resource: PolicyDocument,
        resource_type: str,
        extras: Optional[Dict] = None,
    ):
        for statement in resource.statement_as_list():
            filtered_principals = statement.principals_with(self.FULL_REGEX)
            if statement.Effect == "Allow" and filtered_principals:
                for principal in filtered_principals:
                    # if we can't find the account ID it might be a canonical ID
                    identifier = get_account_id_from_principal(
                        principal) or principal

                    # Check if account ID / canonical ID is allowed. `self._get_allowed_from_config()` used here
                    # to reduce number of false negatives and only allow exemptions for accounts
                    # which belong to AWS Services (such as ELB and ElastiCache).
                    if identifier in self._get_allowed_from_config():
                        continue
                    if statement.Condition and statement.Condition.dict():
                        # Ignoring condition checks since they will get reviewed in other rules and future improvements
                        continue
                    else:
                        self.add_failure_to_result(
                            result,
                            self.REASON_WILDCARD_PRINCIPAL.format(
                                logical_id, principal),
                            resource_ids={logical_id},
                            resource_types={resource_type},
                            context={
                                "config": self._config,
                                "extras": extras,
                                "logical_id": logical_id,
                                "resource": resource,
                                "statement": statement,
                                "principal": principal,
                                "account_id": identifier,
                            },
                        )