From 02639faafafad3c72d5265ab72c70690c3d168d1 Mon Sep 17 00:00:00 2001 From: odg0318 Date: Sat, 18 Jun 2022 23:12:04 +0900 Subject: [PATCH] Automate prompt for mfa, app, role selections --- README.md | 1 + gimme_aws_creds/config.py | 11 ++++++++++- gimme_aws_creds/main.py | 11 +++++++++++ gimme_aws_creds/okta.py | 9 ++++++++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 75b3442d..a6f5f42b 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ A configuration wizard will prompt you to enter the necessary configuration para - sms - OTP via SMS message - web - DUO uses localhost webbrowser to support push|call|passcode - passcode - DUO uses `OKTA_MFA_CODE` or `--mfa-code` if set, or prompts user for passcode(OTP). +preffered_mfa_provider - automatically select a mfa provider when prompted for MFA - resolve_aws_alias - y or n. If yes, gimme-aws-creds will try to resolve AWS account ids with respective alias names (default: n). This option can also be set interactively in the command line using `-r` or `--resolve` parameter - include_path - (optional) Includes full role path to the role name in AWS credential profile name. (default: n). If `y`: `-/some/path/administrator`. If `n`: `-administrator` diff --git a/gimme_aws_creds/config.py b/gimme_aws_creds/config.py index cbd99d53..78ce2bf5 100644 --- a/gimme_aws_creds/config.py +++ b/gimme_aws_creds/config.py @@ -55,6 +55,8 @@ def __init__(self, gac_ui, create_config=True): self.action_output_format = False self.output_format = 'export' self.roles = [] + self.okta_app = None + self.okta_role = None if self.ui.environ.get("OKTA_USERNAME") is not None: self.username = self.ui.environ.get("OKTA_USERNAME") @@ -145,6 +147,8 @@ def get_args(self): '--action-setup-fido-authenticator', action='store_true', help='Sets up a new FIDO WebAuthn authenticator in Okta' ) + parser.add_argument('--okta-app', type=int) + parser.add_argument('--okta-role', type=int) args = parser.parse_args(self.ui.args) self.action_configure = args.action_configure @@ -173,6 +177,11 @@ 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.okta_app is not None: + self.okta_app = args.okta_app + if args.okta_role is not None: + self.okta_role = args.okta_role + self.conf_profile = args.profile or 'DEFAULT' def _handle_config(self, config, profile_config, include_inherits = True): @@ -578,4 +587,4 @@ def fail_if_profile_not_found(self, profile_config, conf_profile, default_sectio """ if not profile_config and conf_profile == default_section: raise errors.GimmeAWSCredsError( - 'DEFAULT profile is missing! This is profile is required when not using --profile') \ No newline at end of file + 'DEFAULT profile is missing! This is profile is required when not using --profile') diff --git a/gimme_aws_creds/main.py b/gimme_aws_creds/main.py index 600e783d..c5eba89c 100644 --- a/gimme_aws_creds/main.py +++ b/gimme_aws_creds/main.py @@ -319,6 +319,10 @@ def _choose_app(self, aws_info): if len(aws_info) == 1: return aws_info[0] # auto select when only 1 choice + if self.config.okta_app is not None: + self.ui.info("Detected app in config: {}".format(aws_info[self.config.okta_app]['name'])) + return aws_info[self.config.okta_app] + app_strs = [] for i, app in enumerate(aws_info): app_strs.append('[{}] {}'.format(i, app["name"])) @@ -415,6 +419,10 @@ def _choose_roles(self, roles): self.ui.info("Detected single role: {}".format(single_role)) return {single_role} + if self.config.okta_role is not None: + self.ui.info("Detected role in config: {}".format(roles[self.config.okta_role].role)) + return {roles[self.config.okta_role].role} + # Gather the roles available to the user. role_strs = self.resolver._display_role(roles) @@ -549,6 +557,9 @@ def okta(self): if self.conf_dict.get('preferred_mfa_type'): okta.set_preferred_mfa_type(self.conf_dict['preferred_mfa_type']) + if self.conf_dict.get('preffered_mfa_provider'): + okta.set_preferred_mfa_provider(self.conf_dict['preffered_mfa_provider']) + if self.config.mfa_code is not None: okta.set_mfa_code(self.config.mfa_code) elif self.conf_dict.get('okta_mfa_code'): diff --git a/gimme_aws_creds/okta.py b/gimme_aws_creds/okta.py index 83875d72..c9b742c2 100644 --- a/gimme_aws_creds/okta.py +++ b/gimme_aws_creds/okta.py @@ -63,6 +63,7 @@ def __init__(self, gac_ui, okta_org_url, verify_ssl_certs=True, device_token=Non self._username = None self._password = None self._preferred_mfa_type = None + self._preferred_mfa_provider = None self._mfa_code = None self._remember_device = None @@ -102,6 +103,9 @@ def set_password(self, password): def set_preferred_mfa_type(self, preferred_mfa_type): self._preferred_mfa_type = preferred_mfa_type + def set_preferred_mfa_provider(self, preferred_mfa_provider): + self._preferred_mfa_provider = preferred_mfa_provider + def set_mfa_code(self, mfa_code): self._mfa_code = mfa_code @@ -787,6 +791,9 @@ def _choose_factor(self, factors): factor_name = self._build_factor_name(preferred_factors[0]) self.ui.info(factor_name + ' selected') selection = factors.index(preferred_factors[0]) + elif self._preferred_mfa_provider is not None: + self.ui.info('Detected preferred provider in config: {}'.format(self._preferred_mfa_provider)) + selection = factors.index([v for v in factors if v['provider'] == self._preferred_mfa_provider][0]) else: self.ui.info("Pick a factor:") # print out the factors and let the user select @@ -1028,7 +1035,7 @@ def _introspect_factors(self, state_token): @staticmethod def _extract_state_token_from_http_response(http_res): saml_soup = BeautifulSoup(http_res.text, "html.parser") - + mfa_string = ( 'Dodatečné ověření', 'Ekstra verificering',