Subscriptions using TLS


#1

Hi,
I am having issues getting subcriptions working with 2 OpenHistorians on the network on different boxes.

Firstly, I created all the required certificates as detailed on
https://blog.jayway.com/2014/10/27/configure-iis-to-use-your-self-signed-certificates-with-your-application/

After making these certificates trusted on both machines, I used the SSL certificate when creating the Creating Authorization Request

subscriber5

On the Publishing machine, under Manage Authorized Subscribers, I added this request like this, which created for me a CLOUD.cer file

publisher4

I then copied this CLOUD.cer file back to the subscriber machine and modified the configuration so it points to this certificate.

subscriber2

I set up CLOUD.cer to be trusted on both machines.
publisher2
publisher3

When I try and make a connection, this what I get on the publisher

publisher1

and on the subcriber

subscriber1

Whenever I go back and change something in the Manage Authorized Subscribers and click “Save”, I get this message.

publisher5

Any tips on whats going on here?


#2

I would recommend reading the following explanations and then starting over from the beginning.


First, some clarification about the CLOUD.cer file. When you created the subscription authorization request, the OpenHistorianSSL.cer file was serialized to the SRQ file. When you imported the SRQ file into the publisher, the OpenHistorianSSL.cer file was deserialized and written to the CLOUD.cer file. So they are actually the same file; it was essentially just renamed and placed on the publisher server. Therefore, from the subscriber’s perspective, you probably should not be setting the remote certificate to be CLOUD.cer, but rather the certificate that you generated for the publisher server. Note that it would be unusual to use the same certificate to authenticate both systems, and so I would recommend generating a certificate for each system.

Now let’s talk about defaults. The openHistorian will actually create a certificate automatically (openHistorian.cer) and place it in the installation directory. The configuration pages in openHistorian Manager assume that you will be using the default certificate rather than creating a separate one. Therefore, if you feel the need to create a separate certificate, you will need to override some of the defaults.

  1. Configuration for the publisher’s local certificate is located in the configuration file (openHistorian.exe.config). Search for the section called tlsDataPublisher. In that section, there is a setting called CertificateFile which defaults to Eval(systemSettings.LocalCertificate). You will need to change the value to be the file path to the publisher’s local certificate. Modifying this configuration file requires you to restart the service for the change to take effect. Also make sure that the local certificate is placed in a directory in which the openHistorian service account has read access.

  2. Configuration for the subscriber’s local certificate is placed in the connection string. However, this can be configured more easily on the subscription authorization request page by clicking the Advanced button at the bottom of the page.

Throughout the process, keep in mind that the subscriber’s local certificate is the same as the publisher’s remote certificate and vice-versa. Also, if you have added the remote certificates to the computer’s trusted certificate store on each system, then you should not need to mark any of the Self-signed checkboxes throughout this process.


#3

Ok thanks! I’ll try it with the default OpenHistorian.cer and see how I go


#4

Ok, I got it working using the supplied OpenHistorian.cer files created for each OpenHistorian thanks to your instructions. Good one, thanks!

I am now trying to get the automated data recovery working. The sample demo on youtube shows how to configure this using an internal subscription, but I want to stick with using TLS as the providers here are concerned with security.
So what I did is create an internal subscription and copy the relevant parts of the connection string to the TLS connection string

image .

So I added this to my working TLS subcriber connection string.

dataGapRecovery={enabled=true; recoveryStartDelay=20; dataMonitoringInterval=10; minimumRecoverySpan=30; maximumRecoverySpan=864000; recoveryProcessingInterval=66}; loggingPath=ConfigurationCache;receiveInternalMetadata=True; receiveExternalMetadata=False;

So I now simulated a network outage and watched with Grafana

image

and it didn’t work. The status log on the subscriber shows this.
image

and the publisher shows this

[2/4/2019 1:12:43 PM] [TLS!DATAPUBLISHER] Client disconnected from command channel.

image

Do I absolutely need a Internal subscription to get this working over Tcpip or perhaps TLS doesn’t support data recovery?


#5

I have managed to get a slightly better result, but I cannot get Data Gap recovery to work at all with 2 OpenHistorians.

This is the extracts from the Status and Error logs on both Publisher and Subscriber.

Any idea’s whats stopping the Data gap recovery from sending data back to the subscriber?

Subscriber Status Log

[2/6/2019 2:49:33 PM] [CLOUD] Data subscriber command channel connection to publisher was established.
[2/6/2019 2:49:33 PM] [CLOUD] Success code received in response to server command "Subscribe": Client subscribed as compact unsynchronized with 50 signals.
[2/6/2019 2:49:33 PM] [CLOUD] [DataGapRecoverer] Data gap recovery requested for period "2019-02-06 04:49:04.461" - "2019-02-06 04:49:33.530"...
[2/6/2019 2:49:33 PM] [CLOUD] TSSC algorithm reset before sequence number: 46964
[2/6/2019 2:49:33 PM] [CLOUD] Success code received in response to server command "MetaDataRefresh": latest meta-data received.
[2/6/2019 2:49:33 PM] [CLOUD] Received a total of 152 records spanning 4 tables of meta-data that was uncompressed and deserialized in 1.98 milliseconds...
[2/6/2019 2:49:37 PM] [CLOUD] [DataGapRecoverer] Attempting connection to tcp://10.10.151.142:6177...
[2/6/2019 2:49:37 PM] [CLOUD] [DataGapRecoverer] Attempting command channel connection to publisher...
[2/6/2019 2:49:37 PM] [CLOUD] [DataGapRecoverer] Connection established.
[2/6/2019 2:49:37 PM] [CLOUD] [DataGapRecoverer] Data subscriber command channel connection to publisher was established.
[2/6/2019 2:50:03 PM] [CLOUD] [DataGapRecoverer] Starting data gap recovery for period "2019-02-06 04:48:44.461" - "2019-02-06 04:49:43.530"...
[2/6/2019 2:50:03 PM] [CLOUD] [DataGapRecoverer] Failure code received in response to server command "Subscribe": Failed to process client data subscription due to exception: Object reference not set to an instance of an object.
[2/6/2019 2:50:23 PM] [CLOUD] [DataGapRecoverer] WARNING: No data received in 10.0 seconds, canceling current data recovery operation...
[2/6/2019 2:50:23 PM] [CLOUD] [DataGapRecoverer] WARNING: Recovered 0 measurements for period "2019-02-06 04:48:44.461" - "2019-02-06 04:49:43.530".
[2/6/2019 2:50:23 PM] [CLOUD] [DataGapRecoverer] Success code received in response to server command "Unsubscribe": Client unsubscribed.

Subscribers Error Log

Empty

Publisher Status Log

[2/6/2019 2:49:32 PM] [TLS!DATAPUBLISHER] Client connected to command channel.
[2/6/2019 2:49:32 PM] [TLS!DATAPUBLISHER] Starting measurement route calculation...
[2/6/2019 2:49:32 PM] [TLS!DATAPUBLISHER] Client subscribed as compact unsynchronized with 50 signals.
[2/6/2019 2:49:32 PM] [TLS!DATAPUBLISHER] Received meta-data refresh request from noja-180.nojapower.local ([::ffff:10.10.150.87]:60523), preparing response...
[2/6/2019 2:49:32 PM] [TLS!DATAPUBLISHER] Calculated 50 routes for 1 destination in 0 seconds.
[2/6/2019 2:49:32 PM] [TLS!DATAPUBLISHER] Start time sent to noja-180.nojapower.local ([::ffff:10.10.150.87]:60523).
[2/6/2019 2:49:32 PM] [noja-180.nojapower.local] TSSC algorithm reset before sequence number: 0
[2/6/2019 2:49:32 PM] [TLS!DATAPUBLISHER] 152 records spanning 4 tables of meta-data prepared in 47.99 milliseconds, sending response to noja-180.nojapower.local ([::ffff:10.10.150.87]:60523)...

Publishers Error Log

[2/6/2019 2:50:02 PM] (Inner Exception)
Date and Time:         2/6/2019 2:50:02 PM
Machine Name:          NOJA-063
Machine IP:            fe80::6d3b:cad3:80a8:fe36%4
Machine OS:            Microsoft Windows NT 6.2.9200.0

Application Domain:    openHistorian.exe
Assembly Codebase:     C:/Program Files/openHistorian/openHistorian.exe
Assembly Full Name:    openHistorian, Version=2.5.6.0, Culture=neutral, PublicKeyToken=null
Assembly Version:      2.5.6.0
Assembly Build Date:   6/1/2018 12:22:34 AM
.Net Runtime Version:  4.0.30319.42000

Exception Source:      GSF.TimeSeries
Exception Type:        System.NullReferenceException
Exception Message:     Object reference not set to an instance of an object.
Exception Target Site: ExtractTemporalConfiguration

---- Stack Trace ----
   GSF.TimeSeries.Adapters.IaonSession.ExtractTemporalConfiguration(realtimeConfiguration As DataSet)
       openHistorian.exe: N 01439
   GSF.TimeSeries.Transport.IClientSubscriptionExtensions.CreateTemporalSession(clientSubscription As IClientSubscription)
       openHistorian.exe: N 01274
   GSF.TimeSeries.Transport.UnsynchronizedClientSubscription.Initialize()
       openHistorian.exe: N 00951
   GSF.TimeSeries.Transport.DataPublisher.HandleSubscribeRequest(connection As ClientConnection, buffer As Byte[], startIndex As Int32, length As Int32)
       openHistorian.exe: N 02792


(Outer Exception)
Date and Time:         2/6/2019 2:50:02 PM
Machine Name:          NOJA-063
Machine IP:            fe80::6d3b:cad3:80a8:fe36%4
Machine OS:            Microsoft Windows NT 6.2.9200.0

Application Domain:    openHistorian.exe
Assembly Codebase:     C:/Program Files/openHistorian/openHistorian.exe
Assembly Full Name:    openHistorian, Version=2.5.6.0, Culture=neutral, PublicKeyToken=null
Assembly Version:      2.5.6.0
Assembly Build Date:   6/1/2018 12:22:34 AM
.Net Runtime Version:  4.0.30319.42000

Exception Source:      
Exception Type:        System.InvalidOperationException
Exception Message:     Failed to process client data subscription due to exception: Object reference not set to an instance of an object.

---- Stack Trace ----