From 6d73aaa3537291f5b04f96c0e11f74f8553fbca5 Mon Sep 17 00:00:00 2001 From: Mohammed Ammer Date: Tue, 8 Oct 2024 14:04:50 +0200 Subject: [PATCH] Adjust create offline sessions --- Dockerfile | 30 +++++++ .../authentication/AuthorizationCode.scala | 4 +- .../dataset/DatasetResourceProvider.java | 84 ++++++++++++++----- .../dataset/config/DatasetConfig.java | 4 +- .../keycloak/keycloak-quarkus-postgres.yml | 2 +- 5 files changed, 96 insertions(+), 28 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..5df1270c1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +# Use the official Ubuntu base image +FROM ubuntu:20.04 + +# Set environment variables to avoid interactive prompts during package installation +ENV DEBIAN_FRONTEND=noninteractive + +# Update the package list and install required packages: curl, unzip, and JDK +RUN apt update && \ + apt install -y curl unzip openjdk-21-jdk w3m links lynx jq uuid-runtime && \ + apt clean && \ + rm -rf /var/lib/apt/lists/* + +# Set JAVA_HOME environment variable +ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 +ENV PATH="$JAVA_HOME/bin:${PATH}" + +# Download the Keycloak Benchmark zip file +COPY ./benchmark/target/keycloak-benchmark-0.13-SNAPSHOT.zip . + +# Unzip the downloaded file +RUN unzip keycloak-benchmark-0.13-SNAPSHOT.zip -d /opt + +# Set the working directory +WORKDIR /opt/keycloak-benchmark-0.13-SNAPSHOT + +# Default command: Start a bash shell +CMD ["/bin/bash"] + +## docker build -t keycloak-benchmark . && docker run -v /Users/mohammed.ammer/Documents/projects/keycloak-benchmark/reports:/opt/keycloak-benchmark-0.14-SNAPSHOT/results/ -it keycloak-benchmark +## diff --git a/benchmark/src/main/scala/keycloak/scenario/authentication/AuthorizationCode.scala b/benchmark/src/main/scala/keycloak/scenario/authentication/AuthorizationCode.scala index 98465ea61..2cb62ef4f 100644 --- a/benchmark/src/main/scala/keycloak/scenario/authentication/AuthorizationCode.scala +++ b/benchmark/src/main/scala/keycloak/scenario/authentication/AuthorizationCode.scala @@ -8,7 +8,7 @@ class AuthorizationCode extends CommonSimulation { .openLoginPage(true) .loginUsernamePassword() .exchangeCode() - .repeatRefresh() - .logout(true)) + .repeatRefresh()) +// .logout(true)) } diff --git a/dataset/src/main/java/org/keycloak/benchmark/dataset/DatasetResourceProvider.java b/dataset/src/main/java/org/keycloak/benchmark/dataset/DatasetResourceProvider.java index 3120a80d0..2df413470 100644 --- a/dataset/src/main/java/org/keycloak/benchmark/dataset/DatasetResourceProvider.java +++ b/dataset/src/main/java/org/keycloak/benchmark/dataset/DatasetResourceProvider.java @@ -24,11 +24,14 @@ import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import java.util.Base64; +import java.util.UUID; import org.jboss.logging.Logger; import org.jboss.resteasy.reactive.NoCache; import org.keycloak.benchmark.dataset.config.ConfigUtil; import org.keycloak.benchmark.dataset.config.DatasetConfig; import org.keycloak.benchmark.dataset.config.DatasetException; +import org.keycloak.common.util.Time; import org.keycloak.connections.infinispan.InfinispanConnectionProvider; import org.keycloak.events.Event; import org.keycloak.events.EventStoreProvider; @@ -48,6 +51,7 @@ import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; import org.keycloak.models.cache.CacheRealmProvider; +import org.keycloak.models.session.UserSessionPersisterProvider; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper; import org.keycloak.protocol.oidc.OIDCLoginProtocol; @@ -55,7 +59,6 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.services.managers.ClientManager; import org.keycloak.services.managers.RealmManager; -import org.keycloak.services.managers.UserSessionManager; import org.keycloak.services.resource.RealmResourceProvider; import java.util.ArrayList; @@ -594,31 +597,49 @@ private void createOfflineSessionsImpl(Task task, DatasetConfig config, int last // Run this concurrently with multiple threads executor.addTaskRunningInTransaction(session -> { - int realmIdx = new Random().nextInt(lastRealmIndex + 1); - String realmName = config.getRealmPrefix() + realmIdx; - RealmModel realm = session.realms().getRealmByName(realmName); - if (realm == null) { - throw new IllegalStateException("Not found realm with name '" + realmName + "'"); - } - // Just use user like "user-0" - String username = config.getUserPrefix() + "0"; - UserModel user = session.users().getUserByUsername(realm, username); - if (user == null) { - throw new IllegalStateException("Not found user with username '" + username + "' in the realm '" + realmName + "'"); - } - // Just use client like "client-0" - String clientId = config.getClientPrefix() + "0"; - ClientModel client = session.clients().getClientByClientId(realm, clientId); - if (client == null) { - throw new IllegalStateException("Not found client with clientId '" + client + "' in the realm '" + clientId + "'"); - } - for (int j = 0; j < offlineSessionsPerTransaction; j++) { - UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, "127.0.0.1", "form", false, null, null); + int realmIdx = new Random().nextInt(lastRealmIndex + 1); + String realmName = config.getRealmPrefix() + realmIdx; + RealmModel realm = session.realms().getRealmByName(realmName); + if (realm == null) { + throw new IllegalStateException("Not found realm with name '" + realmName + "'"); + } + // Just use user like "user-0" + String username = config.getUserPrefix() + new Random().ints(0, config.getUsersPerRealm()).findFirst().getAsInt(); + UserModel user = session.users().getUserByUsername(realm, username); + if (user == null) { + throw new IllegalStateException("Not found user with username '" + username + "' in the realm '" + realmName + "'"); + } + // Just use client like "client-0" + String clientId = config.getClientPrefix() + new Random().ints(0, config.getClientsPerRealm()).findFirst().getAsInt(); + ClientModel client = session.clients().getClientByClientId(realm, clientId); + if (client == null) { + throw new IllegalStateException("Not found client with clientId '" + client + "' in the realm '" + clientId + "'"); + } + + UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, "127.0.0.1", "openid-connect", false, null, null); + userSession.setNote("KC_DEVICE_NOTE", Base64.getEncoder().encodeToString("{ \"ipAddress\": \"127.0.0.1\", \"os\": \"Mac OS X\", \"osVersion\": \"10.8\", \"browser\": \"Firefox/16.0\", \"device\": \"Mac\", \"lastAccess\": 0, \"mobile\": false}".getBytes())); + userSession.setNote("AUTH_TIME", userSession.getStarted() + ""); + userSession.setNote("authenticators-completed", "{\"" + UUID.randomUUID() + "\": \"" + userSession.getStarted() + "\"}"); + userSession.setNote("state", "LOGGED_IN"); AuthenticatedClientSessionModel clientSession = session.sessions().createClientSession(userSession.getRealm(), client, userSession); - // Convert user and client sessions to offline. - new UserSessionManager(session).createOrUpdateOfflineSession(clientSession, userSession); + String redirectUri = "https://idp.live.free-now.com/keycloak/realms/" + realmName + "/account"; + clientSession.setRedirectUri(redirectUri); + clientSession.setNote("clientId", client.getId()); + clientSession.setNote("scope", "openid profile"); + clientSession.setNote("userSessionStartedAt", userSession.getStarted() + ""); + clientSession.setNote("iss", "https://idp.live.free-now.com/keycloak/realms/" + realmName); + clientSession.setNote("startedAt", userSession.getStarted() + ""); + clientSession.setNote("response_type", "code"); + clientSession.setNote("level-of-authentication", "-1"); + clientSession.setNote("redirect_uri", redirectUri); + clientSession.setNote("state", UUID.randomUUID().toString()); + clientSession.setNote("client_request_param_login", "true"); + + + // Persist the user sessions + createOrUpdateUserSession(session, clientSession, userSession); } @@ -640,6 +661,23 @@ private void createOfflineSessionsImpl(Task task, DatasetConfig config, int last } } + + public void createOrUpdateUserSession(KeycloakSession kcSession, AuthenticatedClientSessionModel clientSession, UserSessionModel userSession) { + UserSessionModel storedUserSession = kcSession.sessions().getUserSession(clientSession.getRealm(), userSession.getId()); + UserSessionPersisterProvider persister = kcSession.getProvider(UserSessionPersisterProvider.class); + if (storedUserSession == null) { + persister.createUserSession(userSession, false); + } else { + storedUserSession.setLastSessionRefresh(Time.currentTime()); + } + + AuthenticatedClientSessionModel storedClientSession = storedUserSession.getAuthenticatedClientSessionByClient(clientSession.getClient().getId()); + if (storedClientSession == null) { + persister.createClientSession(clientSession, false); + } + + } + @GET @Path("/remove-realms") @NoCache diff --git a/dataset/src/main/java/org/keycloak/benchmark/dataset/config/DatasetConfig.java b/dataset/src/main/java/org/keycloak/benchmark/dataset/config/DatasetConfig.java index bae36b344..9b84ab4d7 100644 --- a/dataset/src/main/java/org/keycloak/benchmark/dataset/config/DatasetConfig.java +++ b/dataset/src/main/java/org/keycloak/benchmark/dataset/config/DatasetConfig.java @@ -78,7 +78,7 @@ public class DatasetConfig { @QueryParamFill(paramName = "client-prefix", defaultValue = "client-", operations = { CREATE_REALMS, CREATE_CLIENTS, CREATE_USERS, CREATE_OFFLINE_SESSIONS, LAST_CLIENT }) private String clientPrefix; - @QueryParamIntFill(paramName = "clients-per-realm", defaultValue = 30, operations = { CREATE_REALMS }) + @QueryParamIntFill(paramName = "clients-per-realm", defaultValue = 30, operations = { CREATE_REALMS, CREATE_OFFLINE_SESSIONS }) private Integer clientsPerRealm; // Count of clients created in every DB transaction @@ -135,7 +135,7 @@ public class DatasetConfig { private String userPrefix; // Count of users to be created in every realm (In case of CREATE_REALMS) - @QueryParamIntFill(paramName = "users-per-realm", defaultValue = 200, operations = { CREATE_REALMS, CREATE_AUTHZ_CLIENT }) + @QueryParamIntFill(paramName = "users-per-realm", defaultValue = 200, operations = { CREATE_REALMS, CREATE_AUTHZ_CLIENT, CREATE_OFFLINE_SESSIONS }) private Integer usersPerRealm; // Count of groups assigned to every user diff --git a/provision/docker-compose/keycloak/keycloak-quarkus-postgres.yml b/provision/docker-compose/keycloak/keycloak-quarkus-postgres.yml index 799357267..17ea6f803 100644 --- a/provision/docker-compose/keycloak/keycloak-quarkus-postgres.yml +++ b/provision/docker-compose/keycloak/keycloak-quarkus-postgres.yml @@ -17,7 +17,7 @@ services: ports: - "5432:5432" keycloak: - image: quay.io/keycloak/keycloak:latest + image: quay.io/keycloak/keycloak:25.0.2 container_name: keycloak command: - start-dev