Public/Set-PWSHYBKPIVPuk.ps1

function Set-PWSHYBKPIVPuk {
    <#
    .SYNOPSIS
        Changes the PUK of a locally attached YubiKey's PIV application.
    .DESCRIPTION
        Wraps "yubico-piv-tool.exe --action change-puk". Requires the current PUK and the new
        PUK; a wrong current PUK still consumes one of the YubiKey's limited PUK retries, so this
        cmdlet supports -WhatIf/-Confirm (ConfirmImpact 'Medium'). Throws on failure rather than
        returning a boolean, matching Set- verb convention.

        Accepts the "change-puk" action's config-declared options (-Puk, -NewPuk, -Reader) as
        dynamic parameters built from Config\Posh-YBKPIV.json. -Puk and -NewPuk are distinct
        catalog entries from -Pin/-NewPin used by Set-PWSHYBKPIVPin, even though yubico-piv-tool
        maps both pairs to the same --pin/--new-pin CLI flags - keeping them distinct avoids
        exposing a misleading "-Pin" parameter on a cmdlet that actually changes the PUK.
    .PARAMETER Puk
        The current PUK, as a SecureString.
    .PARAMETER NewPuk
        The new PUK to set, as a SecureString.
    .PARAMETER Reader
        Name of the smart card reader to target, when more than one is attached. If omitted,
        yubico-piv-tool.exe uses its own default reader selection.
    .INPUTS
        None. This cmdlet does not accept pipeline input.
    .OUTPUTS
        None. Throws a terminating error on failure; produces no output on success.
    .NOTES
        -Reader is declared dynamically from Config\Posh-YBKPIV.json and therefore does not
        appear in Get-Help's PARAMETERS/SYNTAX sections. Run
        `Get-Command Set-PWSHYBKPIVPuk -Syntax` for the authoritative, current parameter list.
    .EXAMPLE
        Set-PWSHYBKPIVPuk -Puk $currentPuk -NewPuk $newPuk
        Changes the PUK after confirmation.
    .LINK
        https://developers.yubico.com/yubico-piv-tool/Actions/
    .LINK
        Unblock-PWSHYBKPIVPin
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')]
    param()

    DynamicParam {
        $dynamicConfig = Read-PWSHYBKPIVConfigFile
        Get-PWSHYBKPIVActionParameter -Action 'change-puk' -CmdletWrapping $dynamicConfig.cmdletWrapping
    }

    begin {
        $config = Read-PWSHYBKPIVConfigFile
        Write-PWSHYBKPIVLog -Config $config -Level Debug -CmdletName $MyInvocation.MyCommand.Name `
            -Message 'Cmdlet invoked' -BoundParameters $PSBoundParameters

        $architecture = Resolve-PWSHYBKPIVArchitecture -Architecture $config.installation.architecture
        $exePath = Get-PWSHYBKPIVInstallPath -Installation $config.installation -Architecture $architecture
        if (-not (Test-Path -Path $exePath -PathType Leaf)) {
            throw "yubico-piv-tool.exe was not found at '$exePath'. Run Install-PWSHYBKPIVTool first."
        }
    }

    end {
        if (-not $PSCmdlet.ShouldProcess('YubiKey PIV application', 'Change PUK')) {
            return
        }

        try {
            $null = Invoke-PWSHYBKPIVTool -ExePath $exePath -Action 'change-puk' `
                -CmdletWrapping $config.cmdletWrapping -BoundParameters $PSBoundParameters
            Write-PWSHYBKPIVLog -Config $config -Level Information -CmdletName $MyInvocation.MyCommand.Name `
                -Message 'PUK changed successfully'
        } catch {
            Write-PWSHYBKPIVLog -Config $config -Level Error -CmdletName $MyInvocation.MyCommand.Name -Message "PUK change failed: $_"
            throw
        }
    }
}