2

Context:

I have an n-tier dynamic-ish application that currently builds its elastic indexes at app startup.

While this was ok to get things going, I'd prefer to have a small CLI application/util that I can later re-use in some scripts and or run ad-hoc if I need to do things like, creating a new instance, seeding mock data etc.

Problem:

When I use the exact same code that worked in my dotnetcore web app's startup, in my console app, I get the following issue:

Invalid NEST response built from a unsuccessful low level call on PUT: /jobs-ng
# Audit trail of this API call:
 - [1] BadRequest: Node: https://localhost:9200/ Took: 00:00:01.3948230
# OriginalException: System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Net.Http.CurlException: SSL connect error
   at System.Net.Http.CurlHandler.ThrowIfCURLEError(CURLcode error)
   at System.Net.Http.CurlHandler.MultiAgent.FinishRequest(StrongToWeakReference`1 easyWrapper, CURLcode messageResult)
   --- End of inner exception stack trace ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at System.Net.Http.HttpClient.<FinishSendAsyncBuffered>d__58.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Elasticsearch.Net.HttpConnection.Request[TReturn](RequestData requestData) in C:\Users\russ\source\elasticsearch-net-5.x\src\Elasticsearch.Net\Connection\HttpConnection-CoreFx.cs:line 78
# Request:
<Request stream not captured or already read to completion by serializer. Set DisableDirectStreaming() on ConnectionSettings to force it to be set on the response.>
# Response:
<Response stream not captured or already read to completion by serializer. Set DisableDirectStreaming() on ConnectionSettings to force it to be set on the response.>

Additional Info:

Currently my ElasticClient class only gets set like this:

 var uri = new Uri("https://localhost:9200");
 services.AddSingleton(new ElasticClient(new ConnectionSettings(uri)));

... thus I don't explicitly set a cert anywhere. (Hasn't been required thus far)

My best guess is that the native console app is missing something that the default web app projects provide, but as to what, I don't know?

I have set DisableDirectStreaming() as per the error log, but still no change.

I believe this might be a bug within .Net Core, but I'm hoping someone knows of a work around, or way around this issue for the time being (other that having this code be part of the we apps startup? (which is what my current working solution is))

Rohan Büchner
  • 5,333
  • 4
  • 62
  • 106
  • 2
    The problem is that the cert is coming back as invalid for your console app. If it worked for your web app, the self-signed certificate must have been installed on that server, so that the cert appears valid there. The obvious solution is to do the same where this console app is running. Short of that, you have to pass in a different `IConnection` that disables server certificate validation. See: https://stackoverflow.com/a/46626858/654031 – Chris Pratt Oct 30 '17 at 14:47
  • 1
    @ChrisPratt Thank you for the info, will check it out. Erm, as a quick fyi, currently both are running on my local machine (thus I'm assuming that same cert should have been set for both?). – Rohan Büchner Oct 30 '17 at 14:49
  • That is a little odd. The issue boils down to the built-in cert validation behavior of `HttpClient`, so it's not application type or even Elasticsearch-specific. As long as you can connect from that machine without without getting a cert error for that URL, you're golden. – Chris Pratt Oct 30 '17 at 15:03
  • if you do need to do anything with certificate validation, take a look at the methods on `ConnectionSettings` that expose validation configuration: https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/working-with-certificates.html – Russ Cam Oct 30 '17 at 23:04
  • @RussCam, thank you... I tried adding the AllowAll cert validation, but turns out the issue I have is todo with my platform, I'm currently on OSX.. I believe, after reading this thread, theres an issue with the curl implementation on OSX. https://github.com/dotnet/corefx/issues/9728 – Rohan Büchner Oct 31 '17 at 07:26
  • Yes there is. Using the version of libcurl built against OpenSSL should fix the issue – Russ Cam Oct 31 '17 at 07:30
  • @RussCam (a bit of a reach, but you would perhaps now how to do that) I have updated my curl via brew, but still no beuno... – Rohan Büchner Oct 31 '17 at 09:14
  • @RohanBüchner I tested and got this working quite a while ago, following jchannon's approach on https://github.com/dotnet/corefx/issues/9728#issuecomment-239413686. Sadly, I think we are at the mercy of the implementation for the moment :( – Russ Cam Oct 31 '17 at 23:21

1 Answers1

2

There is currently a documented issue, within the dotnet-core project's CURL implementation/usage thereof/within CURL on OSX... you get the idea. It seems to have been fixed for 1.1, but as I'm on 2.0 (and I've attempted all of the suggested fixes on the various github threads, to no success), I'm unable to verify if that fix works.

Thus the answer:

There is a bug thats preventing this from working on OSX currently.

Workaround:

Since my console app / cli-tool will run ad hoc internal to our applications network / same machine instance, I don't, in theory need HTTPS for this utility, HTTP should be sufficient. (Once I made that change, the code worked fine across the board)

Rohan Büchner
  • 5,333
  • 4
  • 62
  • 106