Esempio n. 1
0
    def get_role(self, prompt: bool, role_override: str = None, is_setup: bool = False) -> Role:
        """
        Returns a string of the user's selected role.

        Lookup the user's default role from the config file (created via the --configure option), an ENV variable, or
        instead prompt the user for the session.

        :param prompt: True/False - if True, users will always be prompted to input their role
        :param role_override: String representation of the role to get, regardless of defaults.
        :return: str: name of the selected role.
        """

        defaults = FiggySetup.stc_get_defaults(self._is_setup_command, profile=self._profile)
        if defaults is not None and not prompt:

            if role_override:
                if role_override in [role.role.role for role in defaults.assumable_roles] or is_setup:
                    return Role(role=role_override)
                else:
                    self._utils.error_exit(f"Invalid role override provided of: {role_override}. "
                                           f"You do not have permissions to assume this role. Contact your system "
                                           f"administrator to receive permissions then rerun `{CLI_NAME} "
                                           f"--{configure.name}`.")

            return defaults.role
        else:
            roles = self.__setup().get_assumable_roles()
            role_names = list(set([x.role.role for x in roles]))
            return Input.select_role(role_names)
Esempio n. 2
0
 def __init__(self, command: CliCommand, context: HelpContext, figgy_context: FiggyContext):
     self._command = command
     self._context = context
     self._figgy_context = figgy_context
     self._options = context.options
     self._utils = Utils(False)
     self._setup: FiggySetup = FiggySetup(self._figgy_context)
Esempio n. 3
0
    def __command_factory(self) -> CommandFactory:
        if not self._command_factory:
            self._command_factory = CommandFactory(self._context,
                                                   FiggySetup.stc_get_defaults(skip=self._is_setup_command,
                                                                               profile=self._profile))

        return self._command_factory
Esempio n. 4
0
 def __init__(self, command: CliCommand,
              context: CommandContext,
              session_manager: SessionManager,
              figgy_context: FiggyContext):
     self._command = command
     self._context = context
     self._utils = Utils(False)
     self._setup: FiggySetup = FiggySetup(figgy_context)
     self._session_manager = session_manager
Esempio n. 5
0
 def __init__(self, command: CliCommand, context: MaintenanceContext,
              figgy_context: FiggyContext, config: Optional[ConfigService]):
     self._command = command
     self._context = context
     self._figgy_context = figgy_context
     self._options = context.options
     self._utils = Utils(False)
     self._setup: FiggySetup = FiggySetup(self._figgy_context)
     self._config: Optional[ConfigService] = config
Esempio n. 6
0
    def get_colors_enabled(self) -> bool:
        """
        Defaults to true, unless user ran --configure and disabled colored output
        Returns: True/False
        """

        defaults = FiggySetup.stc_get_defaults(skip=self._is_setup_command, profile=self._profile)
        if defaults is not None:
            return defaults.colors_enabled
        else:
            return Utils.not_windows()
Esempio n. 7
0
    def __init__(self, help_context: HelpContext, figgy_setup: FiggySetup,
                 figgy_context: FiggyContext):
        super().__init__(login, Utils.not_windows(), help_context)
        self._setup = figgy_setup
        self._defaults: CLIDefaults = figgy_setup.get_defaults()
        self._figgy_context = figgy_context
        self._utils = Utils(self._defaults.colors_enabled)
        self._aws_cfg = AWSConfig(color=self.c)
        self._out = Output(self._defaults.colors_enabled)

        self.example = f"\n\n{self.c.fg_bl}{CLI_NAME} {login.name} \n" \
                       f"{self.c.rs}{self.c.fg_yl}  --or--{self.c.rs}\n" \
                       f"{self.c.fg_bl}{CLI_NAME} {login.name} {sandbox.name}{self.c.rs}"
        def inner(self, *args, **kwargs):
            if os.environ.get(
                    AnonymousUsageTracker._DISABLE_METRICS_ENV_VAR) == "true":
                return function(self, *args, **kwargs)

            command = getattr(self, 'type', None)
            log.info(f'GOt command {command}')

            if command:
                command = command.name
                cache = CacheManager(AnonymousUsageTracker._CACHE_NAME)

                if hasattr(self, 'context') and hasattr(
                        self.context,
                        'defaults') and self.context.defaults is not None:
                    if isinstance(self.context.defaults, CLIDefaults):
                        user_id = self.context.defaults.user_id
                    else:
                        user_id = "EmptyDefaults"
                else:
                    user_id = "NoOne"

                last_write, metrics = cache.get(
                    AnonymousUsageTracker._METRICS_KEY,
                    default=FiggyMetrics(user_id=user_id))

                metrics.increment_count(command)
                if Utils.millis_since_epoch(
                ) - metrics.last_report > AnonymousUsageTracker.REPORT_FREQUENCY:
                    defaults = FiggySetup.stc_get_defaults(skip=True)
                    if defaults and defaults.usage_tracking:
                        # Ship it async. If it don't worky, oh well :shruggie:
                        with ThreadPoolExecutor(max_workers=1) as pool:
                            pool.submit(AnonymousUsageTracker.report_usage,
                                        metrics)
                            log.info(
                                f'Reporting anonymous usage for metrics: {metrics}'
                            )
                            cache.write(AnonymousUsageTracker._METRICS_KEY,
                                        FiggyMetrics(user_id=user_id))
                            return function(self, *args, **kwargs)
                else:
                    cache.write(AnonymousUsageTracker._METRICS_KEY, metrics)

            return function(self, *args, **kwargs)
Esempio n. 9
0
    def get_profile(self, prompt: bool) -> str:
        """Returns the user's profile.

        Checks ENV variable, if not there, checks the config file (created via the --configure option), otherwise prompts
        the user

        Args:
            prompt: True/False - if True, users will always be prompted to input their profile

        :return: str: aws profile name
        """

        if BASTION_PROFILE_ENV_NAME in os.environ and not prompt:
            return os.environ.get(BASTION_PROFILE_ENV_NAME)
        else:
            defaults: CLIDefaults = FiggySetup.stc_get_defaults(self._is_setup_command, profile=self._profile)
            if defaults is not None and not prompt:
                return defaults.provider_config.profile
            else:
                return Input.select_aws_cli_profile()
Esempio n. 10
0
    def find_assumable_role(self, env: RunEnv, role: Role, skip: bool = False, profile=None) -> AssumableRole:
        """
        Looks up the appropriate assumable role based on the user's selected defaults or command-line overrides for
        --env, --role, and --profile.
        """

        if profile:
            return AssumableRole.from_profile(profile)

        assumable_roles: List[AssumableRole] = FiggySetup.stc_get_defaults(skip=skip).assumable_roles
        matching_role = [ar for ar in assumable_roles if ar.role == role and ar.run_env == env]
        if matching_role:
            matching_role = matching_role.pop()
        else:
            if not skip:
                matching_role = None
            else:
                matching_role = AssumableRole.default_from_role_env(role, env)

        return matching_role
Esempio n. 11
0
def main():
    """
        Entrypoint to figgy.

        Performs generic validation, then routes user down appropriate execution path based on command line parameters
    """
    arguments = sys.argv
    user = getpass.getuser()
    Utils.stc_validate(user != ROOT_USER, f"Hey! Stop trying to run {CLI_NAME} as {ROOT_USER}. That's bad!")
    original_command = ' '.join(arguments)
    sys.argv = arguments
    os.makedirs(os.path.dirname(BOTO3_CLIENT_FILE_LOCK_PATH), exist_ok=True)

    try:
        # Parse / Validate Args
        args = FiggyCLI.parse_args()
        if hasattr(args, 'debug') and args.debug:
            root_logger.setLevel(logging.INFO)
            root_logger.addHandler(stdout_handler)

        cli: FiggyCLI = FiggyCLI(args)
        command: Command = cli.get_command()
        if hasattr(args, 'info') and args.info:
            command.print_help_text()
        else:
            command.execute()

    except AssertionError as e:
        Utils.stc_error_exit(e.args[0])
    except KeyboardInterrupt:
        pass
    except SystemExit:
        pass
    except (BaseException, Exception) as e:
        try:
            error_reporter = FiggyErrorReporter(FiggySetup.stc_get_defaults(skip=True, profile=None))
            error_reporter.log_error(original_command, e)
        except Exception as e:
            print(e)
            print(f"\n\nUnable to log or report this exception. Please submit a Github issue to: {FIGGY_GITHUB}")
Esempio n. 12
0
    def __init__(self, args):
        """
        Initializes global shared properties
        :param args: Arguments passed in from user, collected from ArgParse
        """
        self._profile = None
        self._command_factory = None
        self._setup = None
        self._is_setup_command: bool = FiggyCLI.is_setup_command(args)
        self._utils = Utils(self.get_colors_enabled())
        self._profile = Utils.attr_if_exists(profile, args)
        self._defaults: CLIDefaults = FiggySetup.stc_get_defaults(skip=self._is_setup_command, profile=self._profile)
        self._run_env = self._defaults.run_env
        role_override = Utils.attr_if_exists(role, args)
        self._role: Role = self.get_role(args.prompt, role_override=role_override, is_setup=self._is_setup_command)

        FiggyCLI.validate_environment(self._defaults)

        if not self._is_setup_command:
            if not hasattr(args, 'env') or args.env is None:
                print(f"{EMPTY_ENV_HELP_TEXT}{self._run_env.env}\n")
            else:
                Utils.stc_validate(args.env in self._defaults.valid_envs,
                                   f'{ENV_HELP_TEXT} {self._defaults.valid_envs}. Provided: {args.env}')
                self._run_env = RunEnv(env=args.env)

        self._utils.validate(Utils.attr_exists(configure, args) or Utils.attr_exists(command, args),
                             f"No command found. Proper format is `{CLI_NAME} <resource> <command> --option(s)`")

        self._assumable_role = self.find_assumable_role(self._run_env, self._role, skip=self._is_setup_command,
                                                        profile=self._profile)

        command_name = Utils.attr_if_exists(command, args)
        resource_name = Utils.attr_if_exists(resource, args)

        found_command: CliCommand = Utils.find_command(str(command_name))
        found_resource: CliCommand = Utils.find_resource(str(resource_name))

        self._context: FiggyContext = FiggyContext(self.get_colors_enabled(), found_resource, found_command,
                                                   self._run_env, self._assumable_role, args)
Esempio n. 13
0
    def __setup(self) -> FiggySetup:
        if not self._setup:
            self._setup = FiggySetup(self._context)

        return self._setup