Skip to content

Commit

Permalink
Persistence-related fixes and improvements
Browse files Browse the repository at this point in the history
Add a configuration option to use message persistence. The default is to
not use persistence; if set to "true" in-memory persistence will be
used.
Fix the client using the default file persistence for admin messages,
resulting in errors in deployments where temporary files could not be
opened - typically in containers.
Document deployment steps for quarkus-based versions of Keycloak.

Change-Id: I8430b4b9c8aad536a6f53090a1a14aea7fad5546
  • Loading branch information
mhuin committed Sep 9, 2022
1 parent 894a411 commit b96a118
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 6 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

A Keycloak SPI that publishes events to a MQTT broker.

This SPI has been deployed successfully on a containerized Keycloak 15.0.2
and on a Keycloak 19.0 server on a kubernetes cluster. It should therefore
work properly on any version of Keycloak above 15.0.2.

# Build

```
Expand All @@ -10,6 +14,8 @@ mvn clean install

# Deploy

## Keycloak on Wildfly

* Copy target/event-listener-mqtt-jar-with-dependencies.jar to {KEYCLOAK_HOME}/standalone/deployments
* Edit standalone.xml to configure the MQTT service settings. Find the following
section in the configuration:
Expand All @@ -29,11 +35,27 @@ And add below:
<property name="username" value="mqtt_user"/>
<property name="password" value="mqtt_password"/>
<property name="topic" value="my_topic"/>
<property name="usePersistence" value="true">
</properties>
</provider>
</spi>
```
Leave username and password out if the service allows anonymous write access.
If unset, the default message topic is "keycloak/events".
By default, the SPI won't use persistence. If set to true, messages will be persisted in memory.

* Restart the keycloak server.

## Keycloak on Quarkus

* Copy the jar archive to /opt/keycloak/providers/ in the keycloak container.
* run keycloak with the following options:

```
kc.sh start
--spi-events-listener-mqtt-server-uri "tcp://your.mqtt.server:port" \
--spi-events-listener-mqtt-username mqtt_user \
--spi-events-listener-mqtt-password mqtt_password \
--spi-events-listener-mqtt-topic my_topic
--spi-events-listener-mqtt-user-persistence true
```
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,16 @@ public class MQTTEventListenerProvider implements EventListenerProvider {
private String password;
public static final String publisherId = "keycloak";
public String TOPIC;
public boolean usePersistence;

public MQTTEventListenerProvider(Set<EventType> excludedEvents, Set<OperationType> excludedAdminOperations, String serverUri, String username, String password, String topic) {
public MQTTEventListenerProvider(Set<EventType> excludedEvents, Set<OperationType> excludedAdminOperations, String serverUri, String username, String password, String topic, boolean usePersistence) {
this.excludedEvents = excludedEvents;
this.excludedAdminOperations = excludedAdminOperations;
this.serverUri = serverUri;
this.username = username;
this.password = password;
this.TOPIC = topic;
this.usePersistence = usePersistence;
}

@Override
Expand All @@ -65,7 +67,10 @@ public void onEvent(Event event) {
} else {
String stringEvent = toString(event);
try {
MemoryPersistence persistence = new MemoryPersistence();
MemoryPersistence persistence = null;
if (this.usePersistence == true) {
persistence = new MemoryPersistence();
}
MqttClient client = new MqttClient(this.serverUri ,publisherId, persistence);
MqttConnectOptions options = new MqttConnectOptions();
options.setAutomaticReconnect(true);
Expand All @@ -84,7 +89,7 @@ public void onEvent(Event event) {
client.disconnect();
} catch(Exception e) {
// ?
System.out.println("UH OH!! " + e.toString());
System.out.println("Caught the following error: " + e.toString());
e.printStackTrace();
return;
}
Expand All @@ -99,7 +104,11 @@ public void onEvent(AdminEvent event, boolean includeRepresentation) {
} else {
String stringEvent = toString(event);
try {
MqttClient client = new MqttClient(this.serverUri ,publisherId);
MemoryPersistence persistence = null;
if (this.usePersistence == true) {
persistence = new MemoryPersistence();
}
MqttClient client = new MqttClient(this.serverUri ,publisherId, persistence);
MqttConnectOptions options = new MqttConnectOptions();
options.setAutomaticReconnect(true);
options.setCleanSession(true);
Expand All @@ -117,7 +126,7 @@ public void onEvent(AdminEvent event, boolean includeRepresentation) {
client.disconnect();
} catch(Exception e) {
// ?
System.out.println("UH OH!! " + e.toString());
System.out.println("Caught the following error: " + e.toString());
e.printStackTrace();
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ public class MQTTEventListenerProviderFactory implements EventListenerProviderFa
private String username;
private String password;
private String topic;
private boolean usePersistence;

@Override
public EventListenerProvider create(KeycloakSession session) {
return new MQTTEventListenerProvider(excludedEvents, excludedAdminOperations, serverUri, username, password, topic);
return new MQTTEventListenerProvider(excludedEvents, excludedAdminOperations, serverUri, username, password, topic, usePersistence);
}

@Override
Expand All @@ -68,6 +69,7 @@ public void init(Config.Scope config) {
username = config.get("username", null);
password = config.get("password", null);
topic = config.get("topic", "keycloak/events");
usePersistence = config.getBoolean("usePersistence", false);
}

@Override
Expand Down

0 comments on commit b96a118

Please sign in to comment.