Skip to content

[Hardening]: Connect-TargetHost should use -Credential instead of -User/-Password — empirical repro where byte-identical creds fail one way and succeed the other #129

@damir-topic

Description

@damir-topic

This is a hardening request, not a crisp bug report — please read the root-cause section before triaging, the actual fault appears to be in PowerCLI, not Holodeck.

Environment

  • Holodeck 9.0.x, unattended New-HoloDeckInstance
  • PowerCLI VMware.PowerCLI 13.3.0.24145081, target vCenter VCF 9.0.2.0
  • Service-account password shaped Aa1!<16 alphanumerics> (a policy-compliant VCF 9.0 SSO password), set via govc sso.user.update -p

Symptom

Connect-TargetHost in Modules/Auth.psm1 connects with the two-separate-string form:

Connect-VIServer -Server $config.target.hostname -User $config.Target.username -Password $config.Target.password -Force

For certain passwords this returns Cannot complete login due to an incorrect user name or password, even though the exact same $config.Target.password string:

  • works first try when passed through a [PSCredential] (ConvertTo-SecureString + New-Object PSCredential) against the same vCenter, and
  • works via govc sso.user.id <user> with the same value, and
  • is byte-clean (sha256 of the in-memory value matches the stored secret).

Holodeck's 5-attempt retry loop then compounds the false failure into an SSO account lockout.

Minimal A/B repro (same config, same value)

$cfg = Get-Content -Raw /holodeck-runtime/config/<configId>.json | ConvertFrom-Json

# A — Holodeck's current call shape: FAILS for affected passwords
try { Connect-VIServer -Server $cfg.Target.hostname -User $cfg.Target.username -Password $cfg.Target.password -Force -ErrorAction Stop; "A: SUCCESS" }
catch { "A: FAIL — $($_.Exception.Message)" }

# B — same value via -Credential: SUCCEEDS
$cred = New-Object System.Management.Automation.PSCredential($cfg.Target.username, (ConvertTo-SecureString -String $cfg.Target.password -AsPlainText -Force))
try { Connect-VIServer -Server $cfg.Target.hostname -Credential $cred -Force -ErrorAction Stop; "B: SUCCESS" }
catch { "B: FAIL — $($_.Exception.Message)" }

A: FAIL + B: SUCCESS for the byte-identical value is the signature.

Root cause (honest assessment)

We could not root-cause this conclusively, and the fault does not appear to be in Holodeck — it's in PowerCLI's -User/-Password parameter-binding / credential-serialisation path versus its -Credential path. Candidate explanations (none verified): a different auth flow for -Password [string] vs -Credential (STS/UPN-aware vs a Basic-style bind that VCF 9 SSO rejects for non-@vsphere.local domains); character-class handling at the WCF channel layer; or a vCenter-side SSO binding-mode difference between the two paths. We're explicitly not filing a PowerCLI bug because the repro is environment-specific and we can't isolate it cleanly.

Requested change (conservative, Holodeck-side)

Have Connect-TargetHost build a [PSCredential] and use -Credential instead of -User/-Password:

$secpw = ConvertTo-SecureString -String $config.Target.password -AsPlainText -Force
$cred  = New-Object System.Management.Automation.PSCredential($config.Target.username, $secpw)
Connect-VIServer -Server $config.target.hostname -Credential $cred -Force | Out-Null

-Credential is the more robust call shape regardless of the underlying cause — it sidesteps the failing path entirely, with no behavioural downside for the cases that already work. This is purely defensive; the empirical A/B above is the justification.

Workaround for affected users

Patch Modules/Auth.psm1 on the deployed HoloRouter to the -Credential form above (then Import-Module HoloDeck -Force / fresh pwsh). Verified working against a VCF 9.0.2.0 vCenter with a freshly-rotated 20-char policy-compliant password.

Note on issue tracking

Same as #122 / #127 / #128 — module is bundled in the HoloRouter OVA, not this repo. Filing here per the Support page. Sibling per-appliance fixes: #122, #127, #128. This one is intentionally lower-priority — a hardening ask, not a deterministic blocker.

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions