NoaMatout/powershell-ad-toolkit

GitHub: NoaMatout/powershell-ad-toolkit

将 DSInternals 密码质量报告解析为结构化对象并对多次审计结果进行差异比较的 PowerShell 模块,帮助持续跟踪 Active Directory 密码安全态势变化。

Stars: 0 | Forks: 0

## 状态 版本 0.1.0。密码审计部分已实现并经过测试;在 [路线图](#roadmap) 中描述的其余部分尚未编写。这里没有任何占位符——发布的内容都是可用的。 | 功能 | 用途 | | --- | --- | | `ConvertFrom-PasswordQualityReport` | 将归档的 DSInternals `Test-PasswordQuality` 报告解析为发现对象 | | `Compare-PasswordAudit` | 将两份报告中的发现分类为 New、Resolved 或 Persisting | ## 安装 需要 PowerShell 5.1 或更高版本。该模块本身没有依赖项——它只是解析其他工具生成的文本。而生成这些文本需要 [DSInternals](https://github.com/MichaelGrafnetter/DSInternals) 以及 Domain Admin(或等效的复制)权限: ``` Get-ADReplAccount -All -Server $DC -NamingContext 'DC=example,DC=local' | Test-PasswordQuality -WeakPasswordsFile .\pwnedpasswords.txt | Out-File ".\archive\audit-$(Get-Date -Format 'yyyy-MM-dd').txt" ``` 请将这些归档文件妥善保存在合适的地方。它们列出了域中所有密码薄弱、密码共享或没有密码的账户——报告的敏感程度与其描述的弱点相当。 ## 它的功能 ### 发现转为对象 报告中的每个条目都会变成一个对象,包含其所属部分、严重程度、拆分为 domain 和 SAM 名称的账户身份,以及它是否为计算机账户。 ``` $report = ConvertFrom-PasswordQualityReport -Path .\archive\audit-2026-07-15.txt $report.Findings | Group-Object Section | Sort-Object Count -Descending $report.Findings | Where-Object { $_.Severity -eq 'Critical' -and -not $_.IsComputerAccount } ``` 源报告中的部分标题是完整的英文句子,其措辞在 DSInternals 的不同版本之间有所变化,因此它们被统一映射到稳定的关键字(`InDictionary`、`DuplicatePasswords`、`Kerberoastable` 等)——位于 [`Private/Get-PasswordQualitySectionMap.ps1`](Private/Get-PasswordQualitySectionMap.ps1) 中。 模块无法识别的标题会产生警告,并且其条目会被跳过,而不是静默地被错误归类到前一个标题下。 ### 空部分不等于缺失部分 下面没有任何内容的标题意味着检查已运行且未发现任何内容。而完全缺失的标题意味着检查未运行。这是两种不同的情况,将它们混为一谈会导致比较结果出现谎言——停止报告的某个部分中的每个账户都会显示为 `Resolved`。即使部分为空,也会被记录下来;并且如果某个部分仅存在于两份报告中的一份中,则会作为警告报告,而不进行比较。 ### 重复密码组基于成员身份匹配 报告将共享密码的账户分组为 `Group 1`、`Group 2` 等等。这种编号是每次运行时分配的,在多次运行之间没有任何意义——相同的两个服务账户可能在一周内是 `Group 1`,在下一周就成了 `Group 17`。 因此,组是通过其排序后的成员身份来标识的,而不是通过其标签。如果某个状态持续的账户所在的组成员身份发生了变化,则会被标记为 `GroupChanged`:它仍然共享密码,但共享的对象变成了另一组不同的账户,这通常意味着有人轮换了组内部分账户的密码后就停止了操作。 ## 设计说明 **没有内置(vendor)第三方二进制文件。** PingCastle、ADRecon 和 DSInternals 非常出色,我不便对其进行二次分发。该模块期望它们已被安装,并直接调用它们。 **源代码中没有特定环境的值。** 域、控制器和路径都是参数,绝不是默认值。测试夹具(fixtures)是合成的。 **文本输入,对象输出。** 归档的文本报告通常是几周后唯一仍然存在的工件(artefact),因此它被视为输入格式,而不是需要被替换的东西。 ## 路线图 按我的期望程度排序,而不是按它们落地的先后时间排序: - `Invoke-PasswordAudit` —— 封装 DSInternals 收集过程,以便使用一致的名称和布局生成归档 - `Get-PasswordAuditArchive` —— 解析目录中最近的两个归档(包括压缩的归档),从而让每周的比较只需一行代码即可完成 - `New-AuditReport` —— 将比较结果渲染为 Markdown 或 HTML 以便发送邮件 - `Invoke-ADHealthCheck` —— 驱动 PingCastle 并将其 XML 暴露为对象 - `Invoke-ShareAudit` —— 驱动 PowerHunt 进行 SMB 共享暴露检查 ## 开发 ``` Install-Module Pester -MinimumVersion 5.5 -Scope CurrentUser Install-Module PSScriptAnalyzer -Scope CurrentUser Invoke-Pester .\tests Invoke-ScriptAnalyzer -Path . -Recurse -Severity Error,Warning ``` 在 CI 中,每次 push 都会针对 PowerShell 5.1 和 7 运行这两者。 ## 许可证 MIT —— 见 [LICENSE](LICENSE)。
标签:AI合规, Libemu