Files
tomas.kracmar e2a523dfda feat(report): JSON report and summary output; UPNs from the replicated accounts
The weak-password report was text only: DSInternals' formatted output
captured with Out-String, with UPNs spliced in by re-parsing that
text. Nothing downstream could consume it reliably.

- Next to the text report, Invoke-WeakPasswordTest now writes
  <domain>_WeakPasswordReport_<timestamp>.json: tool, version,
  generatedAt, domain, DC, accountsTested, and one finding per
  non-empty check (WeakPassword, LMHash, DuplicatePasswordGroups, ...)
  listing each account's logon name and UPN. Duplicate-password groups
  stay grouped. The text and UPN-only reports are unchanged.
- ConvertTo-PasswordQualityFinding builds that data generically from
  the result object's properties, so it does not depend on the exact
  set of checks a DSInternals version reports. Arrays are assembled
  with List.ToArray() rather than pipeline output, because Windows
  PowerShell 5.1's ConvertTo-Json renders pipeline-wrapped arrays as
  {"value": [...], "Count": n}.
- Test-ElysiumPasswordQuality returns a summary object: domain,
  accounts tested, finding counts per check, and the three report
  paths.
- UPNs come from the DSAccount objects already replicated for the
  test (SamAccountName -> UserPrincipalName) instead of one Get-ADUser
  query per dictionary hit; Get-UserUPN is removed. Missing UPNs still
  read "UPN not found" in the text report (null in the JSON).

Tests: the converter on a result shaped like DSInternals' (string
sets, a list of sets for duplicate groups, an empty check) - empty
checks omitted, UPNs mapped, unknown UPN null, groups preserved, no
array-wrapper artefacts in the JSON. 33/33 Pester tests pass on pwsh 7.
The JSON shape on Windows PowerShell 5.1 and the real DSInternals
result object still need the Windows run.
2026-11-04 14:22:48 +01:00
..