"Received an unexpected EOF or 0 bytes from the transport stream" Azure WebService

Viewed 534

I have the following issue: I have built a webservice that is supposed to run as an Azure Webservice, which calls an external API retrieve some data. For the connection, the external company has provided me with a certificate which I succesfully stored in the Azure Keyvault. After some trial and error I managed to verify that the certificate is succesfully being retrieved from the vault as I locally tested the code block below. This resulted in a success response with the data I wanted to retrieve. So far so good - until I publish this to Azure. Everything seems to work fine, however I get the following error message:

Received an unexpected EOF or 0 bytes from the transport stream

I have exhausted the first 5 pages of google. I keep finding answers regarding TLS, but I explicitly set it to the correct version as I tested the options (even in this code snippet, i am actually good only using TLS 1.2).

What causes this? Is it some mysterious Azure config setting that I am missing? As I said, the code works 100% on my computer. The issue seems not to be the key or the vault. The biggest difference is that locally I run the code as the tenant admin, however I provided the app service with a managed identity with the correct permissions to the keyvault.

I will also provide the stacktrace. var result = await client.GetAsync(url);

The error is thrown at

var result = await client.GetAsync(url);

I hope I have provided enough information. Thank you in advance

Code snippet:

 public async Task<string>GetData(string url) {
  try {
    var client = await GetHttpClient();
    var result = await client.GetAsync(url);
    if (result.IsSuccessStatusCode) {
      var content = await result.Content.ReadAsStringAsync();
      return content;
    } else {
      Exception ex = new Exception("Failed getting data: " + result.Content.ReadAsStringAsync().Result);
      throw ex;
    }
  } catch (Exception ex) {
    _telemetry.TrackException(ex);
    throw;
  }
}
public async Task<HttpClient> GetHttpClient() {
  var cert = await GetCertFromVault();
  var handler = new HttpClientHandler() {
    ClientCertificateOptions = ClientCertificateOption.Manual,
    SslProtocols = SslProtocols.Tls 
    | SslProtocols.Tls11 
    | SslProtocols.Tls12,
  };
  handler.ClientCertificates.Add(cert);
  handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true;
  var client = new HttpClient(handler);
  return client;
}

async Task<X509Certificate2> GetCertFromVault() {
  try {
    string keyVaultUrl = _configuration["KeyVault"];
    string certKeyName = _configuration["CertKeyName"];
    
    var cred = new DefaultAzureCredential();

    //Get certificate as secret as to include the key:
    var keyVaultClient = new SecretClient(new Uri(keyVaultUrl), cred);
    var certResponse = await keyVaultClient.GetSecretAsync(certKeyName);
    byte[] cert = System.Convert.FromBase64String(certResponse.Value.Value);

    //Convert retrieved values to X509Certificate2
    var resultKey = new X509Certificate2(cert, "", X509KeyStorageFlags.MachineKeySet
                         | X509KeyStorageFlags.PersistKeySet
                         | X509KeyStorageFlags.Exportable);
    return resultKey;

  } catch (Exception ex) {
    _telemetry.TrackException(ex);
    throw;
  }
}

Stacktrace:

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.
   at System.Net.Security.SslStream.<FillHandshakeBufferAsync>g__InternalFillHandshakeBufferAsync|182_0[TIOAdapter](TIOAdapter adap, ValueTask`1 task, Int32 minSize)
   at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Boolean async, Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
   at MyService.MyClient.GetData(String url) in [path]\MyClient.cs:line 40

Line 40 corresponds with

var result = await client.GetAsync(url);
0 Answers
Related