From 8c02ffa689e50b68f2a42027baf92ce31512d675 Mon Sep 17 00:00:00 2001 From: Francis PEROT Date: Thu, 10 Apr 2025 10:37:44 +0200 Subject: [PATCH] [CLOUDTRUST-5584] Migrate to Keycloak 26 --- README.md | 46 +-- keycloak-event-emitter-tests/pom.xml | 11 +- .../flatbuffers/events/EventTypeTest.java | 23 -- .../flatbuffers/events/OperationTypeTest.java | 22 -- .../flatbuffers/events/ResourceTypeTest.java | 22 -- .../java/flatbuffers/events/TypesTest.java | 53 ++++ .../{ => eventemitter}/AbstractTest.java | 9 +- .../EventEmitterProviderTest.java | 267 ---------------- .../eventemitter/MessageGenerationItTest.java | 111 ------- .../eventemitter/SerializationUtilsTest.java | 85 ++--- .../KafkaEventEmitterProviderTest.java | 8 +- .../{ => eventemitter}/pages/LogoutPage.java | 2 +- .../snowflake/IdGeneratorTest.java | 5 +- .../SerializationUtilsTest.java | 287 ----------------- .../src/test/resources/keycloak.properties | 9 - keycloak-event-emitter/module.conf | 10 - keycloak-event-emitter/pom.xml | 4 +- .../src/main/flatbuffers/event.fbs | 18 ++ .../flatbuffers/events/EventType.java | 18 +- .../flatbuffers/events/ResourceType.java | 58 ++-- .../java/flatbuffers/events/AdminEvent.java | 12 +- .../main/java/flatbuffers/events/Event.java | 8 +- .../java/flatbuffers/events/EventType.java | 18 +- .../java/flatbuffers/events/ResourceType.java | 58 ++-- .../keycloak/eventemitter/Container.java | 23 -- .../eventemitter/EventEmitterException.java | 12 - .../eventemitter/EventEmitterProvider.java | 290 ------------------ .../EventEmitterProviderFactory.java | 173 ----------- .../eventemitter/SerialisationFormat.java | 9 - ...tionUtils.java => SerializationUtils.java} | 17 +- .../customevent/ExtendedAdminEvent.java | 2 +- .../customevent/ExtendedAuthDetails.java | 2 +- .../customevent/IdentifiedAdminEvent.java | 2 +- .../customevent/IdentifiedEvent.java | 2 +- .../KafkaEventEmitterProvider.java | 25 +- .../KafkaEventEmitterProviderFactory.java | 13 +- .../kafkaemitter}/KafkaEventEmitterState.java | 2 +- .../snowflake/IdGenerator.java | 57 ++-- .../snowflake/IdGeneratorConfig.java | 2 +- .../snowflake/InvalidSystemClock.java | 2 +- .../kafkaeventemitter/SerialisationUtils.java | 251 --------------- ...ycloak.events.EventListenerProviderFactory | 3 +- pom.xml | 4 +- 43 files changed, 278 insertions(+), 1777 deletions(-) delete mode 100644 keycloak-event-emitter-tests/src/test/java/flatbuffers/events/EventTypeTest.java delete mode 100644 keycloak-event-emitter-tests/src/test/java/flatbuffers/events/OperationTypeTest.java delete mode 100644 keycloak-event-emitter-tests/src/test/java/flatbuffers/events/ResourceTypeTest.java create mode 100644 keycloak-event-emitter-tests/src/test/java/flatbuffers/events/TypesTest.java rename keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/{ => eventemitter}/AbstractTest.java (94%) delete mode 100644 keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProviderTest.java delete mode 100644 keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/MessageGenerationItTest.java rename keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/{kafkaeventemitter => eventemitter/kafkaemitter}/KafkaEventEmitterProviderTest.java (96%) rename keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/{ => eventemitter}/pages/LogoutPage.java (91%) rename keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/{ => eventemitter}/snowflake/IdGeneratorTest.java (93%) delete mode 100644 keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/kafkaeventemitter/SerializationUtilsTest.java delete mode 100644 keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/Container.java delete mode 100644 keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterException.java delete mode 100644 keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProvider.java delete mode 100644 keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProviderFactory.java delete mode 100644 keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerialisationFormat.java rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/{SerialisationUtils.java => SerializationUtils.java} (94%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{ => eventemitter}/customevent/ExtendedAdminEvent.java (95%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{ => eventemitter}/customevent/ExtendedAuthDetails.java (92%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{ => eventemitter}/customevent/IdentifiedAdminEvent.java (95%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{ => eventemitter}/customevent/IdentifiedEvent.java (94%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{kafkaeventemitter => eventemitter/kafkaemitter}/KafkaEventEmitterProvider.java (89%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{kafkaeventemitter => eventemitter/kafkaemitter}/KafkaEventEmitterProviderFactory.java (94%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{kafkaeventemitter => eventemitter/kafkaemitter}/KafkaEventEmitterState.java (93%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{ => eventemitter}/snowflake/IdGenerator.java (60%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{ => eventemitter}/snowflake/IdGeneratorConfig.java (94%) rename keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/{ => eventemitter}/snowflake/InvalidSystemClock.java (81%) delete mode 100644 keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/SerialisationUtils.java diff --git a/README.md b/README.md index 41c65ca..9d1c77d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The aim of this module is to send those Events and AdminEvents to another server ## Compilation -Java 8 is required (Java 9+ is not supported yet). +Java 21 is required. ### Build and Tests This project 2 modules, one with the event emitter code (could contain unit tests) and one for integration tests using a parent inherited from Keycloak tests for simplifying the @@ -15,13 +15,6 @@ POM content. The integration tests rely on the arquillian-based Keycloak test framework. As Keycloak does not publish publicly the related jars for testing, one needs to manually build them so that they are available for maven for testing. -For building these tests-jars, you need to: -* clone the official Keycloak repository (https://github.com/keycloak/keycloak) -* checkout the tag of the Keycloak version related to the version of the event-emitter module -* execute `mvn clean install -DskipTests` in the Keycloak repository to build the jars and put them in your maven repository - -Once these test-jars are built, the event-emitter module can be built. - ### Binary The build produces the JAR of the module, along with a TAR.GZ file that contains the dependencies to be installed with the module. @@ -40,43 +33,6 @@ tar -zxf keycloak-event-emitter--dist.tar.gz --directory /modules/system/layers/event-emitter ``` -For enabling the newly created layer, edit __layers.conf__: -```Bash -layers=keycloak,event-emitter -``` - - -## Enable & Configure - -In __standalone.xml__, add the new module and configure it - -```xml - - - auth - - - module:io.cloudtrust.keycloak.eventemitter - - - - - - - - - - - - - - - - - - - -``` Configuration parameters: * format: JSON or FLATBUFFER diff --git a/keycloak-event-emitter-tests/pom.xml b/keycloak-event-emitter-tests/pom.xml index 6fdb406..d33610e 100644 --- a/keycloak-event-emitter-tests/pom.xml +++ b/keycloak-event-emitter-tests/pom.xml @@ -5,16 +5,16 @@ io.cloudtrust kc-cloudtrust-testsuite - 20.0.0 + 26.0.0-SNAPSHOT keycloak-event-emitter-tests - 20.1.1-SNAPSHOT + 26.0.0-SNAPSHOT 3.4.1 - 2.9.0 + 2.12.1 ${java.version} @@ -60,11 +60,6 @@ system-lambda test - - com.google.code.gson - gson - ${gson.version} - org.mockito mockito-core diff --git a/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/EventTypeTest.java b/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/EventTypeTest.java deleted file mode 100644 index 40e7490..0000000 --- a/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/EventTypeTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package flatbuffers.events; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.keycloak.events.EventType; - -public class EventTypeTest { - - /** - * This test checks that the list of EventType defined in flatbuffers matches the list defined by the current - * Keycloak version. If it is not the case, it means that the file events.fbs needs to be updated according - * to the new EventType file defined in the root GitHub repository of the correct version. - */ - @Test - void testEventTypesAreUpToDate() { - EventType[] updatedEventTypes = EventType.values(); - String[] flatbufferEventTypes = flatbuffers.events.EventType.names; - - for (int i = 0; i < updatedEventTypes.length; i++) { - Assertions.assertEquals(updatedEventTypes[i].name(), flatbufferEventTypes[i]); - } - } -} diff --git a/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/OperationTypeTest.java b/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/OperationTypeTest.java deleted file mode 100644 index 0cb2538..0000000 --- a/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/OperationTypeTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package flatbuffers.events; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.keycloak.events.admin.OperationType; - -public class OperationTypeTest { - /** - * This test checks that the list of OperationType defined in flatbuffers matches the list defined by the current - * Keycloak version. If it is not the case, it means that the file events.fbs needs to be updated according - * to the new OperationType file defined in the root GitHub repository of the correct version. - */ - @Test - void testOperationTypesAreUpToDate() { - OperationType[] updatedOperationTypes = OperationType.values(); - String[] flatbufferOperationTypes = flatbuffers.events.OperationType.names; - - for (int i = 0; i < updatedOperationTypes.length; i++) { - Assertions.assertEquals(updatedOperationTypes[i].name(), flatbufferOperationTypes[i]); - } - } -} diff --git a/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/ResourceTypeTest.java b/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/ResourceTypeTest.java deleted file mode 100644 index af9a091..0000000 --- a/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/ResourceTypeTest.java +++ /dev/null @@ -1,22 +0,0 @@ -package flatbuffers.events; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.keycloak.events.admin.ResourceType; - -public class ResourceTypeTest { - /** - * This test checks that the list of ResourceType defined in flatbuffers matches the list defined by the current - * Keycloak version. If it is not the case, it means that the file events.fbs needs to be updated according - * to the new ResourceType file defined in the root GitHub repository of the correct version. - */ - @Test - void testResourceTypesAreUpToDate() { - ResourceType[] updatedResourceTypes = ResourceType.values(); - String[] flatbufferResourceTypes = flatbuffers.events.ResourceType.names; - - for (int i = 0; i < updatedResourceTypes.length; i++) { - Assertions.assertEquals(updatedResourceTypes[i].name(), flatbufferResourceTypes[i]); - } - } -} diff --git a/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/TypesTest.java b/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/TypesTest.java new file mode 100644 index 0000000..ace55e2 --- /dev/null +++ b/keycloak-event-emitter-tests/src/test/java/flatbuffers/events/TypesTest.java @@ -0,0 +1,53 @@ +package flatbuffers.events; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.keycloak.events.EventType; +import org.keycloak.events.admin.OperationType; +import org.keycloak.events.admin.ResourceType; + +import java.util.Arrays; +import java.util.List; + +public class TypesTest { + protected > void validateNames(Class enumClass, String[] flatbufferTypes) { + List enumNames = Arrays.stream(enumClass.getEnumConstants()).map(Enum::name).toList(); + int flatLen = flatbufferTypes.length - ("UNKNOWN".equals(flatbufferTypes[flatbufferTypes.length-1]) ? 1 : 0); + for(int i=0; i"; + String valueFlatb = i"; + Assertions.assertEquals(valueEnum, valueFlatb); + } + Assertions.assertEquals(enumNames.size(), flatLen); + } + + /** + * This test checks that the list of EventType defined in flatbuffers matches the list defined by the current + * Keycloak version. If it is not the case, it means that the file events.fbs needs to be updated according + * to the new EventType file defined in the root GitHub repository of the correct version. + */ + @Test + void testEventTypesAreUpToDate() { + validateNames(EventType.class, flatbuffers.events.EventType.names); + } + + /** + * This test checks that the list of OperationType defined in flatbuffers matches the list defined by the current + * Keycloak version. If it is not the case, it means that the file events.fbs needs to be updated according + * to the new OperationType file defined in the root GitHub repository of the correct version. + */ + @Test + void testOperationTypesAreUpToDate() { + validateNames(OperationType.class, flatbuffers.events.OperationType.names); + } + + /** + * This test checks that the list of ResourceType defined in flatbuffers matches the list defined by the current + * Keycloak version. If it is not the case, it means that the file events.fbs needs to be updated according + * to the new ResourceType file defined in the root GitHub repository of the correct version. + */ + @Test + void testResourceTypesAreUpToDate() { + validateNames(ResourceType.class, flatbuffers.events.ResourceType.names); + } +} diff --git a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/AbstractTest.java b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/AbstractTest.java similarity index 94% rename from keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/AbstractTest.java rename to keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/AbstractTest.java index ffe9d85..969e10f 100644 --- a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/AbstractTest.java +++ b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/AbstractTest.java @@ -1,6 +1,6 @@ -package io.cloudtrust.keycloak; +package io.cloudtrust.keycloak.eventemitter; -import io.cloudtrust.keycloak.eventemitter.EventEmitterProviderFactory; +import io.cloudtrust.keycloak.eventemitter.kafkaemitter.KafkaEventEmitterProviderFactory; import io.cloudtrust.keycloak.test.AbstractInKeycloakTest; import io.cloudtrust.keycloak.test.http.HttpServerManager; import io.cloudtrust.keycloak.test.pages.LoginPage; @@ -8,6 +8,7 @@ import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.util.StatusCodes; +import jakarta.ws.rs.core.Response; import org.apache.commons.io.IOUtils; import org.jboss.logging.Logger; import org.junit.jupiter.api.AfterAll; @@ -21,7 +22,6 @@ import org.keycloak.representations.idm.UserRepresentation; import org.xnio.streams.ChannelInputStream; -import javax.ws.rs.core.Response; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.LinkedList; @@ -97,7 +97,7 @@ public String toString() { private void setupTestRealm(RealmResource testRealm) { RealmRepresentation realm = testRealm.toRepresentation(); - realm.getEventsListeners().add(EventEmitterProviderFactory.PROVIDER_ID); + realm.getEventsListeners().add(KafkaEventEmitterProviderFactory.PROVIDER_ID); testRealm.update(realm); CredentialRepresentation credentialPass = new CredentialRepresentation(); @@ -118,5 +118,4 @@ private void setupTestRealm(RealmResource testRealm) { } } } - } diff --git a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProviderTest.java b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProviderTest.java deleted file mode 100644 index 09d93c3..0000000 --- a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProviderTest.java +++ /dev/null @@ -1,267 +0,0 @@ -package io.cloudtrust.keycloak.eventemitter; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.github.stefanbirkner.systemlambda.Statement; -import com.github.stefanbirkner.systemlambda.SystemLambda; - -import io.cloudtrust.keycloak.customevent.ExtendedAdminEvent; -import io.cloudtrust.keycloak.customevent.IdentifiedEvent; -import io.cloudtrust.keycloak.snowflake.IdGenerator; -import io.cloudtrust.keycloak.test.AbstractInKeycloakTest; -import io.cloudtrust.keycloak.test.container.KeycloakDeploy; -import io.cloudtrust.keycloak.test.http.HttpServerManager; -import io.undertow.server.HttpHandler; -import io.undertow.server.HttpServerExchange; -import io.undertow.util.StatusCodes; -import org.apache.commons.io.IOUtils; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.keycloak.events.Event; -import org.keycloak.events.EventType; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserModel; -import org.keycloak.models.jpa.RealmAdapter; -import org.keycloak.models.jpa.UserAdapter; -import org.keycloak.models.jpa.entities.RealmEntity; -import org.keycloak.models.jpa.entities.UserEntity; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.xnio.streams.ChannelInputStream; - -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.concurrent.LinkedBlockingQueue; - -@ExtendWith(KeycloakDeploy.class) -class EventEmitterProviderTest extends AbstractInKeycloakTest { - private static final int LISTEN_PORT = 9994; - private static final String TARGET = "http://localhost:" + LISTEN_PORT + "/test"; - private static final int BUFFER_CAPACITY = 3; - - private static final String username = "toto"; - private static final String password = "passwordverylongandhardtoguess"; - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private KeycloakSession keycloakSession; - - protected void runWithEnvironments(Statement stmt) throws Exception { - SystemLambda.withEnvironmentVariable(EventEmitterProvider.KEYCLOAK_BRIDGE_SECRET_TOKEN, password) - .and(EventEmitterProvider.HOSTNAME, username) - .execute(stmt); - } - - protected void runWithHttpHandler(HttpHandler handler, Statement stmt) { - try { - HttpServerManager.getDefault().startHttpServer(LISTEN_PORT, handler); - this.runWithEnvironments(stmt); - } catch (Exception e) { - Assertions.fail(e); - } finally { - HttpServerManager.getDefault().stop(LISTEN_PORT); - } - } - - @BeforeEach - public void initMock() { - MockitoAnnotations.openMocks(this); - // user - UserEntity userEntity = new UserEntity(); - userEntity.setUsername("test-user"); - UserModel user = new UserAdapter(null, null, null, userEntity); - Mockito.when(keycloakSession.users().getUserById((RealmModel) Mockito.any(), Mockito.any())).thenReturn(user); - - // Realm - RealmEntity realmEntity = new RealmEntity(); - realmEntity.setId("realmId"); - RealmModel realm = new RealmAdapter(null, null, realmEntity); - Mockito.when(keycloakSession.realms().getRealm(Mockito.any())).thenReturn(realm); - } - - @Test - void testFlatbufferFormatOutput() { - final HttpJsonReceiverHandler handler = new HttpJsonReceiverHandler(); - runWithHttpHandler(handler, () -> { - CloseableHttpClient httpClient = HttpClients.createDefault(); - IdGenerator idGenerator = new IdGenerator(1, 1); - LinkedBlockingQueue pendingEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - LinkedBlockingQueue pendingAdminEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - EventEmitterProvider eventEmitterProvider = new EventEmitterProvider(keycloakSession, httpClient, - idGenerator, TARGET, SerialisationFormat.FLATBUFFER, pendingEvents, pendingAdminEvents, null); - - Event event = createEvent(); - eventEmitterProvider.onEvent(event); - - httpClient.close(); - - ObjectMapper mapper = new ObjectMapper(); - Container container = mapper.readValue(handler.getResponse(), Container.class); - - Assertions.assertEquals("Event", container.getType()); - - byte[] b = Base64.getDecoder().decode(container.getObj()); - flatbuffers.events.Event receivedEvent = flatbuffers.events.Event.getRootAsEvent(ByteBuffer.wrap(b)); - Assertions.assertEquals(event.getTime(), receivedEvent.time()); - Assertions.assertEquals(event.getType().ordinal(), receivedEvent.type()); - Assertions.assertEquals(event.getClientId(), receivedEvent.clientId()); - }); - } - - @Test - void testJsonFormatOutput() { - HttpJsonReceiverHandler handler = new HttpJsonReceiverHandler(); - this.runWithHttpHandler(handler, () -> { - HttpServerManager.getDefault().startHttpServer(LISTEN_PORT, handler); - - CloseableHttpClient httpClient = HttpClients.createDefault(); - IdGenerator idGenerator = new IdGenerator(1, 1); - LinkedBlockingQueue pendingEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - LinkedBlockingQueue pendingAdminEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - EventEmitterProvider eventEmitterProvider = new EventEmitterProvider(keycloakSession, httpClient, - idGenerator, TARGET, SerialisationFormat.JSON, pendingEvents, pendingAdminEvents, null); - - Event event = createEvent(); - eventEmitterProvider.onEvent(event); - - httpClient.close(); - - IdentifiedEvent receivedIdentifiedEvent = mapper.readValue(handler.getResponse(), IdentifiedEvent.class); - - Assertions.assertEquals(event.getTime(), receivedIdentifiedEvent.getTime()); - Assertions.assertEquals(event.getType(), receivedIdentifiedEvent.getType()); - Assertions.assertEquals(event.getClientId(), receivedIdentifiedEvent.getClientId()); - }); - } - - @Test - void testNoConnection() throws Exception { - this.runWithEnvironments(() -> { - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - IdGenerator idGenerator = new IdGenerator(1, 1); - LinkedBlockingQueue pendingEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - LinkedBlockingQueue pendingAdminEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - EventEmitterProvider eventEmitterProvider = new EventEmitterProvider(keycloakSession, httpClient, - idGenerator, TARGET, SerialisationFormat.JSON, pendingEvents, pendingAdminEvents, null); - - Assertions.assertEquals(0, pendingEvents.size()); - - Event event = createEvent(); - eventEmitterProvider.onEvent(event); - - Assertions.assertEquals(1, pendingEvents.size()); - - Event event2 = createEvent(); - eventEmitterProvider.onEvent(event2); - - Assertions.assertEquals(2, pendingEvents.size()); - } - }); - } - - @Test - void testServerError() { - final HttpErrorHandler handler = new HttpErrorHandler(); - this.runWithHttpHandler(handler, () -> { - try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - IdGenerator idGenerator = new IdGenerator(1, 1); - LinkedBlockingQueue pendingEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - LinkedBlockingQueue pendingAdminEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - EventEmitterProvider eventEmitterProvider = new EventEmitterProvider(keycloakSession, httpClient, - idGenerator, TARGET, SerialisationFormat.JSON, pendingEvents, pendingAdminEvents, null); - - Assertions.assertEquals(0, pendingEvents.size()); - - Event event = createEvent(); - eventEmitterProvider.onEvent(event); - - Assertions.assertEquals(1, pendingEvents.size()); - - Event event2 = createEvent(); - eventEmitterProvider.onEvent(event2); - - Assertions.assertEquals(2, pendingEvents.size()); - } - }); - } - - @Test - void testBufferAndSend() throws Exception { - runWithEnvironments(() -> { - CloseableHttpClient httpClient = HttpClients.createDefault(); - IdGenerator idGenerator = new IdGenerator(1, 1); - LinkedBlockingQueue pendingEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - LinkedBlockingQueue pendingAdminEvents = new LinkedBlockingQueue<>(BUFFER_CAPACITY); - EventEmitterProvider eventEmitterProvider = new EventEmitterProvider(keycloakSession, httpClient, - idGenerator, TARGET, SerialisationFormat.JSON, pendingEvents, pendingAdminEvents, null); - - Assertions.assertEquals(0, pendingEvents.size()); - - Event event = createEvent(); - eventEmitterProvider.onEvent(event); - - Assertions.assertEquals(1, pendingEvents.size()); - - Event event2 = createEvent(); - eventEmitterProvider.onEvent(event2); - - Assertions.assertEquals(2, pendingEvents.size()); - - try { - HttpJsonReceiverHandler handler = new HttpJsonReceiverHandler(); - HttpServerManager.getDefault().startHttpServer(LISTEN_PORT, handler); - - Event event3 = createEvent(); - eventEmitterProvider.onEvent(event3); - - httpClient.close(); - - Assertions.assertEquals(0, pendingEvents.size()); - Assertions.assertEquals(3, handler.getCounter()); - } finally { - HttpServerManager.getDefault().stop(LISTEN_PORT); - } - }); - } - - static class HttpJsonReceiverHandler implements HttpHandler { - String jsonReceived; - int counter = 0; - - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception { - exchange.setStatusCode(StatusCodes.OK); - ChannelInputStream cis = new ChannelInputStream(exchange.getRequestChannel()); - jsonReceived = IOUtils.toString(cis, StandardCharsets.UTF_8); - counter++; - } - - String getResponse() { - return jsonReceived; - } - - int getCounter() { - return counter; - } - } - - static class HttpErrorHandler implements HttpHandler { - @Override - public void handleRequest(HttpServerExchange exchange) { - exchange.setStatusCode(StatusCodes.MULTIPLE_CHOICES); - } - } - - private Event createEvent() { - Event event = new Event(); - event.setTime(120001); - event.setType(EventType.CLIENT_LOGIN); - return event; - } -} diff --git a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/MessageGenerationItTest.java b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/MessageGenerationItTest.java deleted file mode 100644 index 9f22fbb..0000000 --- a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/MessageGenerationItTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package io.cloudtrust.keycloak.eventemitter; - -import com.google.gson.Gson; -import io.cloudtrust.keycloak.AbstractTest; -import io.cloudtrust.keycloak.customevent.ExtendedAdminEvent; -import io.cloudtrust.keycloak.pages.LogoutPage; -import io.cloudtrust.keycloak.test.container.KeycloakDeploy; -import io.cloudtrust.keycloak.test.pages.WebPage; -import org.jboss.logging.Logger; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.keycloak.admin.client.Keycloak; -import org.keycloak.events.Event; -import org.keycloak.events.EventType; -import org.keycloak.representations.idm.RealmEventsConfigRepresentation; -import org.keycloak.representations.idm.UserRepresentation; - -import javax.ws.rs.core.Response; - -import static io.cloudtrust.keycloak.test.matchers.CtMatchers.and; -import static io.cloudtrust.keycloak.test.matchers.EventMatchers.doesNotExist; -import static io.cloudtrust.keycloak.test.matchers.EventMatchers.hasUserId; -import static io.cloudtrust.keycloak.test.matchers.EventMatchers.isKeycloakType; -import static io.cloudtrust.keycloak.test.matchers.PageMatchers.isCurrent; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - -@ExtendWith(KeycloakDeploy.class) -public class MessageGenerationItTest extends AbstractTest { - protected static final Logger logger = Logger.getLogger(MessageGenerationItTest.class); - - private static final String CLIENT = "admin-cli"; - private static final String TEST_USER = "user-test-event-emitter"; - - @WebPage - LogoutPage logoutPage; - - @BeforeAll - public static void initRealmAndUsers() { - // setup event listener - String url = KeycloakDeploy.getContainer().getBaseUrl(); - Keycloak keycloak = Keycloak.getInstance(url, "master", "admin", "admin", CLIENT); - RealmEventsConfigRepresentation eventConfig = keycloak.realm("master").getRealmEventsConfig(); - eventConfig.getEventsListeners().add("event-emitter"); - keycloak.realm("master").updateRealmEventsConfig(eventConfig); - } - - /** - * Simulate login, and expect the event emitter to report this event - */ - @Test - void testLoginEventReporting() { - int nbLoginEvents = 0; - Keycloak keycloak = Keycloak.getInstance(this.getKeycloakURL(), "master", "admin", "admin", CLIENT); - - // test login event - keycloak.realm("master").users().search(TEST_USER); - // wait for the event to be reported - this.sleep(1000); - String jsonAsString = handler.toString(); - Event e = new Gson().fromJson(jsonAsString, Event.class); - if (e.getType() == EventType.LOGIN) { - nbLoginEvents++; - } - Assertions.assertEquals(1, nbLoginEvents); - } - - /** - * Simulate logout, and expect the event emitter to report this event - */ - @Test - void testLogoutEventReporting() { - System.out.println(loginPage.getOAuthClient().getLoginFormUrl()); - System.out.println(loginPage.getOAuthClient().getLogoutFormUrl()); - loginPage.open(); - loginPage.login("test.user", "password"); - assertThat(events().poll(), isKeycloakType(EventType.LOGIN)); - - loginPage.openLogout(false); - assertThat(logoutPage, isCurrent()); - logoutPage.logout(); - - assertThat(events().poll(), and(isKeycloakType(EventType.LOGOUT), hasUserId()/*, hasDetail(Details.USERNAME, "test.user")*/)); - assertThat(events().poll(), doesNotExist()); - } - - /** - * Simulate user creation and check that the username of the user created appears - * in the event, as well as the username of the agent creating the user - */ - @Test - void testCreateUserEventReporting() { - UserRepresentation user = new UserRepresentation(); - user.setUsername("test_user_creation"); - Response rsp = this.getRealm("test").users().create(user); - String loc = rsp.getHeaderString("Location"); - String createdUserId = loc.substring(loc.lastIndexOf("/") + 1); - - assertThat(rsp.getStatus(), is(201)); - - // wait for the event to be reported - this.sleep(1000); - String jsonAsString = handler.toString(); - ExtendedAdminEvent e = new Gson().fromJson(jsonAsString, ExtendedAdminEvent.class); - assertThat(e.getAuthDetails().getUsername(), is("admin")); - assertThat(e.getDetails().get("user_id"), is(createdUserId)); - assertThat(e.getDetails().get("username"), is("test_user_creation")); - } -} \ No newline at end of file diff --git a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/SerializationUtilsTest.java b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/SerializationUtilsTest.java index d540db5..08a45d5 100644 --- a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/SerializationUtilsTest.java +++ b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/SerializationUtilsTest.java @@ -1,10 +1,10 @@ package io.cloudtrust.keycloak.eventemitter; import com.fasterxml.jackson.core.JsonProcessingException; -import io.cloudtrust.keycloak.customevent.ExtendedAdminEvent; -import io.cloudtrust.keycloak.customevent.ExtendedAuthDetails; -import io.cloudtrust.keycloak.customevent.IdentifiedAdminEvent; -import io.cloudtrust.keycloak.customevent.IdentifiedEvent; +import io.cloudtrust.keycloak.eventemitter.customevent.ExtendedAdminEvent; +import io.cloudtrust.keycloak.eventemitter.customevent.ExtendedAuthDetails; +import io.cloudtrust.keycloak.eventemitter.customevent.IdentifiedAdminEvent; +import io.cloudtrust.keycloak.eventemitter.customevent.IdentifiedEvent; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.junit.jupiter.api.Assertions; @@ -22,72 +22,43 @@ import java.util.Map; class SerializationUtilsTest { - private static final long UID = 123456789L; + private long UID = 123456789L; @Test - void testContainerToJson() { - Container c = new Container("Event", "obj"); - try { - String jsonEvent = SerialisationUtils.toJson(c); - Assertions.assertEquals("{\"type\":\"Event\",\"obj\":\"obj\"}", jsonEvent); - } catch (JsonProcessingException e) { - Assertions.fail(e); - } - } - - @Test - void testEventToJson() { + void testEventToJson() throws JsonProcessingException { Event event = createEvent(); - - try { - String jsonEvent = SerialisationUtils.toJson(new IdentifiedEvent(UID, event)); - Assertions.assertEquals("{\"id\":null,\"time\":120000,\"type\":\"CLIENT_LOGIN\"," + - "\"realmId\":\"realmId\",\"clientId\":\"clientId\",\"userId\":\"userId\"," + - "\"sessionId\":\"sessionId\",\"ipAddress\":\"127.0.0.1\",\"error\":\"Error\"," + - "\"details\":{\"detailsKey2\":\"detailsValue2\",\"detailsKey1\":\"detailValue1\"},\"uid\":123456789}", jsonEvent); - } catch (JsonProcessingException e) { - Assertions.fail(); - } + String jsonEvent = SerializationUtils.toJson(new IdentifiedEvent(UID, event)); + Assertions.assertEquals("{\"id\":null,\"time\":120000,\"type\":\"CLIENT_LOGIN\"," + + "\"realmId\":\"realmId\",\"realmName\":null,\"clientId\":\"clientId\",\"userId\":\"userId\"," + + "\"sessionId\":\"sessionId\",\"ipAddress\":\"127.0.0.1\",\"error\":\"Error\"," + + "\"details\":{\"detailsKey2\":\"detailsValue2\",\"detailsKey1\":\"detailValue1\"},\"uid\":123456789}", jsonEvent); } @Test - void testEventMinimalToJson() { + void testEventMinimalToJson() throws JsonProcessingException { Event eventMinimal = createMinimalEvent(); - try { - String jsonEvent = SerialisationUtils.toJson(new IdentifiedEvent(UID, eventMinimal)); - Assertions.assertEquals("{\"id\":null,\"time\":120000,\"type\":\"CLIENT_LOGIN\"," + - "\"realmId\":null,\"clientId\":null,\"userId\":null,\"sessionId\":null," + - "\"ipAddress\":null,\"error\":null,\"details\":null,\"uid\":123456789}", jsonEvent); - } catch (JsonProcessingException e) { - Assertions.fail(); - } - + String jsonEvent = SerializationUtils.toJson(new IdentifiedEvent(UID, eventMinimal)); + Assertions.assertEquals("{\"id\":null,\"time\":120000,\"type\":\"CLIENT_LOGIN\"," + + "\"realmId\":null,\"realmName\":null,\"clientId\":null,\"userId\":null,\"sessionId\":null," + + "\"ipAddress\":null,\"error\":null,\"details\":null,\"uid\":123456789}", jsonEvent); } @Test - void testAdminEventToJson() { - try { - String jsonEvent = SerialisationUtils.toJson(createExtendedAdminEvent()); - Assertions.assertEquals("{\"id\":null,\"time\":120000,\"realmId\":\"realmId\",\"resourceType\":\"AUTHORIZATION_RESOURCE\",\"operationType\":\"CREATE\",\"resourcePath\":\"resource/path\",\"representation\":\"representation\",\"error\":\"error\",\"uid\":123456789,\"extAuthDetails\":{\"realmId\":\"authDetails-realmId\",\"clientId\":\"authDetails-clientId\",\"userId\":\"authDetails-userId\",\"ipAddress\":\"authDetails-ipAddress\",\"username\":\"authDetails-username\"},\"details\":{\"user_id\":\"userid\",\"username\":\"username\"}}", jsonEvent); - } catch (JsonProcessingException e) { - Assertions.fail(); - } + void testAdminEventToJson() throws JsonProcessingException { + String jsonEvent = SerializationUtils.toJson(createExtendedAdminEvent()); + Assertions.assertEquals("{\"id\":null,\"time\":120000,\"realmId\":\"realmId\",\"realmName\":null,\"resourceType\":\"AUTHORIZATION_RESOURCE\",\"operationType\":\"CREATE\",\"resourcePath\":\"resource/path\",\"representation\":\"representation\",\"error\":\"error\",\"uid\":123456789,\"extAuthDetails\":{\"realmId\":\"authDetails-realmId\",\"realmName\":null,\"clientId\":\"authDetails-clientId\",\"userId\":\"authDetails-userId\",\"ipAddress\":\"authDetails-ipAddress\",\"username\":\"authDetails-username\"},\"details\":{\"user_id\":\"userid\",\"username\":\"username\"}}", jsonEvent); } @Test - void testMinimalAdminEventToJson() { - try { - String jsonEvent = SerialisationUtils.toJson(createMinimalExtendedAdminEvent()); - Assertions.assertEquals("{\"id\":null,\"time\":120000,\"realmId\":null,\"resourceType\":null,\"operationType\":null,\"resourcePath\":null,\"representation\":null,\"error\":null,\"uid\":123456789,\"extAuthDetails\":null,\"details\":{}}", jsonEvent); - } catch (JsonProcessingException e) { - Assertions.fail(); - } + void testMinimalAdminEventToJson() throws JsonProcessingException { + String jsonEvent = SerializationUtils.toJson(createMinimalExtendedAdminEvent()); + Assertions.assertEquals("{\"id\":null,\"time\":120000,\"realmId\":null,\"realmName\":null,\"resourceType\":null,\"operationType\":null,\"resourcePath\":null,\"representation\":null,\"error\":null,\"uid\":123456789,\"extAuthDetails\":null,\"details\":{}}", jsonEvent); } @Test void testEventToFlatbuffers() { Event event = createEvent(); - ByteBuffer buffer = SerialisationUtils.toFlat(new IdentifiedEvent(UID, event)); + ByteBuffer buffer = SerializationUtils.toFlat(new IdentifiedEvent(UID, event)); flatbuffers.events.Event deserializedEvent = flatbuffers.events.Event.getRootAsEvent(buffer); Assertions.assertTrue(equals(event, deserializedEvent)); Assertions.assertEquals(UID, deserializedEvent.uid()); @@ -96,7 +67,7 @@ void testEventToFlatbuffers() { @Test void testMinimalEventToFlatbuffers() { Event event = createMinimalEvent(); - ByteBuffer buffer = SerialisationUtils.toFlat(new IdentifiedEvent(UID, event)); + ByteBuffer buffer = SerializationUtils.toFlat(new IdentifiedEvent(UID, event)); flatbuffers.events.Event deserializedEvent = flatbuffers.events.Event.getRootAsEvent(buffer); Assertions.assertTrue(equals(event, deserializedEvent)); Assertions.assertEquals(UID, deserializedEvent.uid()); @@ -105,7 +76,7 @@ void testMinimalEventToFlatbuffers() { @Test void testAdminEventToFlatbuffers() { ExtendedAdminEvent adminEvent = createExtendedAdminEvent(); - ByteBuffer buffer = SerialisationUtils.toFlat(adminEvent); + ByteBuffer buffer = SerializationUtils.toFlat(adminEvent); flatbuffers.events.AdminEvent deserializedAdminEvent = flatbuffers.events.AdminEvent.getRootAsAdminEvent(buffer); Assertions.assertTrue(equals(adminEvent, deserializedAdminEvent)); Assertions.assertEquals(UID, deserializedAdminEvent.uid()); @@ -114,7 +85,7 @@ void testAdminEventToFlatbuffers() { @Test void testMinimalAdminEventToFlatbuffers() { ExtendedAdminEvent adminEvent = createMinimalExtendedAdminEvent(); - ByteBuffer buffer = SerialisationUtils.toFlat(adminEvent); + ByteBuffer buffer = SerializationUtils.toFlat(adminEvent); flatbuffers.events.AdminEvent deserializedAdminEvent = flatbuffers.events.AdminEvent.getRootAsAdminEvent(buffer); Assertions.assertTrue(equals(adminEvent, deserializedAdminEvent)); Assertions.assertEquals(UID, deserializedAdminEvent.uid()); @@ -202,7 +173,7 @@ private boolean equals(ExtendedAdminEvent adminEvent, flatbuffers.events.AdminEv int adminEventResourceType = adminEvent.getResourceType() == null ? 0 : adminEvent.getResourceType().ordinal(); int adminEventOperationType = adminEvent.getOperationType() == null ? 0 : adminEvent.getOperationType().ordinal(); int adminEventDetailsSize = adminEvent.getDetails() == null ? 0 : adminEvent.getDetails().size(); - new EqualsBuilder() + return new EqualsBuilder() .append(adminEvent.getTime(), adminEventFlat.time()) .append(adminEvent.getRealmId(), adminEventFlat.realmId()) .appendSuper(equals(adminEvent.getAuthDetails(), adminEventFlat.authDetails())) @@ -213,8 +184,6 @@ private boolean equals(ExtendedAdminEvent adminEvent, flatbuffers.events.AdminEv .append(adminEventDetailsSize, adminEventFlat.detailsLength()) .append(adminEvent.getError(), adminEventFlat.error()) .build(); - - return true; } private static boolean equals(ExtendedAuthDetails adminEventDetails, flatbuffers.events.AuthDetails adminEventFlatDetails) { diff --git a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterProviderTest.java b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterProviderTest.java similarity index 96% rename from keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterProviderTest.java rename to keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterProviderTest.java index 0bfd5e5..0ab96cb 100644 --- a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterProviderTest.java +++ b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterProviderTest.java @@ -1,15 +1,12 @@ -package io.cloudtrust.keycloak.kafkaeventemitter; +package io.cloudtrust.keycloak.eventemitter.kafkaemitter; - -import io.cloudtrust.keycloak.snowflake.IdGenerator; -import io.cloudtrust.keycloak.test.container.KeycloakDeploy; +import io.cloudtrust.keycloak.eventemitter.snowflake.IdGenerator; import org.apache.kafka.clients.producer.MockProducer; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.serialization.StringSerializer; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.keycloak.events.Event; import org.keycloak.events.EventType; import org.keycloak.events.admin.AdminEvent; @@ -33,7 +30,6 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.locks.ReentrantLock; -@ExtendWith(KeycloakDeploy.class) class KafkaEventEmitterProviderTest { private static final String topicEvent = "test-event"; private static final String topicAdminEvent = "test-admin-event"; diff --git a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/pages/LogoutPage.java b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/pages/LogoutPage.java similarity index 91% rename from keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/pages/LogoutPage.java rename to keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/pages/LogoutPage.java index 36919af..075c98b 100644 --- a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/pages/LogoutPage.java +++ b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/pages/LogoutPage.java @@ -1,4 +1,4 @@ -package io.cloudtrust.keycloak.pages; +package io.cloudtrust.keycloak.eventemitter.pages; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; diff --git a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/snowflake/IdGeneratorTest.java b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/snowflake/IdGeneratorTest.java similarity index 93% rename from keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/snowflake/IdGeneratorTest.java rename to keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/snowflake/IdGeneratorTest.java index 4140e3e..09ca287 100644 --- a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/snowflake/IdGeneratorTest.java +++ b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/eventemitter/snowflake/IdGeneratorTest.java @@ -1,8 +1,11 @@ -package io.cloudtrust.keycloak.snowflake; +package io.cloudtrust.keycloak.eventemitter.snowflake; import java.util.HashSet; import java.util.Set; +import io.cloudtrust.keycloak.eventemitter.snowflake.IdGenerator; +import io.cloudtrust.keycloak.eventemitter.snowflake.IdGeneratorConfig; +import io.cloudtrust.keycloak.eventemitter.snowflake.InvalidSystemClock; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; diff --git a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/kafkaeventemitter/SerializationUtilsTest.java b/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/kafkaeventemitter/SerializationUtilsTest.java deleted file mode 100644 index a59061a..0000000 --- a/keycloak-event-emitter-tests/src/test/java/io/cloudtrust/keycloak/kafkaeventemitter/SerializationUtilsTest.java +++ /dev/null @@ -1,287 +0,0 @@ -package io.cloudtrust.keycloak.kafkaeventemitter; - -import com.fasterxml.jackson.core.JsonProcessingException; -import io.cloudtrust.keycloak.customevent.ExtendedAdminEvent; -import io.cloudtrust.keycloak.customevent.IdentifiedAdminEvent; -import io.cloudtrust.keycloak.customevent.IdentifiedEvent; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.keycloak.events.Event; -import org.keycloak.events.EventType; -import org.keycloak.events.admin.AdminEvent; -import org.keycloak.events.admin.AuthDetails; -import org.keycloak.events.admin.OperationType; -import org.keycloak.events.admin.ResourceType; - -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -class SerializationUtilsTest { - private long UID = 123456789L; - - @Test - void testEventToJson() { - Event event = createEvent(); - - try { - String jsonEvent = SerialisationUtils.toJson(new IdentifiedEvent(UID, event)); - Assertions.assertEquals("{\"id\":null,\"time\":120000,\"type\":\"CLIENT_LOGIN\"," + - "\"realmId\":\"realmId\",\"clientId\":\"clientId\",\"userId\":\"userId\"," + - "\"sessionId\":\"sessionId\",\"ipAddress\":\"127.0.0.1\",\"error\":\"Error\"," + - "\"details\":{\"detailsKey2\":\"detailsValue2\",\"detailsKey1\":\"detailValue1\"},\"uid\":123456789}", jsonEvent); - } catch (JsonProcessingException e) { - Assertions.fail(); - } - } - - @Test - void testEventMinimalToJson() { - Event eventMinimal = createMinimalEvent(); - try { - String jsonEvent = SerialisationUtils.toJson(new IdentifiedEvent(UID, eventMinimal)); - Assertions.assertEquals("{\"id\":null,\"time\":120000,\"type\":\"CLIENT_LOGIN\"," + - "\"realmId\":null,\"clientId\":null,\"userId\":null,\"sessionId\":null," + - "\"ipAddress\":null,\"error\":null,\"details\":null,\"uid\":123456789}", jsonEvent); - } catch (JsonProcessingException e) { - Assertions.fail(); - } - - } - - @Test - void testAdminEventToJson() { - try { - String jsonEvent = SerialisationUtils.toJson(createExtendedAdminEvent()); - Assertions.assertEquals("{\"id\":null,\"time\":120000,\"realmId\":\"realmId\",\"resourceType\":\"AUTHORIZATION_RESOURCE\",\"operationType\":\"CREATE\",\"resourcePath\":\"resource/path\",\"representation\":\"representation\",\"error\":\"error\",\"uid\":123456789,\"extAuthDetails\":{\"realmId\":\"authDetails-realmId\",\"clientId\":\"authDetails-clientId\",\"userId\":\"authDetails-userId\",\"ipAddress\":\"authDetails-ipAddress\",\"username\":\"authDetails-username\"},\"details\":{\"user_id\":\"userid\",\"username\":\"username\"}}", jsonEvent); - } catch (JsonProcessingException e) { - Assertions.fail(); - } - } - - @Test - void testMinimalAdminEventToJson() { - try { - String jsonEvent = SerialisationUtils.toJson(createMinimalExtendedAdminEvent()); - Assertions.assertEquals("{\"id\":null,\"time\":120000,\"realmId\":null,\"resourceType\":null,\"operationType\":null,\"resourcePath\":null,\"representation\":null,\"error\":null,\"uid\":123456789,\"extAuthDetails\":null,\"details\":{}}", jsonEvent); - } catch (JsonProcessingException e) { - Assertions.fail(); - } - } - - @Test - void testEventToFlatbuffers() { - Event event = createEvent(); - ByteBuffer buffer = SerialisationUtils.toFlat(new IdentifiedEvent(UID, event)); - flatbuffers.events.Event deserializedEvent = flatbuffers.events.Event.getRootAsEvent(buffer); - Assertions.assertTrue(equals(event, deserializedEvent)); - Assertions.assertEquals(UID, deserializedEvent.uid()); - } - - @Test - void testMinimalEventToFlatbuffers() { - Event event = createMinimalEvent(); - ByteBuffer buffer = SerialisationUtils.toFlat(new IdentifiedEvent(UID, event)); - flatbuffers.events.Event deserializedEvent = flatbuffers.events.Event.getRootAsEvent(buffer); - Assertions.assertTrue(equals(event, deserializedEvent)); - Assertions.assertEquals(UID, deserializedEvent.uid()); - } - - @Test - void testAdminEventToFlatbuffers() { - ExtendedAdminEvent adminEvent = createExtendedAdminEvent(); - ByteBuffer buffer = SerialisationUtils.toFlat(adminEvent); - flatbuffers.events.AdminEvent deserializedAdminEvent = flatbuffers.events.AdminEvent.getRootAsAdminEvent(buffer); - Assertions.assertTrue(equals(adminEvent, deserializedAdminEvent)); - Assertions.assertEquals(UID, deserializedAdminEvent.uid()); - } - - @Test - void testMinimalAdminEventToFlatbuffers() { - ExtendedAdminEvent adminEvent = createMinimalExtendedAdminEvent(); - ByteBuffer buffer = SerialisationUtils.toFlat(adminEvent); - flatbuffers.events.AdminEvent deserializedAdminEvent = flatbuffers.events.AdminEvent.getRootAsAdminEvent(buffer); - Assertions.assertTrue(equals(adminEvent, deserializedAdminEvent)); - Assertions.assertEquals(UID, deserializedAdminEvent.uid()); - } - - private Event createEvent() { - Event event = new Event(); - event.setTime(120000); - event.setType(EventType.CLIENT_LOGIN); - event.setRealmId("realmId"); - event.setClientId("clientId"); - event.setUserId("userId"); - event.setSessionId("sessionId"); - event.setIpAddress("127.0.0.1"); - event.setError("Error"); - - Map details = new HashMap<>(); - details.put("detailsKey1", "detailValue1"); - details.put("detailsKey2", "detailsValue2"); - event.setDetails(details); - return event; - } - - private Event createMinimalEvent() { - Event event = new Event(); - event.setTime(120000); - event.setType(EventType.CLIENT_LOGIN); - return event; - } - - private ExtendedAdminEvent createExtendedAdminEvent() { - IdentifiedAdminEvent iae = new IdentifiedAdminEvent(UID, createAdminEvent()); - ExtendedAdminEvent eae = new ExtendedAdminEvent(iae); - eae.getAuthDetails().setUsername("authDetails-username"); - eae.getDetails().put("user_id", "userid"); - eae.getDetails().put("username", "username"); - return eae; - } - - private AdminEvent createAdminEvent() { - AdminEvent adminEvent = new AdminEvent(); - adminEvent.setTime(120000); - adminEvent.setRealmId("realmId"); - AuthDetails authDetails = new AuthDetails(); - authDetails.setRealmId("authDetails-realmId"); - authDetails.setClientId("authDetails-clientId"); - authDetails.setIpAddress("authDetails-ipAddress"); - authDetails.setUserId("authDetails-userId"); - adminEvent.setAuthDetails(authDetails); - adminEvent.setResourceType(ResourceType.AUTHORIZATION_RESOURCE); - adminEvent.setOperationType(OperationType.CREATE); - adminEvent.setResourcePath("resource/path"); - adminEvent.setRepresentation("representation"); - adminEvent.setError("error"); - return adminEvent; - } - - private ExtendedAdminEvent createMinimalExtendedAdminEvent() { - IdentifiedAdminEvent iae = new IdentifiedAdminEvent(UID, createMinimalAdminEvent()); - return new ExtendedAdminEvent(iae); - } - - private AdminEvent createMinimalAdminEvent() { - AdminEvent adminEvent = new AdminEvent(); - adminEvent.setTime(120000); - return adminEvent; - } - - private boolean equals(Event event, flatbuffers.events.Event eventFlat) { - if (event.getTime() != eventFlat.time()) { - return false; - } - - if (event.getType().ordinal() != eventFlat.type()) { - return false; - } - - if (!Objects.equals(event.getRealmId(), eventFlat.realmId())) { - return false; - } - - if (!Objects.equals(event.getClientId(), eventFlat.clientId())) { - return false; - } - - if (!Objects.equals(event.getUserId(), eventFlat.userId())) { - return false; - } - - if (!Objects.equals(event.getSessionId(), eventFlat.sessionId())) { - return false; - } - - if (!Objects.equals(event.getIpAddress(), eventFlat.ipAddress())) { - return false; - } - - if (!Objects.equals(event.getError(), eventFlat.error())) { - return false; - } - - if (event.getDetails() == null) { - if (eventFlat.detailsLength() != 0) { - return false; - } - } else if (event.getDetails().size() != eventFlat.detailsLength()) { - return false; - } - - return true; - } - - private boolean equals(ExtendedAdminEvent adminEvent, flatbuffers.events.AdminEvent adminEventFlat) { - if (adminEvent.getTime() != adminEventFlat.time()) { - return false; - } - - if (!Objects.equals(adminEvent.getRealmId(), adminEventFlat.realmId())) { - return false; - } - - if (adminEvent.getAuthDetails() == null) { - if (adminEventFlat.authDetails() != null) { - return false; - } - } else { - if (!Objects.equals(adminEvent.getAuthDetails().getUserId(), adminEventFlat.authDetails().userId())) { - return false; - } - if (!Objects.equals(adminEvent.getAuthDetails().getUsername(), adminEventFlat.authDetails().username())) { - return false; - } - if (!Objects.equals(adminEvent.getAuthDetails().getClientId(), adminEventFlat.authDetails().clientId())) { - return false; - } - if (!Objects.equals(adminEvent.getAuthDetails().getIpAddress(), adminEventFlat.authDetails().ipAddress())) { - return false; - } - if (!Objects.equals(adminEvent.getAuthDetails().getRealmId(), adminEventFlat.authDetails().realmId())) { - return false; - } - } - - if (adminEvent.getResourceType() == null) { - if (adminEventFlat.resourceType() != 0) { - return false; - } - } else if (adminEvent.getResourceType().ordinal() != adminEventFlat.resourceType()) { - return false; - } - - if (adminEvent.getOperationType() == null) { - if (adminEventFlat.operationType() != 0) { - return false; - } - } else if (adminEvent.getOperationType().ordinal() != adminEventFlat.operationType()) { - return false; - } - - if (!Objects.equals(adminEvent.getResourcePath(), adminEventFlat.resourcePath())) { - return false; - } - - if (!Objects.equals(adminEvent.getRepresentation(), adminEventFlat.representation())) { - return false; - } - - - if (adminEvent.getDetails() == null) { - if (adminEventFlat.detailsLength() != 0) { - return false; - } - } else if (adminEvent.getDetails().size() != adminEventFlat.detailsLength()) { - return false; - } - - if (!Objects.equals(adminEvent.getError(), adminEventFlat.error())) { - return false; - } - - return true; - } - -} diff --git a/keycloak-event-emitter-tests/src/test/resources/keycloak.properties b/keycloak-event-emitter-tests/src/test/resources/keycloak.properties index 32fccdc..f2887b0 100644 --- a/keycloak-event-emitter-tests/src/test/resources/keycloak.properties +++ b/keycloak-event-emitter-tests/src/test/resources/keycloak.properties @@ -2,15 +2,6 @@ ../keycloak-event-emitter/target/keycloak-event-emitter-0.0.0-SNAPSHOT.tar.gz [properties] -spi-events-listener-event-emitter-enabled=true -spi-events-listener-event-emitter-format=JSON -spi-events-listener-event-emitter-target-uri=http://localhost:9999/event/receiver -spi-events-listener-event-emitter-buffer-capacity=1 -spi-events-listener-event-emitter-keycloak-id=1 -spi-events-listener-event-emitter-datacenter-id=1 -spi-events-listener-event-emitter-connect-timeout-millis=500 -spi-events-listener-event-emitter-connection-request-timeout-millis=500 -spi-events-listener-event-emitter-socket-timeout-millis=500 spi-events-listener-kafka-event-emitter-buffer-capacity=50 spi-events-listener-kafka-event-emitter-client-id=keycloak spi-events-listener-kafka-event-emitter-bootstrap-servers=kafka:29093 diff --git a/keycloak-event-emitter/module.conf b/keycloak-event-emitter/module.conf index a04ae26..946536f 100644 --- a/keycloak-event-emitter/module.conf +++ b/keycloak-event-emitter/module.conf @@ -1,14 +1,4 @@ # add SPI configuration for events listeners (if not already there) -spi-events-listener-event-emitter-enabled=true -spi-events-listener-event-emitter-format=FLATBUFFER -spi-events-listener-event-emitter-target-uri=PARAM_TARGET_URI -spi-events-listener-event-emitter-buffer-capacity=10 -spi-events-listener-event-emitter-keycloak-id=1 -spi-events-listener-event-emitter-datacenter-id=1 -spi-events-listener-event-emitter-connect-timeout-millis=500 -spi-events-listener-event-emitter-connection-request-timeout-millis=500 -spi-events-listener-event-emitter-socket-timeout-millis=500 - spi-events-listener-kafka-event-emitter-buffer-capacity=50 spi-events-listener-kafka-event-emitter-client-id=keycloak spi-events-listener-kafka-event-emitter-bootstrap-servers=kafka:29093 diff --git a/keycloak-event-emitter/pom.xml b/keycloak-event-emitter/pom.xml index 91bda50..ee23058 100644 --- a/keycloak-event-emitter/pom.xml +++ b/keycloak-event-emitter/pom.xml @@ -5,7 +5,7 @@ io.cloudtrust keycloak-event-emitter-parent - 20.1.1-SNAPSHOT + 26.0.0-SNAPSHOT keycloak-event-emitter @@ -13,7 +13,7 @@ jar - 3.4.0 + 3.7.1 25.2.10 ${java.version} diff --git a/keycloak-event-emitter/src/main/flatbuffers/event.fbs b/keycloak-event-emitter/src/main/flatbuffers/event.fbs index 0a48fc9..38d40ca 100644 --- a/keycloak-event-emitter/src/main/flatbuffers/event.fbs +++ b/keycloak-event-emitter/src/main/flatbuffers/event.fbs @@ -107,6 +107,20 @@ enum EventType:byte { DELETE_ACCOUNT_ERROR, PUSHED_AUTHORIZATION_REQUEST, PUSHED_AUTHORIZATION_REQUEST_ERROR, + USER_DISABLED_BY_PERMANENT_LOCKOUT, + USER_DISABLED_BY_PERMANENT_LOCKOUT_ERROR, + USER_DISABLED_BY_TEMPORARY_LOCKOUT, + USER_DISABLED_BY_TEMPORARY_LOCKOUT_ERROR, + OAUTH2_EXTENSION_GRANT, + OAUTH2_EXTENSION_GRANT_ERROR, + FEDERATED_IDENTITY_OVERRIDE_LINK, + FEDERATED_IDENTITY_OVERRIDE_LINK_ERROR, + UPDATE_CREDENTIAL, + UPDATE_CREDENTIAL_ERROR, + REMOVE_CREDENTIAL, + REMOVE_CREDENTIAL_ERROR, + INVITE_ORG, + INVITE_ORG_ERROR, UNKNOWN // Default case } @@ -119,6 +133,7 @@ enum ResourceType:byte { AUTH_EXECUTION_FLOW, AUTH_EXECUTION, AUTHENTICATOR_CONFIG, + REQUIRED_ACTION_CONFIG, REQUIRED_ACTION, IDENTITY_PROVIDER, IDENTITY_PROVIDER_MAPPER, @@ -144,6 +159,9 @@ enum ResourceType:byte { AUTHORIZATION_SCOPE, AUTHORIZATION_POLICY, CUSTOM, + USER_PROFILE, + ORGANIZATION, + ORGANIZATION_MEMBERSHIP, UNKNOWN // Default case } diff --git a/keycloak-event-emitter/src/main/flatbuffers/flatbuffers/events/EventType.java b/keycloak-event-emitter/src/main/flatbuffers/flatbuffers/events/EventType.java index cf198a2..c130b9d 100644 --- a/keycloak-event-emitter/src/main/flatbuffers/flatbuffers/events/EventType.java +++ b/keycloak-event-emitter/src/main/flatbuffers/flatbuffers/events/EventType.java @@ -109,9 +109,23 @@ private EventType() { } public static final byte DELETE_ACCOUNT_ERROR = 101; public static final byte PUSHED_AUTHORIZATION_REQUEST = 102; public static final byte PUSHED_AUTHORIZATION_REQUEST_ERROR = 103; - public static final byte UNKNOWN = 104; + public static final byte USER_DISABLED_BY_PERMANENT_LOCKOUT = 104; + public static final byte USER_DISABLED_BY_PERMANENT_LOCKOUT_ERROR = 105; + public static final byte USER_DISABLED_BY_TEMPORARY_LOCKOUT = 106; + public static final byte USER_DISABLED_BY_TEMPORARY_LOCKOUT_ERROR = 107; + public static final byte OAUTH2_EXTENSION_GRANT = 108; + public static final byte OAUTH2_EXTENSION_GRANT_ERROR = 109; + public static final byte FEDERATED_IDENTITY_OVERRIDE_LINK = 110; + public static final byte FEDERATED_IDENTITY_OVERRIDE_LINK_ERROR = 111; + public static final byte UPDATE_CREDENTIAL = 112; + public static final byte UPDATE_CREDENTIAL_ERROR = 113; + public static final byte REMOVE_CREDENTIAL = 114; + public static final byte REMOVE_CREDENTIAL_ERROR = 115; + public static final byte INVITE_ORG = 116; + public static final byte INVITE_ORG_ERROR = 117; + public static final byte UNKNOWN = 118; - public static final String[] names = { "LOGIN", "LOGIN_ERROR", "REGISTER", "REGISTER_ERROR", "LOGOUT", "LOGOUT_ERROR", "CODE_TO_TOKEN", "CODE_TO_TOKEN_ERROR", "CLIENT_LOGIN", "CLIENT_LOGIN_ERROR", "REFRESH_TOKEN", "REFRESH_TOKEN_ERROR", "VALIDATE_ACCESS_TOKEN", "VALIDATE_ACCESS_TOKEN_ERROR", "INTROSPECT_TOKEN", "INTROSPECT_TOKEN_ERROR", "FEDERATED_IDENTITY_LINK", "FEDERATED_IDENTITY_LINK_ERROR", "REMOVE_FEDERATED_IDENTITY", "REMOVE_FEDERATED_IDENTITY_ERROR", "UPDATE_EMAIL", "UPDATE_EMAIL_ERROR", "UPDATE_PROFILE", "UPDATE_PROFILE_ERROR", "UPDATE_PASSWORD", "UPDATE_PASSWORD_ERROR", "UPDATE_TOTP", "UPDATE_TOTP_ERROR", "VERIFY_EMAIL", "VERIFY_EMAIL_ERROR", "VERIFY_PROFILE", "VERIFY_PROFILE_ERROR", "REMOVE_TOTP", "REMOVE_TOTP_ERROR", "GRANT_CONSENT", "GRANT_CONSENT_ERROR", "UPDATE_CONSENT", "UPDATE_CONSENT_ERROR", "REVOKE_GRANT", "REVOKE_GRANT_ERROR", "SEND_VERIFY_EMAIL", "SEND_VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD", "SEND_RESET_PASSWORD_ERROR", "SEND_IDENTITY_PROVIDER_LINK", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "RESET_PASSWORD", "RESET_PASSWORD_ERROR", "RESTART_AUTHENTICATION", "RESTART_AUTHENTICATION_ERROR", "INVALID_SIGNATURE", "INVALID_SIGNATURE_ERROR", "REGISTER_NODE", "REGISTER_NODE_ERROR", "UNREGISTER_NODE", "UNREGISTER_NODE_ERROR", "USER_INFO_REQUEST", "USER_INFO_REQUEST_ERROR", "IDENTITY_PROVIDER_LINK_ACCOUNT", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "IDENTITY_PROVIDER_LOGIN", "IDENTITY_PROVIDER_LOGIN_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "IDENTITY_PROVIDER_RESPONSE", "IDENTITY_PROVIDER_RESPONSE_ERROR", "IDENTITY_PROVIDER_RETRIEVE_TOKEN", "IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR", "IMPERSONATE", "IMPERSONATE_ERROR", "CUSTOM_REQUIRED_ACTION", "CUSTOM_REQUIRED_ACTION_ERROR", "EXECUTE_ACTIONS", "EXECUTE_ACTIONS_ERROR", "EXECUTE_ACTION_TOKEN", "EXECUTE_ACTION_TOKEN_ERROR", "CLIENT_INFO", "CLIENT_INFO_ERROR", "CLIENT_REGISTER", "CLIENT_REGISTER_ERROR", "CLIENT_UPDATE", "CLIENT_UPDATE_ERROR", "CLIENT_DELETE", "CLIENT_DELETE_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "TOKEN_EXCHANGE", "TOKEN_EXCHANGE_ERROR", "OAUTH2_DEVICE_AUTH", "OAUTH2_DEVICE_AUTH_ERROR", "OAUTH2_DEVICE_VERIFY_USER_CODE", "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", "OAUTH2_DEVICE_CODE_TO_TOKEN", "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", "AUTHREQID_TO_TOKEN", "AUTHREQID_TO_TOKEN_ERROR", "PERMISSION_TOKEN", "PERMISSION_TOKEN_ERROR", "DELETE_ACCOUNT", "DELETE_ACCOUNT_ERROR", "PUSHED_AUTHORIZATION_REQUEST", "PUSHED_AUTHORIZATION_REQUEST_ERROR", "UNKNOWN", }; + public static final String[] names = { "LOGIN", "LOGIN_ERROR", "REGISTER", "REGISTER_ERROR", "LOGOUT", "LOGOUT_ERROR", "CODE_TO_TOKEN", "CODE_TO_TOKEN_ERROR", "CLIENT_LOGIN", "CLIENT_LOGIN_ERROR", "REFRESH_TOKEN", "REFRESH_TOKEN_ERROR", "VALIDATE_ACCESS_TOKEN", "VALIDATE_ACCESS_TOKEN_ERROR", "INTROSPECT_TOKEN", "INTROSPECT_TOKEN_ERROR", "FEDERATED_IDENTITY_LINK", "FEDERATED_IDENTITY_LINK_ERROR", "REMOVE_FEDERATED_IDENTITY", "REMOVE_FEDERATED_IDENTITY_ERROR", "UPDATE_EMAIL", "UPDATE_EMAIL_ERROR", "UPDATE_PROFILE", "UPDATE_PROFILE_ERROR", "UPDATE_PASSWORD", "UPDATE_PASSWORD_ERROR", "UPDATE_TOTP", "UPDATE_TOTP_ERROR", "VERIFY_EMAIL", "VERIFY_EMAIL_ERROR", "VERIFY_PROFILE", "VERIFY_PROFILE_ERROR", "REMOVE_TOTP", "REMOVE_TOTP_ERROR", "GRANT_CONSENT", "GRANT_CONSENT_ERROR", "UPDATE_CONSENT", "UPDATE_CONSENT_ERROR", "REVOKE_GRANT", "REVOKE_GRANT_ERROR", "SEND_VERIFY_EMAIL", "SEND_VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD", "SEND_RESET_PASSWORD_ERROR", "SEND_IDENTITY_PROVIDER_LINK", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "RESET_PASSWORD", "RESET_PASSWORD_ERROR", "RESTART_AUTHENTICATION", "RESTART_AUTHENTICATION_ERROR", "INVALID_SIGNATURE", "INVALID_SIGNATURE_ERROR", "REGISTER_NODE", "REGISTER_NODE_ERROR", "UNREGISTER_NODE", "UNREGISTER_NODE_ERROR", "USER_INFO_REQUEST", "USER_INFO_REQUEST_ERROR", "IDENTITY_PROVIDER_LINK_ACCOUNT", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "IDENTITY_PROVIDER_LOGIN", "IDENTITY_PROVIDER_LOGIN_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "IDENTITY_PROVIDER_RESPONSE", "IDENTITY_PROVIDER_RESPONSE_ERROR", "IDENTITY_PROVIDER_RETRIEVE_TOKEN", "IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR", "IMPERSONATE", "IMPERSONATE_ERROR", "CUSTOM_REQUIRED_ACTION", "CUSTOM_REQUIRED_ACTION_ERROR", "EXECUTE_ACTIONS", "EXECUTE_ACTIONS_ERROR", "EXECUTE_ACTION_TOKEN", "EXECUTE_ACTION_TOKEN_ERROR", "CLIENT_INFO", "CLIENT_INFO_ERROR", "CLIENT_REGISTER", "CLIENT_REGISTER_ERROR", "CLIENT_UPDATE", "CLIENT_UPDATE_ERROR", "CLIENT_DELETE", "CLIENT_DELETE_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "TOKEN_EXCHANGE", "TOKEN_EXCHANGE_ERROR", "OAUTH2_DEVICE_AUTH", "OAUTH2_DEVICE_AUTH_ERROR", "OAUTH2_DEVICE_VERIFY_USER_CODE", "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", "OAUTH2_DEVICE_CODE_TO_TOKEN", "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", "AUTHREQID_TO_TOKEN", "AUTHREQID_TO_TOKEN_ERROR", "PERMISSION_TOKEN", "PERMISSION_TOKEN_ERROR", "DELETE_ACCOUNT", "DELETE_ACCOUNT_ERROR", "PUSHED_AUTHORIZATION_REQUEST", "PUSHED_AUTHORIZATION_REQUEST_ERROR", "USER_DISABLED_BY_PERMANENT_LOCKOUT", "USER_DISABLED_BY_PERMANENT_LOCKOUT_ERROR", "USER_DISABLED_BY_TEMPORARY_LOCKOUT", "USER_DISABLED_BY_TEMPORARY_LOCKOUT_ERROR", "OAUTH2_EXTENSION_GRANT", "OAUTH2_EXTENSION_GRANT_ERROR", "FEDERATED_IDENTITY_OVERRIDE_LINK", "FEDERATED_IDENTITY_OVERRIDE_LINK_ERROR", "UPDATE_CREDENTIAL", "UPDATE_CREDENTIAL_ERROR", "REMOVE_CREDENTIAL", "REMOVE_CREDENTIAL_ERROR", "INVITE_ORG", "INVITE_ORG_ERROR", "UNKNOWN", }; public static String name(int e) { return names[e]; } } diff --git a/keycloak-event-emitter/src/main/flatbuffers/flatbuffers/events/ResourceType.java b/keycloak-event-emitter/src/main/flatbuffers/flatbuffers/events/ResourceType.java index d3b7ec2..c6adfe1 100644 --- a/keycloak-event-emitter/src/main/flatbuffers/flatbuffers/events/ResourceType.java +++ b/keycloak-event-emitter/src/main/flatbuffers/flatbuffers/events/ResourceType.java @@ -13,34 +13,38 @@ private ResourceType() { } public static final byte AUTH_EXECUTION_FLOW = 5; public static final byte AUTH_EXECUTION = 6; public static final byte AUTHENTICATOR_CONFIG = 7; - public static final byte REQUIRED_ACTION = 8; - public static final byte IDENTITY_PROVIDER = 9; - public static final byte IDENTITY_PROVIDER_MAPPER = 10; - public static final byte PROTOCOL_MAPPER = 11; - public static final byte USER = 12; - public static final byte USER_LOGIN_FAILURE = 13; - public static final byte USER_SESSION = 14; - public static final byte USER_FEDERATION_PROVIDER = 15; - public static final byte USER_FEDERATION_MAPPER = 16; - public static final byte GROUP = 17; - public static final byte GROUP_MEMBERSHIP = 18; - public static final byte CLIENT = 19; - public static final byte CLIENT_INITIAL_ACCESS_MODEL = 20; - public static final byte CLIENT_ROLE = 21; - public static final byte CLIENT_ROLE_MAPPING = 22; - public static final byte CLIENT_SCOPE = 23; - public static final byte CLIENT_SCOPE_MAPPING = 24; - public static final byte CLIENT_SCOPE_CLIENT_MAPPING = 25; - public static final byte CLUSTER_NODE = 26; - public static final byte COMPONENT = 27; - public static final byte AUTHORIZATION_RESOURCE_SERVER = 28; - public static final byte AUTHORIZATION_RESOURCE = 29; - public static final byte AUTHORIZATION_SCOPE = 30; - public static final byte AUTHORIZATION_POLICY = 31; - public static final byte CUSTOM = 32; - public static final byte UNKNOWN = 33; + public static final byte REQUIRED_ACTION_CONFIG = 8; + public static final byte REQUIRED_ACTION = 9; + public static final byte IDENTITY_PROVIDER = 10; + public static final byte IDENTITY_PROVIDER_MAPPER = 11; + public static final byte PROTOCOL_MAPPER = 12; + public static final byte USER = 13; + public static final byte USER_LOGIN_FAILURE = 14; + public static final byte USER_SESSION = 15; + public static final byte USER_FEDERATION_PROVIDER = 16; + public static final byte USER_FEDERATION_MAPPER = 17; + public static final byte GROUP = 18; + public static final byte GROUP_MEMBERSHIP = 19; + public static final byte CLIENT = 20; + public static final byte CLIENT_INITIAL_ACCESS_MODEL = 21; + public static final byte CLIENT_ROLE = 22; + public static final byte CLIENT_ROLE_MAPPING = 23; + public static final byte CLIENT_SCOPE = 24; + public static final byte CLIENT_SCOPE_MAPPING = 25; + public static final byte CLIENT_SCOPE_CLIENT_MAPPING = 26; + public static final byte CLUSTER_NODE = 27; + public static final byte COMPONENT = 28; + public static final byte AUTHORIZATION_RESOURCE_SERVER = 29; + public static final byte AUTHORIZATION_RESOURCE = 30; + public static final byte AUTHORIZATION_SCOPE = 31; + public static final byte AUTHORIZATION_POLICY = 32; + public static final byte CUSTOM = 33; + public static final byte USER_PROFILE = 34; + public static final byte ORGANIZATION = 35; + public static final byte ORGANIZATION_MEMBERSHIP = 36; + public static final byte UNKNOWN = 37; - public static final String[] names = { "REALM", "REALM_ROLE", "REALM_ROLE_MAPPING", "REALM_SCOPE_MAPPING", "AUTH_FLOW", "AUTH_EXECUTION_FLOW", "AUTH_EXECUTION", "AUTHENTICATOR_CONFIG", "REQUIRED_ACTION", "IDENTITY_PROVIDER", "IDENTITY_PROVIDER_MAPPER", "PROTOCOL_MAPPER", "USER", "USER_LOGIN_FAILURE", "USER_SESSION", "USER_FEDERATION_PROVIDER", "USER_FEDERATION_MAPPER", "GROUP", "GROUP_MEMBERSHIP", "CLIENT", "CLIENT_INITIAL_ACCESS_MODEL", "CLIENT_ROLE", "CLIENT_ROLE_MAPPING", "CLIENT_SCOPE", "CLIENT_SCOPE_MAPPING", "CLIENT_SCOPE_CLIENT_MAPPING", "CLUSTER_NODE", "COMPONENT", "AUTHORIZATION_RESOURCE_SERVER", "AUTHORIZATION_RESOURCE", "AUTHORIZATION_SCOPE", "AUTHORIZATION_POLICY", "CUSTOM", "UNKNOWN", }; + public static final String[] names = { "REALM", "REALM_ROLE", "REALM_ROLE_MAPPING", "REALM_SCOPE_MAPPING", "AUTH_FLOW", "AUTH_EXECUTION_FLOW", "AUTH_EXECUTION", "AUTHENTICATOR_CONFIG", "REQUIRED_ACTION_CONFIG", "REQUIRED_ACTION", "IDENTITY_PROVIDER", "IDENTITY_PROVIDER_MAPPER", "PROTOCOL_MAPPER", "USER", "USER_LOGIN_FAILURE", "USER_SESSION", "USER_FEDERATION_PROVIDER", "USER_FEDERATION_MAPPER", "GROUP", "GROUP_MEMBERSHIP", "CLIENT", "CLIENT_INITIAL_ACCESS_MODEL", "CLIENT_ROLE", "CLIENT_ROLE_MAPPING", "CLIENT_SCOPE", "CLIENT_SCOPE_MAPPING", "CLIENT_SCOPE_CLIENT_MAPPING", "CLUSTER_NODE", "COMPONENT", "AUTHORIZATION_RESOURCE_SERVER", "AUTHORIZATION_RESOURCE", "AUTHORIZATION_SCOPE", "AUTHORIZATION_POLICY", "CUSTOM", "USER_PROFILE", "ORGANIZATION", "ORGANIZATION_MEMBERSHIP", "UNKNOWN", }; public static String name(int e) { return names[e]; } } diff --git a/keycloak-event-emitter/src/main/java/flatbuffers/events/AdminEvent.java b/keycloak-event-emitter/src/main/java/flatbuffers/events/AdminEvent.java index a56cdfe..2b1eeb5 100644 --- a/keycloak-event-emitter/src/main/java/flatbuffers/events/AdminEvent.java +++ b/keycloak-event-emitter/src/main/java/flatbuffers/events/AdminEvent.java @@ -32,13 +32,13 @@ public final class AdminEvent extends Table { public String realmId() { int o = __offset(8); return o != 0 ? __string(o + bb_pos) : null; } public ByteBuffer realmIdAsByteBuffer() { return __vector_as_bytebuffer(8, 1); } public ByteBuffer realmIdInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 1); } - public AuthDetails authDetails() { return authDetails(new AuthDetails()); } - public AuthDetails authDetails(AuthDetails obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } - public Tuple details(int j) { return details(new Tuple(), j); } - public Tuple details(Tuple obj, int j) { int o = __offset(12); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public flatbuffers.events.AuthDetails authDetails() { return authDetails(new flatbuffers.events.AuthDetails()); } + public flatbuffers.events.AuthDetails authDetails(flatbuffers.events.AuthDetails obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public flatbuffers.events.Tuple details(int j) { return details(new flatbuffers.events.Tuple(), j); } + public flatbuffers.events.Tuple details(flatbuffers.events.Tuple obj, int j) { int o = __offset(12); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } public int detailsLength() { int o = __offset(12); return o != 0 ? __vector_len(o) : 0; } - public Tuple.Vector detailsVector() { return detailsVector(new Tuple.Vector()); } - public Tuple.Vector detailsVector(Tuple.Vector obj) { int o = __offset(12); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } + public flatbuffers.events.Tuple.Vector detailsVector() { return detailsVector(new flatbuffers.events.Tuple.Vector()); } + public flatbuffers.events.Tuple.Vector detailsVector(flatbuffers.events.Tuple.Vector obj) { int o = __offset(12); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } public byte resourceType() { int o = __offset(14); return o != 0 ? bb.get(o + bb_pos) : 0; } public byte operationType() { int o = __offset(16); return o != 0 ? bb.get(o + bb_pos) : 0; } public String resourcePath() { int o = __offset(18); return o != 0 ? __string(o + bb_pos) : null; } diff --git a/keycloak-event-emitter/src/main/java/flatbuffers/events/Event.java b/keycloak-event-emitter/src/main/java/flatbuffers/events/Event.java index b2a7c02..bc441aa 100644 --- a/keycloak-event-emitter/src/main/java/flatbuffers/events/Event.java +++ b/keycloak-event-emitter/src/main/java/flatbuffers/events/Event.java @@ -48,11 +48,11 @@ public final class Event extends Table { public String error() { int o = __offset(20); return o != 0 ? __string(o + bb_pos) : null; } public ByteBuffer errorAsByteBuffer() { return __vector_as_bytebuffer(20, 1); } public ByteBuffer errorInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 20, 1); } - public Tuple details(int j) { return details(new Tuple(), j); } - public Tuple details(Tuple obj, int j) { int o = __offset(22); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public flatbuffers.events.Tuple details(int j) { return details(new flatbuffers.events.Tuple(), j); } + public flatbuffers.events.Tuple details(flatbuffers.events.Tuple obj, int j) { int o = __offset(22); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } public int detailsLength() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } - public Tuple.Vector detailsVector() { return detailsVector(new Tuple.Vector()); } - public Tuple.Vector detailsVector(Tuple.Vector obj) { int o = __offset(22); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } + public flatbuffers.events.Tuple.Vector detailsVector() { return detailsVector(new flatbuffers.events.Tuple.Vector()); } + public flatbuffers.events.Tuple.Vector detailsVector(flatbuffers.events.Tuple.Vector obj) { int o = __offset(22); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } public static int createEvent(FlatBufferBuilder builder, long uid, diff --git a/keycloak-event-emitter/src/main/java/flatbuffers/events/EventType.java b/keycloak-event-emitter/src/main/java/flatbuffers/events/EventType.java index cf198a2..c130b9d 100644 --- a/keycloak-event-emitter/src/main/java/flatbuffers/events/EventType.java +++ b/keycloak-event-emitter/src/main/java/flatbuffers/events/EventType.java @@ -109,9 +109,23 @@ private EventType() { } public static final byte DELETE_ACCOUNT_ERROR = 101; public static final byte PUSHED_AUTHORIZATION_REQUEST = 102; public static final byte PUSHED_AUTHORIZATION_REQUEST_ERROR = 103; - public static final byte UNKNOWN = 104; + public static final byte USER_DISABLED_BY_PERMANENT_LOCKOUT = 104; + public static final byte USER_DISABLED_BY_PERMANENT_LOCKOUT_ERROR = 105; + public static final byte USER_DISABLED_BY_TEMPORARY_LOCKOUT = 106; + public static final byte USER_DISABLED_BY_TEMPORARY_LOCKOUT_ERROR = 107; + public static final byte OAUTH2_EXTENSION_GRANT = 108; + public static final byte OAUTH2_EXTENSION_GRANT_ERROR = 109; + public static final byte FEDERATED_IDENTITY_OVERRIDE_LINK = 110; + public static final byte FEDERATED_IDENTITY_OVERRIDE_LINK_ERROR = 111; + public static final byte UPDATE_CREDENTIAL = 112; + public static final byte UPDATE_CREDENTIAL_ERROR = 113; + public static final byte REMOVE_CREDENTIAL = 114; + public static final byte REMOVE_CREDENTIAL_ERROR = 115; + public static final byte INVITE_ORG = 116; + public static final byte INVITE_ORG_ERROR = 117; + public static final byte UNKNOWN = 118; - public static final String[] names = { "LOGIN", "LOGIN_ERROR", "REGISTER", "REGISTER_ERROR", "LOGOUT", "LOGOUT_ERROR", "CODE_TO_TOKEN", "CODE_TO_TOKEN_ERROR", "CLIENT_LOGIN", "CLIENT_LOGIN_ERROR", "REFRESH_TOKEN", "REFRESH_TOKEN_ERROR", "VALIDATE_ACCESS_TOKEN", "VALIDATE_ACCESS_TOKEN_ERROR", "INTROSPECT_TOKEN", "INTROSPECT_TOKEN_ERROR", "FEDERATED_IDENTITY_LINK", "FEDERATED_IDENTITY_LINK_ERROR", "REMOVE_FEDERATED_IDENTITY", "REMOVE_FEDERATED_IDENTITY_ERROR", "UPDATE_EMAIL", "UPDATE_EMAIL_ERROR", "UPDATE_PROFILE", "UPDATE_PROFILE_ERROR", "UPDATE_PASSWORD", "UPDATE_PASSWORD_ERROR", "UPDATE_TOTP", "UPDATE_TOTP_ERROR", "VERIFY_EMAIL", "VERIFY_EMAIL_ERROR", "VERIFY_PROFILE", "VERIFY_PROFILE_ERROR", "REMOVE_TOTP", "REMOVE_TOTP_ERROR", "GRANT_CONSENT", "GRANT_CONSENT_ERROR", "UPDATE_CONSENT", "UPDATE_CONSENT_ERROR", "REVOKE_GRANT", "REVOKE_GRANT_ERROR", "SEND_VERIFY_EMAIL", "SEND_VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD", "SEND_RESET_PASSWORD_ERROR", "SEND_IDENTITY_PROVIDER_LINK", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "RESET_PASSWORD", "RESET_PASSWORD_ERROR", "RESTART_AUTHENTICATION", "RESTART_AUTHENTICATION_ERROR", "INVALID_SIGNATURE", "INVALID_SIGNATURE_ERROR", "REGISTER_NODE", "REGISTER_NODE_ERROR", "UNREGISTER_NODE", "UNREGISTER_NODE_ERROR", "USER_INFO_REQUEST", "USER_INFO_REQUEST_ERROR", "IDENTITY_PROVIDER_LINK_ACCOUNT", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "IDENTITY_PROVIDER_LOGIN", "IDENTITY_PROVIDER_LOGIN_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "IDENTITY_PROVIDER_RESPONSE", "IDENTITY_PROVIDER_RESPONSE_ERROR", "IDENTITY_PROVIDER_RETRIEVE_TOKEN", "IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR", "IMPERSONATE", "IMPERSONATE_ERROR", "CUSTOM_REQUIRED_ACTION", "CUSTOM_REQUIRED_ACTION_ERROR", "EXECUTE_ACTIONS", "EXECUTE_ACTIONS_ERROR", "EXECUTE_ACTION_TOKEN", "EXECUTE_ACTION_TOKEN_ERROR", "CLIENT_INFO", "CLIENT_INFO_ERROR", "CLIENT_REGISTER", "CLIENT_REGISTER_ERROR", "CLIENT_UPDATE", "CLIENT_UPDATE_ERROR", "CLIENT_DELETE", "CLIENT_DELETE_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "TOKEN_EXCHANGE", "TOKEN_EXCHANGE_ERROR", "OAUTH2_DEVICE_AUTH", "OAUTH2_DEVICE_AUTH_ERROR", "OAUTH2_DEVICE_VERIFY_USER_CODE", "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", "OAUTH2_DEVICE_CODE_TO_TOKEN", "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", "AUTHREQID_TO_TOKEN", "AUTHREQID_TO_TOKEN_ERROR", "PERMISSION_TOKEN", "PERMISSION_TOKEN_ERROR", "DELETE_ACCOUNT", "DELETE_ACCOUNT_ERROR", "PUSHED_AUTHORIZATION_REQUEST", "PUSHED_AUTHORIZATION_REQUEST_ERROR", "UNKNOWN", }; + public static final String[] names = { "LOGIN", "LOGIN_ERROR", "REGISTER", "REGISTER_ERROR", "LOGOUT", "LOGOUT_ERROR", "CODE_TO_TOKEN", "CODE_TO_TOKEN_ERROR", "CLIENT_LOGIN", "CLIENT_LOGIN_ERROR", "REFRESH_TOKEN", "REFRESH_TOKEN_ERROR", "VALIDATE_ACCESS_TOKEN", "VALIDATE_ACCESS_TOKEN_ERROR", "INTROSPECT_TOKEN", "INTROSPECT_TOKEN_ERROR", "FEDERATED_IDENTITY_LINK", "FEDERATED_IDENTITY_LINK_ERROR", "REMOVE_FEDERATED_IDENTITY", "REMOVE_FEDERATED_IDENTITY_ERROR", "UPDATE_EMAIL", "UPDATE_EMAIL_ERROR", "UPDATE_PROFILE", "UPDATE_PROFILE_ERROR", "UPDATE_PASSWORD", "UPDATE_PASSWORD_ERROR", "UPDATE_TOTP", "UPDATE_TOTP_ERROR", "VERIFY_EMAIL", "VERIFY_EMAIL_ERROR", "VERIFY_PROFILE", "VERIFY_PROFILE_ERROR", "REMOVE_TOTP", "REMOVE_TOTP_ERROR", "GRANT_CONSENT", "GRANT_CONSENT_ERROR", "UPDATE_CONSENT", "UPDATE_CONSENT_ERROR", "REVOKE_GRANT", "REVOKE_GRANT_ERROR", "SEND_VERIFY_EMAIL", "SEND_VERIFY_EMAIL_ERROR", "SEND_RESET_PASSWORD", "SEND_RESET_PASSWORD_ERROR", "SEND_IDENTITY_PROVIDER_LINK", "SEND_IDENTITY_PROVIDER_LINK_ERROR", "RESET_PASSWORD", "RESET_PASSWORD_ERROR", "RESTART_AUTHENTICATION", "RESTART_AUTHENTICATION_ERROR", "INVALID_SIGNATURE", "INVALID_SIGNATURE_ERROR", "REGISTER_NODE", "REGISTER_NODE_ERROR", "UNREGISTER_NODE", "UNREGISTER_NODE_ERROR", "USER_INFO_REQUEST", "USER_INFO_REQUEST_ERROR", "IDENTITY_PROVIDER_LINK_ACCOUNT", "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", "IDENTITY_PROVIDER_LOGIN", "IDENTITY_PROVIDER_LOGIN_ERROR", "IDENTITY_PROVIDER_FIRST_LOGIN", "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR", "IDENTITY_PROVIDER_POST_LOGIN", "IDENTITY_PROVIDER_POST_LOGIN_ERROR", "IDENTITY_PROVIDER_RESPONSE", "IDENTITY_PROVIDER_RESPONSE_ERROR", "IDENTITY_PROVIDER_RETRIEVE_TOKEN", "IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR", "IMPERSONATE", "IMPERSONATE_ERROR", "CUSTOM_REQUIRED_ACTION", "CUSTOM_REQUIRED_ACTION_ERROR", "EXECUTE_ACTIONS", "EXECUTE_ACTIONS_ERROR", "EXECUTE_ACTION_TOKEN", "EXECUTE_ACTION_TOKEN_ERROR", "CLIENT_INFO", "CLIENT_INFO_ERROR", "CLIENT_REGISTER", "CLIENT_REGISTER_ERROR", "CLIENT_UPDATE", "CLIENT_UPDATE_ERROR", "CLIENT_DELETE", "CLIENT_DELETE_ERROR", "CLIENT_INITIATED_ACCOUNT_LINKING", "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", "TOKEN_EXCHANGE", "TOKEN_EXCHANGE_ERROR", "OAUTH2_DEVICE_AUTH", "OAUTH2_DEVICE_AUTH_ERROR", "OAUTH2_DEVICE_VERIFY_USER_CODE", "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", "OAUTH2_DEVICE_CODE_TO_TOKEN", "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", "AUTHREQID_TO_TOKEN", "AUTHREQID_TO_TOKEN_ERROR", "PERMISSION_TOKEN", "PERMISSION_TOKEN_ERROR", "DELETE_ACCOUNT", "DELETE_ACCOUNT_ERROR", "PUSHED_AUTHORIZATION_REQUEST", "PUSHED_AUTHORIZATION_REQUEST_ERROR", "USER_DISABLED_BY_PERMANENT_LOCKOUT", "USER_DISABLED_BY_PERMANENT_LOCKOUT_ERROR", "USER_DISABLED_BY_TEMPORARY_LOCKOUT", "USER_DISABLED_BY_TEMPORARY_LOCKOUT_ERROR", "OAUTH2_EXTENSION_GRANT", "OAUTH2_EXTENSION_GRANT_ERROR", "FEDERATED_IDENTITY_OVERRIDE_LINK", "FEDERATED_IDENTITY_OVERRIDE_LINK_ERROR", "UPDATE_CREDENTIAL", "UPDATE_CREDENTIAL_ERROR", "REMOVE_CREDENTIAL", "REMOVE_CREDENTIAL_ERROR", "INVITE_ORG", "INVITE_ORG_ERROR", "UNKNOWN", }; public static String name(int e) { return names[e]; } } diff --git a/keycloak-event-emitter/src/main/java/flatbuffers/events/ResourceType.java b/keycloak-event-emitter/src/main/java/flatbuffers/events/ResourceType.java index d3b7ec2..c6adfe1 100644 --- a/keycloak-event-emitter/src/main/java/flatbuffers/events/ResourceType.java +++ b/keycloak-event-emitter/src/main/java/flatbuffers/events/ResourceType.java @@ -13,34 +13,38 @@ private ResourceType() { } public static final byte AUTH_EXECUTION_FLOW = 5; public static final byte AUTH_EXECUTION = 6; public static final byte AUTHENTICATOR_CONFIG = 7; - public static final byte REQUIRED_ACTION = 8; - public static final byte IDENTITY_PROVIDER = 9; - public static final byte IDENTITY_PROVIDER_MAPPER = 10; - public static final byte PROTOCOL_MAPPER = 11; - public static final byte USER = 12; - public static final byte USER_LOGIN_FAILURE = 13; - public static final byte USER_SESSION = 14; - public static final byte USER_FEDERATION_PROVIDER = 15; - public static final byte USER_FEDERATION_MAPPER = 16; - public static final byte GROUP = 17; - public static final byte GROUP_MEMBERSHIP = 18; - public static final byte CLIENT = 19; - public static final byte CLIENT_INITIAL_ACCESS_MODEL = 20; - public static final byte CLIENT_ROLE = 21; - public static final byte CLIENT_ROLE_MAPPING = 22; - public static final byte CLIENT_SCOPE = 23; - public static final byte CLIENT_SCOPE_MAPPING = 24; - public static final byte CLIENT_SCOPE_CLIENT_MAPPING = 25; - public static final byte CLUSTER_NODE = 26; - public static final byte COMPONENT = 27; - public static final byte AUTHORIZATION_RESOURCE_SERVER = 28; - public static final byte AUTHORIZATION_RESOURCE = 29; - public static final byte AUTHORIZATION_SCOPE = 30; - public static final byte AUTHORIZATION_POLICY = 31; - public static final byte CUSTOM = 32; - public static final byte UNKNOWN = 33; + public static final byte REQUIRED_ACTION_CONFIG = 8; + public static final byte REQUIRED_ACTION = 9; + public static final byte IDENTITY_PROVIDER = 10; + public static final byte IDENTITY_PROVIDER_MAPPER = 11; + public static final byte PROTOCOL_MAPPER = 12; + public static final byte USER = 13; + public static final byte USER_LOGIN_FAILURE = 14; + public static final byte USER_SESSION = 15; + public static final byte USER_FEDERATION_PROVIDER = 16; + public static final byte USER_FEDERATION_MAPPER = 17; + public static final byte GROUP = 18; + public static final byte GROUP_MEMBERSHIP = 19; + public static final byte CLIENT = 20; + public static final byte CLIENT_INITIAL_ACCESS_MODEL = 21; + public static final byte CLIENT_ROLE = 22; + public static final byte CLIENT_ROLE_MAPPING = 23; + public static final byte CLIENT_SCOPE = 24; + public static final byte CLIENT_SCOPE_MAPPING = 25; + public static final byte CLIENT_SCOPE_CLIENT_MAPPING = 26; + public static final byte CLUSTER_NODE = 27; + public static final byte COMPONENT = 28; + public static final byte AUTHORIZATION_RESOURCE_SERVER = 29; + public static final byte AUTHORIZATION_RESOURCE = 30; + public static final byte AUTHORIZATION_SCOPE = 31; + public static final byte AUTHORIZATION_POLICY = 32; + public static final byte CUSTOM = 33; + public static final byte USER_PROFILE = 34; + public static final byte ORGANIZATION = 35; + public static final byte ORGANIZATION_MEMBERSHIP = 36; + public static final byte UNKNOWN = 37; - public static final String[] names = { "REALM", "REALM_ROLE", "REALM_ROLE_MAPPING", "REALM_SCOPE_MAPPING", "AUTH_FLOW", "AUTH_EXECUTION_FLOW", "AUTH_EXECUTION", "AUTHENTICATOR_CONFIG", "REQUIRED_ACTION", "IDENTITY_PROVIDER", "IDENTITY_PROVIDER_MAPPER", "PROTOCOL_MAPPER", "USER", "USER_LOGIN_FAILURE", "USER_SESSION", "USER_FEDERATION_PROVIDER", "USER_FEDERATION_MAPPER", "GROUP", "GROUP_MEMBERSHIP", "CLIENT", "CLIENT_INITIAL_ACCESS_MODEL", "CLIENT_ROLE", "CLIENT_ROLE_MAPPING", "CLIENT_SCOPE", "CLIENT_SCOPE_MAPPING", "CLIENT_SCOPE_CLIENT_MAPPING", "CLUSTER_NODE", "COMPONENT", "AUTHORIZATION_RESOURCE_SERVER", "AUTHORIZATION_RESOURCE", "AUTHORIZATION_SCOPE", "AUTHORIZATION_POLICY", "CUSTOM", "UNKNOWN", }; + public static final String[] names = { "REALM", "REALM_ROLE", "REALM_ROLE_MAPPING", "REALM_SCOPE_MAPPING", "AUTH_FLOW", "AUTH_EXECUTION_FLOW", "AUTH_EXECUTION", "AUTHENTICATOR_CONFIG", "REQUIRED_ACTION_CONFIG", "REQUIRED_ACTION", "IDENTITY_PROVIDER", "IDENTITY_PROVIDER_MAPPER", "PROTOCOL_MAPPER", "USER", "USER_LOGIN_FAILURE", "USER_SESSION", "USER_FEDERATION_PROVIDER", "USER_FEDERATION_MAPPER", "GROUP", "GROUP_MEMBERSHIP", "CLIENT", "CLIENT_INITIAL_ACCESS_MODEL", "CLIENT_ROLE", "CLIENT_ROLE_MAPPING", "CLIENT_SCOPE", "CLIENT_SCOPE_MAPPING", "CLIENT_SCOPE_CLIENT_MAPPING", "CLUSTER_NODE", "COMPONENT", "AUTHORIZATION_RESOURCE_SERVER", "AUTHORIZATION_RESOURCE", "AUTHORIZATION_SCOPE", "AUTHORIZATION_POLICY", "CUSTOM", "USER_PROFILE", "ORGANIZATION", "ORGANIZATION_MEMBERSHIP", "UNKNOWN", }; public static String name(int e) { return names[e]; } } diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/Container.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/Container.java deleted file mode 100644 index ca51b11..0000000 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/Container.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.cloudtrust.keycloak.eventemitter; - -public class Container { - - private String type; - private String obj; - - public Container() { - } - - public Container(String type, String obj) { - this.type = type; - this.obj = obj; - } - - public String getType() { - return type; - } - - public String getObj() { - return obj; - } -} diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterException.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterException.java deleted file mode 100644 index e6a9f1f..0000000 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterException.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.cloudtrust.keycloak.eventemitter; - -/** - * Exception for EventEmitter Provider - */ -class EventEmitterException extends Exception { - private static final long serialVersionUID = 7324694216864444008L; - - EventEmitterException(String message) { - super(message); - } -} diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProvider.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProvider.java deleted file mode 100644 index 3365502..0000000 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProvider.java +++ /dev/null @@ -1,290 +0,0 @@ -package io.cloudtrust.keycloak.eventemitter; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.google.common.base.Strings; -import io.cloudtrust.keycloak.customevent.ExtendedAdminEvent; -import io.cloudtrust.keycloak.customevent.ExtendedAuthDetails; -import io.cloudtrust.keycloak.customevent.IdentifiedAdminEvent; -import io.cloudtrust.keycloak.customevent.IdentifiedEvent; -import io.cloudtrust.keycloak.snowflake.IdGenerator; - -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.jboss.logging.Logger; -import org.keycloak.events.Details; -import org.keycloak.events.Event; -import org.keycloak.events.EventListenerProvider; -import org.keycloak.events.admin.AdminEvent; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserModel; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Base64; -import java.util.HashMap; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * EventEmitterProvider. - * Provider which emit a serialized version of the event to the targetUri. - * Serialization format can either be flatbuffer or json according to constructor parameter. - */ -public class EventEmitterProvider implements EventListenerProvider { - private static final Logger logger = Logger.getLogger(EventEmitterProvider.class); - - public static final String KEYCLOAK_BRIDGE_SECRET_TOKEN = "CT_KEYCLOAK_BRIDGE_SECRET_TOKEN"; - public static final String HOSTNAME = "HOSTNAME"; - - private static final String BASIC = "Basic"; - private static final String AUTHORIZATION = "Authorization"; - - private static final int HTTP_OK = 200; - - interface EventSender { - void send(T event) throws EventEmitterException, IOException; - } - - private KeycloakSession keycloakSession; - private CloseableHttpClient httpClient; - private HttpClientContext httpContext; - private IdGenerator idGenerator; - private LinkedBlockingQueue pendingEvents; - private LinkedBlockingQueue pendingAdminEvents; - private String targetUri; - private String username; - private String secretToken; - private SerialisationFormat format; - private RequestConfig requestConfig; - - /** - * Constructor. - * - * @param keycloakSession session context - * @param httpClient to send serialized events to target server - * @param idGenerator for unique event ID genration - * @param targetUri where serialized events are sent - * @param format of the serialized events - * @param pendingEvents to send due to failure during previous trial - * @param pendingAdminEvents to send due to failure during previous trial - * @param requestConfig configuration used for HTTP calls - */ - EventEmitterProvider(KeycloakSession keycloakSession, - CloseableHttpClient httpClient, IdGenerator idGenerator, - String targetUri, SerialisationFormat format, - LinkedBlockingQueue pendingEvents, - LinkedBlockingQueue pendingAdminEvents, - RequestConfig requestConfig) { - logger.debug("EventEmitterProvider constructor call"); - this.keycloakSession = keycloakSession; - this.httpClient = httpClient; - this.httpContext = HttpClientContext.create(); - this.idGenerator = idGenerator; - this.targetUri = targetUri; - this.format = format; - this.pendingEvents = pendingEvents; - this.pendingAdminEvents = pendingAdminEvents; - this.requestConfig = requestConfig; - - // Secret token - secretToken = checkEnv(KEYCLOAK_BRIDGE_SECRET_TOKEN); - // Hostname - username = checkEnv(HOSTNAME); - } - - private String checkEnv(String key) { - String env = System.getenv(key); - if (env != null) { - return env; - } - String message = "Cannot find the environment variable '" + key + "'"; - logger.error(message); - throw new IllegalStateException(message); - } - - public void onEvent(Event event) { - logger.debug("EventEmitterProvider onEvent call for Event"); - completeEventAttributes(event); - logger.debugf("Pending Events to send stored in buffer: %d", pendingEvents.size()); - long uid = idGenerator.nextValidId(); - IdentifiedEvent identifiedEvent = new IdentifiedEvent(uid, event); - - while (!pendingEvents.offer(identifiedEvent)) { - Event skippedEvent = pendingEvents.poll(); - if (skippedEvent != null) { - String strEvent = null; - try { - strEvent = SerialisationUtils.toJson(skippedEvent); - } catch (JsonProcessingException e) { - strEvent = "SerializationFailure"; - } - logger.errorf("Event dropped(%s) due to full queue", strEvent); - } - } - - sendEvents(); - } - - - public void onEvent(AdminEvent adminEvent, boolean b) { - logger.debug("EventEmitterProvider onEvent call for AdminEvent"); - logger.debugf("Pending AdminEvents to send stored in buffer: %d", pendingAdminEvents.size()); - long uid = idGenerator.nextValidId(); - IdentifiedAdminEvent identifiedAdminEvent = new IdentifiedAdminEvent(uid, adminEvent); - ExtendedAdminEvent customAdminEvent = completeAdminEventAttributes(identifiedAdminEvent); - - while (!pendingAdminEvents.offer(customAdminEvent)) { - AdminEvent skippedAdminEvent = pendingAdminEvents.poll(); - if (skippedAdminEvent != null) { - String strAdminEvent = null; - try { - strAdminEvent = SerialisationUtils.toJson(skippedAdminEvent); - } catch (JsonProcessingException e) { - strAdminEvent = "SerializationFailure"; - } - logger.errorf("AdminEvent dropped(%s) due to full queue", strAdminEvent); - } - } - - sendEvents(); - } - - public void close() { - //Nothing to do - } - - private void sendEvents() { - switch (format) { - case FLATBUFFER: - sendEventsWithFlatbufferFormat(); - break; - case JSON: - sendEventsWithJsonFormat(); - break; - default: - logger.infov("Unknown format type (%s), JSON will be used", format.name()); - sendEventsWithJsonFormat(); - } - } - - - private void sendEvents(LinkedBlockingQueue queue, EventSender eventProcessor) { - int pendingEventsSize = queue.size(); - for (int i = 0; i < pendingEventsSize; i++) { - T event = queue.poll(); - - if (event == null) { - return; - } - - try { - eventProcessor.send(event); - } catch (EventEmitterException | IOException e) { - String repushed = queue.offer(event) ? "success" : "failure"; - logger.infof("Failed to send %s(ID=%s), try again later. Re-push: %s", event.getClass().getName(), event.getUid(), repushed); - logger.debug("Failed to serialize or send event", e); - return; - } - } - } - - private void sendEventsWithJsonFormat() { - sendEvents(pendingEvents, e -> sendJson(SerialisationUtils.toJson(e))); - sendEvents(pendingAdminEvents, e -> sendJson(SerialisationUtils.toJson(e))); - } - - private void sendEventsWithFlatbufferFormat() { - sendEvents(pendingEvents, e -> sendBytes(SerialisationUtils.toFlat(e), Event.class.getSimpleName())); - sendEvents(pendingAdminEvents, e -> sendBytes(SerialisationUtils.toFlat(e), AdminEvent.class.getSimpleName())); - } - - private void sendBytes(ByteBuffer buffer, String type) throws IOException, EventEmitterException { - byte[] b = new byte[buffer.remaining()]; - buffer.get(b); - - String obj = Base64.getEncoder().encodeToString(b); - Container c = new Container(type, obj); - String json = SerialisationUtils.toJson(c); - sendJson(json); - } - - private void sendJson(String json) throws IOException, EventEmitterException { - HttpPost httpPost = new HttpPost(targetUri); - httpPost.setConfig(requestConfig); - - StringEntity stringEntity = new StringEntity(json); - httpPost.setEntity(stringEntity); - httpPost.setHeader("Content-type", "application/json"); - - String token = username + ":" + secretToken; - String b64Token = Base64.getEncoder().encodeToString(token.getBytes()); - httpPost.setHeader(AUTHORIZATION, BASIC + " " + b64Token); - - send(httpPost); - } - - private void send(HttpPost httpPost) throws EventEmitterException, IOException { - try (CloseableHttpResponse response = httpClient.execute(httpPost, httpContext)) { - int status = response.getStatusLine().getStatusCode(); - - if (status != HTTP_OK) { - logger.errorv("Sending failure (Server response:{0})", status); - throw new EventEmitterException("Target server failure."); - } - } - } - - private void completeEventAttributes(Event event) { - // add username if missing - if (event.getDetails() == null) { - event.setDetails(new HashMap<>()); - } - String eventUsername = event.getDetails().get(Details.USERNAME); - if (!Strings.isNullOrEmpty(event.getUserId()) && Strings.isNullOrEmpty(eventUsername)) { - RealmModel realm = keycloakSession.realms().getRealm(event.getRealmId()); - // retrieve username from userId - UserModel user = keycloakSession.users().getUserById(realm, event.getUserId()); - if (user != null) { - event.getDetails().put(Details.USERNAME, user.getUsername()); - } - } - } - - private ExtendedAdminEvent completeAdminEventAttributes(IdentifiedAdminEvent adminEvent) { - ExtendedAdminEvent extendedAdminEvent = new ExtendedAdminEvent(adminEvent); - // add always missing agent username - ExtendedAuthDetails extendedAuthDetails = extendedAdminEvent.getAuthDetails(); - if (!Strings.isNullOrEmpty(extendedAuthDetails.getUserId())) { - RealmModel realm = keycloakSession.realms().getRealm(extendedAuthDetails.getRealmId()); - UserModel user = keycloakSession.users().getUserById(realm, extendedAuthDetails.getUserId()); - extendedAuthDetails.setUsername(user.getUsername()); - } - // add username if resource is a user - String resourcePath = extendedAdminEvent.getResourcePath(); - if (resourcePath != null && resourcePath.startsWith("users")) { - // parse userID - String pattern = "^users/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"; - Pattern r = Pattern.compile(pattern); - Matcher m = r.matcher(resourcePath); - if (m.matches()) { - String userId = m.group(1); - RealmModel realm = keycloakSession.realms().getRealm(adminEvent.getRealmId()); - // retrieve user - UserModel user = keycloakSession.users().getUserById(realm, userId); - extendedAdminEvent.getDetails().put("user_id", userId); - if (user != null) { - extendedAdminEvent.getDetails().put("username", user.getUsername()); - } - } - } - - return extendedAdminEvent; - } -} diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProviderFactory.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProviderFactory.java deleted file mode 100644 index 5b324b8..0000000 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/EventEmitterProviderFactory.java +++ /dev/null @@ -1,173 +0,0 @@ -package io.cloudtrust.keycloak.eventemitter; - -import io.cloudtrust.keycloak.customevent.ExtendedAdminEvent; -import io.cloudtrust.keycloak.customevent.IdentifiedEvent; -import io.cloudtrust.keycloak.snowflake.IdGenerator; - -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.config.RequestConfig.Builder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.jboss.logging.Logger; -import org.keycloak.Config; -import org.keycloak.events.EventListenerProvider; -import org.keycloak.events.EventListenerProviderFactory; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.KeycloakSessionFactory; -import org.keycloak.provider.ServerInfoAwareProviderFactory; - -import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.function.IntConsumer; - -/** - * Factory for EventEmitterProvider. - * Mandatory configuration parameters: - *
  • - *
      targetUri: valid HTTP target URI
    - *
      format: serialization format (FLATBUFFERS or JSON)
    - *
      bufferCapacity: capacity of buffer which stores events that cannot be sent to target
    - *
      keycloakId: keycloak Id configuration for snowflake Id generator
    - *
      datacenterId: datacenterId configuration for snowflake Id generator
    - *
  • - */ -public class EventEmitterProviderFactory implements EventListenerProviderFactory, ServerInfoAwareProviderFactory { - - private static final Logger logger = Logger.getLogger(EventEmitterProviderFactory.class); - - private static final String PROVIDER_NAME = "Event Emitter"; - public static final String PROVIDER_ID = "event-emitter"; - private static final String PROVIDER_VERSION = "1.0"; - - private static final String TARGET_URI_CONFIG_KEY = "targetUri"; - private static final String FORMAT_CONFIG_KEY = "format"; - private static final String BUFFER_CAPACITY_CONFIG_KEY = "bufferCapacity"; - private static final String SNOWFLAKE_KEYCLOAKID_CONFIG_KEY = "keycloakId"; - private static final String SNOWFLAKE_DATACENTERID_CONFIG_KEY = "datacenterId"; - private static final String CONNECT_TIMEOUT_MILLIS = "connectTimeoutMillis"; - private static final String CONNECTION_REQUEST_TIMEOUT_MILLIS = "connectionRequestTimeoutMillis"; - private static final String SOCKET_TIMEOUT_MILLIS = "socketTimeoutMillis"; - - private String targetUri; - private SerialisationFormat format; - private Integer bufferCapacity; - private Integer keycloakId; - private Integer datacenterId; - private RequestConfig requestConfig; - - private CloseableHttpClient httpClient; - private IdGenerator idGenerator; - private LinkedBlockingQueue pendingEventsToSend; - private LinkedBlockingQueue pendingAdminEventsToSend; - - - public EventListenerProvider create(KeycloakSession keycloakSession) { - logger.debug("EventEmitterProviderFactory creation"); - - return new EventEmitterProvider(keycloakSession, httpClient, idGenerator, targetUri, - format, pendingEventsToSend, pendingAdminEventsToSend, requestConfig); - } - - public void init(Config.Scope config) { - logger.info("EventEmitter initialisation..."); - - // Serializer config - String formatConfig = config.get(FORMAT_CONFIG_KEY); - - if (formatConfig == null) { - logger.error("No serialization configuration found."); - throw new IllegalArgumentException("No serialization configuration found."); - } - - try { - format = SerialisationFormat.valueOf(formatConfig); - } catch (IllegalArgumentException e) { - logger.errorv(e, "Invalid serialization format: " + formatConfig); - throw e; - } - - // Target URI config - targetUri = config.get(TARGET_URI_CONFIG_KEY); - - if (targetUri == null) { - logger.error("Target URI configuration is missing."); - throw new IllegalArgumentException("Target URI configuration is missing."); - } - - // Buffer capacity - bufferCapacity = getIntConfig(config, BUFFER_CAPACITY_CONFIG_KEY, true); - - // Snowflake ID generator configuration - // KeycloakId - keycloakId = getIntConfig(config, SNOWFLAKE_KEYCLOAKID_CONFIG_KEY, true); - - // DatacenterId - datacenterId = getIntConfig(config, SNOWFLAKE_DATACENTERID_CONFIG_KEY, true); - - // Creates request configuration - Builder requestConfigBuilder = RequestConfig.custom(); - applyValueWhenDefined(config, CONNECT_TIMEOUT_MILLIS, requestConfigBuilder::setConnectTimeout); - applyValueWhenDefined(config, CONNECTION_REQUEST_TIMEOUT_MILLIS, requestConfigBuilder::setConnectionRequestTimeout); - applyValueWhenDefined(config, SOCKET_TIMEOUT_MILLIS, requestConfigBuilder::setSocketTimeout); - this.requestConfig = requestConfigBuilder.build(); - - // Initialisation - httpClient = HttpClients.createDefault(); - idGenerator = new IdGenerator(keycloakId, datacenterId); - pendingEventsToSend = new LinkedBlockingQueue<>(bufferCapacity); - pendingAdminEventsToSend = new LinkedBlockingQueue<>(bufferCapacity); - } - - private void applyValueWhenDefined(Config.Scope config, String name, IntConsumer consumer) { - Integer value = getIntConfig(config, name, false); - if (value!=null) { - consumer.accept(value); - } - } - - private Integer getIntConfig(Config.Scope config, String name, boolean mandatory) { - try { - Integer value = config.getInt(name); - if (value==null && mandatory) { - String message = name+" configuration is missing"; - logger.errorf(message); - throw new IllegalArgumentException(message); - } - return value; - } catch (NumberFormatException e) { - logger.errorv(e, "Invalid %s configuration parameter", name); - throw e; - } - } - - public void postInit(KeycloakSessionFactory keycloakSessionFactory) { - - } - - public void close() { - try { - httpClient.close(); - } catch (IOException e) { - logger.infof(e, "Error while closing."); - } - } - - public String getId() { - return PROVIDER_ID; - } - - public Map getOperationalInfo() { - Map ret = new LinkedHashMap<>(); - ret.put("Version", PROVIDER_VERSION); - ret.put("Name", PROVIDER_NAME); - ret.put("Target URI", targetUri); - ret.put("Serialisation format", format.toString()); - ret.put("Buffer capacity", Integer.toString(bufferCapacity)); - ret.put("Snowflake Id Generator - Keycloak ID", Integer.toString(keycloakId)); - ret.put("Snowflake Id Generator - Datacenter ID", Integer.toString(datacenterId)); - - return ret; - } -} diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerialisationFormat.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerialisationFormat.java deleted file mode 100644 index 6f058c5..0000000 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerialisationFormat.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.cloudtrust.keycloak.eventemitter; - -/** - * Supported serialisation format by the event-emitter. - */ -public enum SerialisationFormat { - FLATBUFFER, - JSON -} diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerialisationUtils.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerializationUtils.java similarity index 94% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerialisationUtils.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerializationUtils.java index 3cd100c..e24f31d 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerialisationUtils.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/SerializationUtils.java @@ -3,28 +3,27 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.flatbuffers.FlatBufferBuilder; -import io.cloudtrust.keycloak.customevent.ExtendedAdminEvent; -import io.cloudtrust.keycloak.customevent.IdentifiedEvent; +import io.cloudtrust.keycloak.eventemitter.customevent.ExtendedAdminEvent; +import io.cloudtrust.keycloak.eventemitter.customevent.IdentifiedEvent; import java.nio.ByteBuffer; import java.util.Map; - /** * Utility class to serialize Event and AdminEvent in Flatbuffer or JSON format. * In order to allow idempotence, a unique ID is added to the entity. */ -class SerialisationUtils { +public class SerializationUtils { private static final int FLATBUFFER_INIT_SIZE = 1024; - private SerialisationUtils() { + private SerializationUtils() { } - static String toJson(Object obj) throws JsonProcessingException { + public static String toJson(Object obj) throws JsonProcessingException { return new ObjectMapper().writeValueAsString(obj); } - static ByteBuffer toFlat(IdentifiedEvent event) { + public static ByteBuffer toFlat(IdentifiedEvent event) { FlatBufferBuilder builder = new FlatBufferBuilder(FLATBUFFER_INIT_SIZE); // uid @@ -73,7 +72,7 @@ static ByteBuffer toFlat(IdentifiedEvent event) { return builder.dataBuffer(); } - static ByteBuffer toFlat(ExtendedAdminEvent adminEvent) { + public static ByteBuffer toFlat(ExtendedAdminEvent adminEvent) { FlatBufferBuilder builder = new FlatBufferBuilder(FLATBUFFER_INIT_SIZE); // uid @@ -169,7 +168,7 @@ private static int createString(FlatBufferBuilder builder, String value) { } private static int createMap(FlatBufferBuilder builder, Map map) { - if (map==null) { + if (map == null) { return 0; } int[] details = map.entrySet().stream() diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/ExtendedAdminEvent.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/ExtendedAdminEvent.java similarity index 95% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/ExtendedAdminEvent.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/ExtendedAdminEvent.java index c62477e..648e8c8 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/ExtendedAdminEvent.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/ExtendedAdminEvent.java @@ -1,4 +1,4 @@ -package io.cloudtrust.keycloak.customevent; +package io.cloudtrust.keycloak.eventemitter.customevent; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/ExtendedAuthDetails.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/ExtendedAuthDetails.java similarity index 92% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/ExtendedAuthDetails.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/ExtendedAuthDetails.java index c58abc8..a7e1992 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/ExtendedAuthDetails.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/ExtendedAuthDetails.java @@ -1,4 +1,4 @@ -package io.cloudtrust.keycloak.customevent; +package io.cloudtrust.keycloak.eventemitter.customevent; import org.keycloak.events.admin.AuthDetails; diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/IdentifiedAdminEvent.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/IdentifiedAdminEvent.java similarity index 95% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/IdentifiedAdminEvent.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/IdentifiedAdminEvent.java index 9079b89..b8e9fca 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/IdentifiedAdminEvent.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/IdentifiedAdminEvent.java @@ -1,4 +1,4 @@ -package io.cloudtrust.keycloak.customevent; +package io.cloudtrust.keycloak.eventemitter.customevent; import com.fasterxml.jackson.annotation.JsonIgnore; import io.cloudtrust.keycloak.eventemitter.HasUid; diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/IdentifiedEvent.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/IdentifiedEvent.java similarity index 94% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/IdentifiedEvent.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/IdentifiedEvent.java index be7487f..80633b8 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/customevent/IdentifiedEvent.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/customevent/IdentifiedEvent.java @@ -1,4 +1,4 @@ -package io.cloudtrust.keycloak.customevent; +package io.cloudtrust.keycloak.eventemitter.customevent; import io.cloudtrust.keycloak.eventemitter.HasUid; diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterProvider.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterProvider.java similarity index 89% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterProvider.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterProvider.java index 132dd10..b7ba792 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterProvider.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterProvider.java @@ -1,11 +1,12 @@ -package io.cloudtrust.keycloak.kafkaeventemitter; - -import com.google.common.base.Strings; -import io.cloudtrust.keycloak.customevent.ExtendedAdminEvent; -import io.cloudtrust.keycloak.customevent.ExtendedAuthDetails; -import io.cloudtrust.keycloak.customevent.IdentifiedAdminEvent; -import io.cloudtrust.keycloak.customevent.IdentifiedEvent; -import io.cloudtrust.keycloak.snowflake.IdGenerator; +package io.cloudtrust.keycloak.eventemitter.kafkaemitter; + +import io.cloudtrust.keycloak.eventemitter.SerializationUtils; +import io.cloudtrust.keycloak.eventemitter.customevent.ExtendedAdminEvent; +import io.cloudtrust.keycloak.eventemitter.customevent.ExtendedAuthDetails; +import io.cloudtrust.keycloak.eventemitter.customevent.IdentifiedAdminEvent; +import io.cloudtrust.keycloak.eventemitter.customevent.IdentifiedEvent; +import io.cloudtrust.keycloak.eventemitter.snowflake.IdGenerator; +import org.apache.commons.lang3.StringUtils; import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.clients.producer.RecordMetadata; @@ -60,7 +61,7 @@ public void onEvent(Event event) { IdentifiedEvent identifiedEvent = new IdentifiedEvent(uid, event); // Flatbuffer serialization - ByteBuffer buffer = SerialisationUtils.toFlat(identifiedEvent); + ByteBuffer buffer = SerializationUtils.toFlat(identifiedEvent); produceEvent(buffer, identifiedEvent.getUserId(), eventTopic); } @@ -72,7 +73,7 @@ public void onEvent(AdminEvent adminEvent, boolean includeRepresentation) { ExtendedAdminEvent customAdminEvent = completeAdminEventAttributes(identifiedAdminEvent); // Flatbuffer serialization - ByteBuffer buffer = SerialisationUtils.toFlat(customAdminEvent); + ByteBuffer buffer = SerializationUtils.toFlat(customAdminEvent); produceEvent(buffer, customAdminEvent.getAuthDetails().getUserId(), adminEventTopic); } @@ -88,7 +89,7 @@ private void completeEventAttributes(Event event) { event.setDetails(new HashMap<>()); } String eventUsername = event.getDetails().get(Details.USERNAME); - if (!Strings.isNullOrEmpty(event.getUserId()) && Strings.isNullOrEmpty(eventUsername)) { + if (StringUtils.isNotBlank(event.getUserId()) && StringUtils.isBlank(eventUsername)) { findUser(event.getUserId(), event.getRealmId(), u -> event.getDetails().put(Details.USERNAME, u.getUsername())); } } @@ -97,7 +98,7 @@ private ExtendedAdminEvent completeAdminEventAttributes(IdentifiedAdminEvent adm ExtendedAdminEvent extendedAdminEvent = new ExtendedAdminEvent(adminEvent); // add always missing agent username ExtendedAuthDetails extendedAuthDetails = extendedAdminEvent.getAuthDetails(); - if (!Strings.isNullOrEmpty(extendedAuthDetails.getUserId())) { + if (StringUtils.isNotBlank(extendedAuthDetails.getUserId())) { findUser(extendedAuthDetails.getUserId(), extendedAuthDetails.getRealmId(), u -> extendedAuthDetails.setUsername(u.getUsername())); } // add username if resource is a user diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterProviderFactory.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterProviderFactory.java similarity index 94% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterProviderFactory.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterProviderFactory.java index 435c8a4..0a361e3 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterProviderFactory.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterProviderFactory.java @@ -1,12 +1,12 @@ -package io.cloudtrust.keycloak.kafkaeventemitter; +package io.cloudtrust.keycloak.eventemitter.kafkaemitter; -import io.cloudtrust.keycloak.snowflake.IdGenerator; +import io.cloudtrust.keycloak.eventemitter.snowflake.IdGenerator; import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.config.SaslConfigs; -import org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerLoginCallbackHandler; +import org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginCallbackHandler; import org.apache.kafka.common.serialization.StringSerializer; import org.jboss.logging.Logger; import org.keycloak.Config; @@ -26,8 +26,9 @@ public class KafkaEventEmitterProviderFactory implements EventListenerProviderFactory, ServerInfoAwareProviderFactory { private static final Logger logger = Logger.getLogger(KafkaEventEmitterProviderFactory.class); + public static final String PROVIDER_ID = "kafka-event-emitter"; + private static final String PROVIDER_NAME = "Kafka Event Emitter"; - private static final String PROVIDER_ID = "kafka-event-emitter"; private static final String PROVIDER_VERSION = "1.0"; private static final String SECURITY_PROTOCOL_CONFIG = "security.protocol"; @@ -61,7 +62,7 @@ public class KafkaEventEmitterProviderFactory implements EventListenerProviderFa public EventListenerProvider create(KeycloakSession session) { if (state.isInitialized()) { state.starting(); - producer = new KafkaProducer(kafkaProperties); + producer = new KafkaProducer<>(kafkaProperties); } return new KafkaEventEmitterProvider(session, producer, eventTopic, adminEventTopic, idGenerator, pendingEvents, state, stateLock); } @@ -95,7 +96,7 @@ public void init(Config.Scope config) { @Override public void postInit(KeycloakSessionFactory factory) { - + // Nothing to initialize } @Override diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterState.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterState.java similarity index 93% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterState.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterState.java index dfb3608..e7e803c 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/KafkaEventEmitterState.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/kafkaemitter/KafkaEventEmitterState.java @@ -1,4 +1,4 @@ -package io.cloudtrust.keycloak.kafkaeventemitter; +package io.cloudtrust.keycloak.eventemitter.kafkaemitter; public class KafkaEventEmitterState { private state currentState; diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/snowflake/IdGenerator.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/snowflake/IdGenerator.java similarity index 60% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/snowflake/IdGenerator.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/snowflake/IdGenerator.java index 2ef6a94..7391c52 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/snowflake/IdGenerator.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/snowflake/IdGenerator.java @@ -1,22 +1,11 @@ -package io.cloudtrust.keycloak.snowflake; +package io.cloudtrust.keycloak.eventemitter.snowflake; -import com.google.common.base.MoreObjects; +import org.apache.commons.lang3.builder.ToStringBuilder; import org.jboss.logging.Logger; import java.util.concurrent.atomic.AtomicLong; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.DATACENTER_ID_BITS; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.DATACENTER_ID_SHIFT; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.KEYCLOAK_ID_BITS; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.KEYCLOAK_ID_SHIFT; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.MAX_DATACENTER_ID; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.MAX_KEYCLOAK_ID; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.SEQUENCE_BITS; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.SEQUENCE_MASK; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.START_EPOCH; -import static io.cloudtrust.keycloak.snowflake.IdGeneratorConfig.TIMESTAMP_LEFT_SHIFT; /** * @author Sébastien Pasche @@ -35,26 +24,22 @@ public IdGenerator(final int keycloakId, final int datacenterId) { } public IdGenerator(final int keycloakId, final int datacenterId, final long startSequence) { - checkNotNull(keycloakId); checkArgument(keycloakId >= 0, String.format("component Id can't be greater than %d or less than 0", - MAX_KEYCLOAK_ID)); - checkArgument(keycloakId <= MAX_KEYCLOAK_ID, String.format("component Id can't be greater than %d " - + "or less than 0", MAX_KEYCLOAK_ID)); + IdGeneratorConfig.MAX_KEYCLOAK_ID)); + checkArgument(keycloakId <= IdGeneratorConfig.MAX_KEYCLOAK_ID, String.format("component Id can't be greater than %d " + + "or less than 0", IdGeneratorConfig.MAX_KEYCLOAK_ID)); - checkNotNull(datacenterId); checkArgument(datacenterId >= 0, String.format("Datacenter ID can't be greater than %d or less than 0", - MAX_DATACENTER_ID)); - checkArgument(datacenterId <= MAX_DATACENTER_ID, String.format("Datacenter ID can't be greater than %d or " - + "less than 0", MAX_DATACENTER_ID)); - - checkNotNull(startSequence); + IdGeneratorConfig.MAX_DATACENTER_ID)); + checkArgument(datacenterId <= IdGeneratorConfig.MAX_DATACENTER_ID, String.format("Datacenter ID can't be greater than %d or " + + "less than 0", IdGeneratorConfig.MAX_DATACENTER_ID)); this.keycloakId = keycloakId; this.datacenterId = datacenterId; logger.infof("IdGenerator general settings: timestamp left shift = %d, datacenter ID bits = %d, " - + "keycloak ID bits = %d, sequence bits = %d", TIMESTAMP_LEFT_SHIFT, DATACENTER_ID_BITS, - KEYCLOAK_ID_BITS, SEQUENCE_BITS); + + "keycloak ID bits = %d, sequence bits = %d", IdGeneratorConfig.TIMESTAMP_LEFT_SHIFT, IdGeneratorConfig.DATACENTER_ID_BITS, + IdGeneratorConfig.KEYCLOAK_ID_BITS, IdGeneratorConfig.SEQUENCE_BITS); logger.infof("IdGenerator instance settings: datacenter ID = %d, keycloak ID = %d", datacenterId, keycloakId); sequence = new AtomicLong(startSequence); } @@ -78,7 +63,7 @@ public synchronized long nextId() throws InvalidSystemClock { } if (prevTimestamp == timestamp) { - curSequence = sequence.incrementAndGet() & SEQUENCE_MASK; + curSequence = sequence.incrementAndGet() & IdGeneratorConfig.SEQUENCE_MASK; if (curSequence == 0) { timestamp = tilNextMillis(prevTimestamp); } @@ -88,9 +73,9 @@ public synchronized long nextId() throws InvalidSystemClock { } lastTimestamp.set(timestamp); - final long id = ((timestamp - START_EPOCH) << TIMESTAMP_LEFT_SHIFT) - | (datacenterId << DATACENTER_ID_SHIFT) - | (keycloakId << KEYCLOAK_ID_SHIFT) | curSequence; + final long id = ((timestamp - IdGeneratorConfig.START_EPOCH) << IdGeneratorConfig.TIMESTAMP_LEFT_SHIFT) + | (datacenterId << IdGeneratorConfig.DATACENTER_ID_SHIFT) + | (keycloakId << IdGeneratorConfig.KEYCLOAK_ID_SHIFT) | curSequence; logger.debugf( "prevTimestamp = %d, timestamp = %d, sequence = %d, id = %d", @@ -136,13 +121,13 @@ public AtomicLong getSequence() { @Override public String toString() { - return MoreObjects.toStringHelper(this) - .add("componentId", keycloakId) - .add("datacenterId", datacenterId) - .add("timestamp left shift", TIMESTAMP_LEFT_SHIFT) - .add("datacenter ID bits", DATACENTER_ID_BITS) - .add("component ID bits", KEYCLOAK_ID_BITS) - .add("sequence bits", SEQUENCE_BITS) + return new ToStringBuilder(this) + .append("componentId", keycloakId) + .append("datacenterId", datacenterId) + .append("timestamp left shift", IdGeneratorConfig.TIMESTAMP_LEFT_SHIFT) + .append("datacenter ID bits", IdGeneratorConfig.DATACENTER_ID_BITS) + .append("component ID bits", IdGeneratorConfig.KEYCLOAK_ID_BITS) + .append("sequence bits", IdGeneratorConfig.SEQUENCE_BITS) .toString(); } } diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/snowflake/IdGeneratorConfig.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/snowflake/IdGeneratorConfig.java similarity index 94% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/snowflake/IdGeneratorConfig.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/snowflake/IdGeneratorConfig.java index ecd358c..9c6553b 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/snowflake/IdGeneratorConfig.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/snowflake/IdGeneratorConfig.java @@ -1,4 +1,4 @@ -package io.cloudtrust.keycloak.snowflake; +package io.cloudtrust.keycloak.eventemitter.snowflake; /** diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/snowflake/InvalidSystemClock.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/snowflake/InvalidSystemClock.java similarity index 81% rename from keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/snowflake/InvalidSystemClock.java rename to keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/snowflake/InvalidSystemClock.java index 52f3049..14af6a7 100644 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/snowflake/InvalidSystemClock.java +++ b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/eventemitter/snowflake/InvalidSystemClock.java @@ -1,4 +1,4 @@ -package io.cloudtrust.keycloak.snowflake; +package io.cloudtrust.keycloak.eventemitter.snowflake; /** * @author Sébastien Pasche diff --git a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/SerialisationUtils.java b/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/SerialisationUtils.java deleted file mode 100644 index 3a3f8ea..0000000 --- a/keycloak-event-emitter/src/main/java/io/cloudtrust/keycloak/kafkaeventemitter/SerialisationUtils.java +++ /dev/null @@ -1,251 +0,0 @@ -package io.cloudtrust.keycloak.kafkaeventemitter; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.flatbuffers.FlatBufferBuilder; -import io.cloudtrust.keycloak.customevent.ExtendedAdminEvent; -import io.cloudtrust.keycloak.customevent.IdentifiedEvent; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - - -/** - * Utility class to serialize Event and AdminEvent in Flatbuffer or JSON format. - * In order to allow idempotence, a unique ID is added to the entity. - */ -class SerialisationUtils { - private static final ThreadLocal objectMapperProvider = ThreadLocal.withInitial(ObjectMapper::new); - - private static final int FLATBUFFER_INIT_SIZE = 1024; - - static String toJson(Object obj) throws JsonProcessingException { - return objectMapperProvider.get().writeValueAsString(obj); - } - - static ByteBuffer toFlat(IdentifiedEvent event) { - FlatBufferBuilder builder = new FlatBufferBuilder(FLATBUFFER_INIT_SIZE); - - // uid - long uid = event.getUid(); - - // Time - long time = event.getTime(); - - // Type - byte type; - // size of the list minus 1 because we add UNKNOWN event type in flatbuffers list - int eventTypeSize = flatbuffers.events.EventType.names.length - 1; - - if (event.getType().ordinal() < eventTypeSize) { - type = (byte) event.getType().ordinal(); - } else { - // EventType returned by the Event is unknown by flatbuffers - type = flatbuffers.events.EventType.UNKNOWN; - } - - // RealmId - int realmId = 0; - if (event.getRealmId() != null) { - realmId = builder.createString(event.getRealmId()); - } - - // ClientId - int clientId = 0; - if (event.getClientId() != null) { - clientId = builder.createString(event.getClientId()); - } - - // UserId - int userId = 0; - if (event.getUserId() != null) { - userId = builder.createString(event.getUserId()); - } - - // SessionId - int sessionId = 0; - if (event.getSessionId() != null) { - sessionId = builder.createString(event.getSessionId()); - } - - // IpAddress - int ipAddress = 0; - if (event.getIpAddress() != null) { - ipAddress = builder.createString(event.getIpAddress()); - } - - // Error - int error = 0; - if (event.getError() != null) { - error = builder.createString(event.getError()); - } - - // Details - int detailsVec = 0; - if (event.getDetails() != null) { - List tuples = new ArrayList<>(); - for (Map.Entry entry : event.getDetails().entrySet()) { - int key = builder.createString(entry.getKey()); - int value = builder.createString(entry.getValue()); - int tuple = flatbuffers.events.Tuple.createTuple(builder, key, value); - tuples.add(tuple); - } - - int[] details = new int[tuples.size()]; - for (int i = 0; i < tuples.size(); i++) { - details[i] = tuples.get(i); - } - - detailsVec = flatbuffers.events.Event.createDetailsVector(builder, details); - } - - flatbuffers.events.Event.startEvent(builder); - - flatbuffers.events.Event.addUid(builder, uid); - flatbuffers.events.Event.addTime(builder, time); - flatbuffers.events.Event.addType(builder, type); - flatbuffers.events.Event.addRealmId(builder, realmId); - flatbuffers.events.Event.addClientId(builder, clientId); - flatbuffers.events.Event.addUserId(builder, userId); - flatbuffers.events.Event.addSessionId(builder, sessionId); - flatbuffers.events.Event.addIpAddress(builder, ipAddress); - flatbuffers.events.Event.addError(builder, error); - flatbuffers.events.Event.addDetails(builder, detailsVec); - - int flatEvent = flatbuffers.events.Event.endEvent(builder); - - builder.finish(flatEvent); - - return builder.dataBuffer(); - } - - static ByteBuffer toFlat(ExtendedAdminEvent adminEvent) { - FlatBufferBuilder builder = new FlatBufferBuilder(FLATBUFFER_INIT_SIZE); - - // uid - long uid = adminEvent.getUid(); - - // Time - long timeOffset = adminEvent.getTime(); - - // RealmId - int realmIdOffset = 0; - if (adminEvent.getRealmId() != null) { - realmIdOffset = builder.createString(adminEvent.getRealmId()); - } - - // AuthDetails - int authDetailsOffset = 0; - if (adminEvent.getAuthDetails() != null) { - int authDetailsRealmIdOffset = 0; - int authDetailsClientIdOffset = 0; - int authDetailsUserIdOffset = 0; - int authDetailsUsernameAddressOffset = 0; - int authDetailsIpAddressOffset = 0; - - if (adminEvent.getAuthDetails().getRealmId() != null) { - authDetailsRealmIdOffset = builder.createString(adminEvent.getAuthDetails().getRealmId()); - } - - if (adminEvent.getAuthDetails().getClientId() != null) { - authDetailsClientIdOffset = builder.createString(adminEvent.getAuthDetails().getClientId()); - } - - if (adminEvent.getAuthDetails().getUserId() != null) { - authDetailsUserIdOffset = builder.createString(adminEvent.getAuthDetails().getUserId()); - } - - if (adminEvent.getAuthDetails().getUsername() != null) { - authDetailsUsernameAddressOffset = builder.createString(adminEvent.getAuthDetails().getUsername()); - } - - if (adminEvent.getAuthDetails().getIpAddress() != null) { - authDetailsIpAddressOffset = builder.createString(adminEvent.getAuthDetails().getIpAddress()); - } - - authDetailsOffset = flatbuffers.events.AuthDetails.createAuthDetails(builder, - authDetailsRealmIdOffset, authDetailsClientIdOffset, - authDetailsUserIdOffset, authDetailsUsernameAddressOffset, - authDetailsIpAddressOffset); - } - - // ResourceType - byte resourceTypeOffset = 0; - // size of the list minus 1 because we add UNKNOWN resource type in flatbuffers list - int resourceTypeSize = flatbuffers.events.ResourceType.names.length - 1; - - if (adminEvent.getResourceType() != null) { - if (adminEvent.getResourceType().ordinal() < resourceTypeSize) { - resourceTypeOffset = (byte) adminEvent.getResourceType().ordinal(); - } else { - // ResourceType returned by the AdminEvent is unknown by flatbuffers - resourceTypeOffset = flatbuffers.events.ResourceType.UNKNOWN; - } - } - - // OperationType - byte operationTypeOffset = 0; - if (adminEvent.getOperationType() != null) { - operationTypeOffset = (byte) adminEvent.getOperationType().ordinal(); - } - - // ResourcePath - int resourcePathOffset = 0; - if (adminEvent.getResourcePath() != null) { - resourcePathOffset = builder.createString(adminEvent.getResourcePath()); - } - - // Representation - int representationOffset = 0; - if (adminEvent.getRepresentation() != null) { - representationOffset = builder.createString(adminEvent.getRepresentation()); - } - - // Details - int detailsVec = 0; - if (adminEvent.getDetails() != null) { - List tuples = new ArrayList<>(); - for (Map.Entry entry : adminEvent.getDetails().entrySet()) { - int key = builder.createString(entry.getKey()); - int value = builder.createString(entry.getValue()); - int tuple = flatbuffers.events.Tuple.createTuple(builder, key, value); - tuples.add(tuple); - } - - int[] details = new int[tuples.size()]; - for (int i = 0; i < tuples.size(); i++) { - details[i] = tuples.get(i); - } - - detailsVec = flatbuffers.events.Event.createDetailsVector(builder, details); - } - - // Error - int errorOffset = 0; - if (adminEvent.getError() != null) { - errorOffset = builder.createString(adminEvent.getError()); - } - - flatbuffers.events.AdminEvent.startAdminEvent(builder); - - flatbuffers.events.AdminEvent.addUid(builder, uid); - flatbuffers.events.AdminEvent.addTime(builder, timeOffset); - flatbuffers.events.AdminEvent.addRealmId(builder, realmIdOffset); - flatbuffers.events.AdminEvent.addAuthDetails(builder, authDetailsOffset); - flatbuffers.events.AdminEvent.addResourceType(builder, resourceTypeOffset); - flatbuffers.events.AdminEvent.addOperationType(builder, operationTypeOffset); - flatbuffers.events.AdminEvent.addResourcePath(builder, resourcePathOffset); - flatbuffers.events.AdminEvent.addRepresentation(builder, representationOffset); - flatbuffers.events.AdminEvent.addDetails(builder, detailsVec); - flatbuffers.events.AdminEvent.addError(builder, errorOffset); - - int flatAdminEvent = flatbuffers.events.AdminEvent.endAdminEvent(builder); - - builder.finish(flatAdminEvent); - - return builder.dataBuffer(); - } - -} diff --git a/keycloak-event-emitter/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory b/keycloak-event-emitter/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory index 103787b..ab51e8a 100644 --- a/keycloak-event-emitter/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory +++ b/keycloak-event-emitter/src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory @@ -1,2 +1 @@ -io.cloudtrust.keycloak.eventemitter.EventEmitterProviderFactory -io.cloudtrust.keycloak.kafkaeventemitter.KafkaEventEmitterProviderFactory \ No newline at end of file +io.cloudtrust.keycloak.eventemitter.kafkaemitter.KafkaEventEmitterProviderFactory \ No newline at end of file diff --git a/pom.xml b/pom.xml index daefd0f..01c4259 100644 --- a/pom.xml +++ b/pom.xml @@ -5,11 +5,11 @@ io.cloudtrust kc-cloudtrust-module - 20.0.0 + 26.0.0-SNAPSHOT keycloak-event-emitter-parent - 20.1.1-SNAPSHOT + 26.0.0-SNAPSHOT pom