Skip to content

Commit

Permalink
Update v6.2.0
Browse files Browse the repository at this point in the history
- Updated TLS functionality for HTTP and MQTT
- Added 'Available' topic for MQTT Agent Device
  • Loading branch information
PatrickRitchie committed Mar 27, 2024
1 parent 971f101 commit cf3cf27
Show file tree
Hide file tree
Showing 23 changed files with 431 additions and 246 deletions.
1 change: 1 addition & 0 deletions MTConnect.NET.sln
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{0957974A-C
docs\MQTT-AWS-Greengrass-Mqtt-Bridge.md = docs\MQTT-AWS-Greengrass-Mqtt-Bridge.md
docs\MQTT-AWS-IoT.md = docs\MQTT-AWS-IoT.md
docs\MQTT-HiveMQ.md = docs\MQTT-HiveMQ.md
docs\OpenSSL.md = docs\OpenSSL.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{0F01D2F5-0CFA-4DAE-A0FD-5733D291F6FB}"
Expand Down
83 changes: 69 additions & 14 deletions agent/MTConnect.NET-Agent/agent.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,84 @@ processors:
modules:

- http-server: # - Add HTTP Server module
# hostname: localhost
port: 5000
# allowPut: true
indentOutput: true
documentFormat: xml
accept:
text/xml: xml
application/json: json
# responseCompression:
# - gzip
# - br
# files:
# - path: schemas
# location: schemas
# - path: styles
# location: styles
# - path: styles/favicon.ico
# location: favicon.ico
responseCompression:
- gzip
- br
files:
- path: schemas
location: schemas
- path: styles
location: styles
- path: styles/favicon.ico
location: favicon.ico

- http-server: # - Add HTTP Server module
port: 5001
indentOutput: true
documentFormat: xml
accept:
text/xml: xml
application/json: json
responseCompression:
- gzip
- br
tls:
# pfx:
# certificatePath: c:\test-cert\trakhound.pfx
# certificatePassword: trakhound
pem:
certificateAuthority: c:\test-cert\rootCA.crt
certificatePath: c:\test-cert\trakhound.crt
privateKeyPath: c:\test-cert\trakhound.key
privateKeyPassword: trakhound
files:
- path: schemas
location: schemas
- path: styles
location: styles
- path: styles/favicon.ico
location: favicon.ico

- mqtt-broker: # - Add MQTT Broker module
port: 1883
currentInterval: 10000
sampleInterval: 500

- mqtt-broker: # - Add MQTT Broker module
port: 8883
currentInterval: 10000
sampleInterval: 500
tls:
pem:
certificateAuthority: c:\test-cert\rootCA.crt
certificatePath: c:\test-cert\trakhound.crt
privateKeyPath: c:\test-cert\trakhound.key
privateKeyPassword: trakhound

- mqtt-relay: # - Add MQTT Relay module
server: 192.168.1.128
server: localhost
port: 1883
currentInterval: 10000
sampleInterval: 500

- mqtt-relay: # - Add MQTT Relay module
server: localhost
port: 8883
currentInterval: 10000
sampleInterval: 500
tls:
pem:
certificateAuthority: c:\test-cert\rootCA.crt
certificatePath: c:\test-cert\trakhound.crt
privateKeyPath: c:\test-cert\trakhound.key
privateKeyPassword: trakhound


# - shdr-adapter: # - Add SHDR Adapter module for Device = M12346 and Port = 7878
# deviceKey: M12346
Expand Down Expand Up @@ -65,8 +119,9 @@ observationBufferSize: 150000
assetBufferSize: 1000

# Sets whether the Agent buffers are durable and retain state after restart
durable: false
# durable: true

# Disables the Agent Device
# enableAgentDevice: false

# Sets the default MTConnect version to output response documents for.
Expand Down
15 changes: 15 additions & 0 deletions agent/Modules/MTConnect.NET-AgentModule-HttpServer/README-Nuget.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ This Agent Module implements a MTConnect REST Protocol Http server
* `certificatePath` - The path to the (.pem) file
* `privateKeyPath` - The path to the key containing the private key
* `privateKeyPassword` - The certificate password
* `certificateAuthority` - The path to the (.pem) file containing the Certificate Authority

* `verifyClientCertificate` - Toggles whether Client Certificate chains are verified ("true" or "false")

Expand Down Expand Up @@ -104,6 +105,20 @@ Specify the port and hostname with TLS (PFX Certificate)
```

### Example 5
Specify the port and hostname with TLS (PEM Certificate)
```yaml
- http-server:
hostname: DESKTOP-HV74M4N
port: 5001
tls:
pem:
certificateAuthority: c:\certs\rootCA.crt
certificatePath: c:\certs\mtconnect-testing.crt
privateKeyPath: c:\certs\mtconnect-testing.key
privateKeyPassword: mtconnect
```

### Example 6
Specify with custom Accept headers
```yaml
- http-server:
Expand Down
15 changes: 15 additions & 0 deletions agent/Modules/MTConnect.NET-AgentModule-HttpServer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ This Agent Module implements a MTConnect REST Protocol Http server
* `certificatePath` - The path to the (.pem) file
* `privateKeyPath` - The path to the key containing the private key
* `privateKeyPassword` - The certificate password
* `certificateAuthority` - The path to the (.pem) file containing the Certificate Authority

* `verifyClientCertificate` - Toggles whether Client Certificate chains are verified ("true" or "false")

Expand Down Expand Up @@ -122,6 +123,20 @@ Specify the port and hostname with TLS (PFX Certificate)
```

### Example 5
Specify the port and hostname with TLS (PEM Certificate)
```yaml
- http-server:
hostname: DESKTOP-HV74M4N
port: 5001
tls:
pem:
certificateAuthority: c:\certs\rootCA.crt
certificatePath: c:\certs\mtconnect-testing.crt
privateKeyPath: c:\certs\mtconnect-testing.key
privateKeyPassword: mtconnect
```

### Example 6
Specify with custom Accept headers
```yaml
- http-server:
Expand Down
84 changes: 26 additions & 58 deletions agent/Modules/MTConnect.NET-AgentModule-MqttBroker/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// TrakHound Inc. licenses this file to you under the MIT license.

using MQTTnet;
using MQTTnet.Certificates;
using MQTTnet.Server;
using MTConnect.Agents;
using MTConnect.Assets;
Expand All @@ -15,7 +16,6 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;

Expand Down Expand Up @@ -68,10 +68,10 @@ private async Task StartAsync()
{
try
{
var mqttServerOptionsBuilder = new MqttServerOptionsBuilder();
var mqttServerOptions = new MqttServerOptions();

// Set the Timeout
mqttServerOptionsBuilder.WithDefaultCommunicationTimeout(TimeSpan.FromSeconds(_configuration.Timeout));
mqttServerOptions.DefaultCommunicationTimeout = TimeSpan.FromMilliseconds(_configuration.Timeout);

// Get the IP Address (in case configuration specifies a Hostname)
IPAddress address = null;
Expand All @@ -85,33 +85,28 @@ private async Task StartAsync()
}
else address = IPAddress.Any;

// Set the IP Address
mqttServerOptionsBuilder.WithDefaultEndpointBoundIPAddress(address);

// Set the Port
mqttServerOptionsBuilder.WithDefaultEndpointPort(_configuration.Port);


// Add Certificate & Private Key
if (!string.IsNullOrEmpty(_configuration.PemCertificate) && !string.IsNullOrEmpty(_configuration.PemPrivateKey))
if (_configuration.Tls != null)
{
X509Certificate2 certificate = null;

#if NET5_0_OR_GREATER
certificate = new X509Certificate2(X509Certificate2.CreateFromPemFile(GetFilePath(_configuration.PemCertificate), GetFilePath(_configuration.PemPrivateKey)).Export(X509ContentType.Pfx));
#endif
mqttServerOptions.TlsEndpointOptions.IsEnabled = true;
mqttServerOptions.TlsEndpointOptions.BoundInterNetworkAddress = address;
mqttServerOptions.TlsEndpointOptions.Port = _configuration.Port;

if (certificate != null)
var certificate = _configuration.Tls.GetCertificate();
if (certificate.Success && certificate.Certificate != null)
{
mqttServerOptionsBuilder.WithoutDefaultEndpoint();
mqttServerOptionsBuilder.WithEncryptedEndpoint();
mqttServerOptionsBuilder.WithEncryptedEndpointPort(_configuration.Port);
mqttServerOptionsBuilder.WithEncryptionCertificate(certificate);
mqttServerOptionsBuilder.WithEncryptionSslProtocol(System.Security.Authentication.SslProtocols.Tls12);
mqttServerOptions.TlsEndpointOptions.CertificateProvider = new X509CertificateProvider(certificate.Certificate);
mqttServerOptions.TlsEndpointOptions.SslProtocol = System.Security.Authentication.SslProtocols.Tls12;
}
}
else
{
mqttServerOptions.DefaultEndpointOptions.IsEnabled = true;
mqttServerOptions.DefaultEndpointOptions.BoundInterNetworkAddress = address;
mqttServerOptions.DefaultEndpointOptions.Port = _configuration.Port;
}

var mqttServerOptions = mqttServerOptionsBuilder.Build();

var mqttFactory = new MqttFactory();
_mqttServer = mqttFactory.CreateMqttServer(mqttServerOptions);
Expand All @@ -126,6 +121,11 @@ private async Task StartAsync()
Log(MTConnectLogLevel.Debug, $"MQTT Server : Client Disconnected : {args.ClientId} : {args.Endpoint}");
return Task.CompletedTask;
};
_mqttServer.ValidatingConnectionAsync += (args) =>
{
Log(MTConnectLogLevel.Debug, $"MQTT Server : Validating Client Connection : {args.ClientId} : {args.Endpoint} : {args.ReasonString}");
return Task.CompletedTask;
};

await _mqttServer.StartAsync();
_server.Start();
Expand Down Expand Up @@ -161,12 +161,7 @@ private async void ProbeReceived(IDevice device, IDevicesResponseDocument respon
if (formatResult.Success)
{
var topic = $"{_configuration.TopicPrefix}/{MTConnectMqttDocumentServer.ProbeTopic}/{device.Uuid}";

//var message = new MqttApplicationMessage();
//message.Retain = true;
//message.Topic = topic;
//message.QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce;
//message.Payload = formatResult.Content;
formatResult.Content.Seek(0, SeekOrigin.Begin);

var messageBuilder = new MqttApplicationMessageBuilder();
messageBuilder.WithRetainFlag(true);
Expand All @@ -190,12 +185,7 @@ private async void CurrentReceived(IDevice device, IStreamsResponseOutputDocumen
if (formatResult.Success)
{
var topic = $"{_configuration.TopicPrefix}/{MTConnectMqttDocumentServer.CurrentTopic}/{device.Uuid}";

//var message = new MqttApplicationMessage();
//message.Retain = true;
//message.Topic = topic;
//message.QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce;
//message.Payload = formatResult.Content;
formatResult.Content.Seek(0, SeekOrigin.Begin);

var messageBuilder = new MqttApplicationMessageBuilder();
messageBuilder.WithRetainFlag(true);
Expand All @@ -219,12 +209,7 @@ private async void SampleReceived(IDevice device, IStreamsResponseOutputDocument
if (formatResult.Success)
{
var topic = $"{_configuration.TopicPrefix}/{MTConnectMqttDocumentServer.SampleTopic}/{device.Uuid}";

//var message = new MqttApplicationMessage();
////message.Retain = true;
//message.Topic = topic;
//message.QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce;
//message.Payload = formatResult.Content;
formatResult.Content.Seek(0, SeekOrigin.Begin);

var messageBuilder = new MqttApplicationMessageBuilder();
messageBuilder.WithRetainFlag(true);
Expand Down Expand Up @@ -253,12 +238,7 @@ private async void AssetReceived(IDevice device, IAssetsResponseDocument respons
if (formatResult.Success)
{
var topic = $"{_configuration.TopicPrefix}/{MTConnectMqttDocumentServer.AssetTopic}/{device.Uuid}/{asset.AssetId}";

//var message = new MqttApplicationMessage();
//message.Retain = true;
//message.Topic = topic;
//message.QualityOfServiceLevel = (MQTTnet.Protocol.MqttQualityOfServiceLevel)_configuration.QoS;
//message.Payload = formatResult.Content;
formatResult.Content.Seek(0, SeekOrigin.Begin);

var messageBuilder = new MqttApplicationMessageBuilder();
messageBuilder.WithRetainFlag(true);
Expand All @@ -274,17 +254,5 @@ private async void AssetReceived(IDevice device, IAssetsResponseDocument respons
}
}
}


private static string GetFilePath(string path)
{
var x = path;
if (!Path.IsPathRooted(x))
{
x = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, x);
}

return x;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) 2024 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.

using MTConnect.Tls;

namespace MTConnect.Configurations
{
public class MqttBrokerModuleConfiguration : IMTConnectMqttServerConfiguration
Expand All @@ -17,26 +19,10 @@ public class MqttBrokerModuleConfiguration : IMTConnectMqttServerConfiguration


/// <summary>
/// The path to the Certificate Authority file
/// </summary>
public string CertificateAuthority { get; set; }

/// <summary>
/// The path to the PEM Certificate (.pem) file
/// </summary>
public string PemCertificate { get; set; }

/// <summary>
/// The path to the PEM Private Key file
/// </summary>
public string PemPrivateKey { get; set; }

/// <summary>
/// Sets whether to validate the certificate chain (true or false)
/// Gets or Sets the TLS settings
/// </summary>
public bool AllowUntrustedCertificates { get; set; }
public TlsConfiguration Tls { get; set; }

//public bool UseTls { get; set; }

/// <summary>
/// The timeout (in milliseconds) to use for connection and read/write
Expand Down Expand Up @@ -88,13 +74,14 @@ public class MqttBrokerModuleConfiguration : IMTConnectMqttServerConfiguration

public MqttBrokerModuleConfiguration()
{
Server = null;
Port = 1883;
InitialDelay = 500;
RestartInterval = 5000;
Timeout = 5000;

TopicPrefix = "MTConnect";
DocumentFormat = "JSON";
DocumentFormat = "json-cppagent";

CurrentInterval = 5000;
SampleInterval = 500;
Expand Down
Loading

0 comments on commit cf3cf27

Please sign in to comment.