예제 #1
0
    def get_rendered_policy(self, minimize=None):
        """
        Get the JSON rendered policy

        :param minimize: Reduce the character count of policies without creating overlap with other action names
        :rtype: dict
        """
        statements = []
        # Only set the actions to lowercase if minimize is provided
        all_actions = get_all_actions(lowercase=True)

        # render the policy
        for sid in self.sids:
            actions = self.sids[sid]["actions"]
            if len(actions) == 0:
                logger.debug(f"No actions for sid {sid}")
                continue
            if minimize is not None and isinstance(minimize, int):
                logger.debug("Minimizing statements...")
                actions = minimize_statement_actions(actions,
                                                     all_actions,
                                                     minchars=minimize)
            logger.debug(f"Adding statement with SID {sid}")
            logger.debug(f"{sid} SID has the actions: {actions}")
            logger.debug(
                f"{sid} SID has the resources: {self.sids[sid]['arn']}")

            statements.append({
                "Sid": sid,
                "Effect": "Allow",
                "Action": actions,
                "Resource": self.sids[sid]["arn"],
            })
        policy = {"Version": POLICY_LANGUAGE_VERSION, "Statement": statements}
        return policy
예제 #2
0
def print_policy(arn_dict_with_actions_and_resources,
                 db_session,
                 minimize=None):
    """
    Prints the least privilege policy
    """
    statement = []
    all_actions = get_all_actions(db_session)

    for sid in arn_dict_with_actions_and_resources:
        actions = arn_dict_with_actions_and_resources[sid]['actions']
        if minimize is not None and isinstance(minimize, int):
            actions = minimize_statement_actions(actions,
                                                 all_actions,
                                                 minchars=minimize)
        statement.append({
            "Sid":
            arn_dict_with_actions_and_resources[sid]['name'],
            "Effect":
            "Allow",
            "Action":
            actions,
            "Resource":
            arn_dict_with_actions_and_resources[sid]['arns']
        })

    policy = {"Version": POLICY_LANGUAGE_VERSION, "Statement": statement}
    return policy
예제 #3
0
    def get_rendered_policy(self, db_session, minimize=None):
        """
        Get the JSON rendered policy

        :param db_session: SQLAlchemy database session
        :param minimize: Reduce the character count of policies without creating overlap with other action names
        :rtype: dict
        """
        statements = []
        # Only set the actions to lowercase if minimize is provided
        all_actions = get_all_actions(db_session, lowercase=True)

        # render the policy
        for sid in self.sids:
            actions = self.sids[sid]["actions"]
            if len(actions) == 0:
                continue
            if minimize is not None and isinstance(minimize, int):
                actions = minimize_statement_actions(actions,
                                                     all_actions,
                                                     minchars=minimize)
            statements.append({
                "Sid": sid,
                "Effect": "Allow",
                "Action": actions,
                "Resource": self.sids[sid]["arn"],
            })
        policy = {"Version": POLICY_LANGUAGE_VERSION, "Statement": statements}
        return policy
예제 #4
0
 def test_minimize_statement_actions(self):
     actions_to_minimize = [
         "kms:creategrant", "kms:createcustomkeystore",
         "ec2:authorizesecuritygroupegress",
         "ec2:authorizesecuritygroupingress"
     ]
     desired_result = ['ec2:authorizes*', 'kms:createc*', 'kms:createg*']
     all_actions = get_all_actions(db_session)
     minchars = None
     self.maxDiff = None
     # minimized_actions_list = minimize_statement_actions(desired_actions, all_actions, minchars)
     self.assertListEqual(
         sorted(
             minimize_statement_actions(actions_to_minimize, all_actions,
                                        minchars)), sorted(desired_result))
예제 #5
0
    def get_rendered_policy(self, minimize=None):
        """
        Get the JSON rendered policy

        Arguments:
            minimize: Reduce the character count of policies without creating overlap with other action names
        Returns:
            Dictionary: The IAM Policy JSON
        """
        statements = []
        # Only set the actions to lowercase if minimize is provided
        all_actions = get_all_actions(lowercase=True)

        # render the policy
        for sid in self.sids:
            temp_actions = self.sids[sid]["actions"]
            if len(temp_actions) == 0:
                logger.debug(f"No actions for sid {sid}")
                continue
            actions = []
            if self.exclude_actions:
                for temp_action in temp_actions:
                    if temp_action.lower() in self.exclude_actions:
                        logger.debug(f"\tExcluded action: {temp_action}")
                    else:
                        if temp_action not in actions:
                            actions.append(temp_action)
            else:
                actions = temp_actions
            # temp_actions.clear()
            if minimize is not None and isinstance(minimize, int):
                logger.debug("Minimizing statements...")
                actions = minimize_statement_actions(actions,
                                                     all_actions,
                                                     minchars=minimize)
            logger.debug(f"Adding statement with SID {sid}")
            logger.debug(f"{sid} SID has the actions: {actions}")
            logger.debug(
                f"{sid} SID has the resources: {self.sids[sid]['arn']}")

            statements.append({
                "Sid": sid,
                "Effect": "Allow",
                "Action": actions,
                "Resource": self.sids[sid]["arn"],
            })
        policy = {"Version": POLICY_LANGUAGE_VERSION, "Statement": statements}
        return policy
예제 #6
0
 def test_minimize_statement_actions_funky_case(self):
     actions_to_minimize = [
         "kms:creategrant",
         "kms:createcustomkeystore",
         "ec2:authorizesecuritygroupegress",
         "ec2:authorizesecuritygroupingress",
     ]
     desired_result = ["ec2:authorizes*", "kms:createc*", "kms:createg*"]
     all_actions = get_all_actions(lowercase=True)
     minchars = None
     self.maxDiff = None
     # minimized_actions_list = minimize_statement_actions(desired_actions, all_actions, minchars)
     self.assertListEqual(
         sorted(
             minimize_statement_actions(actions_to_minimize, all_actions,
                                        minchars)),
         sorted(desired_result),
     )
예제 #7
0
 def test_minimize_statement_actions(self):
     actions_to_minimize = [
         "kms:CreateGrant",
         "kms:CreateCustomKeyStore",
         "ec2:AuthorizeSecurityGroupEgress",
         "ec2:AuthorizeSecurityGroupIngress",
     ]
     desired_result = ["ec2:authorizes*", "kms:createc*", "kms:createg*"]
     all_actions = get_all_actions(lowercase=True)
     minchars = None
     self.maxDiff = None
     # minimized_actions_list = minimize_statement_actions(desired_actions, all_actions, minchars)
     self.assertListEqual(
         sorted(
             minimize_statement_actions(actions_to_minimize, all_actions,
                                        minchars)),
         sorted(desired_result),
     )
예제 #8
0
def get_all_action_links():
    """
    Gets a huge list of the links to all AWS IAM actions. This is meant for use by Cloudsplaining.

    :return: A dictionary of all actions present in the database, with the values being the API documentation links.
    """
    all_actions = get_all_actions()
    results = {}
    for action in all_actions:
        try:
            service_prefix, action_name = action.split(":")
        except ValueError as v_e:
            logger.debug(f"{v_e} - for action {action}")
            continue
        link = get_api_documentation_link_for_action(service_prefix,
                                                     action_name)
        result = {action: link}
        results.update(result)
    return results
예제 #9
0
def expand(action):
    """
    expand the action wildcards into a full action

    Arguments:
        action: An action in the form with a wildcard - like s3:Get*, or s3:L*
    Returns:
        List: A list of all the expanded actions (like actions matching s3:Get*)
    """

    all_actions = get_all_actions()

    if isinstance(action, list):
        expanded_actions = []
        for item in action:
            expanded_actions.extend(expand(item))
        return expanded_actions

    if "*" in action:
        expanded = [
            expanded_action
            # for expanded_action in all_permissions
            for expanded_action in all_actions
            if fnmatch.fnmatchcase(expanded_action.lower(), action.lower())
        ]

        # if we get a wildcard for a tech we've never heard of, just return the
        # wildcard
        if not expanded:
            logger.debug(
                "ERROR: The action %s references a wildcard for an unknown resource.",
                action,
            )
            return [action]

        return expanded
    return [action]
예제 #10
0
def expand(action, db_session):
    """
    expand the action wildcards into a full action

    :param action: An action in the form with a wildcard - like s3:Get*, or s3:L*
    :param db_session: SQLAlchemy database session object
    :return: A list of all the expanded actions (like actions matching s3:Get*)
    :rtype: list
    """

    all_actions = get_all_actions(db_session)

    if isinstance(action, list):
        expanded_actions = []
        for item in action:
            expanded_actions.extend(expand(item, db_session))
        return expanded_actions

    if "*" in action:
        expanded = [
            expanded_action.lower()
            # for expanded_action in all_permissions
            for expanded_action in all_actions
            if fnmatch.fnmatchcase(expanded_action.lower(), action.lower())
        ]

        # if we get a wildcard for a tech we've never heard of, just return the
        # wildcard
        if not expanded:
            logger.warning(
                "ERROR: The action %s references a wildcard for an unknown resource.",
                action,
            )
            return [action.lower()]

        return expanded
    return [action.lower()]
예제 #11
0
 def setUp(self) -> None:
     all_actions = get_all_actions()
     self.all_actions = list(all_actions)
     self.all_actions.sort()
예제 #12
0
 def test_get_all_actions(self):
     result = get_all_actions()
     print("Total count of unique IAM actions:", len(result))
     self.assertGreater(len(result), 7000)
예제 #13
0
    def get_rendered_policy(self, minimize=None):
        """
        Get the JSON rendered policy

        Arguments:
            minimize: Reduce the character count of policies without creating overlap with other action names
        Returns:
            Dictionary: The IAM Policy JSON
        """
        statements = []
        # Only set the actions to lowercase if minimize is provided
        all_actions = get_all_actions(lowercase=True)

        # render the policy
        sids_to_be_changed = []
        for sid in self.sids:
            temp_actions = self.sids[sid]["actions"]
            if len(temp_actions) == 0:
                logger.debug(f"No actions for sid {sid}")
                continue
            actions = []
            if self.exclude_actions:
                for temp_action in temp_actions:
                    if temp_action.lower() in self.exclude_actions:
                        logger.debug(f"\tExcluded action: {temp_action}")
                    else:
                        if temp_action not in actions:
                            actions.append(temp_action)
            else:
                actions = temp_actions
            # temp_actions.clear()
            match_found = False
            if minimize is not None and isinstance(minimize, int):
                logger.debug("Minimizing statements...")
                actions = minimize_statement_actions(actions,
                                                     all_actions,
                                                     minchars=minimize)
                # searching in the existing statements
                # further minimizing the the output
                for stmt in statements:
                    if stmt["Resource"] == self.sids[sid]["arn"]:
                        stmt["Action"].extend(actions)
                        match_found = True
                        sids_to_be_changed.append(stmt["Sid"])
                        break
            logger.debug(f"Adding statement with SID {sid}")
            logger.debug(f"{sid} SID has the actions: {actions}")
            logger.debug(
                f"{sid} SID has the resources: {self.sids[sid]['arn']}")

            if not match_found:
                statements.append({
                    "Sid": sid,
                    "Effect": "Allow",
                    "Action": actions,
                    "Resource": self.sids[sid]["arn"],
                })

        if sids_to_be_changed:
            for stmt in statements:
                if stmt['Sid'] in sids_to_be_changed:
                    arn_details = parse_arn(stmt['Resource'][0])
                    resource_path = arn_details.get("resource_path")
                    resource_sid_segment = strip_special_characters(
                        f"{arn_details['resource']}{resource_path}")
                    stmt['Sid'] = create_policy_sid_namespace(
                        arn_details['service'], "Mult", resource_sid_segment)

        policy = {"Version": POLICY_LANGUAGE_VERSION, "Statement": statements}
        return policy
예제 #14
0
#!/usr/bin/env python

from policy_sentry.querying.all import get_all_actions

if __name__ == '__main__':

    all_actions = get_all_actions()  # returns a set
    all_actions = list(all_actions)  # convert to list
    all_actions.sort()  # sort in alphabetical order
    print(all_actions)  # print
"""
Output:

Every IAM action available across all services, without duplicates
"""
예제 #15
0
#!/usr/bin/env python
from policy_sentry.shared.database import connect_db
from policy_sentry.querying.all import get_all_actions


if __name__ == '__main__':
    db_session = connect_db('bundled')
    all_actions = get_all_actions(db_session)
    print(all_actions)

"""
Output:

Every IAM action available across all services, without duplicates
"""
예제 #16
0
from policy_sentry.querying.all import get_all_actions
from cloudsplaining.shared.utils import (
    remove_read_level_actions,
    remove_wildcard_only_actions,
)
from cloudsplaining.shared.exclusions import DEFAULT_EXCLUSIONS, Exclusions

# Copyright (c) 2020, salesforce.com, inc.
# All rights reserved.
# Licensed under the BSD 3-Clause license.
# For full license text, see the LICENSE file in the repo root
# or https://opensource.org/licenses/BSD-3-Clause
logger = logging.getLogger(__name__)
logging.getLogger("policy_sentry").setLevel(logging.WARNING)

ALL_ACTIONS = get_all_actions()


# pylint: disable=too-many-instance-attributes
class StatementDetail:
    """
    Analyzes individual statements within a policy
    """
    def __init__(self,
                 statement: Dict[str, Any],
                 flag_conditional_statements: bool = False,
                 flag_resource_arn_statements: bool = False) -> None:
        self.json = statement
        self.statement = statement
        self.effect = statement["Effect"]
        self.condition = statement.get("Condition", None)
예제 #17
0
    get_actions_matching_arn,
)
from policy_sentry.querying.all import get_all_actions
from cloudsplaining.shared.utils import (
    remove_read_level_actions,
    remove_wildcard_only_actions,
)

# Copyright (c) 2020, salesforce.com, inc.
# All rights reserved.
# Licensed under the BSD 3-Clause license.
# For full license text, see the LICENSE file in the repo root
# or https://opensource.org/licenses/BSD-3-Clause
logger = logging.getLogger(__name__)

all_actions = get_all_actions()


# pylint: disable=too-many-instance-attributes
class StatementDetail:
    """
    Analyzes individual statements within a policy
    """

    def __init__(self, statement):
        self.json = statement
        self.statement = statement
        self.effect = statement["Effect"]
        self.resources = self._resources()
        self.actions = self._actions()
        self.not_action = self._not_action()