From ea3c5b1be6e1ad8252155dcfc5cb57e756ec5355 Mon Sep 17 00:00:00 2001 From: iFargle Date: Mon, 20 Feb 2023 18:47:19 +0900 Subject: [PATCH] test --- pyproject.toml | 2 +- server.py | 154 +++++++++++++++++++++++++++++++------------------ 2 files changed, 98 insertions(+), 58 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6905efb..7f10f17 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ PyYAML = "^6.0" pyuwsgi = "^2.0.21" gunicorn = "^20.1.0" flask-basicauth = "^0.2.0" -flask-providers-oidc = "^1.2.1" +flask-pyoidc = "^3.12.1" [tool.poetry.dev-dependencies] diff --git a/server.py b/server.py index 0f2a051..cde6d5f 100644 --- a/server.py +++ b/server.py @@ -22,50 +22,81 @@ executor = Executor(app) # Set Authentication type: ######################################################################################## if AUTH_TYPE.lower() == "oidc": - # https://flask-oidc2.readthedocs.io/en/latest/# - # https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a/ - # https://www.authelia.com/integration/openid-connect/introduction/ + # https://flask-pyoidc.readthedocs.io/en/latest/ LOG.error("Loading OIDC libraries and configuring app...") + from flask_pyoidc import OIDCAuthentication + from flask_pyoidc.provider_configuration import ProviderConfiguration, ClientMetadata + from flask_pyoidc.user_session import UserSession + DOMAIN_NAME = os.environ["DOMAIN_NAME"] BASE_PATH = os.environ["SCRIPT_NAME"] if os.environ["SCRIPT_NAME"] != "/" else "" OIDC_ISSUER = os.environ["OIDC_ISSUER"].replace('"','') OIDC_SECRET = os.environ["OIDC_CLIENT_SECRET"] OIDC_CLIENT_ID = os.environ["OIDC_CLIENT_ID"] - # Construct client_secrets.json: - client_secrets = """ - { - "web": { - "issuer": \""""+OIDC_ISSUER+"""", - "auth_uri": \""""+OIDC_ISSUER+"""/api/oidc/authorization", - "client_id": \""""+OIDC_CLIENT_ID+"""", - "client_secret": \""""+OIDC_SECRET+"""", - "redirect_uris": [\""""+DOMAIN_NAME+BASE_PATH+"""/oidc_callback"], - "userinfo_uri": \""""+OIDC_ISSUER+"""/api/oidc/userinfo", - "token_uri": \""""+OIDC_ISSUER+"""/api/oidc/token", - "token_introspection_uri": \""""+OIDC_ISSUER+"""/api/oidc/introspection" + REDIRECT_URI = DOMAIN_NAME+BASE_PATH+"/redirect_uri" + + app.config.update( + { + 'OIDC_REDIRECT_URI': REDIRECT_URI, + 'SECRET_KEY': OIDC_SECRET, + 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(days=7).total_seconds(), + 'DEBUG': DEBUG_STATE } - } - """ - LOG.error("Secrets") - LOG.error(client_secrets) - with open("/app/instance/secrets.json", "w+") as secrets_json: - secrets_json.write(client_secrets) - - app.config.update({ - 'SECRET_KEY': secrets.token_urlsafe(32), - 'TESTING': DEBUG_STATE, - 'DEBUG': DEBUG_STATE, - 'OIDC_CLIENT_SECRETS': '/app/instance/secrets.json', - 'OIDC_ID_TOKEN_COOKIE_SECURE': False, - 'OIDC_REQUIRE_VERIFIED_EMAIL': False, - 'OIDC_USER_INFO_ENABLED': True, - 'OIDC_OPENID_REALM': 'Headscale-WebUI', - 'OIDC_SCOPES': ['openid', 'email', 'profile'], - 'OIDC_INTROSPECTION_AUTH_METHOD': 'client_secret_post' - }) - from flask_oidc import OpenIDConnect - oidc = OpenIDConnect(app) + ) + + ISSUER = OIDC_ISSUER + CLIENT = OIDC_CLIENT_ID+"@oidc_provider" + OIDC_PROVIDER = 'oidc_provider' + CONFIG = ProviderConfiguration(issuer=ISSUER, client_metadata=ClientMetadata(CLIENT, OIDC_SECRET)) + oidc = OIDCAuthentication({OIDC_PROVIDER: CONFIG}) + +# Testing another OIDC library +# if AUTH_TYPE.lower() == "oidc": +# # https://flask-oidc2.readthedocs.io/en/latest/# +# # https://gist.github.com/thomasdarimont/145dc9aa857b831ff2eff221b79d179a/ +# # https://www.authelia.com/integration/openid-connect/introduction/ +# LOG.error("Loading OIDC libraries and configuring app...") +# +# DOMAIN_NAME = os.environ["DOMAIN_NAME"] +# BASE_PATH = os.environ["SCRIPT_NAME"] if os.environ["SCRIPT_NAME"] != "/" else "" +# OIDC_ISSUER = os.environ["OIDC_ISSUER"].replace('"','') +# OIDC_SECRET = os.environ["OIDC_CLIENT_SECRET"] +# OIDC_CLIENT_ID = os.environ["OIDC_CLIENT_ID"] +# # Construct client_secrets.json: +# client_secrets = """ +# { +# "web": { +# "issuer": \""""+OIDC_ISSUER+"""", +# "auth_uri": \""""+OIDC_ISSUER+"""/api/oidc/authorization", +# "client_id": \""""+OIDC_CLIENT_ID+"""", +# "client_secret": \""""+OIDC_SECRET+"""", +# "redirect_uris": [\""""+DOMAIN_NAME+BASE_PATH+"""/oidc_callback"], +# "userinfo_uri": \""""+OIDC_ISSUER+"""/api/oidc/userinfo", +# "token_uri": \""""+OIDC_ISSUER+"""/api/oidc/token", +# "token_introspection_uri": \""""+OIDC_ISSUER+"""/api/oidc/introspection" +# } +# } +# """ +# LOG.error("Secrets") +# LOG.error(client_secrets) +# with open("/app/instance/secrets.json", "w+") as secrets_json: +# secrets_json.write(client_secrets) +# +# app.config.update({ +# 'SECRET_KEY': secrets.token_urlsafe(32), +# 'TESTING': DEBUG_STATE, +# 'DEBUG': DEBUG_STATE, +# 'OIDC_CLIENT_SECRETS': '/app/instance/secrets.json', +# 'OIDC_ID_TOKEN_COOKIE_SECURE': False, +# 'OIDC_REQUIRE_VERIFIED_EMAIL': False, +# 'OIDC_USER_INFO_ENABLED': True, +# 'OIDC_OPENID_REALM': 'Headscale-WebUI', +# 'OIDC_SCOPES': ['openid', 'email', 'profile'], +# 'OIDC_INTROSPECTION_AUTH_METHOD': 'client_secret_post' +# }) +# from flask_oidc import OpenIDConnect +# oidc = OpenIDConnect(app) elif AUTH_TYPE.lower() == "basic": # https://flask-basicauth.readthedocs.io/en/latest/ @@ -81,9 +112,18 @@ elif AUTH_TYPE.lower() == "basic": ######################################################################################## # / pages - User-facing pages ######################################################################################## +# Testing OIDC page... +@app.route('/oidctest') +@auth.oidc_auth(OIDC_PROVIDER) +def oidctest_page(): + user_session = UserSession(flask.session) + return jsonify(access_token=user_session.access_token, + id_token=user_session.id_token, + userinfo=user_session.userinfo) + @app.route('/') @app.route('/overview') -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def overview_page(): # Some basic sanity checks: pass_checks = str(helper.load_checks()) @@ -96,7 +136,7 @@ def overview_page(): ) @app.route('/machines', methods=('GET', 'POST')) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def machines_page(): # Some basic sanity checks: pass_checks = str(helper.load_checks()) @@ -111,7 +151,7 @@ def machines_page(): ) @app.route('/users', methods=('GET', 'POST')) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def users_page(): # Some basic sanity checks: pass_checks = str(helper.load_checks()) @@ -126,7 +166,7 @@ def users_page(): ) @app.route('/settings', methods=('GET', 'POST')) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def settings_page(): # Some basic sanity checks: pass_checks = str(helper.load_checks()) @@ -144,7 +184,7 @@ def settings_page(): ) @app.route('/error') -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def error_page(): if helper.access_checks() == "Pass": return redirect(url_for('overview_page')) @@ -162,7 +202,7 @@ def error_page(): ######################################################################################## @app.route('/api/test_key', methods=('GET', 'POST')) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def test_key_page(): api_key = headscale.get_api_key() url = headscale.get_url() @@ -199,7 +239,7 @@ def test_key_page(): return message @app.route('/api/save_key', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def save_key_page(): json_response = request.get_json() api_key = json_response['api_key'] @@ -224,7 +264,7 @@ def save_key_page(): # Machine API Endpoints ######################################################################################## @app.route('/api/update_route', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def update_route_page(): json_response = request.get_json() route_id = json_response['route_id'] @@ -235,7 +275,7 @@ def update_route_page(): return headscale.update_route(url, api_key, route_id, current_state) @app.route('/api/machine_information', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def machine_information_page(): json_response = request.get_json() machine_id = json_response['id'] @@ -245,7 +285,7 @@ def machine_information_page(): return headscale.get_machine_info(url, api_key, machine_id) @app.route('/api/delete_machine', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def delete_machine_page(): json_response = request.get_json() machine_id = json_response['id'] @@ -255,7 +295,7 @@ def delete_machine_page(): return headscale.delete_machine(url, api_key, machine_id) @app.route('/api/rename_machine', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def rename_machine_page(): json_response = request.get_json() machine_id = json_response['id'] @@ -266,7 +306,7 @@ def rename_machine_page(): return headscale.rename_machine(url, api_key, machine_id, new_name) @app.route('/api/move_user', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def move_user_page(): json_response = request.get_json() machine_id = json_response['id'] @@ -277,7 +317,7 @@ def move_user_page(): return headscale.move_user(url, api_key, machine_id, new_user) @app.route('/api/set_machine_tags', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def set_machine_tags(): json_response = request.get_json() machine_id = json_response['id'] @@ -288,7 +328,7 @@ def set_machine_tags(): return headscale.set_machine_tags(url, api_key, machine_id, machine_tags) @app.route('/api/register_machine', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def register_machine(): json_response = request.get_json() machine_key = json_response['key'] @@ -302,7 +342,7 @@ def register_machine(): # User API Endpoints ######################################################################################## @app.route('/api/rename_user', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def rename_user_page(): json_response = request.get_json() old_name = json_response['old_name'] @@ -313,7 +353,7 @@ def rename_user_page(): return headscale.rename_user(url, api_key, old_name, new_name) @app.route('/api/add_user', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def add_user(): json_response = json.dumps(request.get_json()) url = headscale.get_url() @@ -322,7 +362,7 @@ def add_user(): return headscale.add_user(url, api_key, json_response) @app.route('/api/delete_user', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def delete_user(): json_response = request.get_json() user_name = json_response['name'] @@ -332,7 +372,7 @@ def delete_user(): return headscale.delete_user(url, api_key, user_name) @app.route('/api/get_users', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def get_users_page(): url = headscale.get_url() api_key = headscale.get_api_key() @@ -343,7 +383,7 @@ def get_users_page(): # Pre-Auth Key API Endpoints ######################################################################################## @app.route('/api/add_preauth_key', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def add_preauth_key(): json_response = json.dumps(request.get_json()) url = headscale.get_url() @@ -352,7 +392,7 @@ def add_preauth_key(): return headscale.add_preauth_key(url, api_key, json_response) @app.route('/api/expire_preauth_key', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def expire_preauth_key(): json_response = json.dumps(request.get_json()) url = headscale.get_url() @@ -361,7 +401,7 @@ def expire_preauth_key(): return headscale.expire_preauth_key(url, api_key, json_response) @app.route('/api/build_preauthkey_table', methods=['POST']) -@oidc.require_login +@oidc.oidc_auth(OIDC_PROVIDER) def build_preauth_key_table(): json_response = request.get_json() user_name = json_response['name']