Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Just so that we don't store the docker image build output into the repository.
mvn-output/
mvn-output/
target/classes/**/*.class
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ sudo chown $USER:$USER mvn-output
# Deploy

* Copy target/event-listener-http-jar-with-dependencies.jar to {KEYCLOAK_HOME}/standalone/deployments

# Configuration

## Option 1
* Configure the following env variables :

- HTTP_EVENT_SERVERURI - default: http://127.0.0.1:8080/webhook
- HTTP_EVENT_USERNAME - default: keycloak
- HTTP_EVENT_PASSWORD - default: keycloak

* Restart the keycloak server.
## Option 2
* Edit standalone.xml to configure the Webhook settings. Find the following
section in the configuration:

Expand All @@ -50,17 +62,16 @@ And add below:
<property name="serverUri" value="http://127.0.0.1:8080/webhook"/>
<property name="username" value="auth_user"/>
<property name="password" value="auth_password"/>
<property name="topic" value="my_topic"/>
</properties>
</provider>
</spi>
```

Leave username and password out if the service allows anonymous access.
If unset, the default message topic is "keycloak/events".

* Restart the keycloak server.

# Use
# Usage
Add/Update a user, your webhook should be called, looks at the keycloak syslog for debug

Request example
Expand Down
87 changes: 5 additions & 82 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,24 +1,7 @@
<!--
~ Copyright 2019 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<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">
<groupId>org.softwarefactory.keycloak.providers.events.http</groupId>
<version>5.0.0</version>
<version>13.0.0</version>

<name>Keycloak: Event Publisher to HTTP</name>
<description/>
Expand All @@ -32,35 +15,16 @@
<version.keycloak>${project.version}</version.keycloak>

<version.wildfly.maven.plugin>1.2.2.Final</version.wildfly.maven.plugin>
<servlet.api.30.version>1.0.2.Final</servlet.api.30.version>
<jboss-jaxrs-api_2.1_spec>1.0.1.Final</jboss-jaxrs-api_2.1_spec>
<version.jboss.maven.plugin>7.4.Final</version.jboss.maven.plugin>
<version.war.maven.plugin>2.6</version.war.maven.plugin>
<version.enforcer.maven.plugin>1.4.1</version.enforcer.maven.plugin>
<version.surefire.plugin>2.19.1</version.surefire.plugin>
<version.exec.maven.plugin>1.6.0</version.exec.maven.plugin>
<version.antrun.maven.plugin>1.8</version.antrun.maven.plugin>
<version.frontend.maven.plugin>1.4</version.frontend.maven.plugin>
<version.resources.maven.plugin>3.0.2</version.resources.maven.plugin>
<version.compiler.maven.plugin>3.1</version.compiler.maven.plugin>

<arquillian-graphene.version>2.3.2</arquillian-graphene.version>
<arquillian-phantom.version>1.2.1.Final</arquillian-phantom.version>
<version.wildfly.arquillian.container>2.0.2.Final</version.wildfly.arquillian.container>
<version.remote.wildfly.arquillian.container>8.2.1.Final</version.remote.wildfly.arquillian.container>
<version.junit>4.12</version.junit>
<version.hamcrest>1.3</version.hamcrest>
<version.creaper>1.6.1</version.creaper>
<version.jackson>2.9.5</version.jackson>

<arquillian-managed>true</arquillian-managed>
<jboss-cli.executable>./jboss-cli.sh</jboss-cli.executable>
<keycloak.management.port>10090</keycloak.management.port>
<selenium-bom.version>3.11.0</selenium-bom.version>
<arquillian-bom.version>1.4.0.Final</arquillian-bom.version>
<arquillian-drone-bom.version>2.5.1</arquillian-drone-bom.version>
<version.json.javax>1.1.2</version.json.javax>
<version.yasson>1.0.1</version.yasson>
</properties>

<dependencies>
Expand All @@ -82,40 +46,10 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.protocol</groupId>
<artifactId>arquillian-protocol-servlet</artifactId>
<version>1.4.1.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.graphene</groupId>
<artifactId>graphene-webdriver</artifactId>
<version>${arquillian-graphene.version}</version>
<type>pom</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.extension</groupId>
<artifactId>arquillian-phantom-driver</artifactId>
<version>${arquillian-phantom.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wildfly.extras.creaper</groupId>
<artifactId>creaper-core</artifactId>
<version>${version.creaper}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
<version>${version.keycloak}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
Expand All @@ -137,17 +71,6 @@
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${version.surefire.plugin}</version>
<configuration>
<systemPropertyVariables>
<keycloakManagementPort>${keycloak.management.port}</keycloakManagementPort>
<buildDirectory>${project.build.directory}</buildDirectory>
</systemPropertyVariables>
</configuration>
</plugin>
<!-- Maven Assembly Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.softwarefactory.keycloak.providers.events.http;

import java.io.Serializable;

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)
@JsonTypeInfo(use = Id.CLASS)
public class AdminEventNotification extends AdminEvent implements Serializable {

private static final long serialVersionUID = -7367949289101799624L;

public static AdminEventNotification create(AdminEvent adminEvent) {
AdminEventNotification msg = new AdminEventNotification();
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.setTime(adminEvent.getTime());
return msg;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.softwarefactory.keycloak.providers.events.http;

import java.io.Serializable;

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)
@JsonTypeInfo(use = Id.CLASS)
public class ClientEventNotification extends Event implements Serializable {

private static final long serialVersionUID = -2192461924304841222L;

public static ClientEventNotification create(Event event) {
ClientEventNotification msg = new ClientEventNotification();
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;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright 2019 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.softwarefactory.keycloak.providers.events.http;


import org.keycloak.Config.Scope;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
* @author <a href="mailto:[email protected]">Abdoulaye Traore</a>
*/
public class HTTPEventConfiguration {

private String serverUri;
private String username;
private String password;

public static final ObjectMapper httpEventConfigurationObjectMapper = new ObjectMapper();

public static HTTPEventConfiguration createFromScope(Scope config) {
HTTPEventConfiguration configuration = new HTTPEventConfiguration();

configuration.serverUri = resolveConfigVar(config, "serverUri", "http://127.0.0.1:8080/webhook");
configuration.username = resolveConfigVar(config, "username", "keycloak");
configuration.password = resolveConfigVar(config, "password", "keycloak");

return configuration;

}

private static String resolveConfigVar(Scope config, String variableName, String defaultValue) {

String value = defaultValue;
if(config != null && config.get(variableName) != null) {
value = config.get(variableName);
} else {
//try from env variables eg: HTTP_EVENT_:
String envVariableName = "HTTP_EVENT_" + variableName.toUpperCase();
if(System.getenv(envVariableName) != null) {
value = System.getenv(envVariableName);
}
}
System.out.println("HTTPEventListener configuration: " + variableName + "=" + value);
return value;

}

public static String writeAsJson(Object object, boolean isPretty) {
String messageAsJson = "unparsable";
try {
if(isPretty) {
messageAsJson = HTTPEventConfiguration.httpEventConfigurationObjectMapper
.writerWithDefaultPrettyPrinter().writeValueAsString(object);
} else {
messageAsJson = HTTPEventConfiguration.httpEventConfigurationObjectMapper
.writeValueAsString(object);
}

} catch (JsonProcessingException e) {
e.printStackTrace();
}
return messageAsJson;
}



public String getServerUri() {
return serverUri;
}
public void setServerUri(String serverUri) {
this.serverUri = serverUri;
}

public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}


}
Loading