include cert.pem for SSL verification in frozen builds and update build process to handle CA bundles
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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-----
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user