5

I'm getting this cert issue while deploying IdentityServer 4 (ASP.NET Core 1.1) to Azure VM (Windows Server 2012 R2).

crit: IdentityServer4.Hosting.IdentityServerMiddleware[0]
      Unhandled exception: Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: The system cannot find the file specified
         at System.Security.Cryptography.CngKey.Open(String keyName, CngProvider provider, CngKeyOpenOptions openOptions)
         at System.Security.Cryptography.CngKey.Open(String keyName, CngProvider provider)
         at Internal.Cryptography.Pal.CertificatePal.GetPrivateKey[T](Func`2 createCsp, Func`2 createCng)
         at Internal.Cryptography.Pal.CertificatePal.GetRSAPrivateKey()

This will work on local dev computer and I cannot figure it out why. I install the cert on My (Local Machine) store on the VM.

Can anyone help on this. Thanks.

Riza Marhaban
  • 368
  • 6
  • 20

2 Answers2

14

I found the solution here:

http://www.daves-blog.net/post/2014/06/16/X509Certificate-The-System-cannot-find-the-file-specified.aspx

Apparently, I need to enable the Load User Profile on the Application Pool. However, the error now changes to this:

crit: IdentityServer4.Hosting.IdentityServerMiddleware[0]
  Unhandled exception: Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException: Keyset does not exist
     at System.Security.Cryptography.CngKey.Open(String keyName, CngProvider provider, CngKeyOpenOptions openOptions)
     at System.Security.Cryptography.CngKey.Open(String keyName, CngProvider provider)
     at Internal.Cryptography.Pal.CertificatePal.GetPrivateKey[T](Func`2 createCsp, Func`2 createCng)
     at Internal.Cryptography.Pal.CertificatePal.GetRSAPrivateKey()

Looking at the issue now.

Okay, so the issue is permission to read the cert. All we have to do just go to the certificate and grant Read (only) for IIS_IUSRS.

Now it works.

Riza Marhaban
  • 368
  • 6
  • 20
  • What happens if the certificate in question is just an inmemory certificate and not installed anywhere on the machine? I believe that's the recommended approach if you are going to be running IS4 inside a container and deploying certs with the application would be a security risk – Ruskin Aug 18 '17 at 05:42
  • Well, my client infra environment as the requirement needed to be like this, so they can rotate the cert. I personally recommend to use AzureKeyVault instead to store the PFX with HSM key for easy rotation, so there will be no certificate on the app side, even if they move to containers someday. – Riza Marhaban Aug 18 '17 at 06:00
  • So to get this working you simply had the certificate in the same location as the running code to which `IIS_IUSRS` had read access to? – Ruskin Aug 18 '17 at 06:01
  • 1
    So you gave the user read access to the cert store? How did you manage that? – Ruskin Aug 18 '17 at 06:09
  • Okay, it doesn't quite add up...a certificate will be stored in their certificate store, how does the IIS user get read rights to it? Anyways, thanks. – Ruskin Aug 18 '17 at 06:15
  • 3
    @Ruskin just go to cert store. Right click on the cert and choose All Tasks -> Manage Private Keys. I hope that helps. – Riza Marhaban Aug 18 '17 at 06:33
  • link to the blog post is dead – Daniël Tulp Sep 14 '20 at 08:30
5

If anyone is wondering how to give IIS users access to certs

  1. Create / Purchase certificate. Make sure it has a private key.
  2. Import the certificate into the "Local Computer" account. Best to use Certificates MMC. Make sure to check "Allow private key to be exported"
  3. Based upon which, IIS 7.5 Application Pool's identity use one of the following.

    • IIS 7.5 Website is running under ApplicationPoolIdentity. Open MMC => Add Certificates (Local computer) snap-in => Certificates (Local Computer) => Personal => Certificates => Right click the certificate of interest => All tasks => Manage private key => Add IIS AppPool\AppPoolName and grant it Full control. Replace "AppPoolName" with the name of your application pool (sometimes IIS_IUSRS)
    • IIS 7.5 Website is running under NETWORK SERVICE. Using Certificates MMC, added "NETWORK SERVICE" to Full Trust on certificate in "Local Computer\Personal".
    • IIS 7.5 Website is running under "MyIISUser" local computer user account. Using Certificates MMC, added "MyIISUser" (a new local computer user account) to Full Trust on certificate in "Local Computer\Personal".

The above is extracted from here.

Ruskin
  • 1,504
  • 13
  • 25
  • 1
    I agree with the above, with one exception: On bullet one, `Read` permission is sufficient for an Application Pool Identity to access a certificate. – gregsonian Nov 13 '18 at 17:08