diff --git a/README.md b/README.md index 75b3442d..977597ab 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,7 @@ You can run a specific configuration profile with the `--profile` parameter: The username and password you are prompted for are the ones you login to Okta with. You can predefine your username by setting the `OKTA_USERNAME` environment variable or using the `-u username` parameter. -If you have not configured an Okta App or Role, you will prompted to select one. +If you have not configured an Okta App or Role, you will prompted to select one. If you want to filter the resulting list (for those with access to hundreds of roles), you can make use of the `--filter-selection/-f` option like so: `gimme-aws-creds -f prod` which would return only the roles where the account name contains the string `prod`. Note: use of the `-f` option requires `resolve_aws_alias` to be set to `True` to work as intended. If all goes well you will get your temporary AWS access, secret key and token, these will either be written to stdout or `~/.aws/credentials`. diff --git a/gimme_aws_creds/config.py b/gimme_aws_creds/config.py index cbd99d53..5023c87f 100644 --- a/gimme_aws_creds/config.py +++ b/gimme_aws_creds/config.py @@ -55,6 +55,7 @@ def __init__(self, gac_ui, create_config=True): self.action_output_format = False self.output_format = 'export' self.roles = [] + self.filter_selection = "" if self.ui.environ.get("OKTA_USERNAME") is not None: self.username = self.ui.environ.get("OKTA_USERNAME") @@ -106,6 +107,15 @@ def get_args(self): 'for example: arn:aws:iam::123456789012:role/Admin,/:210987654321:/ ' 'would match both account 123456789012 by ARN and 210987654321 by regexp' ) + parser.add_argument( + '--filter-selection', '-f', + help='If set, the input will be used to filter the list of roles presented to the user. ' + 'The filter acts on the so called \'friendly_account_name\' associated with each role. ' + 'The friendly account name contains the account name and number. ' + 'For example: \'nonprod\' would match any roles where the text \'nonprod\' is found. ' + 'If only one match is found, it will be auto selected and credentials generated. ' + 'If no results are found, the program exits.' + ) parser.add_argument( '--resolve', '-r', action='store_true', @@ -173,6 +183,8 @@ def get_args(self): self.output_format = args.output_format if args.roles is not None: self.roles = [role.strip() for role in args.roles.split(',') if role.strip()] + if args.filter_selection is not None: + self.filter_selection = args.filter_selection.strip() self.conf_profile = args.profile or 'DEFAULT' def _handle_config(self, config, profile_config, include_inherits = True): diff --git a/gimme_aws_creds/main.py b/gimme_aws_creds/main.py index 600e783d..9c3e9cdd 100644 --- a/gimme_aws_creds/main.py +++ b/gimme_aws_creds/main.py @@ -372,12 +372,13 @@ def _get_user_int_selection(self, min_int, max_int, max_retries=5): return selection - def _get_selected_roles(self, requested_roles, aws_roles): + def _get_selected_roles(self, requested_roles, aws_roles, filter_selection=""): """ select the role from the config file if it exists in the results from Okta. If not, present the user with a menu. """ + filtered_roles = [role for role in aws_roles if filter_selection in role.friendly_account_name] # 'all' is a special case - skip processing if requested_roles == 'all': - return set(role.role for role in aws_roles) + return set(role.role for role in filtered_roles) # check to see if a role is in the config and look for it in the results from Okta if requested_roles: ret = set() @@ -399,6 +400,9 @@ def _get_selected_roles(self, requested_roles, aws_roles): return ret self.ui.error("ERROR: AWS roles [{}] not found!".format(', '.join(requested_roles))) + if filter_selection: + return self._choose_roles(filtered_roles) + # Present the user with a list of roles to choose from return self._choose_roles(aws_roles) @@ -669,7 +673,7 @@ def aws_roles(self): def aws_selected_roles(self): if 'aws_selected_roles' in self._cache: return self._cache['aws_selected_roles'] - selected_roles = self._get_selected_roles(self.requested_roles, self.aws_roles) + selected_roles = self._get_selected_roles(self.requested_roles, self.aws_roles, self.config.filter_selection) self._cache['aws_selected_roles'] = ret = [ role for role in self.aws_roles diff --git a/tests/test_config.py b/tests/test_config.py index a6daffaf..d1fec750 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -31,6 +31,7 @@ def tearDown(self): remember_device=False, output_format=None, roles=None, + filter_selection = None, action_register_device=False, action_configure=False, action_list_profiles=False,