X509Certificate2 failing in Azure Webjobs calling

2019-04-28 08:43发布

问题:

I have a console app that is scheduled using Azure WebJobs. The execution always fails when attempting to read the private key of p12 certificate. Interestingly enough I can't catch the exception, I've had to use good old Console.WriteLine to debug.

Here is my snippet of code:

var certificate = new X509Certificate2(data, "notasecret", X509KeyStorageFlags.Exportable);

ServiceAccountCredential credential = new ServiceAccountCredential(
 new ServiceAccountCredential.Initializer(serviceAccountEmail)
 {
     Scopes = new[] { BigqueryService.Scope.Bigquery }
 }.FromCertificate(certificate));

Other posts have mention that the flags should be X509KeyStorageFlags.MachineKeySet but unfortunately that causes an error in the Google API. It requires the X509KeyStorageFlags.Exportable flag to be set.

Can anyone confirm that X509KeyStorageFlags.Exportable is usable on Azure Websites and WebJobs?

回答1:

Using X509KeyStorageFlags.Exportable is not usable in IIS. I've tried it with Azure Webjobs, Azure Websites and IIS on my own virtual machine. It works in a development environment when using IISExpress because the process is running in the user's context.

So for it work in an IIS context (including Webjobs), it has to be set to MachineKeySet but the Google API will fail since it needs the private key.

The solution to my problem was actually pretty simple, create a console app that creates the X509Certificate2 object with Exportable flag set and then call ToXmlString(). Here is the snippet:

var certificate = new X509Certificate2(data, "notasecret", X509KeyStorageFlags.Exportable); var xml = certificate.PrivateKey.ToXmlString(true);

I then save the XML and use that XML to create an RSACryptoServiceProvider like this:

var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(xmlKey);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
 {
  Scopes = new[] { BigqueryService.Scope.Bigquery },
  Key = rsa
 });

Hope this helps others.



回答2:

This solution worked in an Azure setting. However I also found one for my needs that was much simpler. Simply add additional Flags so everyone is happy...

 var certificate = new X509Certificate2(data,"notasecret",
                       X509KeyStorageFlags.MachineKeySet | 
                       X509KeyStorageFlags.PersistKeySet | 
                       X509KeyStorageFlags.Exportable);

I found this solution