Apaches ActiveMQ wird häufig für Integrationslösungen verwendet. Sie entkoppelt Prozesse und verbindet Komponenten. Gerade wenn unterschiedlichste Komponenten über eine zentrale Stelle miteinander kommunizieren ist jedoch Vorsicht geboten. Aus Sicherheitsgründen kann es erforderlich sein, dass Queues gegenüber bestimmten Komponenten abgesichert sind. ActiveMQ bietet hierfür einfach bis komplexe Lösungen an, auf die ich in diesem Beitrag eingehen möchte.
Authentifizierung
Wie so oft müssen wir zwischen Authentifizierung und Autorisierung unterscheiden. Das simpleAuthenticationPlugin beispielsweise bietet eine einfache Lösung um Benutzer zu Authentifizieren. Dabei wird geprüft ob ein Benutzer auch der ist, als der er sich ausgibt. Dies geschieht durch ein Passwort. Das simpleAuthenticationPlugin wird in die Liste der Plugins des jeweiligen Brokers geschrieben. Bei der Standardinstallation von ActiveMQ gibt es nur einen Broker. Dieser ist in activemq.xml deklariert. Es können aber auch andere Broker in den Spring-Context geladen worden sein.
<broker> ... <plugins> <simpleAuthenticationPlugin anonymousAccessAllowed="true"> <users> <authenticationUser username="admin" password="admin" groups="users,admins"/> <authenticationUser username="user" password="password" groups="users"/> </users> </simpleAuthenticationPlugin> </plugins> </broker>
Für jeden Benutzer muss das Passwort und dessen Gruppe angegeben werden. Gruppen ergeben sich dynamisch und müssen nicht explizit erstellt werden.
Durch das Attribut anonymousAccessAllowed
kann bestimmt werden ob anonyme Benutzer ohne Passwort Zugriff auf den Broker haben. Anonyme Benutzer sind der Gruppe anonymous
zugeteilt.
JAAS Plugin
Neben dem simpleAuthenticationPlugin
werden weitere Plugins wie das jaasAuthenticationPlugin
angeboten. Der Java Authentication and Authorization Service (JAAS) unterstützt dabei weitaus komplexere Konfigurationsmöglichkeiten.
<broker> ... <plugins> <jaasAuthenticationPlugin configuration="activemq" /> </plugins>
Der Parameter configuration
gibt dabei den Namen der zu Verwendenden Konfiguration an, welche sich in der login.config befindet.
Eine einfache Benutzername-Passwort-Authentifizierung ist beispielsweise durch das PropertiesLoginModule
möglich.
activemq { org.apache.activemq.jaas.PropertiesLoginModule required debug=true org.apache.activemq.jaas.properties.user="org/apache/activemq/security/users.properties" org.apache.activemq.jaas.properties.group="org/apache/activemq/security/groups.properties"; };
In diesem Beispiel wird auf die Property-Dateien users.properties und groups.properties verwiesen.
Die users.properties ist eine simple Key-Value-Map für Benutzername und Passwort
admin=admin
user=password
In der groups.properties werden wiederum die Benutzer in Gruppen zugeordnet. Mit diesen Gruppen ist es dann möglich Rechte für Queues zu vergeben, wie wir gleich sehen werden.
admins=admin
users=user
Autorisierung
Die Autorisierung erfolgt ebenfalls über ein Broker-Plugin. Das authorizationPlugin arbeitet mit drei Berechtigungsleveln. read, write und admin.
read | Erlaubt das Lesen von Queues. Lesen ist dabei gleichzusetzen mit dem Löschen einer Nachricht. Explizites Löschen gibt es nicht als Berechtigung. |
write | Erlaubt es Nachrichten in eine Queue zu schreiben. Diese Aktion ist nur für existierende Queues möglich. |
admin | Erlaubt es neue Queues anzulegen. |
<broker> ... <plugins> <authorizationPlugin> <map> <authorizationMap> <authorizationEntries> <authorizationEntry queue=">" read="admins" write="admins" admin="admins"/> <authorizationEntry topic=">" read="admins" write="admins" admin="admins"/> <authorizationEntry queue="USERS.>" read="users" write="users" admin="users"/> <authorizationEntry topic="ActiveMQ.Advisory.>" read="users" write="users" admin="users"/> </authorizationEntries> <tempDestinationAuthorizationEntry> <tempDestinationAuthorizationEntry read="admins" write="admins" admin="admins"/> </tempDestinationAuthorizationEntry> </authorizationMap> </map> </authorizationPlugin> </plugins> </broker>
In der hier gezeigten Konfiguration wird der Gruppe admins das Recht auf alle Queues und Topics gegeben. Das Wildcard >
sagt dabei aus, dass das Recht für alle Pfade nach dem >
gilt. Möchte man nur Berechtigungen bis zum nächsten Punkt .
einräumen, so benutzt man das Wildcard *
.
Der Gruppe users werden Rechte eingeräumt für Queues die mit USERS.
beginnen. Wichtig dabei. Auch admins haben ebenfalls auf USERS.
Zugriff, da >
diese mit einschließt. Einmal vergebene Rechte können für einen präziseren Pfad später nicht mehr entfernt werden.
Fast alle Aktionen müssen im Audit-Log ActiveMQ.Advisory.>
hinterlegt werden. Es ist daher sinnvoll jeder Gruppe Schreibrechte darauf einzuräumen. Eine granularere Beschreibung findet sich hier.
Der Tag tempDestinationAuthorizationEntry
spezifiziert welche Gruppen temporäre Queues anlegen dürfen.
Verschlüsselung
Die Verschlüsselung erfolgt über den EncryptablePropertyPlaceholderConfigurer
. Dieser ersetzt den PropertyPlaceholderConfigurer
, welche für das laden von einfachen Properties verantwortlich ist. Diese Bean befindet sich für gewöhnlich in der activemq.xml.
<bean id="environmentVariablesConfiguration" class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig"> <property name="algorithm" value="PBEWithMD5AndDES" /> <property name="passwordEnvName" value="ACTIVEMQ\_ENCRYPTION\_PASSWORD" /> </bean> <bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor"> <property name="config" ref="environmentVariablesConfiguration" /> </bean> <bean id="propertyConfigurer" class="org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer"> <constructor-arg ref="configurationEncryptor" /> <property name="location" value="file:${activemq.base}/conf/credentials-enc.properties"/> </bean>
In diesem Beispiel wird anstelle der credentials.properties die credentials-enc.properties geladen. Beide Dateien können die gleichen Inhalte besitzen. Verschlüsselte Passwörter werden jedoch mit ENC(…) deklariert.
myValue=ENC(abcdefghijk)
Alle Passwörter müssen mit einem Passwort verschlüsselt werden. In dem oberen Beispiel wird dies in der Environment-Variable ACTIVEMQ_ENCRYPTION_PASSWORD
hinterlegt. Wenn anstelle des Properties passwordEnvName
einfach password
verwendet wird, kann auch direkt in der XML-Datei das Passwort hinterlegt werden.
Um ein Passwort zu verschlüsseln kann die Binary der ActiveMQ verwendet werden.
bin/activemq encrypt --MyEncryptionPassword activemq --input mypassword
Die verschlüsselten Properties können dann ganz einfach anstelle der Passwörter im simpleAuthenticationPlugin verwendet werden.
<authenticationUser username="system" password="${myValue}" groups="users,admins"/>
Webconsole
Die Webconsole stellt ein Interface bereit, mit dem Queues über den Browser verwaltet werden können.
Die Passwörter für das Login der Webconsole werden in der Datei jetty-realm.properties in der Form Benutzername: Passwort, Role gespeichert.
admin: admin, admin
Wichtig dabei ist, dass das Login in die Webconsole nichts mit dem Passwort für den Broker zu tun hat. Die Webconsole muss sich jedoch ebenfalls bei dem Broker anmelden. Dies geschieht über die Properties activemq.username
und activemq.password
in der credentials.properties.
Auch für den Login der Webconsole können die Properties verschlüsselt werden. Hierzu muss der oben bereits beschriebene EncryptablePropertyPlaceholderConfigurer
in der Datei webapps/admin/WEB-INF/webconsole-embeded.xml ebenfalls hinterlegt werden.