修复Windows部署脚本兼容性
Some checks are pending
Security Checks / security (push) Waiting to run

This commit is contained in:
smail 2026-09-01 11:57:43 +08:00
parent 0a192851a8
commit 9f23c07b7b
5 changed files with 51 additions and 5 deletions

View File

@ -1,10 +1,14 @@
[CmdletBinding()]
[CmdletBinding()]
param(
[string]$PackageRoot = (Split-Path -Parent $PSScriptRoot),
[string]$PackageRoot = $null,
[string]$InstallRoot = (Join-Path $env:ProgramData "Smail"),
[switch]$StartService
)
if ([string]::IsNullOrWhiteSpace($PackageRoot)) {
$PackageRoot = Split-Path -Parent $PSScriptRoot
}
$ErrorActionPreference = "Stop"
function Assert-Administrator {
@ -130,8 +134,6 @@ try {
if (Test-Path -LiteralPath $adminTarget) { Move-Item -LiteralPath $adminTarget -Destination $adminBackup }
Move-Item -LiteralPath (Join-Path $transactionRoot "smail.exe") -Destination $mainTarget
Move-Item -LiteralPath (Join-Path $transactionRoot "smail-admin.exe") -Destination $adminTarget
Set-RestrictedAcl -Root $resolvedInstallRoot
$service = Get-Service -Name "Smail" -ErrorAction SilentlyContinue
if ($null -eq $service) {
$binaryPath = '"' + $mainTarget + '"'
@ -147,6 +149,11 @@ try {
"start=", "auto", "obj=", "NT SERVICE\Smail"
)
}
Invoke-Native -FilePath "sc.exe" -Arguments @(
"sidtype", "Smail", "unrestricted"
)
Set-RestrictedAcl -Root $resolvedInstallRoot
$failureActions = "restart/60000/restart/60000/"
Invoke-Native -FilePath "sc.exe" -Arguments @(
"failure", "Smail", "reset=", "86400", "actions=", $failureActions

View File

@ -1,4 +1,4 @@
[CmdletBinding()]
[CmdletBinding()]
param(
[string]$InstallRoot = (Join-Path $env:ProgramData "Smail")
)

View File

@ -1426,3 +1426,14 @@ AD-065 + CG-053~CG-056 → AD-066 → CG-057
### 发布结论
三份清单要求的可在当前工作区完成的代码实现已进入待复审状态;真实 Ubuntu 22.04/24.04、Windows Service/ACL/Named Pipe、真实 SMTP Relay、MySQL、PostgreSQL、浏览器三角色、多实例和最终发布安全评审保持阻塞。超级管理员自身重置仍只允许受保护的 UDS 或 Named Pipe,本轮未增加 HTTP、localhost TCP、局域网或公网 TCP 重置入口。
## 2026-09-01 Windows 部署脚本兼容性复核记录
- **关联任务**:AD-009~AD-011、AD-061~AD-063。
- **本轮状态**:`[x] 已完成,等待 Windows 实机复审`。
- **发现并修复**:Windows PowerShell 5.1 直接执行时,原部署脚本因中文内容缺少 UTF-8 BOM 发生解析错误;安装脚本的 `$PSScriptRoot` 参数默认值在参数绑定阶段为空;ACL 在创建 `NT SERVICE\Smail` 服务 SID 前执行,存在真实安装失败风险。
- **修改内容**:为 `deploy/install-windows.ps1` 和 `deploy/uninstall-windows.ps1` 增加 UTF-8 BOM;将安装脚本的 `PackageRoot` 改为参数绑定后回退到 `$PSScriptRoot`;创建或配置 `Smail` 服务后先执行 `sc.exe sidtype Smail unrestricted`,再应用服务 ACL。
- **自动化验证**:`go test ./cmd/smail-admin -count=1 -v` 通过;两个脚本使用 Windows PowerShell 5.1 解析并进入预期的管理员权限拒绝分支;`git diff --check` 通过。
- **未完成真实验收**:当前用户不是管理员,尚未执行真实 SCM 注册、服务 SID、ACL 拒绝和升级失败回滚验收;Ubuntu、MySQL、PostgreSQL、真实 SMTP、浏览器三角色和最终安全评审仍保持原阻塞。
- **复审日期**:2026-09-01(本机自动化复核)。

View File

@ -1328,3 +1328,13 @@ CG-053~CG-056 → AD-066 → CG-057
- **自动化验证**:新增外键等价比较和差异拒绝测试;`go test ./... -count=1 -timeout 30m`、`go test -race ./... -count=1 -timeout 45m`、`go vet ./...`、前端 ESLint 和生产构建均通过。
- **发布边界**:真实 MySQL/PostgreSQL/SQLite 迁移、跨平台部署、Nginx、浏览器、邮件系统、多实例和生产故障恢复仍待实机复审;CG-051、CG-056、CG-057 不升级为最终复审通过。
- **复审日期**:2026-08-31(本机自动化复审)。
## 2026-09-01 Windows 部署脚本兼容性复核记录
- **关联任务**:CG-031、CG-051~CG-057。
- **本轮状态**:`[x] 已完成,等待 Windows 实机复审`。
- **实施内容**:修复 Windows PowerShell 5.1 的 UTF-8 中文脚本解析兼容性、安装脚本 `PackageRoot` 参数绑定问题,并确保 `Smail` 服务创建和 SID 类型设置完成后再应用服务 ACL;新增静态顺序和脚本编码回归检查。
- **自动化验证**:`go test ./cmd/smail-admin -count=1 -v`、`go test ./... -count=1 -timeout 30m`、`go vet ./...`、前端生产构建、ESLint 和 `git diff --check` 均通过。
- **发布边界**:真实 Windows 管理员安装、Ubuntu systemd、三数据库、SMTP、浏览器三角色、多实例和最终安全评审仍未完成,CG-045、CG-051、CG-056、CG-057 不升级为最终复审通过。
- **复审日期**:2026-09-01(本机自动化复核)。

View File

@ -18,6 +18,9 @@ func TestWindowsDeploymentScriptsKeepAdminChannelManual(t *testing.T) {
"sc.exe",
"smail-admin.exe",
"Set-RestrictedAcl",
"sidtype",
"$PackageRoot = $null",
"$PackageRoot = Split-Path -Parent $PSScriptRoot",
"NT SERVICE\\Smail:(F)",
".backup-",
"$mainBackup",
@ -28,6 +31,14 @@ func TestWindowsDeploymentScriptsKeepAdminChannelManual(t *testing.T) {
t.Fatalf("Windows installer is missing %q", required)
}
}
if !hasUTF8BOM(installer) {
t.Fatal("Windows installer must be encoded as UTF-8 with BOM for Windows PowerShell")
}
serviceSetup := strings.Index(content, `"sidtype", "Smail", "unrestricted"`)
aclSetup := strings.Index(content, "Set-RestrictedAcl -Root $resolvedInstallRoot")
if serviceSetup < 0 || aclSetup < 0 || serviceSetup > aclSetup {
t.Fatal("Windows installer must create the service SID before applying service ACLs")
}
for _, forbidden := range []string{
"create SmailAdmin",
"Start-Service -Name \"SmailAdmin\"",
@ -39,6 +50,10 @@ func TestWindowsDeploymentScriptsKeepAdminChannelManual(t *testing.T) {
}
}
func hasUTF8BOM(data []byte) bool {
return len(data) >= 3 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF
}
func TestWindowsUninstallerPreservesData(t *testing.T) {
root := filepath.Clean(filepath.Join("..", "..", ".."))
uninstaller, err := os.ReadFile(filepath.Join(root, "deploy", "uninstall-windows.ps1"))
@ -46,6 +61,9 @@ func TestWindowsUninstallerPreservesData(t *testing.T) {
t.Fatal(err)
}
content := string(uninstaller)
if !hasUTF8BOM(uninstaller) {
t.Fatal("Windows uninstaller must be encoded as UTF-8 with BOM for Windows PowerShell")
}
if strings.Contains(content, "Remove-Item -LiteralPath $resolvedInstallRoot -Recurse") {
t.Fatal("Windows uninstaller recursively removes the data root")
}