def choose_supported_factor(self): ''' Give the user a choice from the intersection of configured and supported factors ''' index = 1 for opt in self.option_factors: msg = '{index} - {prompt}'.format(index=index, prompt=opt['prompt']) Common.echo(message=msg, bold=True) index += 1 raw_choice = None try: raw_choice = click.prompt('Choose a MFA type to use', type=int) choice = raw_choice - 1 except ValueError as err: Common.echo(message='Please select a valid option: you chose: {}'. format(raw_choice)) return self.choose_supported_factor() if len(self.option_factors) > choice >= 0: pass else: Common.echo(message='Please select a valid option: you chose: {}'. format(raw_choice)) return self.choose_supported_factor() chosen_option = self.option_factors[choice] matching_okta_factor = [ fact for fact in self.okta_factors if fact['provider'] == chosen_option['provider'] and fact['factorType'] == chosen_option['factor_type'] ] if self.verbose: Common.dump_verbose(message='Using chosen factor: {}'.format( chosen_option['prompt'])) return matching_okta_factor[0]
def verify_preferred_factor(self): ''' Return the Okta MFA configuration for the matching, supported configuration ''' preferred_factors = [ opt for opt in self.option_factors if self.factor_preference == opt['prompt'] ] if preferred_factors: if self.verbose: msg = 'Using preferred factor: {}'.format( self.factor_preference) Common.dump_verbose(message=msg) matching_okta_factor = [ fact for fact in self.okta_factors if fact['provider'] == preferred_factors[0]['provider'] and fact['factorType'] == preferred_factors[0]['factor_type'] ] return matching_okta_factor[0] else: msg = 'The MFA option ({}) in your configuration file is not available'.format( self.factor_preference) Common.dump_err(message=msg, exit_code=3, verbose=self.verbose)
def assume_role(self): ''' entry point for the cli tool ''' profile_mgr = ProfileManager(profile_name=self.profile, verbose=self.verbose) configuration = profile_mgr.initialize_configuration() profile_mgr.update_configuration(profile_configuration=configuration) # Need a directory to store intermediate files. Use the same directory that clokta configuration # is kept in self.data_dir = os.path.dirname(profile_mgr.config_location) saml_assertion = self.__saml_assertion_aws(session_token=None, configuration=configuration) if not saml_assertion: if 'okta_password' not in configuration or not configuration[ 'okta_password']: configuration['okta_password'] = profile_mgr.prompt_for( 'okta_password') session_token = self.__okta_session_token( configuration=configuration) if self.verbose: Common.dump_verbose( message='Okta session token: {}'.format(session_token)) saml_assertion = self.__saml_assertion_aws( session_token=session_token, configuration=configuration) idp_and_role_chooser = RoleChooser( saml_assertion=saml_assertion, role_preference=configuration.get('okta_aws_role_to_assume'), verbose=self.verbose) idp_role_tuple = idp_and_role_chooser.choose_idp_role_tuple() client = boto3.client('sts') # Try for a 12 hour session. If it fails, try for shorter periods durations = [43200, 14400, 3600] for duration in durations: try: assumed_role_credentials = client.assume_role_with_saml( RoleArn=idp_role_tuple[2], PrincipalArn=idp_role_tuple[1], SAMLAssertion=saml_assertion, DurationSeconds=duration) if duration == 3600: Common.echo(message='YOUR SESSION WILL ONLY LAST ONE HOUR') break except ClientError as e: # If we get a validation error and we have shorter durations to try, try a shorter duration if e.response['Error'][ 'Code'] != 'ValidationError' or duration == durations[ -1]: raise profile_mgr.apply_credentials(credentials=assumed_role_credentials, echo_message=True) bash_file = profile_mgr.write_sourceable_file( credentials=assumed_role_credentials) docker_file = profile_mgr.write_dockerenv_file( credentials=assumed_role_credentials) Common.echo( message= 'AWS keys generated. To use, run "export AWS_PROFILE={prof}"\nor use files {file1} with docker compose or {file2} with shell scripts' .format(prof=self.profile, file1=docker_file, file2=bash_file))