fix: take the API token as a SecureString and stop exposing session credentials (#240)

Connect-PveServer -ApiToken was a plain string, so the token landed verbatim
in PSReadLine history and any transcript, and PveSession published ApiToken,
Ticket and CsrfToken as public getters, so Format-List *, ConvertTo-Json and
Export-Clixml of a session printed them.

The parameter is now a SecureString, extracted at the cmdlet boundary with the
Marshal/ZeroFree pattern ADR 0002 established for passwords. A plain string
still binds for one minor release through an argument transformation, and the
cmdlet warns that the string form goes away in the next major; the marker
lives in a ConditionalWeakTable keyed on the converted instance, so an
abandoned binding neither retains the secret nor mislabels a later call.

The three session getters become internal. PveHttpClient is in the same
assembly and the xUnit project already has InternalsVisibleTo, so the header
construction and its tests are unchanged.

Refs ADR 0028, issue #147.

Co-authored-by: goodolclint-claude[bot] <323206664+goodolclint-claude[bot]@users.noreply.github.com>
This commit is contained in:
goodolclint-claude[bot]
2026-09-03 21:34:11 +00:00
committed by GitHub
parent 8d955a0ea8
commit c8a7e809bb
9 changed files with 223 additions and 20 deletions
+6 -3
View File
@@ -20,7 +20,7 @@ Connect-PveServer [-Server] <String> [-Port <Int32>] -Credential <PSCredential>
### ApiToken
```
Connect-PveServer [-Server] <String> [-Port <Int32>] -ApiToken <String> [-SkipCertificateCheck]
Connect-PveServer [-Server] <String> [-Port <Int32>] -ApiToken <SecureString> [-SkipCertificateCheck]
[-TimeoutSeconds <Int32>] [-PassThru] [-Quiet] [-ProgressAction <ActionPreference>] [<CommonParameters>]
```
@@ -39,10 +39,13 @@ PS C:\> {{ Add example code here }}
## PARAMETERS
### -ApiToken
API token in USER@REALM!TOKENID=UUID format.
API token in USER@REALM!TOKENID=UUID format, as a SecureString.
Build one with `Read-Host -AsSecureString`, or read it from a secret vault. `ConvertTo-SecureString 'root@pam!mytoken=...' -AsPlainText -Force` also works, but a token written as a literal lands in shell history and in any transcript.
A plain string is still accepted in this release and emits a deprecation warning; it is removed in the next major release.
```yaml
Type: String
Type: SecureString
Parameter Sets: ApiToken
Aliases: