Intrexx Industrial - Konfiguration eines MQTT-Message-Brokers
1. Allgemeines
Für die Anbindung an Intrexx wird der von Apache entwickelte ActiveMQ-Server verwendet.
Dieser Server ist frei unter der Apache 2.0 Lizenz verfügbar. Das im Folgenden verwendete Kürzel
"<ACTIVE_MQ_INST>" bezieht sich auf den Installationspfad des ActiveMQ-Servers.
In der von United Planet bereitgestellten Test-VM ist der Installationspfad /opt/activemq.
2. SSL-Verschlüsselung
Im Folgenden wird eine einfache Möglichkeit beschrieben, wie mit dem Java-Keytool
ein selbstsigniertes Zertifikat erstellt, und dieses dann in ActiveMQ eingebunden werden kann.
Hierzu muss auf dem System Java installiert und konfiguriert sein.
2.1. Keystore mit selbstsigniertem Private-Key erstellen
Zuerst wird ein Schlüsselbund (Keystore) erstellt, der den privaten Schlüssel enthält:
Als CN (im Dialog: "Vor- und Nachname" bzw. "First and last name") muss der FQHN
der ActiveMQ-Servers übergeben werden. Es muss dann später sichergestellt werden, dass der
ActiveMQ über diesen Namen erreichbar ist, damit das SSL-Handshake funktioniert.
Anfangs muss ausserdem ein Passwort für den Zugriff auf den Keystore eingegeben werden.
Das später anzugebende Passwort für den Alias muss einfach mit ENTER quittiert werden,
und ist somit identisch mit dem Keystore-Passwort. Außerdem sollte die Datei, da sie den
privaten Schlüssel des ActiveMQ enthält, entsprechend vor Zugriff geschützt werden.
2.2 Zertifikat für Clients exportieren
Aus der zuvor erstellten Keystore-Datei wird nun der öffentliche Schlüssel sowie das Zertifikat generiert:
Das Zertifikat wird hier im DER-Format (also binär) exportiert. Über den weiteren Parameter "-rfc"
kann das Zertifikat auch als PEM (als Klartext bzw. BASE64-kodiert) gespeichert werden.
Der Import des Zertifikates in einen Truststore, der in Java-Applikationen häufig verwendet wird,
wird mit folgendem Befehl ausgeführt:
Damit Intrexx später eine verschlüsselte TLS-Verbindung zum ActiveMQ-Server herstellen kann,
muss die gerade erstellte Datei "amq_server.der" nun in Intrexx in den
Portaleigenschaften
eingebunden werden. Wählen Sie im Dialog
Zertifikatsquelle die Option "Import der Datei" und wählen Sie dann die Datei "amq_server.der" aus.
Damit die Änderung greift, muss der Portal-Dienst
neu gestartet werden.
2.4 SSL in ActiveMQ aktivieren und Keystore mit dem privaten Schlüssel einbinden
Hierzu muss in der <ACTIVEMQ_INST>/conf/activemq.xml im "core"-Namespace der Pfad
zum erstellten Keystore, sowie dessen Passwort übergeben werden. Da das Passwort im Klartext vorliegt,
sollte die activemq.xml entsprechend vor unberechtigtem Zugriff geschützt sein.
Für die Pfadangaben sollten laut ActiveMQ-Dokumentation relative Pfade verwendet werden.
Das Arbeitsverzeichnis ist per Default <ACTIVEMQ_INST>/conf/, d.h. liegt die "amq_server.ks"
direkt in diesem Verzeichnis, genügt die Angabe keyStore="amq_server.ks".
Auszug aus der activemq.xml:
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
...
..
.
<!-- Im sslContext muss der Pfad zur Keystore-Datei sowie das Passwort des Keystore übergeben werden -->
<sslContext>
<sslContext
keyStore="/PATH/TO/amq_server.ks" keyStorePassword="GEHEIM" />
</sslContext>
<!-- in den entsprechenden Konnektoren muss dann SSL aktiviert werden, die unbenötigten Konnektoren sollten am besten deaktiviert werden,
Hinweis: openwire wird für die Verbindung zu Intrexx via JMS benötigt-->
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<!-- <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> -->
<transportConnector name="openwire" uri="ssl://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt+ssl" uri="mqtt+ssl://0.0.0.0:8883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<!-- transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/ -->
</transportConnectors>
Bitte beachten Sie die Groß-/Kleinschreibung bei den Parametern.
Weitere Informationen finden Sie hier.
2.5. Keystore in Jetty einbinden
ActiveMQ stellt eine Weboberfläche bereit, die einen Überblick
über bestimmte Statusinformationen, wie z.B. die gerade aktiven Topics, oder auch die aktuell angemeldeten
Publisher/Subscriber bietet. ActiveMQ liefert hierfür den Webserver Jetty von Apache mit aus.
Damit dieser über eine verschlüsselte HTTPS-Verbindung erreichbar ist, muss der zuvor erstellte Keystore
dort ebenfalls eingebunden werden. Hierzu gibt es in der <ACTIVEMQ_INST>/conf/jetty.xml bereits entsprechende,
aber noch auskommentierte Einträge, die, wie zuvor bereits im ActiveMQ entsprechend, um Pfad und Passwort
des Keystores erweitert werden müssen:
<!--
Enable this connector if you wish to use https with web console
-->
<bean id="SecureConnector" class="org.eclipse.jetty.server.ServerConnector">
<constructor-arg ref="Server" />
<constructor-arg>
<bean id="handlers" class="org.eclipse.jetty.util.ssl.SslContextFactory">
<property name="keyStorePath" value="/PATH/TO/amq_server.ks" />
<property name="keyStorePassword" value="GEHEIM" />
</bean>
</constructor-arg>
<property name="port" value="8162" />
</bean>
Mit der Vorgehensweise in Kapitel 1 ist nun eine
Server-seitige Authentizizierung sichergestellt. Außerdem wurde die Verschlüsselung für die Verbindung aktiviert.
Ein zusätzlicher Sicherheitsgewinn kann dadurch erreicht werden, dass sich der Client authentifizieren muss. Die Einrichtung
ist identisch zu der Vorgehensweise in Kapitel 1, nur dass in diesem Fall ein Privater Schlüssel
für den Client erzeugt wird, das entsprechende Zertifikat mit enthaltenem öffentlichen Schlüssel
nun aber auf Server-Seite eingebunden wird.
3.1. Keystore mit einem selbstsignierten privaten Schlüssel für Client erstellen
Zuerst erstellen wir einen Schlüsselbund (Keystore), der den privaten Schlüssel enthält:
Für die spätere Einbindung in ActiveMQ muss das nun exportierte Zertifikat, das momentan
im DER(binär)-Format vorliegt, in einen Keystore bzw. Truststore importiert werden:
3.3 Client-Authentifizierung
in ActiveMQ aktivieren, Truststore mit Zertifikat und öffentlichem Schlüssel einbinden
Im entsprechenden sslContext-Abschnitt der <ACTIVEMQ_INST>/conf/activemq.xml,
den wir in Kapitel 2.4.
bereits erzeugt hatten, wird nun noch der Truststore, der die entsprechenden Client-Zertifikate beinhaltet,
als weiterer Parameter angegeben:
Die Client-Authentifizierung wird nun im entsprechenden Connector über den zusätzlichen
URI-Parameter "needClientAuth=false" aktiviert, also für den Mqtt-Connector z.B. wie folgt:
3.4. Hinweis zur Verwendung eines offiziell signierten Zertifikates
Die oben genannten Punkte beschreiben die einfachste Vorgehensweise über ein selbsigniertes Zertifikat.
Der Vorteil dabei ist, dass man die Verbindung auf einfache Weise verschlüsseln kann. Da das Zertifikat
aber selbstsigniert ist, und eben nicht von einer offiziellen Zertifikatsstelle (CA Authority) signiert wurde
ist die Vertrauenskette (Chain of Trust) nicht gewährleistet. Das führt beispielsweise dazu,
dass im Webbrower beim Zugriff auf die ActiveMQ Webmin-Oberfläche ein Warnhinweis erscheint,
da der Ersteller nicht bekannt ist. Wenn offiziell signierte Zertifikate erstellt werden sollen, wäre die Vorgehensweise wie folgt:
Privaten Schlüssel erstellen
Daraus eine Zertifikatsanforderung generieren
Diese von einer offiziellen Zertifizierungsstelle signieren lassen
Die dann von der Zertifizierungsstelle zurückerhaltenen, signierten Zertifikate
liegen meist in unterschiedlichen Formaten vor. Am Einfachsten lassen sich die Zertifikate im
PEM-Format (im Klartext) einbinden, indem man die entsprechenden Dateien
mit einem Texteditor öffnet, den privaten Schlüssel, Zertifikate sowie Zwischenzertifikate
kopiert, und daraus eine neue Datei, die die komplette Kette enthält, generiert.
Gehen Sie dazu wie folgt vor:
Erstellen Sie eine neue Textdatei mit dem Namen "zertifikatskette.pem", in die per Copy & Paste
der private Schlüssel, sowie sämtliche Zertifikate inklusive BEGIN/END-Prolog eingetragen werden.
Der private Schlüssel (bspw. *.key):
-----BEGIN RSA PRIVATE KEY-----
...
Das Zertifikat (bspw. *.crt):
-----BEGIN CERTIFICATE-----
...
Eventuelle CA-Zwischenzertifikate (bspw. *.ca):
-----BEGIN CERTIFICATE-----
...
Anschließend wird diese pem-Datei über den folgenden Befehl nach pkcs12 konvertiert (OpenSSL muss installiert sein):
Die Einbindung in ActiveMQ bzw. Jetty funktioniert wie in
Kapitel 2.4. bzw.
2.5. beschrieben. Da der gerade erzeugte Keystore vom Typ PKCS12 ist,
muss lediglich noch ein weiterer Parameter, der den Typ des Keystores beschreibt, mitangegeben werden.
Die Benutzer, die sich an der Webmin-Oberfläche anmelden dürfen,
werden in der Datei <ACTIVEMQ_INST>/conf/jetty-realm.properties definiert.
4.2. Benutzerberechtigungen der Connectoren
Die einfachste Möglichkeit ist das direkte Setzen der Berechtigungen
in der activemq.xml mit dem "SimpleAuthenticationPlugin". Über einen entsprechenden
authentication-Eintrag fügt man einen neuen Benutzer, Passwort und Gruppenzugehörigkeit hinzu.
Über das authorizationPlugin können dann den Benutzern die Berechtigungen an den Topics/Queues
zugewiesen werden. Read- bzw. Write-Permissions dürften selbsterklärend sein. Die "admin"-Rolle
beschreibt in dem Zusammenhang die Rechte ein Topic zu erstellen.
ActiveMQ bietet die Möglichkeit, Informationen über die Topics über den ActiveMQ.Advisory-Zweig
zur Verfügung zu stellen, z.B. für das Generieren einer Message beim Verbindungsaufbau eines Clients im ActiveMQ.Advisory.Connection-Zweig.
Falls man die dort bereitsgestellten Informationen benötigt, benötigt der Client auch dort die notwendigen
Lese-/Schreibberechtigungen. Falls die entsprechenden Zweige nicht vorhanden sind, benötigt der Client
dann auch Admin-Berechtigungen um die Topics generieren zu können bzw. muss zuvor sichergestellt werden,
dass die benötigen Advisory topics vorhanden sind. Über den folgenden Eintrag im Broker-Namespace der activemq.xml
lassen sich die Advisory Messages aber auch deaktivieren:
4.3. Berechtigungen sicherstellen und Dienst neu starten
Der ActiveMQ-Server läuft unter dem restriktiven Benutzer-Account "activemq".
Deshalb muss nach den in Kapitel 2 und
3 vorgenommenen Änderungen sichergestellt werden,
dass Besitzer und Gruppenzugehörigkeit der geänderten Dateien noch stimmen.
Besitzer und Gruppenzugehörigkeit der Datei müssen beide "activemq" lauten.
Über folgenden Befehl lässt sich das kontrollieren:
Dasselbe gilt für die in Kapitel 2 erstellte Keystore-Datei.
Der Speicherpfad der Datei und Benutzer/Gruppe müssen entsprechend vom activemq-Benutzer gelesen werden können.
Korrigieren ließe sich das über den folgenden Befehl:
chown activemq.activemq <DATEINAME>
Danach muss der ActiveMQ-Dienst neu gestartet werden: