Rabbitmq on top of VPN network, add users and passwords to rabbitmq
Created skript for automatic update of all the installations
This commit is contained in:
parent
30e4991032
commit
980089d7e0
|
@ -11,6 +11,7 @@ using Microsoft.OpenApi.Models;
|
|||
using InnovEnergy.Lib.Utils;
|
||||
using RabbitMQ.Client;
|
||||
|
||||
|
||||
namespace InnovEnergy.App.Backend;
|
||||
|
||||
public static class Program
|
||||
|
@ -21,7 +22,7 @@ public static class Program
|
|||
Watchdog.NotifyReady();
|
||||
Db.Init();
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
|
||||
RabbitMqManager.InitializeEnvironment();
|
||||
RabbitMqManager.StartRabbitMqConsumer();
|
||||
Console.WriteLine("Queue declared");
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
using System.Drawing.Printing;
|
||||
using System.Net;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using InnovEnergy.App.Backend.Database;
|
||||
|
@ -20,8 +24,130 @@ public static class RabbitMqManager
|
|||
public static void InitializeEnvironment()
|
||||
{
|
||||
|
||||
string vpnServerIp = "194.182.190.208";
|
||||
Factory = new ConnectionFactory { HostName = vpnServerIp};
|
||||
//string vpnServerIp = "194.182.190.208";
|
||||
string vpnServerIp = "10.2.0.11";
|
||||
|
||||
// ConnectionFactory factory = new ConnectionFactory();
|
||||
// factory.HostName = vpnServerIp;
|
||||
// factory.AutomaticRecoveryEnabled = true;
|
||||
// //factory.UserName = "";
|
||||
// //factory.Password = "";
|
||||
// factory.VirtualHost = "/";
|
||||
// factory.Port = 5672;
|
||||
//
|
||||
// //factory.AuthMechanisms = new IAuthMechanismFactory[] { new ExternalMechanismFactory() };
|
||||
//
|
||||
// System.Diagnostics.Debug.WriteLine("2 ");
|
||||
//
|
||||
// X509Certificate2Collection certCollection = new X509Certificate2Collection();
|
||||
// X509Certificate2 certificate = new X509Certificate2("/etc/rabbitmq/testca/ca_certificate.pem");
|
||||
// certCollection.Add(certificate);
|
||||
//
|
||||
// factory.Ssl.Certs = certCollection;
|
||||
// factory.Ssl.Enabled = true;
|
||||
// factory.Ssl.ServerName = "Webserver-FrontAndBack";
|
||||
// factory.Ssl.Version = SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13;
|
||||
// factory.Ssl.AcceptablePolicyErrors = SslPolicyErrors.RemoteCertificateChainErrors;
|
||||
// factory.Ssl.CertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
|
||||
// {
|
||||
// if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
|
||||
// {
|
||||
// // Log or debug information about the chain
|
||||
// foreach (var chainElement in chain.ChainElements)
|
||||
// {
|
||||
// Console.WriteLine($"Element Subject: {chainElement.Certificate.Subject}");
|
||||
// Console.WriteLine($"Element Issuer: {chainElement.Certificate.Issuer}");
|
||||
// // Add more details as needed
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Your custom validation logic
|
||||
// return sslPolicyErrors == SslPolicyErrors.None;
|
||||
// };
|
||||
|
||||
|
||||
Factory = new ConnectionFactory
|
||||
{
|
||||
HostName = vpnServerIp,
|
||||
Port = 5672,
|
||||
VirtualHost = "/",
|
||||
UserName = "consumer",
|
||||
Password = "faceaddb5005815199f8366d3d15ff8a",
|
||||
//AuthMechanisms = new IAuthMechanismFactory[] { new ExternalMechanismFactory() },
|
||||
|
||||
// Ssl = new SslOption
|
||||
// {
|
||||
// Enabled = true,
|
||||
// ServerName = "Webserver-FrontAndBack",
|
||||
// //Roots = new X509Certificate2Collection { caCertificate },
|
||||
// //CertPath = "/etc/rabbitmq/testca/ca_certificate.pem",
|
||||
// CertPath = "/etc/rabbitmq/client/client_certificate.pem",
|
||||
//
|
||||
//
|
||||
// // CertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
|
||||
// // {
|
||||
// // //X509Certificate2 clientCertificate = new X509Certificate2("/etc/rabbitmq/client/client_certificate.pem");
|
||||
// //
|
||||
// // //X509Certificate2 caCertificate = new X509Certificate2("/etc/openvpn/client/ca-certificate");
|
||||
// // X509Certificate2 caCertificate = new X509Certificate2("/etc/rabbitmq/testca/ca_certificate.pem");
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// // Console.WriteLine(certificate.Subject);
|
||||
// // Console.WriteLine("---------------------------------");
|
||||
// // //Console.WriteLine(certificate.GetPublicKey());
|
||||
// // // Your custom validation logic using the CA certificate
|
||||
// // // Return true if the certificate is valid, false otherwise
|
||||
// // return certificate.Issuer == caCertificate.Subject;
|
||||
// // }
|
||||
// CertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
|
||||
// {
|
||||
// X509Certificate2 caCertificate = new X509Certificate2("/etc/rabbitmq/testca/ca_certificate.pem");
|
||||
//
|
||||
// // Add the CA certificate to the chain policy's extra store
|
||||
// chain.ChainPolicy.ExtraStore.Add(caCertificate);
|
||||
//
|
||||
// // Check if the chain builds successfully
|
||||
// bool chainIsValid = chain.Build((X509Certificate2)certificate);
|
||||
//
|
||||
// if (!chainIsValid)
|
||||
// {
|
||||
// Console.WriteLine("Certificate chain validation failed:");
|
||||
//
|
||||
// // Print details of each chain status
|
||||
// foreach (var chainStatus in chain.ChainStatus)
|
||||
// {
|
||||
// Console.WriteLine($"Chain Status: {chainStatus.Status}");
|
||||
// Console.WriteLine($"Chain Status Information: {chainStatus.StatusInformation}");
|
||||
// // Add more details as needed
|
||||
// // Check if the failure is due to UntrustedRoot
|
||||
// if (chainStatus.Status == X509ChainStatusFlags.UntrustedRoot)
|
||||
// {
|
||||
// // Manually check if the root certificate is the expected one
|
||||
// if (certificate.Issuer == caCertificate.Subject)
|
||||
// {
|
||||
// Console.WriteLine("Manually trusting the root certificate.");
|
||||
// chainIsValid = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
//
|
||||
// // Additional validation logic if needed
|
||||
// Console.WriteLine($"Certificate Subject: {certificate.Subject}"+chainIsValid);
|
||||
//
|
||||
// // Return true if the certificate is valid
|
||||
// return chainIsValid;
|
||||
// }
|
||||
|
||||
|
||||
//}
|
||||
};
|
||||
|
||||
|
||||
|
||||
Connection = Factory.CreateConnection();
|
||||
Channel = Connection.CreateModel();
|
||||
Console.WriteLine("Middleware subscribed to RabbitMQ queue, ready for receiving messages");
|
||||
|
@ -36,9 +162,8 @@ public static class RabbitMqManager
|
|||
var body = ea.Body.ToArray();
|
||||
var message = Encoding.UTF8.GetString(body);
|
||||
StatusMessage? receivedStatusMessage = JsonSerializer.Deserialize<StatusMessage>(message);
|
||||
var InstallationConnections = WebsocketManager.InstallationConnections;
|
||||
|
||||
lock (InstallationConnections)
|
||||
lock (WebsocketManager.InstallationConnections)
|
||||
{
|
||||
//Consumer received a message
|
||||
if (receivedStatusMessage != null)
|
||||
|
@ -78,6 +203,7 @@ public static class RabbitMqManager
|
|||
//Traverse the Alarm list, and store each of them to the database
|
||||
if (receivedStatusMessage.Alarms != null)
|
||||
{
|
||||
Console.WriteLine("Add an alarm for installation "+receivedStatusMessage.InstallationId);
|
||||
foreach (var alarm in receivedStatusMessage.Alarms)
|
||||
{
|
||||
Error newError = new Error
|
||||
|
@ -95,11 +221,14 @@ public static class RabbitMqManager
|
|||
}
|
||||
}
|
||||
|
||||
var prevStatus = 0;
|
||||
|
||||
//This installation id does not exist in our data structure, add it.
|
||||
if (!InstallationConnections.ContainsKey(installationId))
|
||||
if (!WebsocketManager.InstallationConnections.ContainsKey(installationId))
|
||||
{
|
||||
prevStatus = -2;
|
||||
Console.WriteLine("Create new empty list for installation: " + installationId);
|
||||
InstallationConnections[installationId] = new InstallationInfo
|
||||
WebsocketManager.InstallationConnections[installationId] = new InstallationInfo
|
||||
{
|
||||
Status = receivedStatusMessage.Status,
|
||||
Timestamp = DateTime.Now
|
||||
|
@ -107,13 +236,14 @@ public static class RabbitMqManager
|
|||
}
|
||||
else
|
||||
{
|
||||
InstallationConnections[installationId].Status = receivedStatusMessage.Status;
|
||||
InstallationConnections[installationId].Timestamp = DateTime.Now;
|
||||
prevStatus = WebsocketManager.InstallationConnections[installationId].Status;
|
||||
WebsocketManager.InstallationConnections[installationId].Status = receivedStatusMessage.Status;
|
||||
WebsocketManager.InstallationConnections[installationId].Timestamp = DateTime.Now;
|
||||
}
|
||||
|
||||
//Console.WriteLine("----------------------------------------------");
|
||||
//Update all the connected front-ends regarding this installation
|
||||
if(InstallationConnections[installationId].Connections.Count > 0)
|
||||
if(prevStatus != receivedStatusMessage.Status && WebsocketManager.InstallationConnections[installationId].Connections.Count > 0)
|
||||
{
|
||||
WebsocketManager.InformWebsocketsForInstallation(installationId);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,65 @@
|
|||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using InnovEnergy.App.Backend.Database;
|
||||
using InnovEnergy.App.Backend.DataTypes;
|
||||
using RabbitMQ.Client;
|
||||
using RabbitMQ.Client.Events;
|
||||
|
||||
namespace InnovEnergy.App.Backend.Websockets;
|
||||
|
||||
public static class WebsocketManager
|
||||
{
|
||||
public static Dictionary<int, InstallationInfo> InstallationConnections = new Dictionary<int, InstallationInfo>();
|
||||
|
||||
public static void InformInstallationsToSubscribeToRabbitMq()
|
||||
{
|
||||
var installationIps = Db.Installations.Select(inst => inst.VpnIp).ToList();
|
||||
Console.WriteLine("Count is "+installationIps.Count);
|
||||
var maxRetransmissions = 2;
|
||||
|
||||
UdpClient udpClient = new UdpClient();
|
||||
udpClient.Client.ReceiveTimeout = 2000;
|
||||
int port = 9000;
|
||||
//Send a message to each installation and tell it to subscribe to the queue
|
||||
using (udpClient)
|
||||
{
|
||||
for (int i = 0; i < installationIps.Count; i++)
|
||||
{
|
||||
if(installationIps[i]==""){continue;}
|
||||
Console.WriteLine("-----------------------------------------------------------");
|
||||
Console.WriteLine("Trying to reach installation with IP: " + installationIps[i]);
|
||||
//Try at most MAX_RETRANSMISSIONS times to reach an installation.
|
||||
for (int j = 0; j < maxRetransmissions; j++)
|
||||
{
|
||||
string message = "This is a message from RabbitMQ server, you can subscribe to the RabbitMQ queue";
|
||||
byte[] data = Encoding.UTF8.GetBytes(message);
|
||||
udpClient.Send(data, data.Length, installationIps[i], port);
|
||||
|
||||
Console.WriteLine($"Sent UDP message to {installationIps[i]}:{port}: {message}");
|
||||
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(installationIps[i]), port);
|
||||
|
||||
try
|
||||
{
|
||||
byte[] replyData = udpClient.Receive(ref remoteEndPoint);
|
||||
string replyMessage = Encoding.UTF8.GetString(replyData);
|
||||
Console.WriteLine("Received " + replyMessage + " from installation " + installationIps[i]);
|
||||
break;
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
if (ex.SocketErrorCode == SocketError.TimedOut){Console.WriteLine("Timed out waiting for a response. Retry...");}
|
||||
else{Console.WriteLine("Error: " + ex.Message);}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Start RabbitMQ Consumer");
|
||||
|
||||
}
|
||||
|
||||
//Every 1 minute, check the timestamp of the latest received message for every installation.
|
||||
//If the difference between the two timestamps is more than one minute, we consider this installation unavailable.
|
||||
|
@ -26,6 +79,8 @@ public static class WebsocketManager
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Inform all the connected websockets regarding installation "installationId"
|
||||
public static void InformWebsocketsForInstallation(int installationId)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
|
||||
dotnet_version='net6.0'
|
||||
salimax_ip="$1"
|
||||
username='ie-entwicklung'
|
||||
root_password='Salimax4x25'
|
||||
|
||||
set -e
|
||||
|
||||
echo -e "\n============================ Build ============================\n"
|
||||
|
||||
dotnet publish \
|
||||
./SaliMax.csproj \
|
||||
-p:PublishTrimmed=false \
|
||||
-c Release \
|
||||
-r linux-x64
|
||||
|
||||
echo -e "\n============================ Deploy ============================\n"
|
||||
ip_addresses=("10.2.3.115" "10.2.3.104" "10.2.4.33" "10.2.4.32" "10.2.4.36" "10.2.4.35" "10.2.4.154" "10.2.4.113" "10.2.4.29")
|
||||
|
||||
for ip_address in "${ip_addresses[@]}"; do
|
||||
rsync -v \
|
||||
--exclude '*.pdb' \
|
||||
./bin/Release/$dotnet_version/linux-x64/publish/* \
|
||||
$username@"$ip_address":~/salimax
|
||||
|
||||
ssh "$username"@"$ip_address" "cd salimax && echo '$root_password' | sudo -S ./restart"
|
||||
|
||||
|
||||
echo "Deployed and ran commands on $ip_address"
|
||||
done
|
||||
|
||||
|
||||
|
|
@ -4,6 +4,7 @@ using System.Net.NetworkInformation;
|
|||
using System.Net.Sockets;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Threading.Tasks;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using Flurl.Http;
|
||||
using InnovEnergy.App.SaliMax.Devices;
|
||||
|
@ -50,8 +51,9 @@ internal static class Program
|
|||
private static readonly Channel RelaysChannel ;
|
||||
private static readonly Channel BatteriesChannel ;
|
||||
|
||||
private const String VpnServerIp = "194.182.190.208";
|
||||
|
||||
//private const String VpnServerIp = "194.182.190.208";
|
||||
private const String VpnServerIp = "10.2.0.11";
|
||||
|
||||
private static IPAddress? _controllerIpAddress;
|
||||
private static UdpClient _udpListener = null!;
|
||||
private static ConnectionFactory? _factory ;
|
||||
|
@ -314,7 +316,34 @@ internal static class Program
|
|||
{
|
||||
try
|
||||
{
|
||||
_factory = new ConnectionFactory { HostName = VpnServerIp };
|
||||
//_factory = new ConnectionFactory { HostName = VpnServerIp };
|
||||
|
||||
_factory = new ConnectionFactory
|
||||
{
|
||||
HostName = VpnServerIp,
|
||||
Port = 5672,
|
||||
VirtualHost = "/",
|
||||
UserName = "producer",
|
||||
Password = "b187ceaddb54d5485063ddc1d41af66f",
|
||||
// Ssl = new SslOption
|
||||
// {
|
||||
// Enabled = true,
|
||||
// ServerName = VpnServerIp, // Disable hostname validation
|
||||
// CertPath = "/etc/openvpn/client/client-certificate",
|
||||
//
|
||||
// CertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
|
||||
// {
|
||||
// X509Certificate2 caCertificate = new X509Certificate2("/etc/openvpn/client/ca-certificate");
|
||||
// //Console.WriteLine(caCertificate);
|
||||
// //Console.WriteLine("---------------------------------");
|
||||
// //Console.WriteLine(certificate.GetPublicKey());
|
||||
// // Your custom validation logic using the CA certificate
|
||||
// // Return true if the certificate is valid, false otherwise
|
||||
// return certificate.Issuer == caCertificate.Subject;
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
_connection = _factory.CreateConnection();
|
||||
_channel = _connection.CreateModel();
|
||||
_channel.QueueDeclare(queue: "statusQueue", durable: true, exclusive: false, autoDelete: false, arguments: null);
|
||||
|
|
Loading…
Reference in New Issue