include cert.pem for SSL verification in frozen builds and update build process to handle CA bundles

This commit is contained in:
Ross
2025-11-24 15:30:48 +00:00
parent 84d18f25e1
commit 377be258de
4 changed files with 100 additions and 5 deletions
+8
View File
@@ -117,6 +117,14 @@ def build(build: bool = True, copy: bool = True, test: bool = False, dest: str |
name_used = f"{base_name}_{ts}"
print(f"Previous artifact appears locked; building as {name_used} to avoid PermissionError")
# Ensure cert.pem is included for test builds as well (if present)
cert_path = project_root / "cert.pem"
if cert_path.exists():
arg = f"{str(cert_path)};."
# Avoid adding duplicate entries
if arg not in add_data_args:
add_data_args += ["--add-data", arg]
PyInstaller.__main__.run([
str(project_root / "nice.py"),
"--onefile",
+21
View File
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDhzCCAm+gAwIBAgIQHLnU4uDoKaJAaqa5Yi/NoTANBgkqhkiG9w0BAQUFADBW
MQswCQYDVQQGEwJHQjERMA8GA1UECBMIQ29ybndhbGwxFTATBgNVBAoTDENvcm53
YWxsIE5IUzEdMBsGA1UEAxMUQ29ybndhbGwgSUNUIFJvb3QgQ0EwHhcNMTMwNjI2
MDkwNjExWhcNMzMwNjI2MDkxNjA1WjBWMQswCQYDVQQGEwJHQjERMA8GA1UECBMI
Q29ybndhbGwxFTATBgNVBAoTDENvcm53YWxsIE5IUzEdMBsGA1UEAxMUQ29ybndh
bGwgSUNUIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCm
m8jF64E3wkxhf2BLfD3lT3v9RebGhJ684jtv0A6qL2BTe/Co4SJ/obYiDw82K4Vw
1O+jwIg77hVrH/YaCsjPiefxxwL/T0bSURlXq5Q8pCQaHjd1iH1JNY1WfW0Ywkni
a7xbm6/2+zwsyTHfhuSU+zmSQxejOX+Ffz6MWZSb+JjppOH6OBKTHGw69JIXcAUu
wT3GSAdYyYKgP6i6jfsEeJkq+s/hd6cVxFWPrWJJaGtfIvLZT38vZeitYDYT9Ad0
gIQPDyLH35tuNszFWkU5DA/U6xXvWkAV7Mq/EaGSVHckGeQiGAQNmV74KugqpcC/
9reOFKEbc6qvDdGaASjZAgMBAAGjUTBPMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBShR/WOiN4mvXi2tYLGtbeAaCXE7DAQBgkrBgEEAYI3
FQEEAwIBADANBgkqhkiG9w0BAQUFAAOCAQEAEMca1BLnKJIXRZhJUTfLrSWtQDgV
T1jGnHFKngPxWUB1u0fVwpnqeuHSWQ2qkNvEZoBQFbJhEny83r8thLamJB1UHEyj
yhWrtjif7dne3LwzLtmiMZIKPjeyCa+zzl5YW+lUenQErl48PC7sJc5gq4lZajOo
fsEtw5zZLWFqXE/KJNt4vrGhQ0SplphbOzau7VrFIFciiKHHHw3rnV5byjqYDy/Z
IJytye488Pi75lBKq8pWW6YbUFmKly5bqF6Q8oicd9y0/9GGmTZGrzp1WbspYF9Y
lc2p6bkhfQ1f7Q+8/sF0D/sGfjfo099OlRhc881Mwt5p8mEZtJTxk3SZlQ==
-----END CERTIFICATE-----
+65 -4
View File
@@ -14,6 +14,7 @@ from datetime import datetime
from loguru import logger
import sys
import os
from anonymiser import Anonymizer
import pydicom
@@ -41,7 +42,11 @@ import importlib.util
# traceback was previously imported for debugging but is unused
# TODO fix ssl
# SSL verification setting. Can be a boolean (True/False) or a path to
# a CA bundle (PEM file) used by requests' 'verify' parameter.
# Default is True. It can be overridden via CLI options (--ca-bundle,
# --insecure) or environment variables: NICE_UPLOADER_CA_BUNDLE,
# REQUESTS_CA_BUNDLE or SSL_CERT_FILE.
VERIFY_SSL = True
SOCKET_PATH = "tcp://localhost:9976"
@@ -79,8 +84,14 @@ logging.getLogger('niceGUI').setLevel(logging.INFO)
# application is frozen into a single executable (PyInstaller --onefile).
try:
if getattr(sys, "frozen", False):
# When frozen, place logs next to the executable
base_path = Path(sys.executable).resolve().parent
# When frozen by PyInstaller, data files are extracted to a temporary
# folder available as sys._MEIPASS. Fall back to the executable
# directory when _MEIPASS is not present.
meipass = getattr(sys, "_MEIPASS", None)
if meipass:
base_path = Path(meipass)
else:
base_path = Path(sys.executable).resolve().parent
else:
base_path = Path(__file__).resolve().parent
except Exception:
@@ -707,7 +718,11 @@ def launch_app(
work_dir: Path = typer.Option(WORK_DIR, help="Working directory"),
nng: bool = typer.Option(True, help="Use nng"),
native_mode: bool = typer.Option(False, help="Use native mode"),
debug: bool = typer.Option(False, help="Debug mode")
debug: bool = typer.Option(False, help="Debug mode"),
ca_bundle: Optional[Path] = typer.Option(
None, help="Path to a CA bundle (PEM file) to verify HTTPS connections"
),
insecure: bool = typer.Option(False, help="Disable SSL verification (insecure)"),
):
global WORK_DIR, EXPORT_PATH, PROCESS_PATH, ANON_PATH, DEBUG
@@ -719,6 +734,52 @@ def launch_app(
logger.debug(f"Work dir: {WORK_DIR}")
# Configure SSL verification behaviour. VERIFY_SSL can be:
# - True (default): use system certs
# - False: disable verification (insecure)
# - path (str): path to CA bundle PEM file used by requests
global VERIFY_SSL
env_ca = (
os.environ.get("NICE_UPLOADER_CA_BUNDLE")
or os.environ.get("REQUESTS_CA_BUNDLE")
or os.environ.get("SSL_CERT_FILE")
)
if insecure:
VERIFY_SSL = False
logger.warning(
"SSL verification disabled (insecure). Only use for troubleshooting in trusted networks."
)
elif ca_bundle is not None:
VERIFY_SSL = str(ca_bundle)
logger.info(f"Using CA bundle from CLI: {VERIFY_SSL}")
elif env_ca:
VERIFY_SSL = env_ca
logger.info(f"Using CA bundle from environment: {VERIFY_SSL}")
else:
VERIFY_SSL = True
# If verification is disabled, suppress urllib3 insecure warnings to keep logs clean
if VERIFY_SSL is False:
try:
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
except Exception:
pass
# If a bundled cert.pem was included in the frozen app, prefer that
# when the user hasn't explicitly provided a CA bundle or disabled
# verification. This lets builders ship a corporate CA with the app.
try:
bundled = base_path / "cert.pem"
if bundled.exists() and VERIFY_SSL is True:
VERIFY_SSL = str(bundled)
logger.info(f"Using bundled CA bundle at {VERIFY_SSL}")
except Exception:
pass
# When running as a frozen executable, the native/webview backend
# (which depends on pythonnet) can fail to load inside the bundled
# runtime. Disable native mode automatically for frozen builds so the
+6 -1
View File
@@ -8,7 +8,12 @@ here = Path(__file__).resolve().parent
project_root = here
# Prepare datas and binaries lists; include icon resources
datas = [(str(project_root / 'icon'), 'icon'), (str(project_root / 'icon' / 'icon1.png'), 'icon')]
datas = [
(str(project_root / 'icon'), 'icon'),
(str(project_root / 'icon' / 'icon1.png'), 'icon'),
# include user-supplied CA bundle if present so frozen app can use it
(str(project_root / 'cert.pem'), '.')
]
binaries = []
# Try to include pythonnet runtime DLLs so Python.Runtime.dll is available