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)
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)
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))