tryd to fix a oid connect related bug, but there is still a BIG problem

This commit is contained in:
2020-07-24 16:45:18 +02:00
parent 1d4c4c8ec2
commit de398d189a
7 changed files with 86 additions and 30 deletions

View File

@@ -5,11 +5,12 @@
import logging
import ssl
import sys
import threading
from jinja2.exceptions import TemplateNotFound
from backend import app, db
from backend.cron import get_default_scheduler, add_default_jobs
from backend.cron import get_default_scheduler, add_default_jobs, async_permanent_cron_recorder_checker
from backend.models import *
from backend.models import room_model, recorder_model, RecorderCommand, Recorder
from backend.recorder_adapters import get_defined_recorder_adapters
@@ -17,13 +18,30 @@ from backend.tools.model_updater import update_recorder_models_database, create_
from backend.websocket.base import WebSocketBase
def _start_initial_recorder_state_update(run_in_thread=True):
if run_in_thread:
thread = threading.Thread(target=async_permanent_cron_recorder_checker.check_object_state, args=())
thread.start()
else:
async_permanent_cron_recorder_checker.check_object_state() # initial check of all recorders
def _create_and_start_default_scheduler():
print("Starting Scheduler")
scheduler = get_default_scheduler()
add_default_jobs(scheduler)
scheduler.start()
return scheduler
def main():
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#db.drop_all()
#db.create_all()
# db.drop_all()
# db.create_all()
#Recorder()
# Recorder()
room_model.pre_fill_table()
update_recorder_models_database(drop=False)
create_default_recorders()
@@ -44,16 +62,14 @@ def main():
except Exception as e:
logging.critical(e)
print("Starting Scheduler")
scheduler = get_default_scheduler()
add_default_jobs(scheduler)
scheduler.start()
scheduler = _create_and_start_default_scheduler()
#_start_initial_recorder_state_update(run_in_thread=False)
wsb = WebSocketBase()
print("running websocket...(replaces normal app.run()")
wsb.start_websocket(debug=True)
# print("running web app...")
#app.run(debug=True, host="0.0.0.0", threaded=True)
# app.run(debug=True, host="0.0.0.0", threaded=True)
wsb.send_test_msg()
while True:

View File

@@ -7,6 +7,7 @@ Login through API does not start a new session, but instead returns JWT.
"""
import base64
import json
import logging
from pprint import pprint
import flask
@@ -29,6 +30,8 @@ from backend.api import auth_api_bp, auth_api_providers_ns, auth_api_register_ns
from backend.auth import AUTH_PROVIDERS, oidc_auth
from backend.models.user_model import User, Group, BlacklistToken
logger = logging.getLogger("lrc.api.auth")
@auth_api_bp.route('/providers', methods=('GET',))
def get_auth_providers():
@@ -92,6 +95,7 @@ def login():
}
return jsonify(token), 200
# Endpoint for revoking the current users access token
@auth_api_bp.route('/logout', methods=['GET', 'DELETE'])
@jwt_required
@@ -135,7 +139,7 @@ def create_or_retrieve_user_from_userinfo(userinfo):
user = User.get_by_identifier(email)
if user is not None:
app.logger.info("user found -> update user")
logger.info("user found -> update user")
pprint(user.to_dict())
user.first_name = userinfo.get("given_name", "")
user.last_name = userinfo.get("family_name", "")
@@ -148,7 +152,7 @@ def create_or_retrieve_user_from_userinfo(userinfo):
last_name=userinfo.get("family_name", ""), external_user=True,
groups=user_groups)
app.logger.info("creating new user")
logger.info("creating new user")
db.session.add(user)
db.session.commit()
@@ -159,8 +163,11 @@ def create_or_retrieve_user_from_userinfo(userinfo):
@auth_api_bp.route('/oidc/<redirect_url>', methods=['GET'])
@oidc_auth.oidc_auth()
def oidc(redirect_url=None):
logger.debug("oidc auth endpoint:")
return "fuck!"
user = create_or_retrieve_user_from_userinfo(flask.session['userinfo'])
if user is None:
logger.error("Could not authenticate: could not find or create user.")
return "Could not authenticate: could not find or create user.", 401
if current_app.config.get("AUTH_RETURN_EXTERNAL_JWT", False):
token = jwt.encode(flask.session['id_token'], current_app.config['SECRET_KEY'])
@@ -169,13 +176,13 @@ def oidc(redirect_url=None):
'access_token': create_access_token(identity=user, fresh=True),
'refresh_token': create_refresh_token(identity=user)
})
logger.info("Token: {}".format(token))
if redirect_url is None:
redirect_url = request.headers.get("Referer")
if redirect_url is None:
redirect_url = request.args.get('redirect_url')
if redirect_url is None:
redirect_url = "/"
app.logger.info("Token: {}".format(token))
response = make_response(redirect(redirect_url))
response.set_cookie('tokens', base64.b64encode(token.encode('utf-8')))
return response
@@ -189,8 +196,7 @@ def refresh():
as we do not actually verify a password in this endpoint."""
jwt_identity = get_jwt_identity()
user = User.get_by_identifier(jwt_identity)
app.logger.info("Refreshing token for " + str(user))
logger.info("Refreshing token for " + str(user))
new_token = create_access_token(identity=user, fresh=False)
ret = {'access_token': new_token}
return jsonify(ret), 200

View File

@@ -15,7 +15,6 @@ from backend.models.user_model import User
from . import auth_bp
from .oidc_config import PROVIDER_NAME, OIDC_PROVIDERS
OIDCAuthentication.oidc_auth_orig = OIDCAuthentication.oidc_auth
OIDCAuthentication.oidc_logout_orig = OIDCAuthentication.oidc_logout
@@ -46,6 +45,7 @@ def create_or_retrieve_user_from_userinfo(userinfo):
if user is not None:
app.logger.info("user found")
app.logger.debug(f"user found: {email}")
user.last_seen = datetime.utcnow()
# TODO: update user!
db.session.commit()
@@ -54,21 +54,24 @@ def create_or_retrieve_user_from_userinfo(userinfo):
user = User(email=email, first_name=userinfo.get("given_name", ""),
last_name=userinfo.get("family_name", ""))
app.logger.info("creating new user")
app.logger.info(f"creating new user: {email}")
db.session.add(user)
db.session.commit()
return user
@auth_bp.route('/oidc', methods=['GET'])
@oidc_auth.oidc_auth()
def oidc():
user_session = UserSession(flask.session)
app.logger.info(user_session.userinfo)
user = create_or_retrieve_user_from_userinfo(user_session.userinfo)
if user is None:
return ''
login_user(user)
app.logger.info(f"logged in user: {str(user)}")
app.logger.debug(f"id token: {str(user_session.id_token)}")
return jsonify(id_token=user_session.id_token,
access_token=flask.session['access_token'],
userinfo=user_session.userinfo)
@@ -78,3 +81,9 @@ def oidc():
def oidc_logout():
oidc_auth.oidc_logout()
return redirect('/')
@oidc_auth.error_view
def error(error=None, error_description=None):
app.logger.error(f"Something wwent wrong with OIDC auth error: {error}, message: {error_description}")
return jsonify({'error': error, 'message': error_description})

Binary file not shown.

View File

@@ -172,4 +172,4 @@ async_permanent_cron_recorder_checker = StateChecker(
for r in Recorder.get_all():
async_permanent_cron_recorder_checker.add_object_to_state_check(r.id)
async_permanent_cron_recorder_checker.check_object_state() # initial check of all recorders

View File

@@ -1,4 +1,7 @@
from backend import LrcException
import logging
logger = logging.getLogger("lrc.tools.exception_decorator")
def exception_decorator(*exceptions):
@@ -8,6 +11,9 @@ def exception_decorator(*exceptions):
ret = func(*args, **kwargs)
return ret
except exceptions as e:
logger.error(str(e))
raise LrcException(e)
return new_func
return decorator

View File

@@ -11,6 +11,7 @@ from typing import Union
import requests
from requests.auth import HTTPBasicAuth
from requests.exceptions import ConnectionError
from multiprocessing.pool import ThreadPool
from multiprocessing.context import TimeoutError
@@ -26,6 +27,8 @@ from backend.recorder_adapters.extron_smp import SMP35x
from backend.tools.recorder_streams_sanity_checks import check_frame_is_valid, check_if_audio_is_valid
from backend.tools.send_mail import send_error_mail, get_smtp_error_handler
from backend.tools.exception_decorator import exception_decorator
logger = logging.getLogger("lrc.tools.simple_state_checker")
smtp_error_handler = get_smtp_error_handler(subject="Errors have been detected while checking recorder states!")
@@ -50,6 +53,7 @@ agent_states_lock = threading.RLock()
agent_states = {}
@exception_decorator(ConnectionError)
def get_service_url(service_type: str):
if service_type in config['service_urls']:
return config['service_urls'][service_type]
@@ -64,19 +68,23 @@ def get_service_url(service_type: str):
return None
@exception_decorator(ConnectionError)
def get_calender(rec_id):
params = {'agentid': rec_id}
url = get_service_url('org.opencastproject.scheduler') + "/calendars"
res = session.get(url, params=params)
if res.ok:
return Calendar(res.text)
raise LrcException(res.text, res.status_code)
@exception_decorator(ConnectionError)
def get_capture_agents():
url = get_service_url("org.opencastproject.capture.admin") + "/agents.json"
res = session.get(url)
if res.ok:
return res.json()["agents"]["agent"]
raise LrcException(res.text, res.status_code)
def get_recorder_details_old():
@@ -117,19 +125,25 @@ def get_recorder_adapter(recorder_info: Union[dict, Recorder]) -> RecorderAdapte
type = recorder_info.get("type")
except KeyError:
type = RecorderModel.get_by_id(recorder_info.get('recorder_model_id')).model_name
if "SMP" in type:
rec = SMP35x(recorder_info.get('ip'), recorder_info.get('password'))
else:
rec = Epiphan(recorder_info.get('ip'), recorder_info.get("username"), recorder_info.get("password"))
return rec
try:
if "SMP" in type:
rec = SMP35x(recorder_info.get('ip'), recorder_info.get('password'))
else:
rec = Epiphan(recorder_info.get('ip'), recorder_info.get("username"), recorder_info.get("password"))
return rec
except LrcException:
raise
def check_stream_sanity(recorder_agent: Union[Recorder, dict], recorder_adapter: RecorderAdapter = None):
if recorder_adapter is None:
recorder_info = get_recorder_by_name(recorder_agent.get('name'))
recorder_adapter = get_recorder_adapter(recorder_info)
if not recorder_adapter.is_recording():
return True, "not recording, so there is no stream!", recorder_agent.get('name')
try:
if recorder_adapter is None:
recorder_info = get_recorder_by_name(recorder_agent.get('name'))
recorder_adapter = get_recorder_adapter(recorder_info)
if not recorder_adapter.is_recording():
return True, "not recording, so there is no stream!", recorder_agent.get('name')
except LrcException:
return False, "Could not determine if recorder is recording!", recorder_agent.get('name')
if recorder_agent.get('archive_stream1') is None and recorder_agent.get(
'archive_stream2') is None: # fall back to default names and rtsp
archive_stream_1_url = "rtsp://{}/{}".format(recorder_adapter.address, Config.DEFAULT_ARCHIVE_STREAM_1_NAME)
@@ -186,7 +200,12 @@ def check_capture_agent_state(recorder_agent: Union[Recorder, dict]):
return True, "Recorder is in offline / maintenance mode", recorder_agent.get('name')
agent_state_error_msg = None
logger.debug("Checking Agent {}".format(recorder_agent.get('name')))
c = get_calender(recorder_agent.get('name'))
try:
c = get_calender(recorder_agent.get('name'))
except LrcException:
error_msg = "Could not get calender of recorder agent: {}!".format(recorder_agent.get('name'))
logger.fatal(error_msg)
return False, error_msg, recorder_agent.get('name')
is_recording_in_calendar = len(list(c.timeline.now())) >= 1
if is_recording_in_calendar:
logger.info("{} has entry in Calender and should therefore be recording... checking now!".format(