docs: 更新 README(口令一节、测试计数、虚拟机验证)并修掉拆文档时留下的重复标题
README 是被人真读的那份文档,而这一路改动让它有三处不再准确: 1. 「口令放在哪里」整节是错的:它写着"默认留空、必须放在仓库之外",而按你的决定,出厂默认值就是仓库根的 baknret.key(靠 .gitignore 兜住不被提交)。整节重写:如实写明这是一次取舍(省事 vs "不提交"依赖一个规则文件),并补上"相对路径按仓库根解析、不按工作目录"这条 —— 计划任务的工作目录是 C:\Windows\System32,按工作目录解析会让加密条目以"拿不到口令"失败而配置看上去没问题。关键提醒也改了:已经在仓库根的人什么都不用做,想搬走才需要动。 2. 测试项数过期:Pester 150 -> 183(含安全描述符套件)、零依赖 101 -> 111。 3. 新增「在 Hyper-V 虚拟机里验证」:这一层本机跑不到,而它覆盖的正是最需要真环境的那条路径 —— 安全描述符回放(把属主改成 NT AUTHORITY\SYSTEM、再靠 CREATOR OWNER 判断恢复后归谁)。附最近一次四步的结果与命令。 另修一个我在拆分 README 时留下的缺陷:4 个二级标题各重复了一次(块替换保留了原标题、又插入了带同名标题的指针行)。markdown 不经过 test.ps1,所以当时没被拦住 —— 现在按"相邻同标题只留一行"折掉,并复查为 0。 验收:test.ps1 9/9 全绿(7 与 5.1)。
This commit is contained in:
1 parent
2446c7c5c7
commit
e8f0a5ae19
1 file changed
+37
-19
@@ -70,20 +70,16 @@
|
||||
| `tools/Rename-Archives.ps1` | 把归档名对齐到当前清单规则(默认试运行) |
|
||||
| `tools/Install-TestDependencies.ps1` | 把 Pester 与 PSScriptAnalyzer 装到仓库内的 `.tools/`(不动机器上的全局模块) |
|
||||
|
||||
## SoftwareCatalog.psd1 —— 软件名 → Slot 组
|
||||
## SoftwareCatalog.psd1 —— 软件名 → Slot 组
|
||||
|
||||
软件名录的语法:一个软件由若干 Slot 组成,每个 Slot 能写路径、排除、追加、加密与说明。详见 [software-catalog.md](./docs/software-catalog.md)。
|
||||
## BackupList.txt 语法
|
||||
## BackupList.txt 语法
|
||||
|
||||
清单每一行的完整语法:方向标记、修饰符、引号与记号边界。详见 [backup-list-syntax.md](./docs/backup-list-syntax.md)。
|
||||
## 归档布局、命名与迁移
|
||||
## 归档布局、命名与迁移
|
||||
|
||||
归档内的层级、归档名怎么来、以及改名与迁移时要注意什么。详见 [archive-layout.md](./docs/archive-layout.md)。
|
||||
## 安全描述符(属主 / ACL)
|
||||
## 安全描述符(属主 / ACL)
|
||||
|
||||
属主与 ACL 为什么不是放进归档、而是旁挂一份 sidecar,以及恢复时怎么回放。详见 [security-descriptor.md](./docs/security-descriptor.md)。
|
||||
## 恢复语义
|
||||
@@ -169,7 +165,7 @@
|
||||
CompressionLevel = 9
|
||||
ToolOutput = 'live' # live | quiet
|
||||
Snapshot = @{ Enabled = $false; KeepCount = 3; KeepDays = 30 }
|
||||
Encryption = @{ Enabled = $false; PasswordFile = ''; EncryptHeaders = $true }
|
||||
Encryption = @{ Enabled = $false; PasswordFile = 'baknret.key'; EncryptHeaders = $true }
|
||||
DefaultExcludes = @('!Thumbs.db', '!desktop.ini')
|
||||
}
|
||||
```
|
||||
@@ -204,16 +200,21 @@ $env:BAKNRET_PASSWORD = '...' # 或
|
||||
|
||||
## 口令放在哪里
|
||||
|
||||
**口令文件必须放在仓库之外。** `BackupConfig.psd1` 的 `PasswordFile` 默认留空,这不是遗漏:
|
||||
出厂默认值指向仓库里的某个文件,等于鼓励把口令提交进版本库。`.gitignore` 里排除 `*.key` 只是
|
||||
第二道防线。三种给它口令的方式:
|
||||
口令文件的出厂默认值是**仓库根的 `baknret.key`**,靠 `.gitignore` 的 `*.key` 兜住"不被提交"。
|
||||
这是一次取舍:留在仓库根最省事(口令与配置在一起,搬家时不会丢),代价是"不提交"这件事
|
||||
依赖一个规则文件 —— 谁写了 `git add -f`、或把整个目录复制到别处再 `git init`,口令就会跟着走。
|
||||
|
||||
```
|
||||
powershell
|
||||
# A. 环境变量(计划任务用这个最省事)
|
||||
**相对路径按仓库根解析,不按当前工作目录。** 计划任务的工作目录通常是 `C:\Windows\System32`,
|
||||
在那里 `Test-Path baknret.key` 为假 —— 如果按工作目录解析,加密条目会以"拿不到口令"失败,
|
||||
而配置看上去毫无问题。
|
||||
|
||||
三种给它口令的方式(优先级见上一节):
|
||||
|
||||
```powershell
|
||||
# A. 环境变量(计划任务用这个最省事,也最不怕仓库被整体复制)
|
||||
$env:BAKNRET_PASSWORD = '...'
|
||||
|
||||
# B. 配置文件里指到一个仓库外的文件
|
||||
# B. 配置文件里指到一个仓库外的文件 —— 想更稳就走这条
|
||||
Encryption = @{ Enabled = $false; PasswordFile = (Join-Path $env:USERPROFILE '.baknret.key'); EncryptHeaders = $true }
|
||||
|
||||
# C. 单次指定
|
||||
@@ -222,10 +223,10 @@ Encryption = @{ Enabled = $false; PasswordFile = (Join-Path $env:USERPROFILE '.b
|
||||
|
||||
取不到口令时,加密条目**明确失败**,绝不退化成明文归档 —— 这条行为没有放宽。
|
||||
|
||||
> 从旧版本迁移的人注意:如果口令文件原先就放在仓库根(`baknret.key`),请把它移到仓库之外,
|
||||
> 再按上面任一种方式指过去。搬之前可以先用 `pwsh -File .\Restore.ps1 -VerifyOnly -Only "WindowsTerminal" -KeyFile <新路径>`
|
||||
> 验一下口令对不对(那份归档是加密的,口令不对会报错)。
|
||||
|
||||
> 从旧版本迁移:如果你的口令文件已经在仓库根(`baknret.key`),**什么都不用做**。
|
||||
> 想改用仓库外的位置,把它移走后按上面 B 或 C 指过去,并先用
|
||||
> `pwsh -File .\Restore.ps1 -VerifyOnly -Only "WindowsTerminal" -KeyFile <新路径>` 验一下
|
||||
> 口令对不对(那份归档是加密的,口令不对会报错)。
|
||||
## 计划任务
|
||||
|
||||
```powershell
|
||||
@@ -242,11 +243,11 @@ Encryption = @{ Enabled = $false; PasswordFile = (Join-Path $env:USERPROFILE '.b
|
||||
|
||||
| 套件 | 命令 | 需要什么 | 覆盖 |
|
||||
| --- | --- | --- | --- |
|
||||
| **Pester 套件**(推荐) | `.\tests\Run-Pester.ps1` | Pester 5.0+ 与 7z | 150 项:清单语法(方向 / `::` / `:-` / `:+` / `:encrypt` / `@ Key='值'` / 整行引号与记号边界)、Slot 结构名录、归档命名、排除翻译(`-x!` / `-xr!` / `!re:`)、Slot 前缀分配、暂存、manifest / 配置 / 名录,外加**用子进程真正跑 `Backup.ps1` / `Restore.ps1`** 的端到端与回归 |
|
||||
| 零依赖套件 | `.\tests\Run-Tests.ps1` | 只要 PowerShell + 7z | 101 项:同样的单元面,适合没装 Pester 的机器 |
|
||||
| **Pester 套件**(推荐) | `.\tests\Run-Pester.ps1` | Pester 5.0+ 与 7z | 183 项(含安全描述符套件):清单语法(方向 / `::` / `:-` / `:+` / `:encrypt` / `@ Key='值'` / 整行引号与记号边界)、Slot 结构名录、归档命名、排除翻译(`-x!` / `-xr!` / `!re:`)、Slot 前缀分配、暂存、manifest / 配置 / 名录,外加**用子进程真正跑 `Backup.ps1` / `Restore.ps1`** 的端到端与回归 |
|
||||
| 零依赖套件 | `.\tests\Run-Tests.ps1` | 只要 PowerShell + 7z | 111 项:同样的单元面,适合没装 Pester 的机器 |
|
||||
| 端到端验收 | `.\tests\Run-E2E.ps1` | 只要 PowerShell + 7z | 36 项:备份 → 确认排除生效 → 删源 → 恢复 → 逐字节对拍,含 `<Slot>\` 布局、文件 Slot、方向标记与旧布局回退 |
|
||||
| **真实归档恢复演练** | `.\tests\Restore-Drill.ps1` | 只要 PowerShell + 7z | 12 个真实归档:解到临时目录再和活源逐字节对拍(全程不碰真实目录) |
|
||||
| **安全描述符套件** | `.\tests\Run-Pester.ps1`(内含 `BakNRet.Security.Tests.ps1`) | Pester 5 + 7z | 25 项:排除判定与 7z `-x!/-xr!` 语义对齐、SID 映射边界(前缀 SID 不被误伤)、采集与 sidecar 往返、回放(`CREATOR OWNER` + 孤儿 SID + `protected` 逐字节一致)、以及真的用子进程跑 `Backup.ps1`/`Restore.ps1` 做端到端 |
|
||||
| **安全描述符套件** | `.\tests\Run-Pester.ps1`(内含 `BakNRet.Security.Tests.ps1`) | Pester 5 + 7z | 含在上面 183 项里:排除判定与 7z `-x!/-xr!` 语义对齐、SID 映射边界(前缀 SID 不被误伤)、采集与 sidecar 往返、回放(`CREATOR OWNER` + 孤儿 SID + `protected` 逐字节一致)、以及真的用子进程跑 `Backup.ps1`/`Restore.ps1` 做端到端 |
|
||||
|
||||
演练会把"源在备份之后变过"和"归档/解压有问题"分开:内容不一致时看活源文件的修改时间,
|
||||
晚于归档时间就算"源变了"(只提示),不晚于归档时间却内容不同才算失败。真实机器上的归档
|
||||
@@ -309,6 +310,23 @@ powershell
|
||||
不带 `-Settings` 的 `Invoke-ScriptAnalyzer -Severity Warning,Error` 会静默漏掉全部排版问题。
|
||||
三条有意排除与 160 字符行长上限的理由见 [docs/adr/0008](./docs/adr/0008-analyzer-deviations.md)。
|
||||
|
||||
### 在 Hyper-V 虚拟机里验证
|
||||
|
||||
上面几层都在本机跑。真正值得单独跑一遍的是 `tools/lab/`:它把仓库同步进一台**干净系统**的
|
||||
Hyper-V 虚拟机(`gsudo pwsh -File .\tools\lab\Lab.ps1 ...`),在那里跑完整流程。本机跑不到的
|
||||
路径只有它能覆盖 —— 最典型的是**安全描述符回放**:需要把某个目录的属主改成 `NT AUTHORITY\SYSTEM`、
|
||||
再靠 `CREATOR OWNER` 的继承规则判断恢复后归谁,而这件事只有在真 VM 里才敢做。
|
||||
|
||||
| 步骤 | 它验证什么 | 最近一次结果 |
|
||||
| --- | --- | --- |
|
||||
| `Lab.ps1 test -Suite all` | 三套仓库测试在干净系统上能不能跑 | Pester 183 / 零依赖 111 / 端到端 36,全部通过 |
|
||||
| `Lab.ps1 backup` | 在 VM 内真跑 `Backup.ps1`(沙盒清单 + 配置) | 退出码 0 |
|
||||
| `Lab.ps1 restore` | 用真实归档做恢复演练,**逐字节对拍** | 通过 6 / 失败 0(含连接点场景 4/4) |
|
||||
| `Lab.ps1 acl-test` | 安全描述符:属主 / `CREATOR OWNER` / 安全指纹 | 全部通过 19 项(含负对照) |
|
||||
|
||||
`acl-test` 里有一个**负对照**值得留意:只搬文件不回放安全描述符时,属主会变成"跑脚本的账户"
|
||||
而不是原账户 —— 那条用例能证明这个演练分辨得出对错,而不是一路绿灯。
|
||||
|
||||
## 设计取舍(有意为之,不是遗漏)
|
||||
|
||||
- **放弃 7z 的更新模式(`u`)。** 7z 默认固实压缩,`u` 本来就要重压大部分数据,收益很小,却让"排除规则改动"和"源里删掉的文件"永远进不了归档。
|
||||
|
||||
Reference in new issue
Block a user