fix and update

This commit is contained in:
lendry
2026-06-29 16:23:40 +03:00
parent aebce54bd7
commit 10253fc76b
8 changed files with 797 additions and 106 deletions

View File

@@ -1384,6 +1384,25 @@ intranet_wildcard_base_domain() {
fi
}
# Регистрируемый домен (eTLD+1) — нужен для FedCM well-known.
# FedCM ВСЕГДА запрашивает /.well-known/web-identity с eTLD+1 домена IdP:
# sso.idpmvk.lpr -> idpmvk.lpr
# api.id.example.ru -> example.ru
# Берём два последних лейбла (корректно для большинства зон и кастомных TLD .lpr).
# Исключение — многосоставные суффиксы вида .co.uk; для них укажите домен вручную.
registrable_domain() {
local domain="${1:-}"
[[ -z "$domain" ]] && return 0
local -a labels
IFS='.' read -ra labels <<< "$domain"
local n=${#labels[@]}
if (( n <= 2 )); then
echo "$domain"
else
echo "${labels[n-2]}.${labels[n-1]}"
fi
}
collect_self_signed_sans() {
local -a sans=()
local base domain
@@ -1400,6 +1419,13 @@ collect_self_signed_sans() {
sans+=("DNS:${base}")
fi
# eTLD+1 для FedCM well-known (например idpmvk.lpr) — гарантированно в сертификате.
local apex
apex="$(registrable_domain "${DOMAIN_FRONTEND:-$DOMAIN_API}")"
if [[ -n "$apex" && "$apex" != "$base" ]]; then
sans+=("DNS:${apex}")
fi
(IFS=,; echo "${sans[*]}")
}
@@ -1896,6 +1922,56 @@ EOF
nginx_publish_config "frontend"
}
# Сервер для eTLD+1 (например idpmvk.lpr): обслуживает FedCM well-known.
# Браузер при FedCM-логине из стороннего приложения запрашивает
# https://<eTLD+1>/.well-known/web-identity. Если этого домена нет в DNS —
# получаем ERR_NAME_NOT_RESOLVED. Зеркалим idp-api/fedcm/oauth/.well-known на
# api-gateway и корень на фронтенд, чтобы домен был полноценным алиасом IdP.
write_nginx_site_fedcm_apex() {
local domain="$1"
local ssl_type="${2:-none}"
local conf upstream http_preamble ssl_block idp_api_block
conf="$(nginx_conf_target fedcm-apex)"
upstream="$(nginx_upstream frontend)"
http_preamble="$(nginx_http_server_preamble "$domain" "$ssl_type")"
idp_api_block="$(build_nginx_idp_api_proxy_block)"
if [[ "$ssl_type" == "none" ]]; then
nginx_write_conf "$conf" <<EOF
server {
listen 80;
listen [::]:80;
server_name ${domain};
client_max_body_size 50m;
${idp_api_block}
location / {
proxy_pass ${upstream};
proxy_http_version 1.1;
${nginx_proxy_headers}
}
}
EOF
else
ssl_block="$(nginx_ssl_directives "$domain" "$ssl_type")"
nginx_write_conf "$conf" <<EOF
${http_preamble}server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name ${domain};
${ssl_block}
client_max_body_size 50m;
${idp_api_block}
location / {
proxy_pass ${upstream};
proxy_http_version 1.1;
${nginx_proxy_headers}
}
}
EOF
fi
nginx_publish_config "fedcm-apex"
}
write_nginx_site_docs() {
local domain="$1"
local ssl_type="${2:-none}"
@@ -2059,6 +2135,21 @@ write_all_nginx_configs() {
write_nginx_site_frontend "$DOMAIN_FRONTEND" "$ssl_type"
write_nginx_site_docs "$DOMAIN_DOCS" "$ssl_type"
# FedCM well-known всегда запрашивается с eTLD+1 (idpmvk.lpr). Если фронтенд/API
# живут на поддоменах, поднимаем отдельный server для корневого домена, иначе
# сторонние приложения получают ERR_NAME_NOT_RESOLVED при FedCM-логине.
local apex_domain
apex_domain="$(registrable_domain "${DOMAIN_FRONTEND:-$DOMAIN_API}")"
if [[ -n "$apex_domain" \
&& "$apex_domain" != "$DOMAIN_FRONTEND" \
&& "$apex_domain" != "$DOMAIN_API" \
&& "$apex_domain" != "${DOMAIN_DOCS:-}" ]]; then
write_nginx_site_fedcm_apex "$apex_domain" "$ssl_type"
else
rm -f "${LOCAL_CONF_DIR}/${NGINX_PREFIX}-fedcm-apex.conf" 2>/dev/null || true
run_root rm -f "${NGINX_ENABLED}/${NGINX_PREFIX}-fedcm-apex.conf" "${NGINX_AVAILABLE}/${NGINX_PREFIX}-fedcm-apex.conf" 2>/dev/null || true
fi
if [[ "$ws_on_api" == "false" ]]; then
write_nginx_site_ws "$DOMAIN_WS" "$ssl_type"
else
@@ -2117,6 +2208,16 @@ obtain_all_certificates() {
obtain_certificate "$DOMAIN_FRONTEND" "$email"
obtain_certificate "$DOMAIN_DOCS" "$email"
# Сертификат для eTLD+1 (FedCM well-known), если он отдельный server.
local apex_domain
apex_domain="$(registrable_domain "${DOMAIN_FRONTEND:-$DOMAIN_API}")"
if [[ -n "$apex_domain" \
&& "$apex_domain" != "$DOMAIN_FRONTEND" \
&& "$apex_domain" != "$DOMAIN_API" \
&& "$apex_domain" != "${DOMAIN_DOCS:-}" ]]; then
obtain_certificate "$apex_domain" "$email"
fi
if [[ -n "${DOMAIN_WS:-}" && "${DOMAIN_WS}" != "${DOMAIN_API}" ]]; then
obtain_certificate "$DOMAIN_WS" "$email"
fi
@@ -2248,9 +2349,22 @@ print_intranet_hint() {
server_ip="$(hostname -I 2>/dev/null | awk '{print $1}' || true)"
[[ -z "$server_ip" ]] && server_ip="<IP-сервера>"
local apex_domain extra_apex=""
apex_domain="$(registrable_domain "${DOMAIN_FRONTEND:-$DOMAIN_API}")"
if [[ -n "$apex_domain" \
&& "$apex_domain" != "$DOMAIN_FRONTEND" \
&& "$apex_domain" != "$DOMAIN_API" \
&& "$apex_domain" != "${DOMAIN_DOCS:-}" ]]; then
extra_apex=" ${apex_domain}"
fi
echo -e " ${BOLD}Локальная сеть (DNS / hosts):${NC}"
echo " Пропишите во внутреннем DNS или C:\\Windows\\System32\\drivers\\etc\\hosts:"
echo " ${server_ip} ${DOMAIN_API} ${DOMAIN_FRONTEND} ${DOMAIN_DOCS}"
echo " ${server_ip} ${DOMAIN_API} ${DOMAIN_FRONTEND} ${DOMAIN_DOCS}${extra_apex}"
if [[ -n "$extra_apex" ]]; then
echo " (${apex_domain} обязателен для входа через FedCM/One Tap из сторонних приложений —"
echo " браузер берёт /.well-known/web-identity именно с корневого домена)"
fi
echo ""
if [[ "$(env_get SSL_TYPE none)" == "selfsigned" ]]; then
echo " Сертификат: ${LOCAL_CERTS_DIR}/shared-intranet (общий для всех доменов)"