def __init__(self, context: FiggyContext): self._cache_mgr = CacheManager(file_override=DEFAULTS_FILE_CACHE_PATH) self._config_mgr, self.c = ConfigManager.figgy(), Utils.default_colors() self._session_mgr = None self._session_provider = None self._secrets_mgr = SecretsManager() self._figgy_context = context
def configure(mfa_enabled: bool = False) -> "GoogleProviderConfig": config, c = ConfigManager(CONFIG_OVERRIDE_FILE_PATH), Utils.default_colors() idp_id = config.get_property(Config.Section.Google.IDP_ID) sp_id = config.get_property(Config.Section.Google.SP_ID) if idp_id and idp_id != FAKE_GOOGLE_IDP_ID: idp_id = config.get_or_prompt(Config.Section.Google.IDP_ID, GoogleProviderConfig.get_idp_id) else: idp_id = config.get_or_prompt(Config.Section.Google.IDP_ID, GoogleProviderConfig.get_idp_id, force_prompt=True) if sp_id and sp_id != FAKE_GOOGLE_SP_ID: sp_id = config.get_or_prompt(Config.Section.Google.SP_ID, GoogleProviderConfig.get_sp_id) else: sp_id = config.get_or_prompt(Config.Section.Google.SP_ID, GoogleProviderConfig.get_sp_id, force_prompt=True) return GoogleProviderConfig(idp_id=idp_id, sp_id=sp_id)
def configure(mfa_enabled: bool = False) -> "OktaProviderConfig": config, c = ConfigManager(CONFIG_OVERRIDE_FILE_PATH), Utils.default_colors() app_link = config.get_property(Config.Section.Google.IDP_ID) if app_link and app_link != FAKE_OKTA_APP_LINK: app_link = config.get_or_prompt(Config.Section.Okta.APP_LINK, OktaProviderConfig.get_app_link, desc=OKTA_APP_LINK_DESC) else: app_link = config.get_or_prompt(Config.Section.Okta.APP_LINK, OktaProviderConfig.get_app_link, force_prompt=True, desc=OKTA_APP_LINK_DESC) if mfa_enabled: factor_type = config.get_or_prompt(Config.Section.Okta.FACTOR_TYPE, OktaProviderConfig.get_factor_type, desc=OKTA_MFA_TYPE_DESC) else: factor_type = None return OktaProviderConfig(app_link=app_link, factor_type=factor_type)
def configure(mfa_enabled: bool = False) -> "BastionProviderConfig": config, c = ConfigManager(CONFIG_OVERRIDE_FILE_PATH), Utils.default_colors() profile = config.get_or_prompt(Config.Section.Bastion.PROFILE, BastionProviderConfig.get_profile) return BastionProviderConfig(profile_name=profile)
def __init__(self, color: Color = Color(False)): self.init_files() self.c = color self._config = ConfigManager(AWS_CONFIG_FILE_PATH) self._creds = ConfigManager(AWS_CREDENTIALS_FILE_PATH)
class AWSConfig: """ Utility methods for interacting with AWSCLI resources, such as the ~/.aws/credentials and ~/.aws/config files """ def __init__(self, color: Color = Color(False)): self.init_files() self.c = color self._config = ConfigManager(AWS_CONFIG_FILE_PATH) self._creds = ConfigManager(AWS_CREDENTIALS_FILE_PATH) @staticmethod def init_files(): os.makedirs(os.path.dirname(AWS_CREDENTIALS_FILE_PATH), exist_ok=True) if not os.path.exists(AWS_CREDENTIALS_FILE_PATH): with open(AWS_CREDENTIALS_FILE_PATH, "w+") as file: file.write("") if not os.path.exists(AWS_CONFIG_FILE_PATH): with open(AWS_CONFIG_FILE_PATH, "w+") as file: file.write("") def _is_temporary_session(self, profile_name: str): if self._creds.has_section(profile_name): return self._creds.has_option(profile_name, AWS_CFG_TOKEN) return False def _backup_section(self, section: str): backup_name, backup_profile = f'{section}-figgy-backup', f'profile {section}-figgy-backup' profile_name = f'profile {section}' if self._creds.has_section(section): for opt in self._creds.options(section): self._creds.set_config(backup_name, opt, self._creds.get_option(section, opt)) if self._config.has_section(profile_name): for opt in self._config.options(profile_name): self._config.set_config( backup_profile, opt, self._config.get_option(profile_name, opt)) def restore(self, profile_name: str): """ Restore a credentials previously backed up by Figgy """ config_profile = f'profile {profile_name}' backup_name, backup_profile = f'{profile_name}-figgy-backup', f'profile {profile_name}-figgy-backup' creds_restored, config_restored = False, False if self._creds.has_section(backup_name): for opt in self._creds.options(backup_name): self._creds.set_config( profile_name, opt, self._creds.get_option(backup_name, opt)) creds_restored = True if self._config.has_section(backup_profile): for opt in self._config.options(backup_profile): self._config.set_config( config_profile, opt, self._config.get_option(backup_profile, opt)) config_restored = True self._creds.delete(profile_name, AWS_CFG_TOKEN) self._creds.save() self._config.save() if creds_restored and config_restored: print(f"\n{self.c.fg_gr}Restoration successful!{self.c.rs}") else: print( f"\n{self.c.fg_yl}Unable to restore credentials. Profile: " f"{self.c.fg_bl}[{backup_name}]{self.c.rs}{self.c.fg_yl} was not found in either the " f"~/.aws/credentials or ~/.aws/config files.{self.c.rs}") def write_credentials(self, access_key: str, secret_key: str, token: str, region: str, profile_name: str = 'default') -> None: """ Overwrite credentials stored in the [default] profile in both ~/.aws/config and ~/.aws/credentials file with the provided temporary credentials. This method also CREATES these files if they do not already exist. """ if not self._is_temporary_session(profile_name): print( f"\n{self.c.fg_yl}Existing AWS Profile {self.c.fg_bl}[{profile_name}]{self.c.rs}{self.c.fg_yl} " f"was found with long-lived access keys " f"in file: {self.c.fg_bl}~/.aws/credentials{self.c.rs}{self.c.fg_yl}.\n" f"To avoid overwriting these keys, they will be moved under profile: " f"{self.c.rs}{self.c.fg_bl}[{profile_name}-figgy-backup]{self.c.rs}{self.c.fg_yl}.{self.c.rs}\n\n" f"These old keys may be restored with: {self.c.fg_bl}`" f"{CLI_NAME} iam restore`{self.c.rs}.") self._backup_section(profile_name) self._creds.set_config(profile_name, AWS_CFG_ACCESS_KEY_ID, access_key) self._creds.set_config(profile_name, AWS_CFG_SECRET_KEY, secret_key) self._creds.set_config(profile_name, AWS_CFG_TOKEN, token) config_section = f'profile {profile_name}' self._config.set_config(config_section, AWS_CFG_REGION, region) self._config.set_config(config_section, AWS_CFG_OUTPUT, 'json') print( f"\n\n{self.c.fg_gr}Successfully updated: {AWS_CREDENTIALS_FILE_PATH}{self.c.rs}" ) print( f"{self.c.fg_gr}Successfully updated: {AWS_CONFIG_FILE_PATH}{self.c.rs}" )
def login_sandbox(self): """ If user provides --role flag, skip role & env selection for a smoother user experience. """ EnvironmentValidator(self._defaults).validate_environment_variables() Utils.wipe_vaults() or Utils.wipe_defaults( ) or Utils.wipe_config_cache() self._out.print( f"{self.c.fg_bl}Logging you into the Figgy Sandbox environment.{self.c.rs}" ) user = Input.input("Please input a user name: ", min_length=2) colors = Input.select_enable_colors() # Prompt user for role if --role not provided if commands.role not in self.context.options: role = Input.select("\n\nPlease select a role to impersonate: ", valid_options=SANDBOX_ROLES) else: role = self.context.role.role self._utils.validate( role in SANDBOX_ROLES, f"Provided role: >>>`{role}`<<< is not a valid sandbox role." f" Please choose from {SANDBOX_ROLES}") params = {'role': role, 'user': user} result = requests.get(GET_SANDBOX_CREDS_URL, params=params) if result.status_code != 200: self._utils.error_exit( "Unable to get temporary credentials from the Figgy sandbox. If this problem " f"persists please notify us on our GITHUB: {FIGGY_GITHUB}") data = result.json() response = SandboxLoginResponse(**data) self._aws_cfg.write_credentials( access_key=response.AWS_ACCESS_KEY_ID, secret_key=response.AWS_SECRET_ACCESS_KEY, token=response.AWS_SESSION_TOKEN, region=FIGGY_SANDBOX_REGION, profile_name=FIGGY_SANDBOX_PROFILE) defaults = CLIDefaults.sandbox(user=user, role=role, colors=colors) self._setup.save_defaults(defaults) run_env = RunEnv( env='dev', account_id=SANDBOX_DEV_ACCOUNT_ID) if self.context.role else None config_mgr = ConfigManager.figgy() config_mgr.set(Config.Section.Bastion.PROFILE, FIGGY_SANDBOX_PROFILE) defaults = self._setup.configure_extras(defaults) defaults = self._setup.configure_roles(current_defaults=defaults, role=Role(role=role), run_env=run_env) defaults = self._setup.configure_figgy_defaults(defaults) self._setup.save_defaults(defaults) self._out.success( f"\nLogin successful. Your sandbox session will last for [[1 hour]]." ) self._out.print( f"\nIf your session expires, you may rerun `{CLI_NAME} login sandbox` to get another sandbox session. " f"\nAll previous figgy sessions have been disabled, you'll need to run {CLI_NAME} " f"--configure to leave the sandbox.")