-
Notifications
You must be signed in to change notification settings - Fork 652
Best X509Certificate2 Practices
When using X509Certificate2 in App Services, there are some best practices to avoid issues with Private Key file (eg. dreaded Keyset not found) or leaking user profiles disk spaces (eg. not enough space on the disk). For starter, this Seven tips for working with X.509 certificates in .NET provides a good read on how it works on .NET.
By default, X509Certificate2's private key is stored in User Profile file. An App Service will need to have AppSettings WEBSITE_LOAD_USER_PROFILE = 1. The equivalent settings which will enable User Profile indirectly is WEBSITE_LOAD_CERTIFICATES = * or . The app can access the certificate from X509Store and need not worry about the private key file management.
However, if the app were to explicitly instantiate the X509Certificate2 from a blob (downloaded from Azure Key Vault for instance) or a PFX file deployed with an app, one needs to pay attention to private key file nature. The recommendation is to avoid storing private key file in the first place by using X509KeyStorageFlags.EphemeralKeySet (see https://github.com/suwatch/InMemoryX509Certificate in case this flag is not available in the previous netframework).
If X509KeyStorageFlags.UserKeySet (or default) flag is used, one private key container file C:\Users\<Site>\AppData\Roaming\Microsoft\Crypto\RSA\<SID>\<KeyContainer> will be created/associated with X509Certificate2 instance. The file is deleted when X509Certificate2 disposal or GC-ed. Hence, the recommendation is to always timely dispose when no longer use the certificate. Often times, application keeps creating this object without proper dispose leading C:\Users\<Site> profile out of disk space.
Given one file is associated with X509Certificate2 instance, one instance per certificate should be be created and reused (it is thread-safe) to avoid filling up the User Profile disk space above.
This is common when loading the cert from KeyVault. See Tip # 5 on this link.