From 9984265c0c4cc7eb96bd3759f1f9abe744fbdbfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Fredrik=20Ki=C3=A6r?= <31612826+anders-kiaer@users.noreply.github.com> Date: Tue, 5 Nov 2019 18:49:22 +0100 Subject: [PATCH] Create localhost cert on the fly (#135) --- .pylintrc | 1 + webviz_config/__init__.py | 1 + webviz_config/_localhost_certificate.py | 34 +++++++++++++++++++ webviz_config/_write_script.py | 7 ---- .../templates/webviz_template.py.jinja2 | 6 +++- 5 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 webviz_config/_localhost_certificate.py diff --git a/.pylintrc b/.pylintrc index 02bfd430..2194c792 100644 --- a/.pylintrc +++ b/.pylintrc @@ -6,6 +6,7 @@ disable = bad-continuation, missing-docstring, duplicate-code max-args = 7 max-attributes = 12 +min-public-methods = 1 [BASIC] diff --git a/webviz_config/__init__.py b/webviz_config/__init__.py index 5d5aea54..71e13176 100644 --- a/webviz_config/__init__.py +++ b/webviz_config/__init__.py @@ -2,6 +2,7 @@ from ._localhost_token import LocalhostToken from ._localhost_open_browser import LocalhostOpenBrowser +from ._localhost_certificate import LocalhostCertificate from ._is_reload_process import is_reload_process from ._container_abc import WebvizContainerABC from ._theme_class import WebvizConfigTheme diff --git a/webviz_config/_localhost_certificate.py b/webviz_config/_localhost_certificate.py new file mode 100644 index 00000000..07e4c614 --- /dev/null +++ b/webviz_config/_localhost_certificate.py @@ -0,0 +1,34 @@ +import os +import atexit +import shutil +import tempfile + +from ._is_reload_process import is_reload_process +from ._certificate import create_certificate, SERVER_KEY_FILENAME, SERVER_CRT_FILENAME + + +class LocalhostCertificate: + """Facilitates creating certificates only valid for localhost, on the fly, + when starting a local process. The certificates are stored in a temporary folder + only readable by the user running the process, and are deleted on exit. + """ + + def __init__(self): + if not is_reload_process(): + self._ssl_temp_dir = os.environ["WEBVIZ_SSL_TEMP_DIR"] = tempfile.mkdtemp() + create_certificate(self._ssl_temp_dir) + atexit.register(self._delete_temp_dir) + else: + self._ssl_temp_dir = os.environ["WEBVIZ_SSL_TEMP_DIR"] + + def _delete_temp_dir(self): + """Delete temporary directory with on-the-fly generated localhost certificates + """ + shutil.rmtree(self._ssl_temp_dir) + + @property + def ssl_context(self): + return ( + os.path.join(self._ssl_temp_dir, SERVER_CRT_FILENAME), + os.path.join(self._ssl_temp_dir, SERVER_KEY_FILENAME), + ) diff --git a/webviz_config/_write_script.py b/webviz_config/_write_script.py index 8814d964..76370102 100644 --- a/webviz_config/_write_script.py +++ b/webviz_config/_write_script.py @@ -4,7 +4,6 @@ import jinja2 from .themes import installed_themes from ._config_parser import ConfigParser -from ._certificate import create_certificate, SERVER_KEY_FILENAME, SERVER_CRT_FILENAME def write_script(args, build_directory, template_filename, output_filename): @@ -23,12 +22,6 @@ def write_script(args, build_directory, template_filename, output_filename): configuration["author"] = getpass.getuser() configuration["current_date"] = datetime.date.today().strftime("%Y-%m-%d") - configuration["ssl_context"] = "({!r}, {!r})".format( - SERVER_CRT_FILENAME, SERVER_KEY_FILENAME - ) - - create_certificate(build_directory) - template_environment = jinja2.Environment( # nosec loader=jinja2.PackageLoader("webviz_config", "templates"), undefined=jinja2.StrictUndefined, diff --git a/webviz_config/templates/webviz_template.py.jinja2 b/webviz_config/templates/webviz_template.py.jinja2 index acd039af..32f994f7 100644 --- a/webviz_config/templates/webviz_template.py.jinja2 +++ b/webviz_config/templates/webviz_template.py.jinja2 @@ -107,6 +107,9 @@ app.layout = dcc.Tabs(parent_className="layoutWrapper", if __name__ == '__main__': # This part is ignored when the webviz app is started # using Docker container and uwsgi (e.g. when hosted on Azure). + # + # It is used only when directly running this script with Python, + # which will then initialize a localhost server. port = webviz_config.utils.get_available_port() @@ -114,10 +117,11 @@ if __name__ == '__main__': webviz_config.LocalhostOpenBrowser(port, token) webviz_config.utils.silence_flask_startup() + app.run_server( host='localhost', port=port, - ssl_context={{ssl_context}}, + ssl_context=webviz_config.LocalhostCertificate().ssl_context, debug=False, use_reloader={{not portable}}, {% if not portable -%}