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?
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.
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