Files
BakNRet/BakNRet/Public/Test-BaknretSecurityRecordNeeded.ps1
T
Shuery 42f02d0eca refactor: 公共面补 BakNRet 前缀,产品名大小写全仓统一
16 个没有前缀的公共函数补上 BakNRet(Write-Log → Write-BakNRetLog、Resolve-BackupEntry →
Resolve-BakNRetBackupEntry、Find-ChildDirectoryByName → Find-BakNRetChildDirectoryByName 等),
另外把全仓的 Baknret 统一成 BakNRet(47 个文件、940 处、65 个定义文件重命名)。

这不是审美问题:静态分析直接拓出一条实据 —— Write-Log 与本机某个已装模块导出的命令
**重名**(PSAvoidOverwritingBuiltInCmdlets),而重名的后果是导入两个模块时有一方的命令被
静默遮蔽。补前缀正是这条规则的解法,改名后它归零。

为什么敢做这个规模:PowerShell 的函数名解析大小写不敏感,所以 Baknret → BakNRet 在功能
上是零风险;真正要验证的是 16 个补前缀的调用点,而 276 个断言几乎覆盖了每个函数。另外
"名字与文件名一致"这条不变式有断言盯着(加载器点源的文件集合 vs 磁盘)。

踩到并记下的坑:Windows 文件系统大小写不敏感,所以**只改大小写**的重命名会被 Move-Item
当成同一个文件而静默跳过 —— 同一批里同时改了名字的那 16 个文件却成功了,于是"看起来能跑"。
最后用"先移到临时名、再移到目标名"的两步走解决,判断与替换全部改用显式大小写敏感的形式
(-creplace / -cmatch)。

顺带把名录指纹缓存从 MD5 换成 SHA256(PSAvoidUsingBrokenHashAlgorithms):它只是缓存键,
没有兼容负担。

验收:test.ps1 9/9 全绿(7 与 5.1)、100 个文件两版解析零错、276 个断言全过、
构建工具仍能合回单文件(3300 行)。
2026-09-27 09:56:36 +08:00

48 lines
2.3 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
function Test-BakNRetSecurityRecordNeeded {
<#
.SYNOPSIS
Smart 模式下判断这条记录是否必须落进 sidecar。
.DESCRIPTION
判据是"恢复时不能被继承自动复现",任何一条成立就得留:
* 读不到(e)—— 必须记账,恢复时要能报出来;
* DACL 是 protected(断开继承)—— 只靠父目录继承永远复现不出这一套;
* 有显式 ACE(Explicit > 0)—— 同上;
* NULL DACL(NO_ACCESS_CONTROL)—— 那不是"没有特殊权限",是"人人全权";
* 属主 / 属组与父目录不同 —— CREATOR OWNER 的解析结果就取决于属主;
* 继承链路与父目录脱节 —— 条数对不上,或某条继承来的 ACE 在父目录 ACL 里
找不到出处(父目录改过权限、子对象还留着老 ACE);空 DACL 也会在这里露出来。
分析不了(Analyzed=$false)时一律保留:多存永远比少存安全。
#>
param(
[Parameter(Mandatory = $true)]$Record,
[string]$ParentOwner,
[string]$ParentGroup,
[int]$ParentInheritable = -1,
[string[]]$ParentSignatures = @(),
[switch]$Force
)
if ($Force) { return $true }
if ($Record.e) { return $true }
if (-not $Record.s) { return $true }
if (-not $Record.Analyzed) { return $true }
if ($Record.Protected) { return $true }
if ($Record.Explicit -gt 0) { return $true }
if ($Record.s -match 'NO_ACCESS_CONTROL') { return $true }
if ($Record.o -and $ParentOwner -and ($Record.o -ne $ParentOwner)) { return $true }
if ($Record.g -and $ParentGroup -and ($Record.g -ne $ParentGroup)) { return $true }
# 继承链还接不接得上父目录:先比条数,再比每一条在父目录 ACL 里有没有出处。
# 只比条数会漏判 —— 真机实测过:子对象留着"改权限之前"的老 ACE,
# 条数与父目录可继承条数正好相等(都 4 条),内容却完全不同。
if ($ParentInheritable -ge 0 -and $Record.Inherited -ne $ParentInheritable) { return $true }
foreach ($signature in @($Record.InheritedSignatures)) {
if ($ParentSignatures -notcontains $signature) { return $true }
}
return $false
}