Search code examples
c#azureazure-web-app-servicex509certificatex509certificate2

Azure, App-service, create X509Certificate2 object from string


Having an App-service in Azure, and working on the AzureServiceManagementAPI, I was downloading the file that contains the managememnt certificate for each subscription.

Any how using the certificate string from the file I'm trying to create a X509Certificate2 object.

string cerStr = subscription.Attribute("ManagementCertificate").Value;
X509Certificate2 x509 = new X509Certificate2(Convert.FromBase64String(cerStr), string.Empty, X509KeyStorageFlags.MachineKeySet)

The constructor of X509Certificate2 throw an exception

Access denied.

System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx) at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)


Solution

  • Since no one has answered this questions, I will try and have go at it. Please correct me if I am wrong, but the problem I think is the following line of code:

    new X509Certificate2(Convert.FromBase64String(cerStr), string.Empty, X509KeyStorageFlags.MachineKeySet) 
    

    This line of code will try to add a new certificate to the certificate store of the virtual machine. All certificates used by the runtime, needs to be hosted in a store somewhere. This is not a good idea because the certificate store of the virtual machine hosting the app service is nothing that you should be storing anything in, it's part of the infrastructure which is not of your concern when you are working with app services.

    What you need to do is to upload the certificate through the azure portal instead (if they are not already there). I ended up reusing a SSL certificate already in place for this purpose. When this is done, you can retreive that certificate in code. You will need to add a new App Setting under "Application Settings" key in the Azure portal for your app service, named WEBSITE_LOAD_CERTIFICATES. The value should be the thumbprint of the certificate.

    To retrieve the cert, you should do something like this:

    public async Task<X509Certificate2> GetCertificate(string certificateThumbprint)
    {
        var store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        var cert = store.Certificates.OfType<X509Certificate2>()
            .FirstOrDefault(x => x.Thumbprint == certificateThumbprint);
        store.Close();
        return cert;
    }
    

    You might be able to get thumbprint of the cert by navigating your subscription using the azure resource explorer https://resources.azure.com/