def sso_authenticate_post(): if settings.app.sso != DUO_AUTH or \ settings.app.sso_duo_mode == 'passcode': return flask.abort(405) username = utils.json_filter_str('username') usernames = [username] email = None if '@' in username: email = username usernames.append(username.split('@')[0]) valid = False for i, username in enumerate(usernames): try: duo_auth = sso.Duo( username=username, factor=settings.app.sso_duo_mode, remote_ip=utils.get_remote_addr(), auth_type='Key', ) valid = duo_auth.authenticate() break except InvalidUser: if i == len(usernames) - 1: logger.warning( 'Invalid duo username', 'sso', username=username, ) if valid: valid, org_id, groups = sso.plugin_sso_authenticate( sso_type='duo', user_name=username, user_email=email, remote_ip=utils.get_remote_addr(), ) if not valid: logger.warning( 'Duo plugin authentication not valid', 'sso', username=username, ) return flask.abort(401) groups = set(groups or []) else: logger.warning( 'Duo authentication not valid', 'sso', username=username, ) return flask.abort(401) if not org_id: org_id = settings.app.sso_org return _validate_user(username, email, DUO_AUTH, org_id, groups)
def auth_session_post(): username = utils.json_filter_str('username') password = utils.json_str('password') otp_code = utils.json_opt_filter_str('otp_code') yubico_key = utils.json_opt_filter_str('yubico_key') remote_addr = utils.get_remote_addr() time.sleep(random.randint(50, 100) / 1000.) admin = auth.get_by_username(username) if not admin: if settings.app.sso and RADIUS_AUTH in settings.app.sso: return _auth_radius(username, password) time.sleep(random.randint(0, 100) / 1000.) return _auth_plugin(username, password) if (not otp_code and admin.otp_auth) or \ (not yubico_key and admin.yubikey_id): return utils.jsonify( { 'error': AUTH_OTP_REQUIRED, 'error_msg': AUTH_OTP_REQUIRED_MSG, 'otp_auth': admin.otp_auth, 'yubico_auth': bool(admin.yubikey_id), }, 402) if not limiter.auth_check(admin.id): return utils.jsonify( { 'error': AUTH_TOO_MANY, 'error_msg': AUTH_TOO_MANY_MSG, }, 400) if not admin.auth_check(password, otp_code, yubico_key, remote_addr): time.sleep(random.randint(0, 100) / 1000.) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) flask.session['session_id'] = admin.new_session() flask.session['admin_id'] = str(admin.id) flask.session['timestamp'] = int(utils.time_now()) if not settings.app.server_ssl: flask.session['source'] = remote_addr utils.set_flask_sig() return utils.jsonify({ 'authenticated': True, 'default': admin.default or False, })
def auth_session_post(): username = utils.json_filter_str('username') password = utils.json_str('password') otp_code = utils.json_opt_filter_str('otp_code') yubico_key = utils.json_opt_filter_str('yubico_key') remote_addr = utils.get_remote_addr() time.sleep(random.randint(50, 100) / 1000.) admin = auth.get_by_username(username, remote_addr) if not admin: if settings.app.sso and RADIUS_AUTH in settings.app.sso: return _auth_radius(username, password) time.sleep(random.randint(0, 100) / 1000.) return _auth_plugin(username, password) if (not otp_code and admin.otp_auth) or \ (not yubico_key and admin.yubikey_id): return utils.jsonify({ 'error': AUTH_OTP_REQUIRED, 'error_msg': AUTH_OTP_REQUIRED_MSG, 'otp_auth': admin.otp_auth, 'yubico_auth': bool(admin.yubikey_id), }, 402) if not admin.auth_check(password, otp_code, yubico_key, remote_addr): time.sleep(random.randint(0, 100) / 1000.) return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) flask.session['session_id'] = admin.new_session() flask.session['admin_id'] = str(admin.id) flask.session['timestamp'] = int(utils.time_now()) if not settings.app.server_ssl: flask.session['source'] = remote_addr utils.set_flask_sig() return utils.jsonify({ 'authenticated': True, 'default': admin.default or False, })
def sso_authenticate_post(): if settings.app.sso != DUO_AUTH or \ settings.app.sso_duo_mode == 'passcode': return flask.abort(405) username = utils.json_filter_str('username') usernames = [username] email = None if '@' in username: email = username usernames.append(username.split('@')[0]) valid = False for i, username in enumerate(usernames): try: duo_auth = sso.Duo( username=username, factor=settings.app.sso_duo_mode, remote_ip=utils.get_remote_addr(), auth_type='Key', ) valid = duo_auth.authenticate() break except InvalidUser: if i == len(usernames) - 1: logger.error( 'Invalid duo username', 'sso', username=username, ) if valid: valid, org_id, groups = sso.plugin_sso_authenticate( sso_type='duo', user_name=username, user_email=email, remote_ip=utils.get_remote_addr(), ) if not valid: logger.error( 'Duo plugin authentication not valid', 'sso', username=username, ) return flask.abort(401) else: logger.error( 'Duo authentication not valid', 'sso', username=username, ) return flask.abort(401) if not org_id: org_id = settings.app.sso_org org = organization.get_by_id(org_id) if not org: logger.error( 'Organization for Duo sso does not exist', 'sso', org_id=org_id, ) return flask.abort(405) usr = org.find_user(name=username) if not usr: usr = org.new_user(name=username, email=email, type=CERT_CLIENT, auth_type=DUO_AUTH, groups=list(groups) if groups else None) usr.audit_event('user_created', 'User created with single sign-on', remote_addr=utils.get_remote_addr()) event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) else: if usr.disabled: return flask.abort(403) if groups and groups - set(usr.groups or []): usr.groups = list(set(usr.groups or []) | groups) usr.commit('groups') if usr.auth_type != DUO_AUTH: usr.auth_type = DUO_AUTH usr.commit('auth_type') event.Event(type=USERS_UPDATED, resource_id=org.id) key_link = org.create_user_key_link(usr.id, one_time=True) usr.audit_event( 'user_profile', 'User profile viewed from single sign-on', remote_addr=utils.get_remote_addr(), ) return utils.get_url_root() + key_link['view_url']
def auth_session_post(): username = utils.json_filter_str('username')[:128] password = flask.request.json['password'] if password: password = password[:128] otp_code = utils.json_opt_filter_str('otp_code') if otp_code: otp_code = otp_code[:64] yubico_key = utils.json_opt_filter_str('yubico_key') if yubico_key: yubico_key = yubico_key[:128] remote_addr = utils.get_remote_addr() time.sleep(random.randint(50, 100) / 1000.) admin = auth.get_by_username(username) if not admin: if settings.app.sso and RADIUS_AUTH in settings.app.sso: return _auth_radius(username, password, remote_addr) time.sleep(random.randint(0, 100) / 1000.) return _auth_plugin(username, password, remote_addr) if (not otp_code and admin.otp_auth) or \ (not yubico_key and admin.yubikey_id): return utils.jsonify( { 'error': AUTH_OTP_REQUIRED, 'error_msg': AUTH_OTP_REQUIRED_MSG, 'otp_auth': admin.otp_auth, 'yubico_auth': bool(admin.yubikey_id), }, 402) if not limiter.auth_check(admin.id): journal.entry( journal.ADMIN_AUTH_FAILURE, admin.journal_data, remote_address=remote_addr, reason=journal.ADMIN_AUTH_REASON_RATE_LIMIT, reason_long='Too many authentication attempts', ) return utils.jsonify( { 'error': AUTH_TOO_MANY, 'error_msg': AUTH_TOO_MANY_MSG, }, 400) if not admin.auth_check(password, otp_code, yubico_key, remote_addr): time.sleep(random.randint(0, 100) / 1000.) return utils.jsonify( { 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) flask.session['session_id'] = admin.new_session() flask.session['admin_id'] = str(admin.id) flask.session['timestamp'] = int(utils.time_now()) if not settings.app.server_ssl: flask.session['source'] = remote_addr journal.entry( journal.ADMIN_SESSION_START, admin.journal_data, remote_address=remote_addr, session_id=flask.session['session_id'], ) utils.set_flask_sig() return utils.jsonify({ 'authenticated': True, 'default': admin.default or False, })
def sso_authenticate_post(): if settings.app.sso != DUO_AUTH or settings.app.sso_duo_mode == "passcode": return flask.abort(405) username = utils.json_filter_str("username") usernames = [username] email = None if "@" in username: email = username usernames.append(username.split("@")[0]) valid = False for i, username in enumerate(usernames): try: duo_auth = sso.Duo( username=username, factor=settings.app.sso_duo_mode, remote_ip=utils.get_remote_addr(), auth_type="Key" ) valid = duo_auth.authenticate() break except InvalidUser: if i == len(usernames) - 1: logger.error("Invalid duo username", "sso", username=username) if valid: valid, org_id, groups = sso.plugin_sso_authenticate( sso_type="duo", user_name=username, user_email=email, remote_ip=utils.get_remote_addr() ) if not valid: logger.error("Duo plugin authentication not valid", "sso", username=username) return flask.abort(401) else: logger.error("Duo authentication not valid", "sso", username=username) return flask.abort(401) if not org_id: org_id = settings.app.sso_org org = organization.get_by_id(org_id) if not org: logger.error("Organization for Duo sso does not exist", "sso", org_id=org_id) return flask.abort(405) usr = org.find_user(name=username) if not usr: usr = org.new_user( name=username, email=email, type=CERT_CLIENT, auth_type=DUO_AUTH, groups=list(groups) if groups else None ) usr.audit_event("user_created", "User created with single sign-on", remote_addr=utils.get_remote_addr()) event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) else: if usr.disabled: return flask.abort(403) if groups and groups - set(usr.groups or []): usr.groups = list(set(usr.groups or []) | groups) usr.commit("groups") if usr.auth_type != DUO_AUTH: usr.auth_type = DUO_AUTH usr.commit("auth_type") event.Event(type=USERS_UPDATED, resource_id=org.id) key_link = org.create_user_key_link(usr.id, one_time=True) usr.audit_event("user_profile", "User profile viewed from single sign-on", remote_addr=utils.get_remote_addr()) return utils.get_url_root() + key_link["view_url"]
def sso_authenticate_post(): if settings.app.sso != DUO_AUTH or \ settings.app.sso_duo_mode == 'passcode': return flask.abort(405) remote_addr = utils.get_remote_addr() username = utils.json_filter_str('username') usernames = [username] email = None if '@' in username: email = username usernames.append(username.split('@')[0]) valid = False for i, username in enumerate(usernames): try: duo_auth = sso.Duo( username=username, factor=settings.app.sso_duo_mode, remote_ip=remote_addr, auth_type='Key', ) valid = duo_auth.authenticate() break except InvalidUser: if i == len(usernames) - 1: logger.warning('Invalid duo username', 'sso', username=username, ) if valid: valid, org_id, groups = sso.plugin_sso_authenticate( sso_type='duo', user_name=username, user_email=email, remote_ip=remote_addr, ) if not valid: logger.warning('Duo plugin authentication not valid', 'sso', username=username, ) journal.entry( journal.SSO_AUTH_FAILURE, user_name=username, remote_address=remote_addr, reason=journal.SSO_AUTH_REASON_PLUGIN_FAILED, reason_long='Duo plugin authentication failed', ) return flask.abort(401) groups = set(groups or []) else: logger.warning('Duo authentication not valid', 'sso', username=username, ) journal.entry( journal.SSO_AUTH_FAILURE, user_name=username, remote_address=remote_addr, reason=journal.SSO_AUTH_REASON_DUO_FAILED, reason_long='Duo authentication failed', ) return flask.abort(401) if not org_id: org_id = settings.app.sso_org return _validate_user(username, email, DUO_AUTH, org_id, groups, remote_addr)
def auth_user_post(): if settings.app.demo_mode: return utils.demo_blocked() auth_token = flask.request.headers.get('Auth-Token', None) auth_timestamp = flask.request.headers.get('Auth-Timestamp', None) auth_nonce = flask.request.headers.get('Auth-Nonce', None) auth_signature = flask.request.headers.get('Auth-Signature', None) if not auth_token or not auth_timestamp or not auth_nonce or \ not auth_signature: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) auth_nonce = auth_nonce[:32] try: if abs(int(auth_timestamp) - int(utils.time_now())) > \ settings.app.auth_time_window: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) except ValueError: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) org = organization.get_by_token(auth_token) if not org: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) auth_string = '&'.join([ auth_token, auth_timestamp, auth_nonce, flask.request.method, flask.request.path, ] + ([flask.request.data] if flask.request.data else [])) if len(auth_string) > AUTH_SIG_STRING_MAX_LEN: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) if not org.auth_secret or len(org.auth_secret) < 8: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) auth_test_signature = base64.b64encode(hmac.new( org.auth_secret.encode(), auth_string, hashlib.sha256).digest()) if auth_signature != auth_test_signature: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) try: org.nonces_collection.insert({ 'token': auth_token, 'nonce': auth_nonce, 'timestamp': utils.now(), }) except pymongo.errors.DuplicateKeyError: return utils.jsonify({ 'error': AUTH_INVALID, 'error_msg': AUTH_INVALID_MSG, }, 401) username = utils.json_filter_str('username') network_links = flask.request.json.get('network_links') usr = org.find_user(name=username) if usr: usr.remove() usr = org.new_user(name=username, type=CERT_CLIENT) usr.audit_event('user_created', 'User created with authentication token', remote_addr=utils.get_remote_addr()) if network_links: for network_link in network_links: try: usr.add_network_link(network_link, force=True) except (ipaddress.AddressValueError, ValueError): return _network_link_invalid() event.Event(type=ORGS_UPDATED) event.Event(type=USERS_UPDATED, resource_id=org.id) event.Event(type=SERVERS_UPDATED) keys = {} for svr in org.iter_servers(): key = usr.build_key_conf(svr.id) keys[key['name']] = key['conf'] return utils.jsonify(keys)