Ejemplo n.º 1
0
async def get_resources_from_events(
        policy_changes: List[Dict]) -> Dict[str, dict]:
    """Returns a dict of resources affected by a list of policy changes along with
    the actions and other data points that are relevant to them.

    Returned dict format:
    {
        "resource_name": {
            "actions": ["service1:action1", "service2:action2"],
            "arns": ["arn:aws:service1:::resource_name", "arn:aws:service1:::resource_name/*"],
            "account": "1234567890",
            "type": "service1",
            "region": "",
        }
    }
    """
    def default_resource():
        return {
            "actions": [],
            "arns": [],
            "account": "",
            "type": "",
            "region": ""
        }

    resource_actions: Dict[str, Dict] = defaultdict(default_resource)
    for event in policy_changes:
        for policy_type in ["inline_policies", "managed_policies"]:
            for policy in event.get(policy_type, []):
                policy_document = policy["policy_document"]
                for statement in policy_document.get("Statement", []):
                    resources = statement.get("Resource", [])
                    resources = (resources if isinstance(resources, list) else
                                 [resources])
                    for resource in resources:
                        if resource == "*":
                            continue
                        resource_name = get_resource_from_arn(resource)
                        if resource_name == "*":
                            continue
                        if not resource_actions[resource_name]["account"]:
                            resource_actions[resource_name][
                                "account"] = await get_resource_account(
                                    resource)
                        if not resource_actions[resource_name]["type"]:
                            resource_actions[resource_name][
                                "type"] = get_service_from_arn(resource)
                        if not resource_actions[resource_name]["region"]:
                            resource_actions[resource_name][
                                "region"] = get_region_from_arn(resource)
                        resource_actions[resource_name]["arns"].append(
                            resource)
                        actions = get_actions_for_resource(resource, statement)
                        resource_actions[resource_name]["actions"].extend(
                            x for x in actions if x not in
                            resource_actions[resource_name]["actions"])
    return dict(resource_actions)
Ejemplo n.º 2
0
def get_actions_for_resource(resource_arn: str, statement: Dict) -> List[str]:
    """For the given resource and policy statement, return the actions that are
    for that resource's service.
    """
    results: List[str] = []
    # Get service from resource
    resource_service = get_service_from_arn(resource_arn)
    # Get relevant actions from policy doc
    actions = statement.get("Action", [])
    actions = actions if isinstance(actions, list) else [actions]
    for action in actions:
        if action == "*":
            results.append(action)
        else:
            if get_service_from_action(action) == resource_service:
                if action not in results:
                    results.append(action)

    return results