diff --git a/src/common/core/customcert/confs/server-http/custom-cert.conf b/src/common/core/customcert/confs/server-http/custom-cert.conf index 800200f91..21cfb6e7f 100644 --- a/src/common/core/customcert/confs/server-http/custom-cert.conf +++ b/src/common/core/customcert/confs/server-http/custom-cert.conf @@ -1,11 +1,12 @@ -{% if USE_CUSTOM_HTTPS == "yes" +%} +{% set os_path = import("os.path") %} +{% if USE_CUSTOM_HTTPS == "yes" and os_path.isfile("/data/cache/customcert/{}".format(CUSTOM_HTTPS_CERT.replace("/", "_"))) and os_path.isfile("/data/cache/customcert/{}".format(CUSTOM_HTTPS_KEY.replace("/", "_"))) +%} # listen on HTTPS PORT listen 0.0.0.0:{{ HTTPS_PORT }} ssl {% if HTTP2 == "yes" %}http2{% endif %} {% if USE_PROXY_PROTOCOL == "yes" %}proxy_protocol{% endif %}; # TLS config -ssl_certificate {{ CUSTOM_HTTPS_CERT }}; -ssl_certificate_key {{ CUSTOM_HTTPS_KEY }}; +ssl_certificate /data/cache/customcert/{{ CUSTOM_HTTPS_CERT.replace("/", "_") }}; +ssl_certificate_key /data/cache/customcert/{{ CUSTOM_HTTPS_KEY.replace("/", "_") }}; ssl_protocols {{ HTTPS_PROTOCOLS }}; ssl_prefer_server_ciphers on; ssl_session_tickets off; diff --git a/src/common/core/customcert/jobs/custom-cert.py b/src/common/core/customcert/jobs/custom-cert.py index 4b49e9036..9eb511fd4 100644 --- a/src/common/core/customcert/jobs/custom-cert.py +++ b/src/common/core/customcert/jobs/custom-cert.py @@ -1,7 +1,8 @@ #!/usr/bin/python3 -from os import getenv, makedirs +from os import environ, getenv, makedirs, remove from os.path import isfile +from shutil import copy from sys import exit as sys_exit, path as sys_path from traceback import format_exc @@ -20,29 +21,86 @@ db = Database( ) -def check_cert(cert_path, first_server: str = None): +def check_cert(cert_path, key_path, first_server: str = None) -> bool: try: - cache_path = ( + if not cert_path or not key_path: + logger.warning( + "Both variables CUSTOM_HTTPS_CERT and CUSTOM_HTTPS_KEY have to be set to use custom certificates" + ) + return False + elif not isfile(cert_path): + logger.warning( + f"Certificate file {cert_path} is not a valid file, ignoring the custom certificate" + ) + return False + + cert_cache_path = ( f"/var/cache/bunkerweb/customcert/{cert_path.replace('/', '_')}.hash" ) - current_hash = file_hash(cert_path) - if not isfile(cache_path): - with open(cache_path, "w") as f: - f.write(current_hash) - old_hash = file_hash(cache_path) - if old_hash == current_hash: + cert_hash = file_hash(cert_path) + + if not isfile(cert_cache_path): + with open(cert_cache_path, "w") as f: + f.write(cert_hash) + + old_hash = file_hash(cert_cache_path) + if old_hash == cert_hash: return False - with open(cache_path, "w") as f: - f.write(current_hash) - err = db.update_job_cache( - "custom-cert", - first_server, - f"{cert_path.replace('/', '_')}.hash", - current_hash.encode("utf-8"), - checksum=current_hash, + + with open(cert_cache_path, "w") as f: + f.write(cert_hash) + + copy(cert_path, cert_cache_path.replace(".hash", "")) + + if not isfile(key_path): + logger.warning( + f"Key file {key_path} is not a valid file, removing the custom certificate ..." + ) + remove(cert_path) + remove(cert_cache_path) + return False + + key_cache_path = ( + f"/var/cache/bunkerweb/customcert/{key_path.replace('/', '_')}.hash" ) + key_hash = file_hash(key_path) + + if not isfile(key_cache_path): + with open(key_cache_path, "w") as f: + f.write(key_hash) + + old_hash = file_hash(key_cache_path) + if old_hash != key_hash: + copy(key_path, key_cache_path.replace(".hash", "")) + + with open(key_path, "r") as f: + err = db.update_job_cache( + "custom-cert", + first_server, + key_cache_path.replace(".hash", "").split("/")[-1], + f.read().encode("utf-8"), + checksum=key_hash, + ) + + if err: + logger.warning( + f"Couldn't update db cache for {key_path.replace('/', '_')}.hash: {err}" + ) + + with open(cert_path, "r") as f: + err = db.update_job_cache( + "custom-cert", + first_server, + cert_cache_path.replace(".hash", "").split("/")[-1], + f.read().encode("utf-8"), + checksum=cert_hash, + ) + if err: - logger.warning(f"Couldn't update db cache: {err}") + logger.warning( + f"Couldn't update db cache for {cert_path.replace('/', '_')}.hash: {err}" + ) + return True except: logger.error( @@ -59,18 +117,25 @@ try: # Multisite case if getenv("MULTISITE") == "yes": for first_server in getenv("SERVER_NAME").split(" "): - if ( - getenv(first_server + "_USE_CUSTOM_HTTPS", getenv("USE_CUSTOM_HTTPS")) + if not first_server or ( + getenv( + f"{first_server}_USE_CUSTOM_HTTPS", getenv("USE_CUSTOM_HTTPS", "no") + ) != "yes" ): continue - if first_server == "": - continue - cert_path = getenv(first_server + "_CUSTOM_HTTPS_CERT") - logger.info( - f"Checking if certificate {cert_path} changed ...", + + cert_path = getenv( + f"{first_server}_CUSTOM_HTTPS_CERT", getenv("CUSTOM_HTTPS_CERT", "") ) - need_reload = check_cert(cert_path, first_server) + key_path = getenv( + f"{first_server}_CUSTOM_HTTPS_KEY", getenv("CUSTOM_HTTPS_KEY", "") + ) + + logger.info( + f"Checking certificate {cert_path} ...", + ) + need_reload = check_cert(cert_path, key_path, first_server) if need_reload: logger.info( f"Detected change for certificate {cert_path}", @@ -78,14 +143,15 @@ try: status = 1 else: logger.info( - "No change for certificate {cert_path}", + f"No change for certificate {cert_path}", ) - # Singlesite case elif getenv("USE_CUSTOM_HTTPS") == "yes" and getenv("SERVER_NAME") != "": - cert_path = getenv("CUSTOM_HTTPS_CERT") - logger.info(f"Checking if certificate {cert_path} changed ...") - need_reload = check_cert(cert_path) + cert_path = getenv("CUSTOM_HTTPS_CERT", "") + key_path = getenv("CUSTOM_HTTPS_KEY", "") + + logger.info(f"Checking certificate {cert_path} ...") + need_reload = check_cert(cert_path, key_path) if need_reload: logger.info(f"Detected change for certificate {cert_path}") status = 1