Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Private keys get deleted unexpectedly in Windows Server 2008 R2

I am facing a strange problem in developing an installation that should in one of the steps install a certificate.

The problem has to do with granting Certificate’s private key access for an account (e.g. IIS_IUSRS) on Windows Server 2008 R2. The private keys are stored in the location C:\Users\All Users\Microsoft\Crypto\RSA\MachineKeys.

A custom C# Setup Project imports a Certificate and gives access for an account on Certificate’s private key during the installation process. After some time (2-3 sec) the private key file is automatically deleted from the MachineKeys folder. Thus the installed Web Application cannot access the specific certificate and displays the following error message:

“System.Security.Cryptography.CryptographicException: Keyset does not exist”. This error occurs only on Windows Server 2008 R2, while for Windows Server 2003 everything is working correctly.

My question is, why the private key gets deleted and which process does this?

Thx

UPDATE 17/05/2012

I have not yet found a solution to the described problem, and no response has been posted on the other forums where I asked (forums.asp.net, social.msdn.microsoft.com). So, can anyone suggest any other resources or advice for further troubleshooting this issue?

Thanks again

like image 328
dimdamop Avatar asked Feb 21 '23 14:02

dimdamop


2 Answers

This was happening to me too - my setup script would add the cert and grant access to the PK file fine, and the app would work. Then later, after I had closed the PowerShell editor I re-launched the app and it failed with a keyset not found.

Adding the PersistKeySet flag when importing the cert fixed the problem. Here's the PowerShell code for adding the cert and private key with persistence:

param(
    [string]$certStore = "LocalMachine\TrustedPeople",
    [string]$filename = "sp.pfx",
    [string]$password = "password",
    [string]$username = "$Env:COMPUTERNAME\WebSiteUser"
)

    function getKeyUniqueName($cert) {
         return $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
    }
    
    function getKeyFilePath($cert) {             
         return "$ENV:ProgramData\Microsoft\Crypto\RSA\MachineKeys\$(getKeyUniqueName($cert))"
    }

$certFromFile = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($filename, $password)
$certFromStore = Get-ChildItem "Cert:\$certStore" | Where-Object {$_.Thumbprint -eq $certFromFile.Thumbprint}
$certExistsInStore = $certFromStore.Count -gt 0
$keyExists = $certExistsInStore -and ($certFromStore.PrivateKey -ne $null) -and (getKeyUniqueName($cert) -ne $null) -and (Test-Path(getKeyFilePath($certFromStore)))

if ((!$certExistsInStore) -or (!$keyExists)) {

    $keyFlags = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet 
    $keyFlags = $keyFlags -bor [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet
    $certFromFile.Import($filename, $password, $keyFlags)

    $store = Get-Item "Cert:\$certStore"
    $store.Open("ReadWrite")

    if ($certExistsInStore) {
        #Cert is in the store, but we have no persisted private key
        #Remove it so we can add the one we just imported with the key file
        $store.Remove($certFromStore)
    }

    $store.Add($certFromFile)
    $store.Close()

    $certFromStore = $certFromFile
    "Installed x509 certificate"
}

$pkFile = Get-Item(getKeyFilePath($certFromStore))
$pkAcl = $pkFile.GetAccessControl("Access")
$readPermission = $username,"Read","Allow"
$readAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $readPermission
$pkAcl.AddAccessRule($readAccessRule)
Set-Acl $pkFile.FullName $pkAcl
"Granted read permission on private key to web user"
like image 67
ejegg Avatar answered Feb 23 '23 05:02

ejegg


Is very clear that is a security issue “System.Security.”. and you do not have permissions to do the installation., you need to set the permissions on the private key to allow that service account access it.

Edit later: Go to Start->Run->cmd->type mmc->Select File->Add/Remove->Select Certificates->Add->Computer Account->Local., i attach a screenshot is in spanish but I indicated the fields:

enter image description here

Open->Certificates->Personal->Certificates->Right click Certificate-> All Tasks->Manage Private Keys->Add Network Service.

Also check this entry to see how works this feature in Windows Server 2008., then please after you try it, come back and say if you could solve the issue with what I have told you.

like image 35
Voislav Sauca Avatar answered Feb 23 '23 05:02

Voislav Sauca