From 9ab2cfe60508a46749f7029443aa0e5921e1f320 Mon Sep 17 00:00:00 2001 From: Steve Hay Date: Tue, 6 Sep 2022 13:44:33 -0400 Subject: [PATCH] swapped out ExpiringDict with Flask session -- may allow multiple workers --- management/auth.py | 21 ++------------------- management/daemon.py | 19 +++++++++++++++---- setup/management.sh | 3 ++- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/management/auth.py b/management/auth.py index b3ace3b7..300ab5b4 100644 --- a/management/auth.py +++ b/management/auth.py @@ -1,7 +1,4 @@ import base64, os, os.path, hmac, json, secrets -from datetime import timedelta - -from expiringdict import ExpiringDict import utils from mailconfig import get_mail_password, get_mail_user_privileges @@ -11,31 +8,17 @@ DEFAULT_KEY_PATH = '/var/lib/mailinabox/api.key' DEFAULT_AUTH_REALM = 'Mail-in-a-Box Management Server' class AuthService: - def __init__(self): + def __init__(self, session): self.auth_realm = DEFAULT_AUTH_REALM self.key_path = DEFAULT_KEY_PATH self.max_session_duration = timedelta(days=2) self.init_system_api_key() - self.sessions = ExpiringDict(max_len=64, max_age_seconds=self.max_session_duration.total_seconds()) + self.sessions = session def init_system_api_key(self): """Write an API key to a local file so local processes can use the API""" - # def create_file_with_mode(path, mode): - # # Based on answer by A-B-B: http://stackoverflow.com/a/15015748 - # old_umask = os.umask(0) - # try: - # return os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT, mode), 'w') - # finally: - # os.umask(old_umask) - - # self.key = secrets.token_hex(32) - - # os.makedirs(os.path.dirname(self.key_path), exist_ok=True) - - # with create_file_with_mode(self.key_path, 0o640) as key_file: - # key_file.write(self.key + '\n') with open(self.key_path, 'r') as file: self.key = file.read() diff --git a/management/daemon.py b/management/daemon.py index 98c6689c..5773f4ed 100755 --- a/management/daemon.py +++ b/management/daemon.py @@ -15,18 +15,19 @@ import multiprocessing.pool, subprocess from functools import wraps -from flask import Flask, request, render_template, abort, Response, send_from_directory, make_response +from flask import Flask, request, render_template, abort, Response, send_from_directory, make_response, session import auth, utils from mailconfig import get_mail_users, get_mail_users_ex, get_admins, add_mail_user, set_mail_password, remove_mail_user from mailconfig import get_mail_user_privileges, add_remove_mail_user_privilege from mailconfig import get_mail_aliases, get_mail_aliases_ex, get_mail_domains, add_mail_alias, remove_mail_alias from mfa import get_public_mfa_state, provision_totp, validate_totp_secret, enable_mfa, disable_mfa +from datetime import timedelta + +DEFAULT_SESSION_SECRET_PATH = '/var/lib/mailinabox/session.key' env = utils.load_environment() -auth_service = auth.AuthService() - # We may deploy via a symbolic link, which confuses flask's template finding. me = __file__ try: @@ -44,6 +45,16 @@ with open(os.path.join(os.path.dirname(me), "csr_country_codes.tsv")) as f: app = Flask(__name__, template_folder=os.path.abspath(os.path.join(os.path.dirname(me), "templates"))) +# sets up Flask session to be permanent and lasting 2 days. +with open(DEFAULT_SESSION_SECRET_PATH, 'r') as file: + app.secret_key = file.read() +app.config['SESSION_PERMANENT'] = True +app.config['SESSION_TYPE'] = 'filesystem' +app.config['PERMANENT_SESSION_LIFETIME']=timedelta(days=2) + +# AuthService uses the Flask session +auth_service = auth.AuthService(session) + # Decorator to protect views that require a user with 'admin' privileges. def authorized_personnel_only(viewfunc): @wraps(viewfunc) @@ -162,7 +173,7 @@ def login(): "privileges": privs, "api_key": auth_service.create_session_key(email, env, type='login'), } - + session.permanent = True app.logger.info("New login session created for {}".format(email)) # Return. diff --git a/setup/management.sh b/setup/management.sh index cebed8d5..cf075102 100755 --- a/setup/management.sh +++ b/setup/management.sh @@ -101,7 +101,8 @@ export LC_TYPE=en_US.UTF-8 mkdir -p /var/lib/mailinabox tr -cd '[:xdigit:]' < /dev/urandom | head -c 32 > /var/lib/mailinabox/api.key -chmod 640 /var/lib/mailinabox/api.key +tr -cd '[:alnum:]' < /dev/urandom | head -c 64 > /var/lib/mailinabox/session.key +chmod 640 /var/lib/mailinabox/{api,session}.key source $venv/bin/activate export PYTHONPATH=$(pwd)/management