fix(harness): grant nginx scoped auth access

This commit is contained in:
kejilion
2026-08-16 11:07:09 +08:00
parent a70793a344
commit 2e3a39ef25
2 changed files with 62 additions and 3 deletions

View File

@@ -239,11 +239,51 @@ write_webui_auth_file() {
umask 077
temporary_file=$(mktemp "${auth_file}.tmp.XXXXXX") || return 1
printf '%s:%s\n' "$username" "$password_hash" >"$temporary_file"
# Nginx worker needs read access; the file stores only an APR1 password hash.
chmod 644 "$temporary_file"
chmod 600 "$temporary_file"
mv -f "$temporary_file" "$auth_file"
}
ensure_webui_acl_tool() {
command -v setfacl >/dev/null 2>&1 && return 0
echo -e "${YELLOW}正在安装 ACL 工具,用于限定 Nginx 仅访问 Harness 认证文件...${NC}"
if command -v apt-get >/dev/null 2>&1; then
apt-get install -y acl >/dev/null 2>&1
elif command -v dnf >/dev/null 2>&1; then
dnf install -y acl >/dev/null 2>&1
elif command -v yum >/dev/null 2>&1; then
yum install -y acl >/dev/null 2>&1
elif command -v apk >/dev/null 2>&1; then
apk add --no-cache acl >/dev/null 2>&1
else
return 1
fi
command -v setfacl >/dev/null 2>&1
}
nginx_worker_uid() {
local uid
uid=$(docker exec nginx id -u nginx 2>/dev/null) || return 1
uid=$(printf '%s' "$uid" | tr -d '[:space:]')
case "$uid" in
''|*[!0-9]*) return 1 ;;
esac
printf '%s' "$uid"
}
grant_webui_auth_access() {
local domain="$1" auth_file auth_path nginx_uid
auth_file=$(webui_auth_file "$domain")
auth_path="/etc/nginx/conf.d/$(basename "$auth_file")"
[ -f "$auth_file" ] || return 1
nginx_uid=$(nginx_worker_uid) || return 1
# Keep the shared conf.d mode unchanged: allow only directory traversal and
# read access to this Harness password file for the Nginx worker UID.
setfacl -m "u:${nginx_uid}:--x" "$WEB_CONF_DIR" || return 1
setfacl -m "u:${nginx_uid}:r--" "$auth_file" || return 1
# Open the file as the worker UID; BusyBox test -r may ignore POSIX ACLs.
docker exec -u "$nginx_uid" nginx sh -c ': < "$1"' sh "$auth_path" >/dev/null 2>&1
}
patch_webui_proxy_config() {
local domain="$1" conf_file auth_path
conf_file="$WEB_CONF_DIR/${domain}.conf"
@@ -330,12 +370,17 @@ create_webui_domain() {
echo -e "${RED}找不到 k 命令,无法调用 k fd 创建反向代理。${NC}"
return 1
}
ensure_webui_acl_tool || {
echo -e "${RED}缺少 ACL 工具,无法安全配置 Nginx 认证文件权限。${NC}"
return 1
}
if ! "$K_COMMAND" fd "$domain" "$LISTEN_HOST" "$LISTEN_PORT"; then
rollback_webui_domain_add "$domain"
echo -e "${RED}k fd 创建反向代理失败,已清理本次产生的文件。${NC}"
return 1
fi
if ! write_webui_auth_file "$domain" "$username" "$password" \
|| ! grant_webui_auth_access "$domain" \
|| ! patch_webui_proxy_config "$domain" \
|| ! reload_managed_nginx \
|| ! add_webui_domain_record "$domain" \

View File

@@ -19,6 +19,7 @@ export DEEPSEEK_HARNESS_K_COMMAND="k"
export MOCK_NPM_ARGS_LOG="${temporary_dir}/npm-args.log"
export MOCK_K_ARGS_LOG="${temporary_dir}/k-args.log"
export MOCK_DOCKER_ARGS_LOG="${temporary_dir}/docker-args.log"
export MOCK_SETFACL_ARGS_LOG="${temporary_dir}/setfacl-args.log"
export PATH="${temporary_dir}/bin:${PATH}"
mkdir -p "${temporary_dir}/bin" "$DSH_HOME" "$DEEPSEEK_HARNESS_WEB_CONF_DIR" "$DEEPSEEK_HARNESS_WEB_CERT_DIR"
@@ -72,8 +73,15 @@ MOCK
cat >"${temporary_dir}/bin/docker" <<'MOCK'
#!/bin/bash
printf '%s\n' "$*" >>"$MOCK_DOCKER_ARGS_LOG"
if [ "$*" = "exec nginx id -u nginx" ]; then
printf '%s\n' '101'
fi
exit 0
MOCK
cat >"${temporary_dir}/bin/setfacl" <<'MOCK'
#!/bin/bash
printf '%s\n' "$*" >>"$MOCK_SETFACL_ARGS_LOG"
MOCK
cat >"${temporary_dir}/bin/k" <<'MOCK'
#!/bin/bash
printf '%s\n' "$*" >>"$MOCK_K_ARGS_LOG"
@@ -113,6 +121,7 @@ chmod +x \
"${temporary_dir}/bin/curl" \
"${temporary_dir}/bin/openssl" \
"${temporary_dir}/bin/docker" \
"${temporary_dir}/bin/setfacl" \
"${temporary_dir}/bin/k"
# shellcheck source=../deepseek_harness_manager.sh
@@ -201,6 +210,7 @@ if valid_domain '127.0.0.1'; then
exit 1
fi
chmod 750 "$DEEPSEEK_HARNESS_WEB_CONF_DIR"
create_webui_domain 'Chat.Example.com' 'admin' 'test-password'
[ "$(cat "$MOCK_K_ARGS_LOG")" = 'fd chat.example.com 127.0.0.1 3080' ]
grep -qxF 'chat.example.com' "$DEEPSEEK_HARNESS_WEBUI_DOMAINS_FILE"
@@ -217,7 +227,11 @@ if grep -Eq '^[[:space:]]*proxy_cache[[:space:]]' "$webui_conf"; then
exit 1
fi
grep -qxF 'admin:$apr1$mock$hashed-password' "$webui_auth"
[ "$(stat -c '%a' "$webui_auth")" = '644' ]
[ "$(stat -c '%a' "$webui_auth")" = '600' ]
[ "$(stat -c '%a' "$DEEPSEEK_HARNESS_WEB_CONF_DIR")" = '750' ]
grep -Fqx -- "-m u:101:--x $DEEPSEEK_HARNESS_WEB_CONF_DIR" "$MOCK_SETFACL_ARGS_LOG"
grep -Fqx -- "-m u:101:r-- $webui_auth" "$MOCK_SETFACL_ARGS_LOG"
grep -Fqx -- 'exec -u 101 nginx sh -c : < "$1" sh /etc/nginx/conf.d/.deepseek-harness-chat.example.com.htpasswd' "$MOCK_DOCKER_ARGS_LOG"
configure_systemd_service
grep -Fq ' --trusted-host chat.example.com' "$DEEPSEEK_HARNESS_SERVICE_FILE"