-1

EDIT: This code does work. I had the wrong value in the Entity List Environment Variable

I've been trying to add certificates to the HTTP client factory using dependency injection. I will need to use many different certificates to connect to the 3rd party depending on the API I need to connect to and my certificates are stored in my Azure Key Vault.

        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddHttpClient();
            builder.Services.AddSingleton<HTTPClientService>();

            string entityList = Environment.GetEnvironmentVariable("EntityList");

            foreach (var entity in entityList.Split(','))
            {
                builder.Services.AddHttpClient(entity).ConfigurePrimaryHttpMessageHandler(() =>
                {
                    var kvClient = new CertificateClient(new Uri(Environment.GetEnvironmentVariable("KeyVaultUri")), new DefaultAzureCredential());
                    var entityCert = kvClient.DownloadCertificate(entity);
                    HttpClientHandler handler = new HttpClientHandler();
                    handler.ClientCertificateOptions = ClientCertificateOption.Manual;
                    handler.ClientCertificates.Add(entityCert);
                    return handler;

                });
            }
        }

I've tried many examples I have found on here and the pattern I've used works locally but by loading the certificates from file as my work's policy does not allow us to access the key vault locally.

When I run this code in Azure after injecting the HTTP Client Factory into the function:-

HttpClient client = _httpClientFactory.CreateClient(entityName);

string uri = string.Format(Settings.Uri, entityName);
var content = new ByteArrayContent(Encoding.UTF8.GetBytes(jsonContent));
var res = httpClient.PostAsync(uri, content);

I get the following error on PostAsync

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream.

Which suggests that the named HTTP Client has been created, but the certificate has not been added to the client.

Are the KeyVault or Environment Variables not available when the injection runs or is there a different way I should be doing this?

If I create the HTTPClient within the function body (i.e. without using dependency injection) and download the certificates, I am able to connect and post data.

2
  • Please share your function code Commented Oct 25, 2023 at 9:07
  • @IkhtesamAfrin - I have added the code I use to make the HTTP Call. Commented Oct 26, 2023 at 12:59

1 Answer 1

0

Turns out it is human error due to unfamiliarity with the HTTPClientFactory. The EntityList I had was not correct and I wrongly assumed that if you call the CreateClient(string name) method, it would throw an exception if you ask for one that has not previously been defined.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.