Compare commits

..
11 Commits
Author SHA1 Message Date
Carneiro fb1ba3a391 remove own auth impl in favor of ldap 2025-02-08 22:22:17 -03:00
Carneiro 8245ee3ab4 add gunicorn 2023-10-05 17:06:14 -03:00
Carneiro 95daba5c8a use es256 for key 2023-10-05 12:07:31 -03:00
Carneiro afc25ff16b update gitignore 2023-10-05 12:05:29 -03:00
Carneiro 23a278e47d update 2023-10-05 07:36:46 -03:00
Carneiro 8ed1a5e3d4 update 2023-10-04 23:18:03 -03:00
Carneiro 423723c673 update 2023-10-04 23:14:30 -03:00
Carneiro 555cbdaaa9 update 2023-10-04 23:11:35 -03:00
Carneiro e533461e34 update 2023-10-04 23:09:54 -03:00
Carneiro 2c9224cfeb update 2023-10-04 23:08:52 -03:00
Carneiro 122ba38beb fix publish 2023-10-04 23:07:21 -03:00
24 changed files with 263 additions and 108 deletions

No files matched your search

Regular → Executable
+1
View File
@@ -5,6 +5,7 @@ teste.py
old
link.sh
*.key*
dbs/
# Created by https://www.toptal.com/developers/gitignore/api/python,pycharm+all
# Edit at https://www.toptal.com/developers/gitignore?templates=python,pycharm+all
Executable
+35
View File
@@ -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
Regular → Executable
View File
File mode changed.
+2
View File
@@ -0,0 +1,2 @@
workers = 4 # Adjust this based on your server's capabilities
bind = "0.0.0.0:8080" # Use the appropriate IP and port
Regular → Executable
+1
View File
@@ -2,3 +2,4 @@ bcrypt
flask
pyjwt
tinydb
gunicorn
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
Regular → Executable
View File
File mode changed.
View File
File mode changed.
View File
File mode changed.
Regular → Executable
+4 -3
View File
@@ -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):
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
openssl ec -in streamkeyEC256.key -pubout -outform PEM -out streamkeyEC256.key.pub
ssh-keygen -t ecdsa -b 256 -m PEM -f streamkeyEC256.key
Regular → Executable
+5 -6
View File
@@ -13,12 +13,11 @@ app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
def main():
app.register_blueprint(user_routes)
app.register_blueprint(stream_routes)
app.run(host=settings.HOST, port=settings.PORT)
# def main(*args, **kwargs):
app.register_blueprint(user_routes)
app.register_blueprint(stream_routes)
if __name__ == "__main__":
main()
app.run(host=settings.HOST, port=settings.PORT)
# main()
View File
File mode changed.
View File
File mode changed.
+23 -7
View File
@@ -1,5 +1,5 @@
import time
import jwt
import jwt as jwtlib
from stream_auth import settings
@@ -11,27 +11,43 @@ def read_key(path):
JWT_PRIV_KEY = read_key(settings.JWT_PRIV_PATH)
JWT_PUB_KEY = read_key(settings.JWT_PUB_PATH)
STREAM_KEY_PRIV_KEY = read_key(settings.STREAM_KEY_PRIV_PATH)
STREAM_KEY_PUB_KEY = read_key(settings.STREAM_KEY_PRIV_PATH)
def create_stream_key(username: str):
payload = {'username': username}
return jwt.encode(payload, JWT_PRIV_KEY, algorithm="RS256")
return jwtlib.encode(payload, STREAM_KEY_PRIV_KEY, algorithm="ES256")
def verify_stream_key(stream_key: str):
try:
jwtlib.decode(stream_key, STREAM_KEY_PUB_KEY, algorithms=["ES256"])
except (jwtlib.exceptions.ExpiredSignatureError, jwtlib.InvalidTokenError):
return False
return True
def decode_stream_key(stream_key: str):
return jwtlib.decode(stream_key, STREAM_KEY_PUB_KEY, algorithms=["RS256"])
def create_token(username: str, stream_key: str, exp: int = settings.JWT_EXP_TIME):
exp = time.time() + exp
payload = {'username': username, 'stream_key': stream_key, 'exp': exp}
return jwt.encode(payload, JWT_PRIV_KEY, algorithm="RS256")
return jwtlib.encode(payload, JWT_PRIV_KEY, algorithm="RS256")
def verify(token: str):
def verify_token(token: str):
# return jwtlib.decode(token, JWT_PUB_KEY, algorithms=["RS256"])
try:
jwt.decode(token, JWT_PUB_KEY, algorithms=["RS256"])
except (jwt.exceptions.ExpiredSignatureError, jwt.InvalidTokenError):
jwtlib.decode(token, JWT_PUB_KEY, algorithms=["RS256"])
except (jwtlib.exceptions.ExpiredSignatureError, jwtlib.InvalidTokenError):
return False
return True
def decode_token(token: str):
return jwt.decode(token, JWT_PUB_KEY, algorithms=["RS256"])
return jwtlib.decode(token, JWT_PUB_KEY, algorithms=["RS256"])
View File
File mode changed.
+23
View File
@@ -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')
Regular → Executable
View File
File mode changed.
Regular → Executable
+40 -28
View File
@@ -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):
'''
View File
File mode changed.
Regular → Executable
+41 -14
View File
@@ -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,21 +23,47 @@ def create_stream():
StreamModel(username, title, description)
@stream.route('/publish_check')
# @user.route('/validate', methods=['POST'])
@stream.route('/publish_check', methods=['POST'])
def publish_check():
# TODO: check if user created stream
# get user
try:
stream_key = request.form.get('stream_key')
username = request.form.get('name')
stream_user = user.search_stream_key(stream_key)[0]
if username != stream_user['username']:
raise ValueError
password = request.form.get('password')
except (IndexError, ValueError):
print('vish')
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():
stream_key = request.args.get('stream_key')
if jwt.verify_token(stream_key):
return Response('OK', 200)
return Response('Invalid Stream Key', 401)
# jwt.verify(stream_key)
Regular → Executable
+76 -48
View File
@@ -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 created with stream key %s',
new_user.username, new_user.stream_key)
# logging.info('User %s valid', username)
res = {'username': new_user.username, 'stream_key': str(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')
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)
Regular → Executable
+5 -2
View File
@@ -4,17 +4,20 @@ 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')
JWT_PRIV_PATH = os.path.join(KEY_DIR, 'jwtRS256.key')
JWT_PUB_PATH = os.path.join(KEY_DIR, 'jwtRS256.key.pub')
STREAM_KEY_PRIV_PATH = os.path.join(KEY_DIR, 'streamkeyEC256.key')
STREAM_KEY_PUB_PATH = os.path.join(KEY_DIR, 'streamkeyEC256.key.pub')
JWT_EXP_TIME = 2592000
DBS_PATH = os.path.join(APP_DIR, 'dbs')
os.path.join(DBS_PATH, 'x.json')
USER_DATABASE = os.path.join(DBS_PATH, 'users.json')
STREAM_DATABASE = os.path.join(DBS_PATH, 'streams.json')
LIVE_STREAM_DATABASE = os.path.join(DBS_PATH, 'live_streams.json')
STREAM_KEY_LENGTH = 32