Public/Install-Certificate.ps1
using namespace System.Security.AccessControl using namespace System.Security.Cryptography using namespace System.Security.Cryptography.X509Certificates function Install-Certificate { [OutputType([X509Certificate])] param( [Parameter(Mandatory)] [string] $FilePath, [Parameter(Mandatory)] [StoreLocation] $StoreLocation, [SecureString] $Password, [string] $User = "$env:USERDOMAIN\$env:USERNAME" ) begin { if (!$IsWindows) { Write-Error $OperatingSystemNotSupportedError -Category NotImplemented -ErrorAction Stop } } process { $Certificate = Import-PfxCertificate -FilePath $FilePath -CertStoreLocation $StoreLocation -Password $Password # Beware that the PrivateKey (PK) property returns a different type between .NET Framework and .NET Core. $UniqueName = if ($PSVersionTable.PSVersion.Major -eq 5) { # PK returns a RSACryptoServiceProvider instance provided by the Cryptographic Service Provider (CSP). # This cryptography subsystem was superseded by CNG with the advent of .NET Core. $Certificate.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName } else { # PK returns a RSACng instance provided by the Cryptography Next Generation (CNG), which is not # available for operating systems other than Windows. On Linux and MacOS, the PK would be of type # RSAOpenSsl. The PrivateKey property was obsoleted for these reasons, and it is now recommended # to use the GetRSAPrivateKey extension method which returns an implementation-agnostic abstract # base class. [RSACertificateExtensions]::GetRSAPrivateKey($Certificate).Key.UniqueName } # Grant persistent read permissions to the domain user, so that the certificate # does not need to be re-installed after a reboot. $AclPath = "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\$UniqueName" $Acl = Get-Acl -Path $AclPath $Rule = [FileSystemAccessRule]::new($User, [FileSystemRights]::Read, [AccessControlType]::Allow) $Acl.AddAccessRule($Rule) Set-Acl -Path $AclPath -AclObject $Acl } clean { Write-Output $Certificate } } |