Beispiel #1
0
def list_role_rollbacks(message: Message) -> ResponderReturn:
    role_id = find_role_in_cache(message.role_name, message.account)

    if not role_id:
        return ResponderReturn(
            successful=False,
            return_message="Unable to find role {} in account {}".format(
                message.role_name, message.account
            ),
        )

    role = Role(role_id=role_id)
    role.fetch(fields=["Policies"])
    return_val = "Restorable versions for role {} in account {}\n".format(
        message.role_name, message.account
    )
    for index, policy_version in enumerate(role.policies):
        total_permissions, _ = get_permissions_in_policy(policy_version["Policy"])
        return_val += "({:>3}):  {:<5}     {:<15}  {}\n".format(
            index,
            len(total_permissions),
            policy_version["Discovered"],
            policy_version["Source"],
        )
    return ResponderReturn(successful=True, return_message=return_val)
Beispiel #2
0
    def get_permissions_for_policy_version(
            self,
            selection: int = -1,
            warn_unknown_perms: bool = False) -> Tuple[Set[str], Set[str]]:
        if not self.policies:
            return set(), set()

        return get_permissions_in_policy(self.policies[selection]["Policy"],
                                         warn_unknown_perms=warn_unknown_perms)
Beispiel #3
0
def _display_role(
    account_number: str,
    role_name: str,
    config: RepokidConfig,
) -> None:
    """
    Displays data about a role in a given account:
      1) Name, which filters are disqualifying it from repo, if it's repoable, total/repoable permissions,
         when it was last repoed, which services can be repoed
      2) The policy history: how discovered (repo, scan, etc), the length of the policy, and start of the contents
      3) Captured stats entry for the role
      4) A list of all services/actions currently allowed and whether they are repoable
      5) What the new policy would look like after repoing (if it is repoable)

    Args:
        account_number (string)
        role_name (string)

    Returns:
        None
    """
    role_id = find_role_in_cache(role_name, account_number)
    if not role_id:
        LOGGER.warning("Could not find role with name {}".format(role_name))
        return

    role = Role(role_id=role_id)
    role.fetch()

    print("\n\nRole repo data:")
    headers = [
        "Name",
        "Refreshed",
        "Disqualified By",
        "Can be repoed",
        "Permissions",
        "Repoable",
        "Repoed",
        "Services",
    ]
    rows = [[
        role.role_name,
        role.refreshed,
        role.disqualified_by,
        len(role.disqualified_by) == 0,
        role.total_permissions,
        role.repoable_permissions,
        role.repoed,
        role.repoable_services,
    ]]
    print(tabulate(rows, headers=headers) + "\n\n")

    print("Policy history:")
    headers = ["Number", "Source", "Discovered", "Permissions", "Services"]
    rows = []
    for index, policies_version in enumerate(role.policies):
        policy_permissions, _ = get_permissions_in_policy(
            policies_version["Policy"])
        rows.append([
            index,
            policies_version["Source"],
            policies_version["Discovered"],
            len(policy_permissions),
            get_services_in_permissions(policy_permissions),
        ])
    print(tabulate(rows, headers=headers) + "\n\n")

    print("Stats:")
    headers = ["Date", "Event Type", "Permissions Count", "Disqualified By"]
    rows = []
    for stats_entry in role.stats:
        rows.append([
            stats_entry["Date"],
            stats_entry["Source"],
            stats_entry["PermissionsCount"],
            stats_entry.get("DisqualifiedBy", []),
        ])
    print(tabulate(rows, headers=headers) + "\n\n")

    # can't do anymore if we don't have AA data
    if not role.aa_data:
        LOGGER.warning("ARN not found in Access Advisor: {}".format(role.arn))
        return

    warn_unknown_permissions = config.get("warnings",
                                          {}).get("unknown_permissions", False)

    permissions, eligible_permissions = role.get_permissions_for_policy_version(
        warn_unknown_perms=warn_unknown_permissions)

    print("Repoable services and permissions")
    headers = ["Service", "Action", "Repoable"]
    rows = []
    for permission in permissions:
        service = permission.split(":")[0]
        action = permission.split(":")[1]
        is_repoable_permission = permission in role.repoable_services
        is_repoable_service = permission.split(
            ":")[0] in role.repoable_services
        # repoable is is True if the action (`permission`) is in the list of repoable
        # services OR if the service (`permission.split(":")[0]`) is in the list
        repoable = is_repoable_permission or is_repoable_service
        rows.append([service, action, repoable])

    rows = sorted(rows, key=lambda x: (x[2], x[0], x[1]))
    print(tabulate(rows, headers=headers) + "\n\n")

    try:
        repoed_policies, _ = role.get_repoed_policy()
        print("Repo'd Policies: \n{}".format(
            json.dumps(repoed_policies, indent=2, sort_keys=True)))
    except MissingRepoableServices:
        print("All Policies Removed")
        repoed_policies = {}

    # need to check if all policies would be too large
    if inline_policies_size_exceeds_maximum(repoed_policies):
        LOGGER.warning(
            "Policies would exceed the AWS size limit after repo for role: {}.  "
            "Please manually minify.".format(role_name))