Example #1
0
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.")
Example #2
0
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.")
Example #3
0
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>'}")
Example #4
0
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))
Example #5
0
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)
Example #6
0
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
Example #7
0
    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)
Example #8
0
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.')
Example #9
0
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")
Example #10
0
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
Example #11
0
def is_active(args):
    keyring = Keyring()
    sess = keyring.get_session(args.profile)

    if sess and not sess.expired():
        print(1)