1
votes

I'm trying to install a self signed certificate in my Azure website and then use it to access Azure Key Vault.
When I run the code locally and read the certificate from StoreLocation.CurrentUser & StoreName.My it all works as expected.
Tried running the same code in my deployed site in Azure but it fails.
When i change the read to use StoreLocation.LocalMachine the certificate is loaded without the private key, which later causes an exception :
"System.NotSupportedException: The private key is not present in the X.509 certificate".
Do I need to load the certificate differently? or maybe I didn't install it properly in Azure in the first place?
These are the installation steps i took:
1. go to https://ms.portal.azure.com
2. select my resource (my site's App Service)
3. click "SSL Certificates"
4. click "Upload Certificate"
5. click browse, select my pfx file and provide the password
6. click "Upload"

This is the code I'm using to read and use the certificate:

    // C-tor
    public SecretRetriever(string thumbprint, string clientId)
    {
        var clientAssertionCertPfx = FindCertificateByThumbprint(thumbprint);
        this.AssertionCert = new ClientAssertionCertificate(clientId, clientAssertionCertPfx);
    }

    /// <summary>
    /// Get the certificate associated with the given secretId
    /// </summary>
    /// <param name="secretId"></param>
    /// <returns></returns>
    public async Task<string> GetSecretAsync(string secretId)
    {
        var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetAccessTokenAsync));
        return (await kv.GetSecretAsync(secretId)).Value;
    }

    private async Task<string> GetAccessTokenAsync(string authority, string resource, string scope)
    {
        var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
        var result = await context.AcquireTokenAsync(resource, AssertionCert);
        return result.AccessToken;
    }

    //when changing to "CurrentUser" the private key is in the certificate. why it is not there when reading from LocalMachine?
    private static X509Certificate2 FindCertificateByThumbprint(string findValue)
    {
        X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        try
        {
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindByThumbprint, findValue, false);
            if (col.Count == 0)
            {
                return null;
            }
            return col[0];
        }
        finally
        {
            store.Close();
        }
    }
1
The problem is that your web application runs under unpriveleged account on Azure and have full control only over CurrentUser store and you have only read-only permissions on LocalMachine store. In addition, you have no access to keys stored in the LocalMachine store. This means that you have to install your personal certificate to CurrentUser store. SSL goes to LocalMachine.Crypt32
After granting access through the application settings it works. Thanks!Eyal Machloof

1 Answers

1
votes

To solve this issue I had to give my site permission to access the certificate.
This was achieved by going to the app in Azure portal --> Settings--> Application Settings
I Added the following app setting:
Key: WEBSITE_LOAD_CERTIFICATES, Value: My_Certificate_Thumbprint
(thanks for pointing me in the right direction, Crypt32)