From 68d9fb37552266809d63732f7e82e4b9040713c8 Mon Sep 17 00:00:00 2001 From: Rauno Tuul Date: Wed, 8 Mar 2023 12:08:07 +0200 Subject: [PATCH 1/4] Support multiple Flask session types, not just filesystem. Set via generic SESSION_TYPE environment variable --- configs/development.py | 2 +- configs/docker_config.py | 6 +++--- docs/wiki/configuration/Environment-variables.md | 2 +- powerdnsadmin/__init__.py | 6 ++---- powerdnsadmin/default_config.py | 3 ++- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/configs/development.py b/configs/development.py index b848d0c..103656a 100644 --- a/configs/development.py +++ b/configs/development.py @@ -24,7 +24,7 @@ CAPTCHA_SESSION_KEY = 'captcha_image' #Server side sessions tracking #Set to TRUE for CAPTCHA, or enable another stateful session tracking system -FILESYSTEM_SESSIONS_ENABLED = True +SESSION_TYPE = 'filesystem' ### DATABASE - MySQL #SQLALCHEMY_DATABASE_URI = 'mysql://{}:{}@{}/{}'.format( diff --git a/configs/docker_config.py b/configs/docker_config.py index 0d006bd..f045e95 100644 --- a/configs/docker_config.py +++ b/configs/docker_config.py @@ -4,7 +4,7 @@ PORT = 80 SQLALCHEMY_DATABASE_URI = 'sqlite:////data/powerdns-admin.db' SESSION_COOKIE_SAMESITE = 'Lax' CSRF_COOKIE_HTTPONLY = True -FILESYSTEM_SESSIONS_ENABLED = True +SESSION_TYPE = 'filesystem' legal_envvars = ( 'SECRET_KEY', @@ -68,7 +68,7 @@ legal_envvars = ( 'LDAP_ENABLED', 'SAML_CERT', 'SAML_KEY', - 'FILESYSTEM_SESSIONS_ENABLED', + 'SESSION_TYPE', 'SESSION_COOKIE_SECURE', 'CSRF_COOKIE_SECURE', 'CAPTCHA_ENABLE', @@ -93,7 +93,7 @@ legal_envvars_bool = ( 'SIGNUP_ENABLED', 'LOCAL_DB_ENABLED', 'LDAP_ENABLED', - 'FILESYSTEM_SESSIONS_ENABLED', + 'SESSION_TYPE', 'SESSION_COOKIE_SECURE', 'CSRF_COOKIE_SECURE', 'CAPTCHA_ENABLE', diff --git a/docs/wiki/configuration/Environment-variables.md b/docs/wiki/configuration/Environment-variables.md index b133ee6..fbbedac 100644 --- a/docs/wiki/configuration/Environment-variables.md +++ b/docs/wiki/configuration/Environment-variables.md @@ -4,7 +4,7 @@ | ---------| ----------- | -------- | ------------- | | BIND_ADDRESS | | CSRF_COOKIE_SECURE | -| FILESYSTEM_SESSIONS_ENABLED | +| SESSION_TYPE | null|filesystem|sqlalchemy | | filesystem | | LDAP_ENABLED | | LOCAL_DB_ENABLED | | LOG_LEVEL | diff --git a/powerdnsadmin/__init__.py b/powerdnsadmin/__init__.py index 0b2c5a1..f3bca83 100755 --- a/powerdnsadmin/__init__.py +++ b/powerdnsadmin/__init__.py @@ -56,10 +56,8 @@ def create_app(config=None): _sslify = SSLify(app) # lgtm [py/unused-local-variable] # Load Flask-Session - if app.config.get('FILESYSTEM_SESSIONS_ENABLED'): - app.config['SESSION_TYPE'] = 'filesystem' - sess = Session() - sess.init_app(app) + sess = Session() + sess.init_app(app) # SMTP app.mail = Mail(app) diff --git a/powerdnsadmin/default_config.py b/powerdnsadmin/default_config.py index 8513915..07de0f3 100644 --- a/powerdnsadmin/default_config.py +++ b/powerdnsadmin/default_config.py @@ -8,7 +8,8 @@ SECRET_KEY = 'e951e5a1f4b94151b360f47edf596dd2' BIND_ADDRESS = '0.0.0.0' PORT = 9191 HSTS_ENABLED = False -FILESYSTEM_SESSIONS_ENABLED = True + +SESSION_TYPE = 'filesystem' SESSION_COOKIE_SAMESITE = 'Lax' CSRF_COOKIE_HTTPONLY = True From aa709519642dcd3f65c2bbbe6c51c98a0d56549b Mon Sep 17 00:00:00 2001 From: Rauno Tuul Date: Wed, 8 Mar 2023 17:05:32 +0200 Subject: [PATCH 2/4] Read flask session type from environment variable and create sessions table if not exist. --- configs/docker_config.py | 1 - powerdnsadmin/__init__.py | 11 +++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/configs/docker_config.py b/configs/docker_config.py index f045e95..030e8d2 100644 --- a/configs/docker_config.py +++ b/configs/docker_config.py @@ -93,7 +93,6 @@ legal_envvars_bool = ( 'SIGNUP_ENABLED', 'LOCAL_DB_ENABLED', 'LDAP_ENABLED', - 'SESSION_TYPE', 'SESSION_COOKIE_SECURE', 'CSRF_COOKIE_SECURE', 'CAPTCHA_ENABLE', diff --git a/powerdnsadmin/__init__.py b/powerdnsadmin/__init__.py index f3bca83..d447a00 100755 --- a/powerdnsadmin/__init__.py +++ b/powerdnsadmin/__init__.py @@ -56,8 +56,15 @@ def create_app(config=None): _sslify = SSLify(app) # lgtm [py/unused-local-variable] # Load Flask-Session - sess = Session() - sess.init_app(app) + app.config['SESSION_TYPE'] = app.config.get('SESSION_TYPE') + if 'SESSION_TYPE' in os.environ: + app.config['SESSION_TYPE'] = os.environ.get('SESSION_TYPE') + + sess = Session(app) + + # create sessions table if using sqlalchemy backend + if os.environ.get('SESSION_TYPE') == 'sqlalchemy': + sess.app.session_interface.db.create_all() # SMTP app.mail = Mail(app) From c707f1e1c58aae83e31693916266cf3412caada5 Mon Sep 17 00:00:00 2001 From: Rauno Tuul Date: Fri, 10 Mar 2023 15:20:18 +0200 Subject: [PATCH 3/4] Added support for dict/json environment variables for docker image --- configs/docker_config.py | 16 +++++++++++++++- docs/wiki/configuration/Environment-variables.md | 4 +++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/configs/docker_config.py b/configs/docker_config.py index 030e8d2..347bc26 100644 --- a/configs/docker_config.py +++ b/configs/docker_config.py @@ -27,6 +27,7 @@ legal_envvars = ( 'SALT', 'SQLALCHEMY_TRACK_MODIFICATIONS', 'SQLALCHEMY_DATABASE_URI', + 'SQLALCHEMY_ENGINE_OPTIONS', 'MAIL_SERVER', 'MAIL_PORT', 'MAIL_DEBUG', @@ -98,14 +99,25 @@ legal_envvars_bool = ( 'CAPTCHA_ENABLE', ) +legal_envvars_dict = ( + 'SQLALCHEMY_ENGINE_OPTIONS', +) + # import everything from environment variables import os import sys - +import json def str2bool(v): return v.lower() in ("true", "yes", "1") +def dictfromstr(v,ret): + try: + return json.loads(ret) + except Exception as e: + print('Cannot parse json {} for variable {}'.format(ret, v)) + print(e) + raise ValueError for v in legal_envvars: @@ -129,4 +141,6 @@ for v in legal_envvars: ret = str2bool(ret) if v in legal_envvars_int: ret = int(ret) + if v in legal_envvars_dict: + ret = dictfromstr(v, ret) sys.modules[__name__].__dict__[v] = ret diff --git a/docs/wiki/configuration/Environment-variables.md b/docs/wiki/configuration/Environment-variables.md index fbbedac..d49f60f 100644 --- a/docs/wiki/configuration/Environment-variables.md +++ b/docs/wiki/configuration/Environment-variables.md @@ -57,6 +57,8 @@ | SESSION_COOKIE_SECURE | | SIGNUP_ENABLED | | SQLALCHEMY_DATABASE_URI | SQL Alchemy URI to connect to database | N | no default | -| SQLALCHEMY_TRACK_MODIFICATIONS | +| SQLALCHEMY_TRACK_MODIFICATIONS | +| SQLALCHEMY_ENGINE_OPTIONS | json string. e.g. '{"pool_recycle":600,"echo":1}' [^2] | [^1]: Flask secret key (see https://flask.palletsprojects.com/en/1.1.x/config/#SECRET_KEY for how to generate) +[^2]: See Flask-SQLAlchemy Documentation for all engine options. From 356667f98904b77e230cd7e4fca7ac6805264c6c Mon Sep 17 00:00:00 2001 From: Matt Scott Date: Fri, 10 Mar 2023 16:34:55 -0500 Subject: [PATCH 4/4] Tweaked PR to include the latest asset build changes for CSS minimizer. Also updated the default session storage to use SQLAlchemy instead of the file system. --- configs/development.py | 2 +- configs/docker_config.py | 2 +- powerdnsadmin/assets.py | 2 +- powerdnsadmin/default_config.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/development.py b/configs/development.py index 103656a..6d1dd0d 100644 --- a/configs/development.py +++ b/configs/development.py @@ -24,7 +24,7 @@ CAPTCHA_SESSION_KEY = 'captcha_image' #Server side sessions tracking #Set to TRUE for CAPTCHA, or enable another stateful session tracking system -SESSION_TYPE = 'filesystem' +SESSION_TYPE = 'sqlalchemy' ### DATABASE - MySQL #SQLALCHEMY_DATABASE_URI = 'mysql://{}:{}@{}/{}'.format( diff --git a/configs/docker_config.py b/configs/docker_config.py index 347bc26..f934548 100644 --- a/configs/docker_config.py +++ b/configs/docker_config.py @@ -4,7 +4,7 @@ PORT = 80 SQLALCHEMY_DATABASE_URI = 'sqlite:////data/powerdns-admin.db' SESSION_COOKIE_SAMESITE = 'Lax' CSRF_COOKIE_HTTPONLY = True -SESSION_TYPE = 'filesystem' +SESSION_TYPE = 'sqlalchemy' legal_envvars = ( 'SECRET_KEY', diff --git a/powerdnsadmin/assets.py b/powerdnsadmin/assets.py index 52e8d26..0db26d1 100644 --- a/powerdnsadmin/assets.py +++ b/powerdnsadmin/assets.py @@ -38,7 +38,7 @@ css_main = Bundle( 'node_modules/admin-lte/dist/css/adminlte.css', 'custom/css/custom.css', 'node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker.css', - filters=('cssmin', 'cssrewrite'), + filters=('rcssmin', 'cssrewrite'), output='generated/main.css') js_main = Bundle( diff --git a/powerdnsadmin/default_config.py b/powerdnsadmin/default_config.py index 07de0f3..55d28ef 100644 --- a/powerdnsadmin/default_config.py +++ b/powerdnsadmin/default_config.py @@ -9,7 +9,7 @@ BIND_ADDRESS = '0.0.0.0' PORT = 9191 HSTS_ENABLED = False -SESSION_TYPE = 'filesystem' +SESSION_TYPE = 'sqlalchemy' SESSION_COOKIE_SAMESITE = 'Lax' CSRF_COOKIE_HTTPONLY = True