Last week, I had to replace the existing ssl-certificate on our crm on premise systems. I installed the ssl-certificates in the IIS certificate store and also installed the corresponding root certificates. I changed the binding in IIS and checked the certificate in the browser, everything was working fine. But after abound 1 hour, the whole crm system was gone offline.
I checked the systems and found an error in the event log with the following message:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
WebHost failed to process a request. Sender Information: System.ServiceModel.ServiceHostingEnvironment+HostingManager/38203409 Exception: System.ServiceModel.ServiceActivationException: The service '/XRMServices/2011/Discovery.svc' cannot be activated due to an exception during compilation. The exception message is: ID1039: The certificate's private key could not be accessed. Ensure the access control list (ACL) on the certificate's private key grants access to the application pool user. Thumbprint: 'xxx'. ---> System.ArgumentException: ID1039: The certificate's private key could not be accessed. Ensure the access control list (ACL) on the certificate's private key grants access to the application pool user. Thumbprint: 'xxx' ---> System.Security.Cryptography.CryptographicException: Keyset does not exist at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() at System.IdentityModel.X509Util.EnsureAndGetPrivateRSAKey(X509Certificate2 certificate) --- End of inner exception stack trace --- at System.IdentityModel.X509Util.EnsureAndGetPrivateRSAKey(X509Certificate2 certificate) at System.IdentityModel.RsaEncryptionCookieTransform..ctor(X509Certificate2 certificate) at Microsoft.Crm.Authentication.Claims.CrmSessionSecurityTokenHandler.get_DefaultTransforms() at Microsoft.Crm.Authentication.Claims.IdentityConfigurationProvider.UpdateTokenHandlers(IdentityConfiguration identityConfiguration) at Microsoft.Crm.Authentication.Claims.IdentityConfigurationProvider.<>c__DisplayClass7.<GetIdentityConfiguration>b__5() at Microsoft.Crm.Authentication.Common.AuthenticationContextExtensions.HandleDatabaseCall[TResult](Func`1 action) at Microsoft.Crm.Authentication.Claims.IdentityConfigurationProvider.<GetIdentityConfiguration>b__4() at Microsoft.Crm.Authentication.Claims.IdentityConfigurationProvider.InitializeConfiguration(Action action) at Microsoft.Crm.Authentication.Claims.IdentityConfigurationProvider.GetIdentityConfiguration() at Microsoft.Crm.Sdk.V5.DiscoveryServiceHost.InitializeRuntime() at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(ServiceActivationInfo serviceActivationInfo, EventTraceActivity eventTraceActivity) at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity) --- End of inner exception stack trace --- at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity) at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath, EventTraceActivity eventTraceActivity) Process Name: w3wp |
Based on the message “The certificate’s private key could not be accessed” I assumed, that this is connected to my certificate replacement. Therefore I switched back to my previous certificate, to solve the interruption and checked the system again.
After some research, I found the root cause: The certificate has to be granted to the user. Therefor I followed these steps:
- Open the Management Console (mmc.exe)
- Add the certificate snap-in based with File > Add/Remove Snap-in …
- Select certificates > Add > computer account > local computer > finished
- Drill down the personal folder and select the certificate on the right. Open the context menu and select All Tasks > Manage Private Keys…
- In the new property window add your users.
- In my case, I had to add the IIS_IUSRS and the user of, which is running the application pool.
Based on my experience, crm creates their own tokens based on the ssl certificate. This token seems to be renewed at least every hour. Therefore, an error might come up not instantly after the certificate replacement, but also after some hours.
Additionally, there are some more services, where you have to change the certificate.
Change SSL on Reporting Service
If you use the reports, don’t forget to change the SSL-Certificate and update the Bindings on the reporting service.
Update Sharepoint Integration
After changing the ssl-certificate on the crm system, don’t forget to also update the trust with your sharepoint server. Therefore open a powershell with administrative rights and run the following command:
1 2 3 4 5 6 7 |
.\CertificateReconfiguration.ps1 -certificateFile C:\Install\cert.pfx -password myPass -updateCrm -certificateType S2STokenIssuer -serviceAccount domain\MyAsyncUser -storeFindType FindBySubjectDistinguishedName |
The cmdlet is located in the toolsfolder of you crm installation. Also use the correct user in paramter serviceAccount, which has to be the user for asynchronous jobs.