Private/PivTool/Invoke-PWSHYBKPIVTool.ps1
|
function Invoke-PWSHYBKPIVTool { <# .SYNOPSIS Builds a yubico-piv-tool.exe argument list from config and BoundParameters, runs it, and returns its raw output. .DESCRIPTION The generic core shared by every public PivTool cmdlet. Looks up CmdletWrapping.actions.<Action> and, for every option name in its requiredOptions plus optionalOptions, checks BoundParameters (that cmdlet's $PSBoundParameters, dynamic parameters included) for a matching value: - Missing required options throw (defense in depth; the calling cmdlet's dynamic Mandatory parameter should already have enforced this). - switch-typed options add only their bare cliFlag, and only when the bound value is true. - secureString-typed options are converted to plain text immediately before being added to the argument list (see ConvertFrom-PWSHYBKPIVSecureString) and never logged. - Every other type adds cliFlag followed by the value's string form. Runs the exe via the call operator with stderr merged into stdout ("2>&1"), mirroring ADCSCertutil's certutil.exe invocation pattern, and reads $LASTEXITCODE for the result. A non-zero exit code throws, including the tool's own output in the exception message. Output parsing into typed objects (where an action's output has predictable structure) is left to the calling public cmdlet, since yubico-piv-tool.exe's output shape varies too widely across actions (PEM blobs, free-text status, nothing at all) to generalize here. .PARAMETER ExePath Full path to yubico-piv-tool.exe. .PARAMETER Action The action name to look up in CmdletWrapping.actions, e.g. 'generate'. .PARAMETER CmdletWrapping The CmdletWrapping section of the parsed configuration (Read-PWSHYBKPIVConfigFile output's .cmdletWrapping property). .PARAMETER BoundParameters The calling cmdlet's $PSBoundParameters. .OUTPUTS PSCustomObject with ExitCode and Output properties. .EXAMPLE Invoke-PWSHYBKPIVTool -ExePath $exePath -Action 'status' -CmdletWrapping $config.cmdletWrapping -BoundParameters $PSBoundParameters Runs "yubico-piv-tool.exe --action status" (plus any bound optional flags) and returns its output. #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory)] [string] $ExePath, [Parameter(Mandatory)] [string] $Action, [Parameter(Mandatory)] [PSCustomObject] $CmdletWrapping, [Parameter(Mandatory)] [hashtable] $BoundParameters ) $actionConfig = $CmdletWrapping.actions.$Action if (-not $actionConfig) { throw "Unknown yubico-piv-tool action '$Action'." } $requiredNames = @($actionConfig.requiredOptions) $optionNames = $requiredNames + @($actionConfig.optionalOptions) foreach ($requiredName in $requiredNames) { $requiredParamName = ConvertTo-PWSHYBKPIVParameterName -Name $requiredName if (-not $BoundParameters.ContainsKey($requiredParamName)) { throw "Action '$Action' requires the -$requiredParamName parameter." } } $argumentList = [System.Collections.Generic.List[string]]::new() $argumentList.Add('--action') $argumentList.Add($actionConfig.cliAction) foreach ($optionName in $optionNames) { $optionDef = $CmdletWrapping.options.$optionName if (-not $optionDef) { continue } $parameterName = ConvertTo-PWSHYBKPIVParameterName -Name $optionName if (-not $BoundParameters.ContainsKey($parameterName)) { continue } $value = $BoundParameters[$parameterName] switch ($optionDef.type) { 'switch' { if ($value) { $argumentList.Add($optionDef.cliFlag) } } 'secureString' { $plainText = ConvertFrom-PWSHYBKPIVSecureString -SecureString $value $argumentList.Add($optionDef.cliFlag) $argumentList.Add($plainText) } default { $argumentList.Add($optionDef.cliFlag) $argumentList.Add([string]$value) } } } $output = & $ExePath @argumentList 2>&1 $exitCode = $LASTEXITCODE if ($exitCode -ne 0) { throw "yubico-piv-tool.exe action '$Action' failed with exit code $exitCode. Output: $($output -join ' ')" } [PSCustomObject]@{ ExitCode = $exitCode Output = $output } } |