From 383e750a6dcdc41cba767ae24a3befd30c040d94 Mon Sep 17 00:00:00 2001 From: Forbes Date: Thu, 29 Jan 2026 22:26:26 -0600 Subject: [PATCH] Fix API URL handling and SSL certificate verification - Auto-append /api to base URL if not already present, so users can enter just the hostname (e.g. https://silo.kindred.internal) - Load system CA certificate bundle in SSL context so the bundled Python trusts internal CAs (FreeIPA) without disabling verification - Update settings dialog placeholder and hint text to clarify expected URL format --- pkg/freecad/silo_commands.py | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/pkg/freecad/silo_commands.py b/pkg/freecad/silo_commands.py index 97fec2c..54b8f78 100644 --- a/pkg/freecad/silo_commands.py +++ b/pkg/freecad/silo_commands.py @@ -26,9 +26,13 @@ def _get_api_url() -> str: """Get Silo API URL from preferences, falling back to env var then default.""" param = FreeCAD.ParamGet(_PREF_GROUP) url = param.GetString("ApiUrl", "") - if url: - return url - return os.environ.get("SILO_API_URL", "http://localhost:8080/api") + if not url: + url = os.environ.get("SILO_API_URL", "http://localhost:8080/api") + url = url.rstrip("/") + # Auto-append /api if the user provided just the base hostname + if url and not url.endswith("/api"): + url = url + "/api" + return url def _get_ssl_verify() -> bool: @@ -40,7 +44,21 @@ def _get_ssl_verify() -> bool: def _get_ssl_context() -> ssl.SSLContext: """Build an SSL context based on the current SSL verification preference.""" if _get_ssl_verify(): - return ssl.create_default_context() + ctx = ssl.create_default_context() + # The bundled Python may not find the system CA store automatically + # (its compiled-in path points to the build environment). Load the + # system CA bundle explicitly so internal CAs (e.g. FreeIPA) are trusted. + for ca_path in ( + "/etc/ssl/certs/ca-certificates.crt", # Debian / Ubuntu + "/etc/pki/tls/certs/ca-bundle.crt", # RHEL / CentOS + ): + if os.path.isfile(ca_path): + try: + ctx.load_verify_locations(ca_path) + except Exception: + pass + break + return ctx else: ctx = ssl.create_default_context() ctx.check_hostname = False @@ -1834,7 +1852,7 @@ class Silo_Settings: layout.addWidget(url_label) url_input = QtGui.QLineEdit() - url_input.setPlaceholderText("http://localhost:8080/api") + url_input.setPlaceholderText("https://silo.kindred.internal") current_url = param.GetString("ApiUrl", "") if current_url: url_input.setText(current_url) @@ -1845,8 +1863,9 @@ class Silo_Settings: layout.addWidget(url_input) url_hint = QtGui.QLabel( - "Leave empty to use SILO_API_URL environment variable " - "or default (http://localhost:8080/api)" + "Enter the server hostname (e.g. https://silo.kindred.internal). " + "The /api path is appended automatically. " + "Leave empty to use SILO_API_URL environment variable." ) url_hint.setWordWrap(True) url_hint.setStyleSheet("color: #888; font-size: 11px;")