Public/Grant-NSPLocalAccountCertificateAccess.ps1
|
function Grant-NSPLocalAccountCertificateAccess { <# .SYNOPSIS Plans read access to one existing LocalMachine software RSA private-key file. .DESCRIPTION No key export, copy or certificate creation. CurrentUser, hardware/unknown providers and certificates without a supported machine RSA key are rejected. Software keys from the CNG Software Key Storage Provider and from the Microsoft software CryptoAPI providers (as New-SelfSignedCertificate -KeySpec creates) are supported in both editions. Access applies only to the selected local account and preserves existing ACLs. #> [CmdletBinding(SupportsShouldProcess)] param([Parameter(Mandatory)][string]$Name,[Parameter(Mandatory)][ValidatePattern('^[A-Fa-f0-9]{40}$')][string]$Thumbprint,[switch]$Execute) $certificate=Get-Item -LiteralPath ('Cert:\LocalMachine\My\'+$Thumbprint) -ErrorAction Stop if(-not $certificate.HasPrivateKey) { throw 'Certificate has no private key.' } $rsa=[Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate) try { $key=if($rsa -is [Security.Cryptography.RSACng]) { @{Provider=[string]$rsa.Key.Provider.Provider;IsMachineKey=[bool]$rsa.Key.IsMachineKey;UniqueName=[string]$rsa.Key.UniqueName;HardwareDevice=$false} } elseif($rsa -is [Security.Cryptography.RSACryptoServiceProvider]) { $info=$rsa.CspKeyContainerInfo @{Provider=[string]$info.ProviderName;IsMachineKey=[bool]$info.MachineKeyStore;UniqueName=[string]$info.UniqueKeyContainerName;HardwareDevice=[bool]$info.HardwareDevice} } else { throw 'Only LocalMachine software RSA keys are supported; provision the certificate for the task account separately.' } $keyPath=Resolve-NSPLocalAccountMachineKeyPath @key } finally { if($rsa) { $rsa.Dispose() } } if(-not $PSCmdlet.ShouldProcess($Thumbprint,"Plan/apply private-key read access for local account $Name")) { return } Grant-NSPLocalAccountPathAccess -Name $Name -LiteralPath $keyPath -Rights Read -Execute:$Execute -Confirm:$false } |