diff --git a/roles/sys-ca-selfsigned/files/with-ca-trust.sh b/roles/sys-ca-selfsigned/files/with-ca-trust.sh index d3419946da..a550d95853 100644 --- a/roles/sys-ca-selfsigned/files/with-ca-trust.sh +++ b/roles/sys-ca-selfsigned/files/with-ca-trust.sh @@ -26,7 +26,6 @@ if [ ! -r "$CA_TRUST_CERT" ]; then exit 2 fi -# Sanitize trust name name="$(printf '%s' "$CA_TRUST_NAME" | tr -c 'A-Za-z0-9._-' '_' )" if [ -z "$name" ]; then echo "[with-ca-trust] ERROR: CA_TRUST_NAME resolved to empty after sanitization" >&2 @@ -37,13 +36,21 @@ log "Sanitized trust name: $name" installed=0 -# Always provide env-based trust hints as a fallback (works for many TLS stacks) export SSL_CERT_FILE="$CA_TRUST_CERT" export REQUESTS_CA_BUNDLE="$CA_TRUST_CERT" export CURL_CA_BUNDLE="$CA_TRUST_CERT" -# Optional (harmless if unused; helps Node-based tools if any) export NODE_EXTRA_CA_CERTS="$CA_TRUST_CERT" +if [ -n "${CA_TRUST_CERT_EXTRA:-}" ] && [ -r "${CA_TRUST_CERT_EXTRA}" ]; then + combined="/tmp/infinito/ca-trust-combined.crt" + mkdir -p "$(dirname "$combined")" + cat "$CA_TRUST_CERT" "$CA_TRUST_CERT_EXTRA" > "$combined" + export SSL_CERT_FILE="$combined" + export REQUESTS_CA_BUNDLE="$combined" + export CURL_CA_BUNDLE="$combined" + export NODE_EXTRA_CA_CERTS="$combined" +fi + install_anchor() { src="$1" dst="$2" @@ -58,9 +65,6 @@ install_anchor() { return 1 } -# -# Debian / Ubuntu style -# if command -v update-ca-certificates >/dev/null 2>&1; then log "Detected update-ca-certificates" if install_anchor "$CA_TRUST_CERT" "/usr/local/share/ca-certificates/${name}.crt"; then @@ -68,9 +72,6 @@ if command -v update-ca-certificates >/dev/null 2>&1; then fi fi -# -# RHEL / p11-kit style -# if command -v update-ca-trust >/dev/null 2>&1; then log "Detected update-ca-trust" if install_anchor "$CA_TRUST_CERT" "/etc/pki/ca-trust/source/anchors/${name}.crt"; then @@ -78,9 +79,6 @@ if command -v update-ca-trust >/dev/null 2>&1; then fi fi -# -# Arch / pure p11-kit style -# if command -v trust >/dev/null 2>&1; then log "Detected trust" if install_anchor "$CA_TRUST_CERT" "/etc/ca-certificates/trust-source/anchors/${name}.crt"; then @@ -88,18 +86,19 @@ if command -v trust >/dev/null 2>&1; then fi fi -# ------------------------------------------------------------ -# Chromium / NSS trust (per-user DB) -# -# Puppeteer/Chromium often uses NSS trust DB and may ignore OS CA store. -# Import the CA into the user's NSS DB if certutil is available. -# -# Requires: -# - Debian/Ubuntu: apt-get install libnss3-tools -# - Alpine: apk add nss-tools -# ------------------------------------------------------------ +if [ -n "${CA_TRUST_CERT_EXTRA:-}" ] && [ -r "${CA_TRUST_CERT_EXTRA}" ]; then + if command -v update-ca-certificates >/dev/null 2>&1 && install_anchor "$CA_TRUST_CERT_EXTRA" "/usr/local/share/ca-certificates/${name}-extra.crt"; then + run update-ca-certificates || true + fi + if command -v update-ca-trust >/dev/null 2>&1 && install_anchor "$CA_TRUST_CERT_EXTRA" "/etc/pki/ca-trust/source/anchors/${name}-extra.crt"; then + run update-ca-trust extract || true + fi + if command -v trust >/dev/null 2>&1 && install_anchor "$CA_TRUST_CERT_EXTRA" "/etc/ca-certificates/trust-source/anchors/${name}-extra.crt"; then + run trust extract-compat || true + fi +fi + if command -v certutil >/dev/null 2>&1; then - # Prefer real HOME; fall back to a writable temp dir home_dir="${HOME:-}" if [ -z "$home_dir" ] || [ ! -d "$home_dir" ] || [ ! -w "$home_dir" ]; then home_dir="/tmp" @@ -108,18 +107,14 @@ if command -v certutil >/dev/null 2>&1; then nss_db="${home_dir}/.pki/nssdb" log "Detected certutil; importing CA into NSS DB: ${nss_db}" - # Ensure directory exists run mkdir -p "$nss_db" 2>/dev/null || true - # Create NSS DB if missing (empty password) if [ ! -f "$nss_db/cert9.db" ]; then run certutil -N -d "sql:${nss_db}" --empty-password 2>/dev/null || true fi - # Remove existing cert entry (best-effort) run certutil -D -d "sql:${nss_db}" -n "$name" >/dev/null 2>&1 || true - # Import as trusted CA (C,, = trusted CA for SSL) run certutil -A -d "sql:${nss_db}" -n "$name" -t "C,," -i "$CA_TRUST_CERT" 2>/dev/null || true log "NSS trust import attempted (best-effort)" diff --git a/roles/sys-svc-compose-ca/files/compose_ca.py b/roles/sys-svc-compose-ca/files/compose_ca.py index 950290067e..f29a0b519f 100755 --- a/roles/sys-svc-compose-ca/files/compose_ca.py +++ b/roles/sys-svc-compose-ca/files/compose_ca.py @@ -502,6 +502,16 @@ def _load_services_via_config( return services +def _cache_frontend_ca_host() -> str: + """Runner-internal path to the package-cache frontend CA, or '' when the cache is inactive.""" + path = os.environ.get( + "CA_TRUST_CERT_EXTRA_HOST", "/opt/package-frontend-ca.crt" + ).strip() + if path and Path(path).is_file() and Path(path).stat().st_size > 0: + return path + return "" + + def render_override( services: dict[str, Any], service_to_compose_cmd: dict[str, list[str]], @@ -537,6 +547,7 @@ def render_override( We escape any $ in the command argv with $$ so container-side expansion works. """ out_services: dict[str, Any] = {} + extra_ca_host = _cache_frontend_ca_host() image_meta = gather_image_meta( sorted( @@ -563,16 +574,22 @@ def render_override( if php_ini_host and php_ini_container: volumes.append(f"{php_ini_host}:{php_ini_container}:ro") + environment: dict[str, str] = { + "CA_TRUST_CERT": ca_container, + "CA_TRUST_NAME": trust_name, + "SSL_CERT_FILE": ca_container, + "REQUESTS_CA_BUNDLE": ca_container, + "CURL_CA_BUNDLE": ca_container, + "NODE_EXTRA_CA_CERTS": ca_container, + } + if extra_ca_host: + extra_ca_container = str(Path(ca_container).parent / "ca-trust-extra.crt") + volumes.append(f"{extra_ca_host}:{extra_ca_container}:ro") + environment["CA_TRUST_CERT_EXTRA"] = extra_ca_container + override_svc: dict[str, Any] = { "volumes": volumes, - "environment": { - "CA_TRUST_CERT": ca_container, - "CA_TRUST_NAME": trust_name, - "SSL_CERT_FILE": ca_container, - "REQUESTS_CA_BUNDLE": ca_container, - "CURL_CA_BUNDLE": ca_container, - "NODE_EXTRA_CA_CERTS": ca_container, - }, + "environment": environment, } if not wrap: diff --git a/roles/sys-svc-container/files/container.py b/roles/sys-svc-container/files/container.py index 367207ab50..551cefe73b 100755 --- a/roles/sys-svc-container/files/container.py +++ b/roles/sys-svc-container/files/container.py @@ -341,10 +341,24 @@ def container_run(argv: list[str], debug: bool, with_ca: bool) -> int: "--entrypoint", wrapper_container, ] + extra_opts: list[str] = [] + extra_host = os.environ.get( + "CA_TRUST_CERT_EXTRA_HOST", "/opt/package-frontend-ca.crt" + ).strip() + extra_path = Path(extra_host) if extra_host else None + if extra_path and extra_path.is_file() and extra_path.stat().st_size > 0: + extra_container = str(Path(ca_container).parent / "ca-trust-extra.crt") + extra_opts = [ + "-v", + f"{extra_host}:{extra_container}:ro", + "-e", + f"CA_TRUST_CERT_EXTRA={extra_container}", + ] final_cmd: list[str] = ["docker", "run"] final_cmd.extend(run_opts) final_cmd.extend(inject_opts) + final_cmd.extend(extra_opts) final_cmd.append(image) if user_entrypoint: