def add_profile(args): if args.external_id and not args.role_to_assume: _print_error("Error: Cannot use --external-id without --role.") sys.exit(1) keyring = Keyring() if keyring.get_profile(args.profile): _print_error(f"Error: Profile \"{args.profile}\" already exists. If you want to modify " "the profile, remove the profile and add it again.") sys.exit(1) jumpcloud_url = args.url or input(f"Enter the JumpCloud SSO URL for \"{args.profile}\": ") jumpcloud_url = jumpcloud_url.strip() if not jumpcloud_url.startswith("https://sso.jumpcloud.com/saml2/"): _print_error("Error: That's not a valid JumpCloud SSO URL. SSO URLs must " "start with \"https://sso.jumpcloud.com/saml2/\".") sys.exit(1) if args.role_to_assume: if is_arn(args.role_to_assume): arn_parts = parse_arn(args.role_to_assume) assumed_role = AssumedRole(aws_account_id=arn_parts.aws_account_id, aws_role=arn_parts.aws_role, external_id=args.external_id) else: assumed_role = AssumedRole(aws_account_id=None, aws_role=args.role_to_assume, external_id=args.external_id) else: assumed_role = None profile = Profile(args.profile, jumpcloud_url, assumed_role) keyring.store_profile(profile) print(f"Profile \"{args.profile}\" added.")
def _remove_all_profiles(args): keyring = Keyring() keyring.delete_all_data() print("") print( "All configuration profiles, temporary IAM sessions, and JumpCloud login" ) print("credentials have been removed from your OS keychain.")
def get_info(args): keyring = Keyring() print("") email = keyring.get_jumpcloud_email() password = keyring.get_jumpcloud_password() ts = keyring.get_jumpcloud_timestamp() print(f"JumpCloud email: {email or '<not stored>'}") print(f"JumpCloud password: {'******** (hidden)' if password else '<not stored>'}") print(f"Last JumpCloud authentication: {ts.astimezone().strftime('%c %Z') if ts else '<never>'}")
def list_profiles(args): keyring = Keyring() profiles = keyring.get_all_profiles() sessions = keyring.get_all_sessions() if len(profiles) == 0: print("") print("No profiles found. Use \"aws-jumpcloud add <profile>\" to store a new profile.") sys.exit(0) print("") _print_columns(headers=["Profile", "AWS Account", "AWS Role", "IAM session expires"], rows=_format_profile_rows(profiles, sessions))
def _rotate_all_sessions(args): keyring = Keyring() profiles = keyring.get_all_profiles() if len(profiles) == 0: print("") print("No profiles found. Use \"aws-jumpcloud add <profile>\" to store a new profile.") sys.exit(0) _login_to_jumpcloud('--all') print("") for profile in profiles.values(): _rotate_single_session(args, profile.name)
def _get_aws_session(profile_name): # Validates the profile parameter and returns the profile's AWS session, # going through the single sign-on process if necessary. This is a wrapper # around _login_to_jumpcloud() and _login_to_aws(). keyring = Keyring() profile = keyring.get_profile(profile_name) if not profile: _print_error(f"Error: Profile \"{profile_name}\" not found; you must add it first.") sys.exit(1) session = keyring.get_session(profile_name) if not session: _login_to_aws(keyring, profile) session = keyring.get_session(profile_name) return session
def _authenticate(self, otp=None): assert not self.logged_in headers = { "Content-Type": "application/json", "X-Requested-With": "XMLHttpRequest", "X-Xsrftoken": self._get_xsrf_token(), } data = {"email": self.email, "password": self.password} if otp is not None: data["otp"] = otp auth_resp = self.http.post( "https://console.jumpcloud.com/userconsole/auth", headers=headers, json=data, allow_redirects=False, timeout=JumpCloudSession.HTTP_TIMEOUT, ) if auth_resp.status_code == 200: self.logged_in = True Keyring().store_jumpcloud_timestamp(datetime.now(tz=timezone.utc)) else: raise self._auth_failure_exception(auth_resp, otp)
def _remove_single_profile(args): keyring = Keyring() if not keyring.get_profile(args.profile): print(f'Profile "{args.profile}" not found, nothing to do.') return has_session = not not keyring.get_session(args.profile) keyring.delete_session(args.profile) keyring.delete_profile(args.profile) if has_session: print(f'Profile "{args.profile}" and temporary IAM session removed.') else: print(f'Profile "{args.profile}" removed.')
def _rotate_single_session(args, profile_name=None): if not profile_name: profile_name = args.profile assert(profile_name is not None) keyring = Keyring() profile = keyring.get_profile(profile_name) if not profile: sys.stderr.write(f"Error: Profile \"{profile_name}\" not found.\n") sys.exit(1) _login_to_jumpcloud(profile_name) keyring.delete_session(profile_name) print(f"Temporary IAM session for \"{profile_name}\" removed.") _login_to_aws(keyring, profile) session = keyring.get_session(profile_name) expires_at = session.expires_at.strftime('%c %Z') print(f"AWS temporary session rotated; new session valid until {expires_at}.\n")
def _login_to_jumpcloud(profile_name): # Returns a JumpCloudSession with the user logged in. If a session already # in the current process, it uses that; otherwise it creates a new one. global _session if _session: return _session keyring = Keyring() email = keyring.get_jumpcloud_email() password = keyring.get_jumpcloud_password() if email and password: sys.stderr.write( "Using JumpCloud login details from your OS keychain.\n") elif sys.stdout.isatty(): email = _get_email() password = _get_password() keyring.store_jumpcloud_email(email) keyring.store_jumpcloud_password(password) sys.stderr.write( "JumpCloud login details saved in your OS keychain.\n") else: _print_error( "Error: JumpCloud login details not found in your OS keychain. " f'Run "{_get_program_name()} rotate {profile_name}" interactively ' "to store your credentials in the keychain, then try again.") sys.exit(1) session = JumpCloudSession(email, password) try: session.login() except JumpCloudError as e: sys.stderr.write("\n") _print_error(f"Error: {e.message}") if isinstance(e, JumpCloudAuthFailure): keyring.store_jumpcloud_email(None) keyring.store_jumpcloud_password(None) _print_error( "- You will be prompted for your username and password the next time you try." ) elif isinstance(e, JumpCloudMFARequired): _print_error( f'Run "{_get_program_name()} rotate {profile_name}" interactively to ' "refresh the temporary credentials in your OS keychain, then try again." ) elif isinstance(e, JumpCloudServerError): _print_error( f"- JumpCloud error message: {e.jumpcloud_error_message or e.response.text}" ) sys.exit(1) _session = session return _session
def is_active(args): keyring = Keyring() sess = keyring.get_session(args.profile) if sess and not sess.expired(): print(1)