From fb1ba3a3912d9ca2b1bc56c82df7bef69188802e Mon Sep 17 00:00:00 2001 From: Gabriel Carneiro Date: Sat, 8 Feb 2025 22:22:17 -0300 Subject: [PATCH] remove own auth impl in favor of ldap --- .gitignore | 0 README | 35 +++++++ README.md | 0 gunicorn_config.py | 0 requirements.txt | 0 setup.cfg | 0 setup.py | 0 src/stream_auth/__init__.py | 0 src/stream_auth/database/__init__.py | 0 src/stream_auth/database/stream.py | 0 src/stream_auth/database/user.py | 7 +- src/stream_auth/main.py | 0 src/stream_auth/middlewares/__init__.py | 0 src/stream_auth/middlewares/auth.py | 0 src/stream_auth/middlewares/jwt.py | 0 src/stream_auth/models/__init__.py | 0 src/stream_auth/models/ldap.py | 23 +++++ src/stream_auth/models/stream.py | 0 src/stream_auth/models/user.py | 68 +++++++------ src/stream_auth/routes/__init__.py | 0 src/stream_auth/routes/stream.py | 42 +++++--- src/stream_auth/routes/user.py | 124 +++++++++++++++--------- src/stream_auth/settings.py | 2 +- 23 files changed, 207 insertions(+), 94 deletions(-) mode change 100644 => 100755 .gitignore create mode 100755 README mode change 100644 => 100755 README.md mode change 100644 => 100755 gunicorn_config.py mode change 100644 => 100755 requirements.txt mode change 100644 => 100755 setup.cfg mode change 100644 => 100755 setup.py mode change 100644 => 100755 src/stream_auth/__init__.py mode change 100644 => 100755 src/stream_auth/database/__init__.py mode change 100644 => 100755 src/stream_auth/database/stream.py mode change 100644 => 100755 src/stream_auth/database/user.py mode change 100644 => 100755 src/stream_auth/main.py mode change 100644 => 100755 src/stream_auth/middlewares/__init__.py mode change 100644 => 100755 src/stream_auth/middlewares/auth.py mode change 100644 => 100755 src/stream_auth/middlewares/jwt.py mode change 100644 => 100755 src/stream_auth/models/__init__.py create mode 100755 src/stream_auth/models/ldap.py mode change 100644 => 100755 src/stream_auth/models/stream.py mode change 100644 => 100755 src/stream_auth/models/user.py mode change 100644 => 100755 src/stream_auth/routes/__init__.py mode change 100644 => 100755 src/stream_auth/routes/stream.py mode change 100644 => 100755 src/stream_auth/routes/user.py mode change 100644 => 100755 src/stream_auth/settings.py diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/README b/README new file mode 100755 index 0000000..cf504af --- /dev/null +++ b/README @@ -0,0 +1,35 @@ +DOCUMENTAÇÃO STREAM ALICE: + + +PACOTES ENVOLVIDOS: + NGINX + APACHE + +NGINX: + Compilado e instalado manualmente em /usr/local/nginx + Binário: /usr/local/nginx/sbin/nginx + Conf: /usr/local/nginx/conf/nginx.conf + Serviço: TODO + Exemplo/Tutorial usado: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-video-streaming-server-using-nginx-rtmp-on-ubuntu-20-04 + + Server RTMP + Porta: 33000 + DASH (arquivo de vídeo): /var/www/html/stream + Revese proxy apache (substitua VIDEO pela chave usada no OBS): https://alice.dcomp.ufsj.edu.br/cast/dash/VIDEO.mpd + + Player HTML: + Porta: 44000 + Root: /var/www/html/stream/dash_player + Revese proxy apache: https://alice.dcomp.ufsj.edu.br/cast/player + TODO: /VIDEO apos player para pegar a CHAVE + +APACHE: + Reverse proxy: + Config em: /etc/apache2/sites-enabled/alice.dcomp.ufsj.edu.br.conf + ProxyPass: /cast http://localhost:44000 + +OBS: + Configurações>Transmissão> + Serviço: Personalizado + Servidor: rtmp://alice.dcomp.ufsj.edu.br:33000/live + Chave (por enquanto apenas a chave 'test'): A chave será o arquivo gerado na pasta /var/www/html/stream/CHAVE.mpd diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/gunicorn_config.py b/gunicorn_config.py old mode 100644 new mode 100755 diff --git a/requirements.txt b/requirements.txt old mode 100644 new mode 100755 diff --git a/setup.cfg b/setup.cfg old mode 100644 new mode 100755 diff --git a/setup.py b/setup.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/__init__.py b/src/stream_auth/__init__.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/database/__init__.py b/src/stream_auth/database/__init__.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/database/stream.py b/src/stream_auth/database/stream.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/database/user.py b/src/stream_auth/database/user.py old mode 100644 new mode 100755 index 33a70f9..dcdd181 --- a/src/stream_auth/database/user.py +++ b/src/stream_auth/database/user.py @@ -10,7 +10,7 @@ db = TinyDB(settings.USER_DATABASE) query = Query() -def create_user(username: str, password: str): +def create_user(username: str): ''' Creates a new unique user, with a unique stream_key ''' @@ -18,7 +18,7 @@ def create_user(username: str, password: str): if len(db.search(query.username == username)) != 0: raise ValueError("Username already exists.") - user = User(username, password) + user = User(username) while db.search(query.stream_key == user.stream_key): user.regenerate_stream_key() @@ -30,7 +30,8 @@ def search_user(username: str): ''' Search for a specific stream key ''' - return db.search(query.username == username) + seuser = db.search(query.username == username)[0] + return User(seuser['username'], seuser['stream_key']) def search_stream_key(stream_key: str): diff --git a/src/stream_auth/main.py b/src/stream_auth/main.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/middlewares/__init__.py b/src/stream_auth/middlewares/__init__.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/middlewares/auth.py b/src/stream_auth/middlewares/auth.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/middlewares/jwt.py b/src/stream_auth/middlewares/jwt.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/models/__init__.py b/src/stream_auth/models/__init__.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/models/ldap.py b/src/stream_auth/models/ldap.py new file mode 100755 index 0000000..df7f9e7 --- /dev/null +++ b/src/stream_auth/models/ldap.py @@ -0,0 +1,23 @@ +import ldap +# import logging + +SERVER = "ldap://localhost" +BASE_DN = "dc=alice,dc=ufsj,dc=edu,dc=br" + +def authenticate(username, password): + user_dn= f"cn={username},ou=User,{BASE_DN}" + try: + l = ldap.initialize(SERVER) + l.protocol_version = ldap.VERSION3 + l.simple_bind_s(user_dn, password) + except ldap.INVALID_CREDENTIALS: + # logging.warning("PASSWORDS DO NOT MATCH") + return False + except ldap.SERVER_DOWN: + # logging.warning("LDAP SERVER DOWN") + return False + + return True + + +# authenticate('emanuels','123123') diff --git a/src/stream_auth/models/stream.py b/src/stream_auth/models/stream.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/models/user.py b/src/stream_auth/models/user.py old mode 100644 new mode 100755 index b9ae5f2..af11cce --- a/src/stream_auth/models/user.py +++ b/src/stream_auth/models/user.py @@ -10,12 +10,24 @@ from stream_auth.middlewares import jwt STREAM_KEY_LENGTH = 64 -def generate_stream_key(key_length: int): - ''' - Generate a new stream key - ''' - key_types = string.ascii_letters + string.digits - return ''.join(random.choice(key_types) for i in range(key_length)) +# def generate_stream_key(key_length: int): +# ''' +# Generate a new stream key +# ''' +# key_types = string.ascii_letters + string.digits +# return ''.join(random.choice(key_types) for i in range(key_length)) + + +# def hash_password(password: str): +# salt = bcrypt.gensalt() +# password = str(bcrypt.hashpw(password.encode('utf-8'), salt), 'utf-8') +# return password +# +# +# def check_password(password: str, hash_password: str): +# input_pass = password.encode('utf-8') +# result = bcrypt.checkpw(input_pass, hash_password.encode('utf-8')) +# return result class User: @@ -23,31 +35,31 @@ class User: User class, for managing a specific user ''' - def __init__(self, username: str, password: str): - salt = bcrypt.gensalt() - self.username = username - self.password = str(bcrypt.hashpw(password.encode('utf-8'), salt), 'utf-8') + def __init__(self, username: str, stream_key: str = None): + # salt = bcrypt.gensalt() + # self.password = hash_password(password) # self.stream_key = generate_stream_key(STREAM_KEY_LENGTH) - self.stream_key = jwt.create_stream_key(username) - self.live = False + self.username = username + self.stream_key = jwt.create_stream_key(username) if stream_key is None else stream_key + # self.live = False - def check_passwrod(self, password: str): - input_pass = password.encode('utf-8') - result = bcrypt.checkpw(input_pass, self.password.encode('utf-8')) - return result + # def check_passwrod(self, password: str): + # input_pass = password.encode('utf-8') + # result = bcrypt.checkpw(input_pass, self.password.encode('utf-8')) + # return result - def change_password(self, current_password: str, new_password: str): - ''' - Changes user defualt password - ''' - ecpass = current_password.encode('utf-8') - enpass = new_password.encode('utf-8') - result = bcrypt.checkpw(ecpass, self.password.encode('utf-8')) - if not result: - logging.warning("PASSWORDS DO NOT MATCH") - - salt = bcrypt.gensalt() - self.password = bcrypt.hashpw(enpass, salt) + # def change_password(self, current_password: str, new_password: str): + # ''' + # Changes user defualt password + # ''' + # ecpass = current_password.encode('utf-8') + # enpass = new_password.encode('utf-8') + # result = bcrypt.checkpw(ecpass, self.password.encode('utf-8')) + # if not result: + # logging.warning("PASSWORDS DO NOT MATCH") + # + # salt = bcrypt.gensalt() + # self.password = bcrypt.hashpw(enpass, salt) def regenerate_stream_key(self): ''' diff --git a/src/stream_auth/routes/__init__.py b/src/stream_auth/routes/__init__.py old mode 100644 new mode 100755 diff --git a/src/stream_auth/routes/stream.py b/src/stream_auth/routes/stream.py old mode 100644 new mode 100755 index e44b44c..1984088 --- a/src/stream_auth/routes/stream.py +++ b/src/stream_auth/routes/stream.py @@ -7,7 +7,8 @@ from flask import Blueprint, Response, request, redirect from stream_auth.middlewares.auth import auth from stream_auth.middlewares import jwt from stream_auth.models.stream import Stream as StreamModel -from stream_auth.database import user +from stream_auth.models import ldap +from stream_auth.database import user as userdb stream = Blueprint('stream', __name__) @@ -22,27 +23,40 @@ def create_stream(): StreamModel(username, title, description) +# @user.route('/validate', methods=['POST']) @stream.route('/publish_check', methods=['POST']) def publish_check(): - - # TODO: check if user created stream - - # get user - stream_key = request.form.get('stream_key') username = request.form.get('name') - print(username, stream_key) - try: - stream_user = user.search_user(username)[0] + password = request.form.get('password') - if username != stream_user['username'] or not jwt.verify_stream_key(stream_key): - raise ValueError('Invalid Token') - - except (IndexError, ValueError): - return Response('Invalid Stream Key', 401) + if ldap.authenticate(username, password) is False: + logging.info('User or password incorrect', username) + return Response('User or password incorrect', 401) return Response('OK', 200) +# @stream.route('/publish_check', methods=['POST']) +# def publish_check(): +# +# # TODO: check if user created stream +# +# # get user +# stream_key = request.form.get('stream_key') +# username = request.form.get('name') +# print(username, stream_key) +# try: +# stream_user = userdb.search_user(username) +# +# if username != stream_user.username or not jwt.verify_stream_key(stream_key): +# raise ValueError('Invalid Token') +# +# except (IndexError, ValueError): +# return Response('Invalid Stream Key', 401) +# +# return Response('OK', 200) + + @stream.route('/test') def test(): diff --git a/src/stream_auth/routes/user.py b/src/stream_auth/routes/user.py old mode 100644 new mode 100755 index dc43fbc..544ff74 --- a/src/stream_auth/routes/user.py +++ b/src/stream_auth/routes/user.py @@ -5,67 +5,95 @@ For controlling user routes import logging from flask import Blueprint, Response, request, jsonify, make_response from stream_auth.models.user import User +from stream_auth.models import ldap from stream_auth.database import user as userdb from stream_auth.middlewares import jwt user = Blueprint('user', __name__) -@user.route('/signin', methods=['POST']) -def create(): - ''' - Create a new user - ''' +# @user.route('/signin', methods=['POST']) +# def create(): +# ''' +# Create a new user +# ''' +# +# json = request.get_json() +# username = json['username'] +# password = json['password'] +# +# new_user = userdb.create_user(username, password) +# +# logging.info('User %s created with stream key %s', +# new_user.username, new_user.stream_key) +# +# res = {'username': new_user.username, 'stream_key': new_user.stream_key} +# return make_response(jsonify(res), 200) + +@user.route('/validate', methods=['POST']) +def validate(): json = request.get_json() username = json['username'] password = json['password'] - new_user = userdb.create_user(username, password) + if ldap.authenticate(username, password) is False: + logging.info('User or password incorrect', username) + return Response('User or password incorrect', 401) + + # logging.info('User %s valid', username) - logging.info('User %s created with stream key %s', - new_user.username, new_user.stream_key) + try: + logging.info('User %s valid', username) + log_user = userdb.search_user(username) + print(log_user) + # return Response(f'User {username} valid') - res = {'username': new_user.username, 'stream_key': new_user.stream_key} + except IndexError: + logging.info('User %s first login, creating stream key', username) + log_user = userdb.create_user(username) + + print(log_user) + res = {'username': log_user.username, 'stream_key': log_user.stream_key} return make_response(jsonify(res), 200) -@user.route('/login', methods=['POST']) -def login(): - ''' - User log in - ''' - - json = request.get_json() - username = json['username'] - password = json['password'] - - try: - log_user = userdb.search_user(username)[0] - except IndexError: - return Response('User or password incorrect', 401) - - if not log_user.check_password(password): - return Response('User or password incorrect', 401) - - token = jwt.create_token(log_user.username, log_user.stream_key) - logging.info('User %s logged in', log_user.username) - - return make_response(jsonify({'token': token}), 201) - - -@user.route('/logout', methods=['POST']) -def logout(): - ''' - Create a new user - ''' - - json = request.get_json() - username = json['username'] - password = json['password'] - - new_user = User(username, password) - - logging.info('User %s logged out', new_user.username) - - return Response('OK', 200) +# @user.route('/login', methods=['POST']) +# def login(): +# ''' +# User log in +# ''' +# +# json = request.get_json() +# username = json['username'] +# password = json['password'] +# +# try: +# log_user = userdb.search_user(username)[0] +# except IndexError: +# return Response('User or password incorrect', 401) +# +# if not check_password(password, log_user['password']): +# return Response('User or password incorrect', 401) +# +# token = jwt.create_token(log_user['username'], log_user['stream_key']) +# logging.info('User %s logged in', log_user['username']) +# +# return make_response(jsonify({'token': token}), 201) +# +# +# @user.route('/logout', methods=['POST']) +# def logout(): +# ''' +# Create a new user +# ''' +# +# json = request.get_json() +# username = json['username'] +# password = json['password'] +# +# new_user = User(username, password) +# +# logging.info('User %s logged out', new_user.username) +# +# return Response('OK', 200) diff --git a/src/stream_auth/settings.py b/src/stream_auth/settings.py old mode 100644 new mode 100755 index 36bbf51..525523a --- a/src/stream_auth/settings.py +++ b/src/stream_auth/settings.py @@ -4,7 +4,7 @@ Settings file, where all globals should be import os HOST = '0.0.0.0' -PORT = 8080 +PORT = 33003 APP_DIR = os.path.dirname(os.path.realpath(__file__)) KEY_DIR = os.path.join(APP_DIR, 'keys')