Example #1
0
    def __initialize_configuration(self):
        """
        Load config file, both the desired section and the default section
        :return: the parameter list
        :rtype: dict
        """
        clokta_cfg_file = configparser.ConfigParser()
        clokta_cfg_file.read(self.clokta_config_file)

        # Make sure we have the bare minimum in the config file.  The DEFAULT section and the app URL.
        if not clokta_cfg_file['DEFAULT']:
            clokta_cfg_file['DEFAULT'] = {'okta_org': ''}
        if not clokta_cfg_file.has_section(self.profile_name):
            msg = 'No profile "{}" in clokta.cfg, but enter the information and clokta will create a profile.\n' + \
                  'Copy the link from the Okta App'
            app_url = click.prompt(text=msg.format(self.profile_name),
                                   type=str,
                                   err=Common.to_std_error()).strip()
            if not app_url.startswith("https://") or not app_url.endswith(
                    "?fromHome=true"):
                Common.dump_err(
                    "Invalid App URL.  URL usually of the form https://xxxxxxxx.okta.com/.../272?fromHome=true",
                    6)
                raise ValueError("Invalid URL")
            else:
                app_url = app_url[:-len("?fromHome=true")]
            clokta_cfg_file.add_section(self.profile_name)
            clokta_cfg_file.set(self.profile_name, 'okta_aws_app_url', app_url)

        config_section = clokta_cfg_file[self.profile_name]
        self.__load_parameters(config_section)
        if self.get('save_password_in_keychain') == 'True':
            self.parameters[
                'okta_password'].save_to = ConfigParameter.SaveTo.KEYRING
Example #2
0
    def __initialize_configuration(self):
        """
        Load config file, both the desired section and the default section
        :return: the parameter list
        :rtype: dict
        """
        clokta_cfg_file = configparser.ConfigParser()
        clokta_cfg_file.read(self.clokta_config_file)

        # Make sure we have the bare minimum in the config file.  The DEFAULT section and the app URL.
        if not clokta_cfg_file['DEFAULT']:
            clokta_cfg_file['DEFAULT'] = {}
        if not clokta_cfg_file.has_section(self.profile_name):
            msg = 'No profile "{}" in clokta.cfg, but enter the information and clokta will create a profile.\n' + \
                  'Copy the link from the Okta App'
            app_url = click.prompt(text=msg.format(self.profile_name),
                                   type=str,
                                   err=Common.to_std_error()).strip()
            app_url = self.__check_url(app_url)
            clokta_cfg_file.add_section(self.profile_name)
            clokta_cfg_file.set(self.profile_name, 'okta_aws_app_url', app_url)

        config_section = clokta_cfg_file[self.profile_name]
        self.__load_parameters(config_section)
        if self.get('save_password_in_keychain') == 'True':
            self.parameters[
                'okta_password'].save_to = ConfigParameter.SaveTo.KEYRING
Example #3
0
 def __prompt_for(self, param):
     prompt = param.prompt if param.prompt else 'Enter a value for {}'.format(
         param.name)
     if param.secret:
         field_value = getpass.getpass(prompt=prompt + ":")
     else:
         field_value = click.prompt(text=prompt,
                                    type=param.param_type,
                                    err=Common.to_std_error(),
                                    default=param.default_value,
                                    show_default=not param.prompt)
     return field_value if param.param_type == str else str(field_value)
Example #4
0
    def __prompt_for_role(self, with_set_default_option):
        """
        Give the user a choice from the intersection of configured and supported factors
        :param with_set_default_option: if True will add an option for setting a default role
        :type with_set_default_option: bool
        :return: a tuple of what role was chosen and whether it is the new default
        :rtype: AwsRole, bool
        """
        index = 1
        for role in self.possible_roles:
            msg = '{index} - {prompt}'.format(index=index,
                                              prompt=role.role_name)
            Common.echo(message=msg, bold=True)
            index += 1
        if with_set_default_option:
            Common.echo('{index} - set a default role'.format(index=index))
        raw_choice = None
        try:
            raw_choice = click.prompt(text='Choose a Role ARN to use',
                                      type=int,
                                      err=Common.to_std_error())
            choice = raw_choice - 1
        except ValueError:
            Common.echo(message='Please select a valid option: you chose: {}'.
                        format(raw_choice))
            return self.__prompt_for_role()

        if choice == len(self.possible_roles):
            # They want to set a default.  Prompt again (just without the set-default option)
            # and return that chosen role and that it's the new default
            chosen_option, _ = self.__prompt_for_role(
                with_set_default_option=False)
            return chosen_option, True
        if len(self.possible_roles) > choice >= 0:
            pass
        else:
            Common.echo(message='Please select a valid option: you chose: {}'.
                        format(raw_choice))
            return self.__prompt_for_role(
                with_set_default_option=with_set_default_option)

        chosen_option = self.possible_roles[choice]
        if Common.is_debug():
            Common.dump_out(
                message='Using chosen Role {role} & IDP {idp}'.format(
                    role=chosen_option.role_arn, idp=chosen_option.idp_arn))

        return chosen_option, False
Example #5
0
    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,
                                      err=Common.to_std_error())
            choice = raw_choice - 1
        except ValueError:
            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 Common.is_debug():
            Common.dump_out(message='Using chosen factor: {}'.format(
                chosen_option['prompt']))

        return matching_okta_factor[0]
Example #6
0
    def determine_okta_onetimepassword(self, factor, first_time):
        """
        Get the one time password, which may be in one password or
        may need to be prompted for
        :param factor: the mfa mechanism being used.  Holds a user friendly label for identifying which mechanism.
        :type factor: dict
        :param first_time: whether this is the first time this run determining one time password
            on subsequent attempts we don't try to get it with an otp secret because that
            obviously didn't work the first time
        :return: the Okta one time password
        :rtype: string
        """

        otp_value = None
        if self.get('okta_onetimepassword_secret'):
            if not first_time:
                Common.dump_err("OTP generator created incorrect OTP")
            else:
                try:
                    # noinspection PyUnresolvedReferences
                    import onetimepass as otp
                except ImportError:
                    msg = 'okta_onetimepassword_secret provided in config but "onetimepass" is not installed. ' + \
                          'run: pip install onetimepass'
                    Common.dump_err(message=msg)
                    raise ValueError("Illegal configuration")
                otp_value = otp.get_totp(
                    self.get('okta_onetimepassword_secret'))

        if not otp_value:
            otp_value = click.prompt(
                text='Enter your {} one time password'.format(
                    factor['clokta_id']),
                type=str,
                err=Common.to_std_error(),
                default='')
        return otp_value