fix(deploy): 默认关闭沙箱公网访问
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
function Get-ServerHttpBindEnvValue {
|
||||
param([string]$Content, [string]$Key)
|
||||
$match = [regex]::Match($Content, "(?m)^$([regex]::Escape($Key))=([^\r\n]*)$")
|
||||
if ($match.Success) { return $match.Groups[1].Value.Trim() }
|
||||
return ""
|
||||
}
|
||||
|
||||
function Set-ServerHttpBindEnvValue {
|
||||
param([string]$Content, [string]$Key, [string]$Value)
|
||||
$line = "$Key=$Value"
|
||||
$pattern = "(?m)^$([regex]::Escape($Key))=.*$"
|
||||
if ($Content -match $pattern) { return ($Content -replace $pattern, $line) }
|
||||
if ($Content -and -not $Content.EndsWith("`n")) { $Content += "`n" }
|
||||
return ($Content + $line + "`n")
|
||||
}
|
||||
|
||||
function Initialize-ServerHttpBindIp {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Path,
|
||||
[string]$Override = ""
|
||||
)
|
||||
|
||||
if (-not (Test-Path $Path)) { throw "Environment file not found: $Path" }
|
||||
$content = Get-Content $Path -Raw -Encoding UTF8
|
||||
if (-not $content) { $content = "" }
|
||||
|
||||
$current = Get-ServerHttpBindEnvValue $content "SERVER_HTTP_BIND_IP"
|
||||
$target = if (-not [string]::IsNullOrWhiteSpace($Override)) { $Override.Trim() } else { $current }
|
||||
if ([string]::IsNullOrWhiteSpace($target)) {
|
||||
$publicApiUrl = Get-ServerHttpBindEnvValue $content "NUXT_PUBLIC_BASE_APIURL"
|
||||
$target = if (
|
||||
$publicApiUrl -eq "/api" -or
|
||||
$publicApiUrl.StartsWith("/api/") -or
|
||||
$publicApiUrl -match '^https?://(127\.0\.0\.1|localhost)(:\d+)?(?:/|$)'
|
||||
) { "127.0.0.1" } elseif ($publicApiUrl -match '^https?://') { "0.0.0.0" } else { "127.0.0.1" }
|
||||
}
|
||||
|
||||
if ($target -notin @("127.0.0.1", "0.0.0.0")) {
|
||||
throw "SERVER_HTTP_BIND_IP only supports 127.0.0.1 or 0.0.0.0, current value: $target"
|
||||
}
|
||||
|
||||
if ($current -ne $target) {
|
||||
$content = Set-ServerHttpBindEnvValue $content "SERVER_HTTP_BIND_IP" $target
|
||||
[System.IO.File]::WriteAllText($Path, $content, [System.Text.UTF8Encoding]::new($false))
|
||||
Write-Host " ✓ SERVER_HTTP_BIND_IP=$target"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
. (Join-Path $PSScriptRoot "Initialize-ServerHttpBindIp.ps1")
|
||||
|
||||
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("easyai-bind-test-" + [guid]::NewGuid().ToString("N"))
|
||||
New-Item -ItemType Directory -Path $tempDir | Out-Null
|
||||
$envPath = Join-Path $tempDir ".env"
|
||||
|
||||
function Assert-BindIp {
|
||||
param([string]$PublicApiUrl, [string]$Expected)
|
||||
[System.IO.File]::WriteAllText($envPath, "NUXT_PUBLIC_BASE_APIURL=$PublicApiUrl`n", [System.Text.UTF8Encoding]::new($false))
|
||||
Initialize-ServerHttpBindIp -Path $envPath
|
||||
$content = Get-Content $envPath -Raw -Encoding UTF8
|
||||
if ($content -notmatch "(?m)^SERVER_HTTP_BIND_IP=$([regex]::Escape($Expected))$") {
|
||||
throw "Expected SERVER_HTTP_BIND_IP=$Expected for $PublicApiUrl"
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Assert-BindIp "/api" "127.0.0.1"
|
||||
Assert-BindIp "http://10.0.0.8:3001" "0.0.0.0"
|
||||
Assert-BindIp "http://127.0.0.1:3001" "127.0.0.1"
|
||||
|
||||
[System.IO.File]::WriteAllText($envPath, "NUXT_PUBLIC_BASE_APIURL=/api`nSERVER_HTTP_BIND_IP=0.0.0.0`n", [System.Text.UTF8Encoding]::new($false))
|
||||
Initialize-ServerHttpBindIp -Path $envPath
|
||||
if ((Get-Content $envPath -Raw -Encoding UTF8) -notmatch '(?m)^SERVER_HTTP_BIND_IP=0\.0\.0\.0$') {
|
||||
throw "Existing explicit bind value was not preserved"
|
||||
}
|
||||
|
||||
$invalidAccepted = $false
|
||||
try {
|
||||
Initialize-ServerHttpBindIp -Path $envPath -Override "192.168.1.8"
|
||||
$invalidAccepted = $true
|
||||
} catch { }
|
||||
if ($invalidAccepted) { throw "Invalid SERVER_HTTP_BIND_IP unexpectedly accepted" }
|
||||
|
||||
Write-Host "Server HTTP bind IP PowerShell tests passed"
|
||||
} finally {
|
||||
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
|
||||
}
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
|
||||
server_bind_read_env_value() {
|
||||
local file="$1"
|
||||
local key="$2"
|
||||
awk -F= -v key="$key" '$1 == key { sub(/^[^=]*=/, ""); print; exit }' "$file" | tr -d '\r'
|
||||
}
|
||||
|
||||
server_bind_write_env_value() {
|
||||
local file="$1"
|
||||
local key="$2"
|
||||
local value="$3"
|
||||
local tmp_file
|
||||
tmp_file="$(mktemp "${file}.XXXXXX")"
|
||||
awk -v key="$key" -v value="$value" '
|
||||
BEGIN { replaced = 0 }
|
||||
$0 ~ "^" key "=" {
|
||||
if (!replaced) {
|
||||
print key "=" value
|
||||
replaced = 1
|
||||
}
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
END {
|
||||
if (!replaced) print key "=" value
|
||||
}
|
||||
' "$file" > "$tmp_file"
|
||||
chmod --reference="$file" "$tmp_file" 2>/dev/null || true
|
||||
mv "$tmp_file" "$file"
|
||||
}
|
||||
|
||||
infer_server_http_bind_ip() {
|
||||
local file="$1"
|
||||
local public_api_url
|
||||
public_api_url="$(server_bind_read_env_value "$file" "NUXT_PUBLIC_BASE_APIURL")"
|
||||
|
||||
case "$public_api_url" in
|
||||
/api|/api/*|http://127.0.0.1:*|https://127.0.0.1:*|http://localhost:*|https://localhost:*)
|
||||
printf '%s\n' "127.0.0.1"
|
||||
;;
|
||||
http://*|https://*)
|
||||
printf '%s\n' "0.0.0.0"
|
||||
;;
|
||||
*)
|
||||
printf '%s\n' "127.0.0.1"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
init_server_http_bind_ip() {
|
||||
local file="${1:-.env}"
|
||||
local override="${2:-}"
|
||||
local current target
|
||||
|
||||
if [ ! -f "$file" ]; then
|
||||
echo "❌ 未找到环境文件: $file" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
current="$(server_bind_read_env_value "$file" "SERVER_HTTP_BIND_IP")"
|
||||
target="${override:-$current}"
|
||||
if [ -z "$target" ]; then
|
||||
target="$(infer_server_http_bind_ip "$file")"
|
||||
fi
|
||||
|
||||
case "$target" in
|
||||
127.0.0.1|0.0.0.0) ;;
|
||||
*)
|
||||
echo "❌ SERVER_HTTP_BIND_IP 仅支持 127.0.0.1 或 0.0.0.0,当前为: $target" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$current" != "$target" ]; then
|
||||
server_bind_write_env_value "$file" "SERVER_HTTP_BIND_IP" "$target"
|
||||
echo " ✓ SERVER_HTTP_BIND_IP=$target"
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
||||
init_server_http_bind_ip "${1:-.env}" "${2:-}"
|
||||
fi
|
||||
@@ -20,6 +20,7 @@ mkdir -p "$TMP_DIR/scripts"
|
||||
cp \
|
||||
"$REPO_ROOT/scripts/init-security-env.sh" \
|
||||
"$REPO_ROOT/scripts/init-public-api-base-url.sh" \
|
||||
"$REPO_ROOT/scripts/init-server-http-bind-ip.sh" \
|
||||
"$TMP_DIR/scripts/"
|
||||
|
||||
cd "$TMP_DIR"
|
||||
@@ -48,6 +49,34 @@ assert_compression_config() {
|
||||
fi
|
||||
}
|
||||
|
||||
assert_sandbox_public_access_disabled() {
|
||||
local config_file="$1"
|
||||
grep -q '^ location = /api/sandbox {' "$config_file"
|
||||
grep -q '^ location \^~ /api/sandbox/ {' "$config_file"
|
||||
grep -q '^ location = /jupyterlab {' "$config_file"
|
||||
grep -q '^ location \^~ /jupyterlab/ {' "$config_file"
|
||||
grep -q '^ location = /sandbox {' "$config_file"
|
||||
grep -q '^ location \^~ /sandbox/ {' "$config_file"
|
||||
if grep -Eq 'proxy_pass http://127\.0\.0\.1:(8081|8888)' "$config_file"; then
|
||||
echo "Unexpected public Sandbox/Jupyter proxy in $config_file" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_compose_exposure() {
|
||||
local expected_server_host_ip="$1"
|
||||
docker compose config --format json | python3 -c '
|
||||
import json, sys
|
||||
expected = sys.argv[1]
|
||||
config = json.load(sys.stdin)
|
||||
sandbox_ports = config["services"]["sandbox"].get("ports") or []
|
||||
assert sandbox_ports == [], f"sandbox ports published: {sandbox_ports}"
|
||||
server_ports = config["services"]["easyai-server"].get("ports") or []
|
||||
assert len(server_ports) == 1, server_ports
|
||||
assert server_ports[0].get("host_ip") == expected, server_ports
|
||||
' "$expected_server_host_ip"
|
||||
}
|
||||
|
||||
sed -i.bak 's/^SERVER_HTTP_PORT=.*/SERVER_HTTP_PORT=4100/' .env.sample
|
||||
rm -f .env.sample.bak
|
||||
DEPLOY_NON_INTERACTIVE=1 \
|
||||
@@ -57,8 +86,9 @@ DEPLOY_NON_INTERACTIVE=1 \
|
||||
bash start.sh >/dev/null
|
||||
grep -qx 'NUXT_PUBLIC_BASE_APIURL=http://10.0.0.8:4100' .env
|
||||
grep -qx 'CONFIG_PUBLIC_API_BASE_URL=http://10.0.0.8:4100' .env
|
||||
grep -qx 'SERVER_HTTP_BIND_IP=0.0.0.0' .env
|
||||
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
|
||||
docker compose config --quiet
|
||||
assert_compose_exposure 0.0.0.0
|
||||
fi
|
||||
|
||||
reset_case
|
||||
@@ -75,6 +105,11 @@ grep -q 'proxy_set_header X-Forwarded-Port $server_port;' demo.example.com.conf
|
||||
grep -q "proxy_set_header X-Original-Prefix '/api';" demo.example.com.conf
|
||||
grep -q 'location = /api {' demo.example.com.conf
|
||||
assert_compression_config demo.example.com.conf
|
||||
assert_sandbox_public_access_disabled demo.example.com.conf
|
||||
grep -qx 'SERVER_HTTP_BIND_IP=127.0.0.1' .env
|
||||
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
|
||||
assert_compose_exposure 127.0.0.1
|
||||
fi
|
||||
|
||||
# 直接验证 https.sh 的缺省配置生成函数会采用完整模板,而不是只代理 3010。
|
||||
eval "$(awk '
|
||||
@@ -90,6 +125,7 @@ grep -q 'proxy_pass http://127.0.0.1:3001/;' easyai-proxy.conf
|
||||
grep -q 'location /socket.io {' easyai-proxy.conf
|
||||
grep -q 'proxy_set_header X-Forwarded-Host $easyai_forwarded_host;' easyai-proxy.conf
|
||||
assert_compression_config easyai-proxy.conf
|
||||
assert_sandbox_public_access_disabled easyai-proxy.conf
|
||||
|
||||
reset_case
|
||||
DEPLOY_NON_INTERACTIVE=1 \
|
||||
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||
|
||||
# shellcheck source=init-server-http-bind-ip.sh
|
||||
. "$REPO_ROOT/scripts/init-server-http-bind-ip.sh"
|
||||
|
||||
write_env() {
|
||||
printf '%s\n' "$1" > "$TMP_DIR/.env"
|
||||
}
|
||||
|
||||
write_env 'NUXT_PUBLIC_BASE_APIURL=/api'
|
||||
init_server_http_bind_ip "$TMP_DIR/.env" >/dev/null
|
||||
grep -qx 'SERVER_HTTP_BIND_IP=127.0.0.1' "$TMP_DIR/.env"
|
||||
|
||||
write_env 'NUXT_PUBLIC_BASE_APIURL=http://10.0.0.8:3001'
|
||||
init_server_http_bind_ip "$TMP_DIR/.env" >/dev/null
|
||||
grep -qx 'SERVER_HTTP_BIND_IP=0.0.0.0' "$TMP_DIR/.env"
|
||||
|
||||
write_env 'NUXT_PUBLIC_BASE_APIURL=http://127.0.0.1:3001'
|
||||
init_server_http_bind_ip "$TMP_DIR/.env" >/dev/null
|
||||
grep -qx 'SERVER_HTTP_BIND_IP=127.0.0.1' "$TMP_DIR/.env"
|
||||
|
||||
write_env $'NUXT_PUBLIC_BASE_APIURL=/api\nSERVER_HTTP_BIND_IP=0.0.0.0'
|
||||
init_server_http_bind_ip "$TMP_DIR/.env" >/dev/null
|
||||
grep -qx 'SERVER_HTTP_BIND_IP=0.0.0.0' "$TMP_DIR/.env"
|
||||
|
||||
if init_server_http_bind_ip "$TMP_DIR/.env" '192.168.1.8' >/dev/null 2>&1; then
|
||||
echo 'Invalid SERVER_HTTP_BIND_IP unexpectedly accepted' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 'Server HTTP bind IP shell tests passed'
|
||||
Reference in New Issue
Block a user