-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented minimum of functionality
- Loading branch information
Showing
11 changed files
with
568 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
*.class | ||
|
||
# Package Files # | ||
*.jar | ||
*.war | ||
*.ear | ||
target/ | ||
.settings/ | ||
.project | ||
.classpath |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,82 @@ | ||
# keycloak-event-listener-rabbitmq | ||
|
||
##### A Keycloak SPI plugin that publishes events to a RabbitMq server. | ||
|
||
For example here is the notification of the user updated by administrator | ||
|
||
* routing key: `KK.EVENT.ADMIN.MYREALM.SUCCESS.USER.UPDATE` | ||
* published to exchange: `amq.topic` | ||
* content: | ||
|
||
|
||
``` | ||
{ | ||
"@class" : "com.github.aznamier.keycloak.event.provider.EventAdminNotificationMqMsg", | ||
"time" : 1596951200408, | ||
"realmId" : "MYREALM", | ||
"authDetails" : { | ||
"realmId" : "master", | ||
"clientId" : "********-****-****-****-**********", | ||
"userId" : "********-****-****-****-**********", | ||
"ipAddress" : "192.168.1.1" | ||
}, | ||
"resourceType" : "USER", | ||
"operationType" : "UPDATE", | ||
"resourcePath" : "users/********-****-****-****-**********", | ||
"representation" : "representation details here....", | ||
"error" : null, | ||
"resourceTypeAsString" : "USER" | ||
} | ||
``` | ||
|
||
The routing key is calculated as follows: | ||
* admin events: `KK.EVENT.ADMIN.<REALM>.<RESULT>.<RESOURCE_TYPE>.<OPERATION>` | ||
* client events: `KK.EVENT.CLIENT.<REALM>.<RESULT>.<CLIENT>.<EVENT_TYPE>` | ||
|
||
And because the recommended exchange is a **TOPIC (amq.topic)**, | ||
therefore its easy for Rabbit client to subscribe to selective combinations eg: | ||
* all events: `KK.EVENT.#` | ||
* all events from my realm: `KK.EVENT.*.MYREALM.#` | ||
* all error events from my realm: `KK.EVENT.*.MYREALM.ERROR.#` | ||
* all user events from my-relam and my-client: `KK.EVENT.*.MY-REALM.*.MY-CLIENT.USER` | ||
|
||
## USAGE: | ||
1. [Download the latest jar](https://github.com/aznamier/keycloak-event-listener-rabbitmq/blob/target/keycloak-to-rabbit-1.0.jar?raw=true) or build from source: ``mvn clean install`` | ||
2. copy jar into your Keycloak `/opt/jboss/keycloak/standalone/deployments/keycloak-to-rabbit-1.0.jar` | ||
3. Configure as described below (option 0 or 1 or 2) | ||
4. Restart the Keycloak server | ||
5. Enable logging in Keycloak UI by adding **keycloak-to-rabbitmq** | ||
`Manage > Events > Config > Events Config > Event Listeners` | ||
|
||
#### Configuration | ||
###### OPTION 1: just configure **ENVIRONMENT VARIABLES** | ||
- `KK_TO_RMQ_URL` - default: *localhost* | ||
- `KK_TO_RMQ_PORT` - default: *5672* | ||
- `KK_TO_RMQ_VHOST` - default: *empty* | ||
- `KK_TO_RMQ_EXCHANGE` - default: *amq.topic* | ||
- `KK_TO_RMQ_USERNAME` - default: *guest* | ||
- `KK_TO_RMQ_PASSWORD` - default: *guest* | ||
|
||
###### OPTION 2: edit Keycloak subsystem of WildFly standalone.xml or standalone-ha.xml: | ||
|
||
```xml | ||
<spi name="eventsListener"> | ||
<provider name="mqtt" enabled="true"> | ||
<properties> | ||
<property name="url" value="${env.KK_TO_RMQ_URL:localhost}"/> | ||
<property name="port" value="${env.KK_TO_RMQ_PORT:5672}"/> | ||
<property name="vhost" value="${env.KK_TO_RMQ_VHOST:}"/> | ||
<property name="exchange" value="${env.KK_TO_RMQ_EXCHANGE:amq.topic}"/> | ||
|
||
<property name="username" value="${env.KK_TO_RMQ_USERNAME:guest}"/> | ||
<property name="password" value="${env.KK_TO_RMQ_PASSWORD:guest}"/> | ||
</properties> | ||
</provider> | ||
</spi> | ||
``` | ||
###### OPTION 3: same effect as OPTION 2 but programatically: | ||
``` | ||
echo "yes" | $KEYCLOAK_HOME/bin/jboss-cli.sh --file=$KEYCLOAK_HOME/KEYCLOAK_TO_RABBIT.cli | ||
``` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<groupId>com.github.aznamier.keycloak.event.provider</groupId> | ||
<artifactId>keycloak-to-rabbit</artifactId> | ||
<packaging>jar</packaging> | ||
<version>1.0-RC-SNAPSHOT-${maven.build.timestamp}</version> | ||
|
||
|
||
|
||
<name>Keycloak: Event Publisher to RabbitMQ</name> | ||
<properties> | ||
<keycloak.version>11.0.0</keycloak.version> | ||
<jar.finalName>${project.artifactId}-${project.version}</jar.finalName> | ||
</properties> | ||
|
||
<distributionManagement> | ||
<repository> | ||
<id>github</id> | ||
<name>GitHub AZNAMIER Apache Maven Packages</name> | ||
<url>https://maven.pkg.github.com/aznamier/keycloak-event-listener-rabbitmq</url> | ||
</repository> | ||
</distributionManagement> | ||
|
||
|
||
|
||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.keycloak</groupId> | ||
<artifactId>keycloak-core</artifactId> | ||
<scope>provided</scope> | ||
<version>${keycloak.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.keycloak</groupId> | ||
<artifactId>keycloak-server-spi</artifactId> | ||
<scope>provided</scope> | ||
<version>${keycloak.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.keycloak</groupId> | ||
<artifactId>keycloak-server-spi-private</artifactId> | ||
<scope>provided</scope> | ||
<version>${keycloak.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.keycloak</groupId> | ||
<artifactId>keycloak-services</artifactId> | ||
<scope>provided</scope> | ||
<version>${keycloak.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.keycloak</groupId> | ||
<artifactId>keycloak-saml-core-public</artifactId> | ||
<scope>provided</scope> | ||
<version>${keycloak.version}</version> | ||
</dependency> | ||
|
||
<!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client --> | ||
<dependency> | ||
<groupId>com.rabbitmq</groupId> | ||
<artifactId>amqp-client</artifactId> | ||
<version>5.9.0</version> | ||
</dependency> | ||
|
||
</dependencies> | ||
|
||
<build> | ||
<finalName>keycloak-to-rabbit</finalName> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<configuration> | ||
<source>1.8</source> | ||
<target>1.8</target> | ||
</configuration> | ||
</plugin> | ||
|
||
<!-- Maven Assembly Plugin --> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-assembly-plugin</artifactId> | ||
<configuration> | ||
<finalName>${jar.finalName}</finalName> | ||
<descriptorRefs> | ||
<descriptorRef>jar-with-dependencies</descriptorRef> | ||
</descriptorRefs> | ||
<appendAssemblyId>false</appendAssemblyId> | ||
</configuration> | ||
<executions> | ||
<execution> | ||
<id>make-assembly</id> | ||
<phase>package</phase> | ||
<goals> | ||
<goal>single</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
|
||
<plugin> | ||
<groupId>org.wildfly.plugins</groupId> | ||
<artifactId>wildfly-maven-plugin</artifactId> | ||
<configuration> | ||
<skip>false</skip> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
35 changes: 35 additions & 0 deletions
35
src/main/java/com/github/aznamier/keycloak/event/provider/EventAdminNotificationMqMsg.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.github.aznamier.keycloak.event.provider; | ||
|
||
import java.io.Serializable; | ||
|
||
import javax.xml.bind.annotation.XmlRootElement; | ||
|
||
import org.keycloak.events.admin.AdminEvent; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import com.fasterxml.jackson.annotation.JsonTypeInfo; | ||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
@XmlRootElement | ||
@JsonTypeInfo(use = Id.CLASS) | ||
public class EventAdminNotificationMqMsg extends AdminEvent implements Serializable { | ||
|
||
private static final long serialVersionUID = -7367949289101799624L; | ||
|
||
public static EventAdminNotificationMqMsg create(AdminEvent adminEvent) { | ||
EventAdminNotificationMqMsg msg = new EventAdminNotificationMqMsg(); | ||
msg.setAuthDetails(adminEvent.getAuthDetails()); | ||
msg.setError(adminEvent.getError()); | ||
msg.setOperationType(adminEvent.getOperationType()); | ||
msg.setRealmId(adminEvent.getRealmId()); | ||
msg.setRepresentation(adminEvent.getRepresentation()); | ||
msg.setResourcePath(adminEvent.getResourcePath()); | ||
msg.setResourceType(adminEvent.getResourceType()); | ||
msg.setResourceTypeAsString(adminEvent.getResourceTypeAsString()); | ||
msg.setTime(adminEvent.getTime()); | ||
return msg; | ||
} | ||
|
||
|
||
} |
36 changes: 36 additions & 0 deletions
36
src/main/java/com/github/aznamier/keycloak/event/provider/EventClientNotificationMqMsg.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.github.aznamier.keycloak.event.provider; | ||
|
||
import java.io.Serializable; | ||
|
||
import javax.xml.bind.annotation.XmlRootElement; | ||
|
||
import org.keycloak.events.Event; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import com.fasterxml.jackson.annotation.JsonTypeInfo; | ||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; | ||
|
||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
@XmlRootElement | ||
@JsonTypeInfo(use = Id.CLASS) | ||
public class EventClientNotificationMqMsg extends Event implements Serializable { | ||
|
||
private static final long serialVersionUID = -2192461924304841222L; | ||
|
||
public static EventClientNotificationMqMsg create(Event event) { | ||
EventClientNotificationMqMsg msg = new EventClientNotificationMqMsg(); | ||
msg.setClientId(event.getClientId()); | ||
msg.setDetails(event.getDetails()); | ||
msg.setError(event.getError()); | ||
msg.setIpAddress(event.getIpAddress()); | ||
msg.setRealmId(event.getRealmId()); | ||
msg.setSessionId(event.getSessionId()); | ||
msg.setTime(event.getTime()); | ||
msg.setType(event.getType()); | ||
msg.setUserId(event.getUserId()); | ||
|
||
return msg; | ||
} | ||
|
||
|
||
} |
Oops, something went wrong.