Added logic to automatically generate the secret key for Flask.

This commit is contained in:
Fabio Manganiello 2023-05-06 22:04:48 +02:00
parent d1f0e1976c
commit 9951d62511
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774

View file

@ -1,4 +1,6 @@
import os import os
import pathlib
import secrets
import threading import threading
from multiprocessing import Process from multiprocessing import Process
@ -14,6 +16,7 @@ import waitress
from platypush.backend import Backend from platypush.backend import Backend
from platypush.backend.http.app import application from platypush.backend.http.app import application
from platypush.bus.redis import RedisBus from platypush.bus.redis import RedisBus
from platypush.config import Config
from platypush.context import get_or_create_event_loop from platypush.context import get_or_create_event_loop
from platypush.utils import get_ssl_server_context from platypush.utils import get_ssl_server_context
@ -170,6 +173,7 @@ class HttpBackend(Backend):
ssl_cafile=None, ssl_cafile=None,
ssl_capath=None, ssl_capath=None,
maps=None, maps=None,
secret_key_file=None,
flask_args=None, flask_args=None,
**kwargs, **kwargs,
): ):
@ -206,6 +210,10 @@ class HttpBackend(Backend):
the value is the absolute path to expose. the value is the absolute path to expose.
:type resource_dirs: dict[str, str] :type resource_dirs: dict[str, str]
:param secret_key_file: Path to the file containing the secret key that will be used by Flask
(default: ``~/.local/share/platypush/flask.secret.key``).
:type secret_key_file: str
:param flask_args: Extra key-value arguments that should be passed to the Flask service. :param flask_args: Extra key-value arguments that should be passed to the Flask service.
:type flask_args: dict[str, str] :type flask_args: dict[str, str]
""" """
@ -243,6 +251,13 @@ class HttpBackend(Backend):
else None else None
) )
self._workdir: str = Config.get('workdir') # type: ignore
assert self._workdir, 'The workdir is not set'
self.secret_key_file = os.path.expanduser(
secret_key_file
or os.path.join(self._workdir, 'flask.secret.key') # type: ignore
)
protocol = 'https' if ssl_cert else 'http' protocol = 'https' if ssl_cert else 'http'
self.local_base_url = f'{protocol}://localhost:{self.port}' self.local_base_url = f'{protocol}://localhost:{self.port}'
self._websocket_lock_timeout = 10 self._websocket_lock_timeout = 10
@ -383,6 +398,25 @@ class HttpBackend(Backend):
) )
self._websocket_loop.run_forever() self._websocket_loop.run_forever()
def _get_secret_key(self, _create=False):
if _create:
self.logger.info('Creating web server secret key')
pathlib.Path(self.secret_key_file).parent.mkdir(parents=True, exist_ok=True)
with open(self.secret_key_file, 'w') as f:
f.write(secrets.token_urlsafe(32))
os.chmod(self.secret_key_file, 0o600)
return secrets.token_urlsafe(32)
try:
with open(self.secret_key_file, 'r') as f:
return f.read()
except IOError as e:
if not _create:
return self._get_secret_key(_create=True)
raise e
def _web_server_proc(self): def _web_server_proc(self):
def proc(): def proc():
self.logger.info('Starting local web server on port %s', self.port) self.logger.info('Starting local web server on port %s', self.port)
@ -396,6 +430,8 @@ class HttpBackend(Backend):
), 'The HTTP backend only works if backed by a Redis bus' ), 'The HTTP backend only works if backed by a Redis bus'
application.config['redis_queue'] = self.bus.redis_queue application.config['redis_queue'] = self.bus.redis_queue
application.secret_key = self._get_secret_key()
if self.ssl_context: if self.ssl_context:
kwargs['ssl_context'] = self.ssl_context kwargs['ssl_context'] = self.ssl_context
if self.flask_args: if self.flask_args: