added option to read flask SECRET_KEY and SECURITY_PASSWORD_SALT from file
This commit is contained in:
parent
db8ee556df
commit
8339294277
|
@ -4,16 +4,17 @@ import argparse
|
|||
from imaginaerraum_door_admin.webapp import create_application
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--key_file", default='/root/flask_keys', help="Path to file with Flask SECRET_KEY and SECURITY_PASSWORD_SALT")
|
||||
parser.add_argument("--token_file", default="/etc/door_tokens", help="path to the file with door tokens and users")
|
||||
parser.add_argument("--nfc_socket", default="/tmp/nfc.sock", help="socket for handling NFC reader commands")
|
||||
parser.add_argument("--template_folder", default="templates", help="path to Flask templates folder")
|
||||
parser.add_argument("--static_folder", default="static", help="path to Flask static folder")
|
||||
parser.add_argument("--admin_file", help="Path to file for creating initial admin users")
|
||||
parser.add_argument("--admin_file", help="Path to file for creating super admin users")
|
||||
parser.add_argument("--log_file", default="/var/log/webinterface.log", help="Path to log file")
|
||||
parser.add_argument("--ldap_url", default="ldaps://ldap.imaginaerraum.de",
|
||||
help="URL for LDAP server for alternative user authorization")
|
||||
parser.add_argument("--mqtt_host", default="10.10.21.2", help="IP address of MQTT broker")
|
||||
parser.add_argument("--port", default=80, help="Port for running the Flask server")
|
||||
parser.add_argument("--flask_port", default=80, help="Port for running the Flask server")
|
||||
parser.add_argument("--mail_server", default="smtp.googlemail.com", help="email server for sending security messages")
|
||||
parser.add_argument("--mail_port", default=465, help="port for security email server")
|
||||
parser.add_argument("--mail_use_tls", default=False, help="use TLS for security emails")
|
||||
|
@ -23,4 +24,4 @@ parser.add_argument("--mail_password", default="password", help="Password for em
|
|||
config = parser.parse_args()
|
||||
|
||||
app = create_application(config)
|
||||
app.run(host='0.0.0.0', port=config.port)
|
||||
app.run(host='0.0.0.0', port=config.flask_port)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import os
|
||||
from flask import Flask, render_template, request, flash, redirect, session, send_file
|
||||
from werkzeug.utils import secure_filename
|
||||
from flask_wtf import FlaskForm
|
||||
|
@ -10,9 +9,9 @@ from flask_security import Security, SQLAlchemyUserDatastore, auth_required, has
|
|||
current_user, roles_required
|
||||
from flask_security.models import fsqla_v2 as fsqla
|
||||
from flask_security.forms import LoginForm, Required, PasswordField
|
||||
from flask_security.utils import find_user, verify_password
|
||||
from flask_security.utils import find_user
|
||||
from flask_mail import Mail
|
||||
from email_validator import validate_email, EmailNotValidError
|
||||
from email_validator import validate_email
|
||||
|
||||
import json
|
||||
import secrets
|
||||
|
@ -83,12 +82,36 @@ def create_application(config):
|
|||
logger.addHandler(ch)
|
||||
|
||||
# do some checks for file existence etc.
|
||||
if not Path(config.template_folder).exists():
|
||||
logger.error(f'Flask template folder not found at {config.template_folder}')
|
||||
if not Path(config.static_folder).exists():
|
||||
logger.error(f'Flask static folder not found at {config.static_folder}')
|
||||
try:
|
||||
with open(config.key_file) as f:
|
||||
data = f.readlines()
|
||||
if 'SECRET_KEY' in data[0]:
|
||||
secret_key = data[0].split()[-1]
|
||||
else:
|
||||
raise Exception("Could not read SECURITY_PASSWORD_SALT")
|
||||
if 'SECURITY_PASSWORD_SALT' in data[1]:
|
||||
security_password_salt = data[1].split()[-1]
|
||||
else:
|
||||
raise Exception("Could not read SECURITY_PASSWORD_SALT")
|
||||
except Exception as e:
|
||||
logger.warning(f"Flask keys could not be read from file at {Path(config.key_file).absolute()}. Exception: {e}. Using default values instead.")
|
||||
secret_key = 'Q7PJu2fg2jabYwP-Psop6c6f2G4'
|
||||
security_password_salt = '10036796768252925167749545152988277953'
|
||||
|
||||
if Path(config.template_folder).is_absolute():
|
||||
if not Path(config.template_folder).exists():
|
||||
logger.error(f'Flask template folder not found at {Path(config.template_folder).absolute()}')
|
||||
else:
|
||||
if not (Path(__file__).parent / config.template_folder).exists():
|
||||
logger.error(f'Flask template folder not found at {(Path(__file__).parent / config.template_folder).absolute()}')
|
||||
if Path(config.static_folder).is_absolute():
|
||||
if not Path(config.static_folder).exists():
|
||||
logger.error(f'Flask static folder not found at {Path(config.static_folder).absolute()}')
|
||||
else:
|
||||
if not (Path(__file__).parent / config.static_folder).exists():
|
||||
logger.error(f'Flask static folder not found at {(Path(__file__).parent / config.static_folder).absolute()}')
|
||||
if not Path(config.token_file).exists():
|
||||
logger.warning(f"Token file not found at {config.token_file}")
|
||||
logger.warning(f"Token file not found at {Path(config.token_file).absolute()}")
|
||||
|
||||
# create door objects which provides access to the token file and current door state via MQTT
|
||||
door = DoorHandle(token_file=config.token_file, mqtt_host=config.mqtt_host, nfc_socket=config.nfc_socket,
|
||||
|
@ -97,11 +120,10 @@ def create_application(config):
|
|||
app = Flask(__name__, template_folder=config.template_folder, static_folder=config.static_folder)
|
||||
|
||||
# Generate a nice key using secrets.token_urlsafe()
|
||||
app.config['SECRET_KEY'] = os.environ.get("SECRET_KEY", 'Q7PJu2fg2jabYwP-Psop6c6f2G4')
|
||||
app.config['SECRET_KEY'] = secret_key
|
||||
# Bcrypt is set as default SECURITY_PASSWORD_HASH, which requires a salt
|
||||
# Generate a good salt using: secrets.SystemRandom().getrandbits(128)
|
||||
app.config['SECURITY_PASSWORD_SALT'] = os.environ.get("SECURITY_PASSWORD_SALT",
|
||||
'10036796768252925167749545152988277953')
|
||||
app.config['SECURITY_PASSWORD_SALT'] = security_password_salt
|
||||
|
||||
app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = [
|
||||
{"email": {"mapper": uia_email_mapper, "case_insensitive": True}},
|
||||
|
@ -233,14 +255,14 @@ def create_application(config):
|
|||
user_datastore.commit()
|
||||
|
||||
self.user = find_user(self.email.data)
|
||||
logger.info(f"Admin user with credentials '{self.email.data}' authorized through LDAP")
|
||||
logger.info(f"User with credentials '{self.email.data}' authorized through LDAP")
|
||||
|
||||
if not authorized:
|
||||
# try authorizing locally using Flask security user datastore
|
||||
authorized = super(ExtendedLoginForm, self).validate()
|
||||
|
||||
if authorized:
|
||||
logger.info(f"Admin user with credentials '{self.email.data}' authorized through local database")
|
||||
logger.info(f"User with credentials '{self.email.data}' authorized through local database")
|
||||
|
||||
# if any of the authorization methods is successful we authorize the user
|
||||
return authorized
|
||||
|
@ -668,7 +690,7 @@ def create_application(config):
|
|||
|
||||
for d in new_admin_data:
|
||||
if user_datastore.find_user(email=d['email'], username=d['username']) is None:
|
||||
logger.info(f"New admin user created with username '{d['username']}' and email '{d['email']}'")
|
||||
logger.info(f"New super admin user created with username '{d['username']}' and email '{d['email']}'")
|
||||
# create new admin (only if admin does not already exist)
|
||||
new_admin = user_datastore.create_user(email=d['email'], username=d['username'],
|
||||
password=hash_password(d['password']),
|
||||
|
|
Loading…
Reference in New Issue
Block a user