nickbabcock / OhmGraphite

Expose hardware sensor data to Graphite / InfluxDB / Prometheus / Postgres / Timescaledb
Other
426 stars 38 forks source link

SSL connection to Influx DB fails on self-signed cert #376

Closed TechnoSwiss closed 1 year ago

TechnoSwiss commented 1 year ago

Connecting to my influx DB server with the following config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="type" value="influx" />
    <add key="interval" value="5" />
    <add key="influx_address" value="https://server.localnetwork:8086" />
    <add key="influx_db" value="systems" />

    <add key="name_lookup" value="system=name" />

    <add key="influx_user" value="influx_user" />
    <add key="influx_password" value="influx_password" />
    <add key="certificate_verification" value="false" />
    <!--
    <add key="certificate_verification" value="C:\Apps\OhmGraphite\influxdb-selfsigned.crt" />
    -->
  </appSettings>
</configuration>

I've been running OhmGraphite stand alone, and keep getting an SSL error message (with either the systems cert, or setting the value to false).

2023-06-09 18:21:52.3915|ERROR|OhmGraphite.MetricTimer|Unable to send metrics!System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
 ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure: RemoteCertificateNameMismatch, RemoteCertificateChainErrors
   at System.Net.Security.SslStream.SendAuthResetSignal(ProtocolToken message, ExceptionDispatchInfo exception)
   at System.Net.Security.SslStream.CompleteHandshake(SslAuthenticationOptions sslAuthenticationOptions)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsync(SslClientAuthenticationOptions sslOptions, HttpRequestMessage request, Boolean async, Stream stream, 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.AddHttp11ConnectionAsync(HttpRequestMessage request)
   at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
   at InfluxDB.LineProtocol.Client.LineProtocolClient.OnSendAsync(String payload, Precision precision, CancellationToken cancellationToken)
   at OhmGraphite.InfluxWriter.ReportMetrics(DateTime reportTime, IEnumerable`1 sensors)
   at OhmGraphite.MetricTimer.ReportMetrics(Object sender, ElapsedEventArgs e)
nickbabcock commented 1 year ago

Hmm, that's odd. Your configuration looks good, but the stacktrace is complaining about a cert name mismatch. I didn't spot any glaring issues when I took a quick glance at the code, so I'll try and reproduce this.

TechnoSwiss commented 1 year ago

I have the source code up on another machines, same error not unexpected since I'm still trying to communicate with the same influx server. I was able to follow along and very that ServicePointManager.ServerCertificateValidationCallback is getting set correctly based on either of the certificate_verification options I've tried, but from the stacktrace it feels like it's ignoring that. I do mostly embedded C++, but am familiar with C# however trying to track down how to look at the cert. that's coming back in the debugger I'm feeling a little out of my depth.

nickbabcock commented 1 year ago

I have good news and bad news. The bad news is that the reason the verification is failing is that the global cert check does not work with the .net version OhmGraphite uses: https://github.com/dotnet/runtime/issues/26048#issuecomment-386030456

And unfortunately, due to the abandonment of the C# influxdb v1 client, there is no hope in getting this officially supported.

The good news is that there is a workaround if the cert is installed machine-wide. Here is how I reproduced:

On influxdb machine (referenced via, vm-ubuntu), generate the cert:

mkdir ssl
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
  -keyout ssl/ohm.key -out ssl/ohm.crt -subj "/CN=vm-ubuntu" \
  -addext "subjectAltName=DNS:vm-ubuntu,IP:172.22.24.52"

Start influxdb v1 with:

version: "3"
services:
  influxdb:
    image: influxdb:1.8
    ports:
      - "8086:8086"
    volumes:
      - influxdb:/var/lib/influxdb
      - ./ssl:/etc/ssl/
    environment:
      - INFLUXDB_DB=db0
      - INFLUXDB_ADMIN_USER=admin
      - INFLUXDB_ADMIN_PASSWORD=supersecretpassword
      - INFLUXDB_HTTP_HTTPS_ENABLED=true
      - INFLUXDB_HTTP_HTTPS_CERTIFICATE=/etc/ssl/ohm.crt
      - INFLUXDB_HTTP_HTTPS_PRIVATE_KEY=/etc/ssl/ohm.key
      - INFLUXDB_HTTP_AUTH_ENABLED=true

volumes:
  influxdb:

Copy ohm.crt onto OhmGraphite machines, then import the cert with powershell

Import-Certificate -FilePath .\ohm.crt -CertStoreLocation 'Cert:\LocalMachine\Root'

Now the cert will be trusted without needing to specify certificate_verification

Can you try this out for me @TechnoSwiss . If it works, I'll deprecate certificate_verification and replace it with these instructions.

TechnoSwiss commented 1 year ago

That does the trick, I'd tried pointing OhmGraphite at the cert, but I hadn't tried importing it into the system. Thank you.

nickbabcock commented 1 year ago

Sounds good, thanks for testing. I've added these to the docs.