feat: add LLM SSL verify control and auto CA cert download
- LLM_SSL_VERIFY env var to disable SSL verification for corporate proxies - install_llm_ca_certs() entrypoint function — downloads PEM/DER certs from LLM_CA_CERT_URLS, converts DER→PEM, installs to system CA store - _format_connection_error() — detailed exception chain logging - 7 new unit tests for _get_ssl_verify, _format_connection_error, verify= param - LLM_CA_CERT_URLS and LLM_SSL_VERIFY in .env.enterprise-clean - Removed duplicate @RELATION DEPENDS_ON -> [EXT:Library:tenacity]
This commit is contained in:
@@ -75,6 +75,143 @@ install_certificates() {
|
||||
}
|
||||
# #endregion docker.backend.entrypoint.install_certificates
|
||||
|
||||
# ======================================================================
|
||||
# install_llm_ca_certs — скачка и установка CA-сертификатов по URL
|
||||
# ======================================================================
|
||||
# #region docker.backend.entrypoint.install_llm_ca_certs [C:4] [TYPE Function]
|
||||
# @BRIEF Скачивает PEM/DER-сертификаты из LLM_CA_CERT_URLS, конвертирует DER→PEM,
|
||||
# устанавливает в системное хранилище, создаёт хеш-симлинки и при необходимости
|
||||
# добавляет в ca-certificates.crt напрямую (fallback для OpenSSL 3-совместимости).
|
||||
# @PRE LLM_CA_CERT_URLS — строка с URL через пробел; curl и openssl установлены.
|
||||
# @POST Сертификаты доступны в /etc/ssl/certs/ca-certificates.crt.
|
||||
# Хеш-симлинки созданы для каждого сертификата.
|
||||
# @SIDE_EFFECT Скачивает файлы из внешних URL. Модифицирует /etc/ssl/certs/.
|
||||
# @LAYER Infrastructure
|
||||
# @EXAMPLE:
|
||||
# LLM_CA_CERT_URLS="http://pki.company.com/root.crt http://pki.company.com/intermediate.crt"
|
||||
install_llm_ca_certs() {
|
||||
local urls="${LLM_CA_CERT_URLS:-}"
|
||||
if [ -z "$urls" ]; then
|
||||
echo "[entrypoint] LLM_CA_CERT_URLS не задан — пропускаем скачку сертификатов"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local work_dir="/tmp/llm-ca-certs"
|
||||
local target_dir="/usr/local/share/ca-certificates/llm"
|
||||
mkdir -p "$work_dir" "$target_dir"
|
||||
|
||||
echo "[entrypoint] === Скачивание и установка LLM CA-сертификатов ==="
|
||||
local index=0
|
||||
local downloaded_names=""
|
||||
|
||||
for url in $urls; do
|
||||
url="$(echo "$url" | xargs)" # trim
|
||||
[ -z "$url" ] && continue
|
||||
index=$((index + 1))
|
||||
|
||||
# Определяем имя файла из URL, или генерируем
|
||||
local filename
|
||||
filename="$(basename "$url" | sed 's/[?#].*//')"
|
||||
if [ -z "$filename" ] || [ "$filename" = "." ] || [ "$filename" = ".." ]; then
|
||||
filename="llm-ca-${index}.crt"
|
||||
fi
|
||||
|
||||
local raw_file="${work_dir}/${filename}"
|
||||
local pem_file="${target_dir}/$(echo "$filename" | sed 's/\.[^.]*$//').pem"
|
||||
|
||||
echo "[entrypoint] [${index}] Скачивание: ${url}"
|
||||
|
||||
# Скачиваем с retry 3 раза
|
||||
local attempt=0
|
||||
local success=0
|
||||
while [ $attempt -lt 3 ]; do
|
||||
attempt=$((attempt + 1))
|
||||
if curl -sS --connect-timeout 10 --max-time 30 -o "$raw_file" "$url" 2>/dev/null; then
|
||||
success=1
|
||||
break
|
||||
fi
|
||||
echo "[entrypoint] ⚠ Попытка ${attempt}/3 не удалась, повтор через 2с..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if [ "$success" -eq 0 ]; then
|
||||
echo "[entrypoint] ❌ Не удалось скачать: ${url} — пропускаем"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Определяем формат: PEM или DER
|
||||
if openssl x509 -in "$raw_file" -inform PEM -noout 2>/dev/null; then
|
||||
echo "[entrypoint] ✓ Формат: PEM"
|
||||
cp "$raw_file" "$pem_file"
|
||||
elif openssl x509 -in "$raw_file" -inform DER -noout 2>/dev/null; then
|
||||
echo "[entrypoint] ↻ Формат: DER — конвертируем в PEM"
|
||||
openssl x509 -in "$raw_file" -inform DER -out "$pem_file" -outform PEM
|
||||
else
|
||||
echo "[entrypoint] ❌ Неизвестный формат (не PEM и не DER) — пропускаем"
|
||||
rm -f "$raw_file"
|
||||
continue
|
||||
fi
|
||||
|
||||
chmod 644 "$pem_file"
|
||||
echo "[entrypoint] ✅ Установлен: $(basename "$pem_file")"
|
||||
downloaded_names="$downloaded_names $(basename "$pem_file" .pem)"
|
||||
rm -f "$raw_file"
|
||||
done
|
||||
|
||||
if [ -z "$(ls -A "$target_dir" 2>/dev/null)" ]; then
|
||||
echo "[entrypoint] Нет скачанных сертификатов — пропускаем"
|
||||
rm -rf "$work_dir"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Обновляем системное хранилище
|
||||
echo "[entrypoint] --- Обновление системного хранилища CA-сертификатов ---"
|
||||
update-ca-certificates --fresh 2>&1 | sed 's/^/[entrypoint] /'
|
||||
|
||||
# Проверяем, попали ли сертификаты в бандл, и создаём хеш-симлинки
|
||||
echo "[entrypoint] --- Валидация установки сертификатов ---"
|
||||
local all_ok=true
|
||||
|
||||
for pem in "$target_dir"/*.pem; do
|
||||
[ -f "$pem" ] || continue
|
||||
local cert_name
|
||||
cert_name="$(basename "$pem" .pem)"
|
||||
local cert_subject
|
||||
cert_subject="$(openssl x509 -in "$pem" -noout -subject 2>/dev/null | head -1 || echo "unknown")"
|
||||
|
||||
# Проверяем есть ли в ca-certificates.crt
|
||||
if grep -q "$cert_name" /etc/ssl/certs/ca-certificates.crt 2>/dev/null || \
|
||||
grep -qF "$(openssl x509 -in "$pem" -noout -serial 2>/dev/null)" /etc/ssl/certs/ca-certificates.crt 2>/dev/null; then
|
||||
echo "[entrypoint] ✅ ${cert_name} — в ca-certificates.crt (${cert_subject})"
|
||||
else
|
||||
echo "[entrypoint] ⚠ ${cert_name} — НЕ в ca-certificates.crt. Добавляем напрямую..."
|
||||
cat "$pem" >> /etc/ssl/certs/ca-certificates.crt
|
||||
echo "[entrypoint] ➕ Добавлен напрямую в ca-certificates.crt"
|
||||
fi
|
||||
|
||||
# Создаём хеш-симлинку в /etc/ssl/certs/
|
||||
local hash_val
|
||||
hash_val="$(openssl x509 -in "$pem" -noout -hash 2>/dev/null || true)"
|
||||
if [ -n "$hash_val" ]; then
|
||||
local link_path="/etc/ssl/certs/${hash_val}.0"
|
||||
if [ ! -L "$link_path" ]; then
|
||||
ln -sf "$pem" "$link_path"
|
||||
echo "[entrypoint] 🔗 Создана симлинка: ${hash_val}.0 → ${cert_name}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Проверяем итоговое количество
|
||||
local total_in_bundle
|
||||
total_in_bundle="$(awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' \
|
||||
< /etc/ssl/certs/ca-certificates.crt 2>/dev/null | wc -l || echo "0")"
|
||||
echo "[entrypoint] ✅ Всего сертификатов в bundle: ${total_in_bundle}"
|
||||
|
||||
rm -rf "$work_dir"
|
||||
echo "[entrypoint] === Установка LLM CA-сертификатов завершена ==="
|
||||
}
|
||||
# #endregion docker.backend.entrypoint.install_llm_ca_certs
|
||||
|
||||
# ======================================================================
|
||||
# bootstrap_admin — создание admin пользователя
|
||||
# ======================================================================
|
||||
@@ -149,6 +286,7 @@ install_playwright() {
|
||||
# ======================================================================
|
||||
|
||||
install_certificates
|
||||
install_llm_ca_certs
|
||||
install_playwright
|
||||
|
||||
# Check DB state: empty, legacy (tables exist but no alembic), or managed
|
||||
|
||||
Reference in New Issue
Block a user