Testsuite PoC - Use service account for admin client (#31478)
Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
parent
9f2eddead8
commit
b4368b75e6
12 changed files with 74 additions and 108 deletions
|
@ -46,9 +46,7 @@ import jakarta.ws.rs.ApplicationPath;
|
||||||
public class QuarkusKeycloakApplication extends KeycloakApplication {
|
public class QuarkusKeycloakApplication extends KeycloakApplication {
|
||||||
|
|
||||||
private static final String KEYCLOAK_ADMIN_ENV_VAR = "KEYCLOAK_ADMIN";
|
private static final String KEYCLOAK_ADMIN_ENV_VAR = "KEYCLOAK_ADMIN";
|
||||||
private static final String KEYCLOAK_ADMIN_PROP_VAR = "keycloakAdmin";
|
|
||||||
private static final String KEYCLOAK_ADMIN_PASSWORD_ENV_VAR = "KEYCLOAK_ADMIN_PASSWORD";
|
private static final String KEYCLOAK_ADMIN_PASSWORD_ENV_VAR = "KEYCLOAK_ADMIN_PASSWORD";
|
||||||
private static final String KEYCLOAK_ADMIN_PASSWORD_PROP_VAR = "keycloakAdminPassword";
|
|
||||||
|
|
||||||
void onStartupEvent(@Observes StartupEvent event) {
|
void onStartupEvent(@Observes StartupEvent event) {
|
||||||
QuarkusPlatform platform = (QuarkusPlatform) Platform.getPlatform();
|
QuarkusPlatform platform = (QuarkusPlatform) Platform.getPlatform();
|
||||||
|
@ -79,8 +77,8 @@ public class QuarkusKeycloakApplication extends KeycloakApplication {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void createTemporaryAdmin(KeycloakSession session) {
|
protected void createTemporaryAdmin(KeycloakSession session) {
|
||||||
var adminUsername = Configuration.getOptionalKcValue(BootstrapAdminOptions.USERNAME.getKey()).orElse(getEnvOrProp(KEYCLOAK_ADMIN_ENV_VAR, KEYCLOAK_ADMIN_PROP_VAR));
|
var adminUsername = Configuration.getOptionalKcValue(BootstrapAdminOptions.USERNAME.getKey()).orElse(System.getenv(KEYCLOAK_ADMIN_ENV_VAR));
|
||||||
var adminPassword = Configuration.getOptionalKcValue(BootstrapAdminOptions.PASSWORD.getKey()).orElse(getEnvOrProp(KEYCLOAK_ADMIN_PASSWORD_ENV_VAR, KEYCLOAK_ADMIN_PASSWORD_PROP_VAR));
|
var adminPassword = Configuration.getOptionalKcValue(BootstrapAdminOptions.PASSWORD.getKey()).orElse(System.getenv(KEYCLOAK_ADMIN_PASSWORD_ENV_VAR));
|
||||||
|
|
||||||
var clientId = Configuration.getOptionalKcValue(BootstrapAdminOptions.CLIENT_ID.getKey()).orElse(null);
|
var clientId = Configuration.getOptionalKcValue(BootstrapAdminOptions.CLIENT_ID.getKey()).orElse(null);
|
||||||
var clientSecret = Configuration.getOptionalKcValue(BootstrapAdminOptions.CLIENT_SECRET.getKey()).orElse(null);
|
var clientSecret = Configuration.getOptionalKcValue(BootstrapAdminOptions.CLIENT_SECRET.getKey()).orElse(null);
|
||||||
|
@ -106,9 +104,4 @@ public class QuarkusKeycloakApplication extends KeycloakApplication {
|
||||||
new ApplianceBootstrap(session).createTemporaryMasterRealmAdminService(clientId, clientSecret /*, adminExpiration*/);
|
new ApplianceBootstrap(session).createTemporaryMasterRealmAdminService(clientId, clientSecret /*, adminExpiration*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getEnvOrProp(String envKey, String propKey) {
|
|
||||||
String value = System.getenv(envKey);
|
|
||||||
return value != null ? value : System.getProperty(propKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package org.keycloak.test.examples;
|
|
||||||
|
|
||||||
import org.keycloak.test.framework.server.KeycloakTestServerConfig;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class NoAdminUserKeycloakTestServerConfig implements KeycloakTestServerConfig {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String adminUserName() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String adminUserPassword() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,17 +1,26 @@
|
||||||
package org.keycloak.test.examples;
|
package org.keycloak.test.examples;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.keycloak.admin.client.Keycloak;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||||
|
import org.keycloak.test.framework.annotations.TestAdminClient;
|
||||||
import org.keycloak.test.framework.page.WelcomePage;
|
import org.keycloak.test.framework.page.WelcomePage;
|
||||||
import org.keycloak.test.framework.annotations.TestWebDriver;
|
import org.keycloak.test.framework.annotations.TestWebDriver;
|
||||||
import org.openqa.selenium.WebDriver;
|
import org.openqa.selenium.WebDriver;
|
||||||
|
|
||||||
@KeycloakIntegrationTest(config = NoAdminUserKeycloakTestServerConfig.class)
|
import java.util.List;
|
||||||
|
|
||||||
|
@KeycloakIntegrationTest
|
||||||
public class WelcomePageTest {
|
public class WelcomePageTest {
|
||||||
|
|
||||||
@TestWebDriver
|
@TestWebDriver
|
||||||
WebDriver driver;
|
WebDriver driver;
|
||||||
|
|
||||||
|
@TestAdminClient
|
||||||
|
Keycloak adminClient;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateUser() {
|
public void testCreateUser() {
|
||||||
final var welcomePage = new WelcomePage(driver);
|
final var welcomePage = new WelcomePage(driver);
|
||||||
|
@ -19,6 +28,11 @@ public class WelcomePageTest {
|
||||||
welcomePage.fillRegistration("admin", "admin");
|
welcomePage.fillRegistration("admin", "admin");
|
||||||
welcomePage.submit();
|
welcomePage.submit();
|
||||||
welcomePage.assertUserCreated();
|
welcomePage.assertUserCreated();
|
||||||
|
|
||||||
|
List<UserRepresentation> users = adminClient.realm("master").users().search("admin", true);
|
||||||
|
Assertions.assertEquals(1, users.size());
|
||||||
|
|
||||||
|
adminClient.realm("master").users().get(users.get(0).getId()).remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package org.keycloak.test.framework.admin;
|
package org.keycloak.test.framework.admin;
|
||||||
|
|
||||||
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.admin.client.Keycloak;
|
import org.keycloak.admin.client.Keycloak;
|
||||||
|
import org.keycloak.admin.client.KeycloakBuilder;
|
||||||
import org.keycloak.test.framework.annotations.TestAdminClient;
|
import org.keycloak.test.framework.annotations.TestAdminClient;
|
||||||
|
import org.keycloak.test.framework.config.Config;
|
||||||
import org.keycloak.test.framework.injection.InstanceContext;
|
import org.keycloak.test.framework.injection.InstanceContext;
|
||||||
import org.keycloak.test.framework.injection.LifeCycle;
|
import org.keycloak.test.framework.injection.LifeCycle;
|
||||||
import org.keycloak.test.framework.injection.RequestedInstance;
|
import org.keycloak.test.framework.injection.RequestedInstance;
|
||||||
|
@ -23,7 +26,13 @@ public class KeycloakAdminClientSupplier implements Supplier<Keycloak, TestAdmin
|
||||||
@Override
|
@Override
|
||||||
public Keycloak getValue(InstanceContext<Keycloak, TestAdminClient> instanceContext) {
|
public Keycloak getValue(InstanceContext<Keycloak, TestAdminClient> instanceContext) {
|
||||||
KeycloakTestServer testServer = instanceContext.getDependency(KeycloakTestServer.class);
|
KeycloakTestServer testServer = instanceContext.getDependency(KeycloakTestServer.class);
|
||||||
return Keycloak.getInstance(testServer.getBaseUrl(), "master", "admin", "admin", "admin-cli");
|
return KeycloakBuilder.builder()
|
||||||
|
.serverUrl(testServer.getBaseUrl())
|
||||||
|
.realm("master")
|
||||||
|
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
|
||||||
|
.clientId(Config.getAdminClientId())
|
||||||
|
.clientSecret(Config.getAdminClientSecret())
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,6 +17,14 @@ public class Config {
|
||||||
return config.getOptionalValue("kc.test." + ValueTypeAlias.getAlias(valueType), String.class).orElse(null);
|
return config.getOptionalValue("kc.test." + ValueTypeAlias.getAlias(valueType), String.class).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getAdminClientId() {
|
||||||
|
return "kc-test-admin";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAdminClientSecret() {
|
||||||
|
return "kc-test-secret";
|
||||||
|
}
|
||||||
|
|
||||||
public static SmallRyeConfig initConfig() {
|
public static SmallRyeConfig initConfig() {
|
||||||
SmallRyeConfigBuilder configBuilder = new SmallRyeConfigBuilder()
|
SmallRyeConfigBuilder configBuilder = new SmallRyeConfigBuilder()
|
||||||
.addDefaultSources()
|
.addDefaultSources()
|
||||||
|
|
|
@ -41,6 +41,9 @@ public class RealmSupplier implements Supplier<RealmResource, TestRealm> {
|
||||||
|
|
||||||
adminClient.realms().create(realmRepresentation);
|
adminClient.realms().create(realmRepresentation);
|
||||||
|
|
||||||
|
// TODO Token needs to be invalidated after creating realm to have roles for new realm in the token. Maybe lightweight access tokens could help.
|
||||||
|
adminClient.tokenManager().invalidate(adminClient.tokenManager().getAccessTokenString());
|
||||||
|
|
||||||
return adminClient.realm(realmRepresentation.getRealm());
|
return adminClient.realm(realmRepresentation.getRealm());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.test.framework.server;
|
package org.keycloak.test.framework.server;
|
||||||
|
|
||||||
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||||
|
import org.keycloak.test.framework.config.Config;
|
||||||
import org.keycloak.test.framework.database.TestDatabase;
|
import org.keycloak.test.framework.database.TestDatabase;
|
||||||
import org.keycloak.test.framework.injection.InstanceContext;
|
import org.keycloak.test.framework.injection.InstanceContext;
|
||||||
import org.keycloak.test.framework.injection.LifeCycle;
|
import org.keycloak.test.framework.injection.LifeCycle;
|
||||||
|
@ -8,8 +9,8 @@ import org.keycloak.test.framework.injection.RequestedInstance;
|
||||||
import org.keycloak.test.framework.injection.Supplier;
|
import org.keycloak.test.framework.injection.Supplier;
|
||||||
import org.keycloak.test.framework.injection.SupplierHelpers;
|
import org.keycloak.test.framework.injection.SupplierHelpers;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.LinkedList;
|
||||||
import java.util.Map;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class AbstractKeycloakTestServerSupplier implements Supplier<KeycloakTestServer, KeycloakIntegrationTest> {
|
public abstract class AbstractKeycloakTestServerSupplier implements Supplier<KeycloakTestServer, KeycloakIntegrationTest> {
|
||||||
|
|
||||||
|
@ -28,17 +29,27 @@ public abstract class AbstractKeycloakTestServerSupplier implements Supplier<Key
|
||||||
KeycloakIntegrationTest annotation = instanceContext.getAnnotation();
|
KeycloakIntegrationTest annotation = instanceContext.getAnnotation();
|
||||||
KeycloakTestServerConfig serverConfig = SupplierHelpers.getInstance(annotation.config());
|
KeycloakTestServerConfig serverConfig = SupplierHelpers.getInstance(annotation.config());
|
||||||
|
|
||||||
Map<String, String> databaseConfig;
|
List<String> rawOptions = new LinkedList<>();
|
||||||
if (requiresDatabase()) {
|
rawOptions.add("start-dev");
|
||||||
TestDatabase testDatabase = instanceContext.getDependency(TestDatabase.class);
|
rawOptions.add("--cache=local");
|
||||||
databaseConfig = testDatabase.getServerConfig();
|
|
||||||
} else {
|
rawOptions.add("--bootstrap-admin-client-id=" + Config.getAdminClientId());
|
||||||
databaseConfig = Collections.emptyMap();
|
rawOptions.add("--bootstrap-admin-client-secret=" + Config.getAdminClientSecret());
|
||||||
|
|
||||||
|
if (!serverConfig.features().isEmpty()) {
|
||||||
|
rawOptions.add("--features=" + String.join(",", serverConfig.features()));
|
||||||
}
|
}
|
||||||
|
|
||||||
KeycloakTestServer keycloakTestServer = getServer();
|
serverConfig.options().forEach((key, value) -> rawOptions.add("--" + key + "=" + value));
|
||||||
keycloakTestServer.start(serverConfig, databaseConfig);
|
|
||||||
return keycloakTestServer;
|
if (requiresDatabase()) {
|
||||||
|
TestDatabase testDatabase = instanceContext.getDependency(TestDatabase.class);
|
||||||
|
testDatabase.getServerConfig().forEach((key, value) -> rawOptions.add("--" + key + "=" + value));
|
||||||
|
}
|
||||||
|
|
||||||
|
KeycloakTestServer server = getServer();
|
||||||
|
server.start(rawOptions);
|
||||||
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -2,42 +2,22 @@ package org.keycloak.test.framework.server;
|
||||||
|
|
||||||
import org.keycloak.it.utils.RawKeycloakDistribution;
|
import org.keycloak.it.utils.RawKeycloakDistribution;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class DistributionKeycloakTestServer implements KeycloakTestServer {
|
public class DistributionKeycloakTestServer implements KeycloakTestServer {
|
||||||
|
|
||||||
private boolean debug = false;
|
private static final boolean DEBUG = false;
|
||||||
private boolean manualStop = true;
|
private static final boolean MANUAL_STOP = true;
|
||||||
private boolean enableTls = false;
|
private static final boolean ENABLE_TLS = false;
|
||||||
private boolean reCreate = false;
|
private static final boolean RE_CREATE = false;
|
||||||
private boolean removeBuildOptionsAfterBuild = false;
|
private static final boolean REMOVE_BUILD_OPTIONS_AFTER_BUILD = false;
|
||||||
private int requestPort = 8080;
|
private static final int REQUEST_PORT = 8080;
|
||||||
|
|
||||||
private RawKeycloakDistribution keycloak;
|
private RawKeycloakDistribution keycloak;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(KeycloakTestServerConfig serverConfig, Map<String, String> databaseConfig) {
|
public void start(List<String> rawOptions) {
|
||||||
keycloak = new RawKeycloakDistribution(debug, manualStop, enableTls, reCreate, removeBuildOptionsAfterBuild, requestPort);
|
keycloak = new RawKeycloakDistribution(DEBUG, MANUAL_STOP, ENABLE_TLS, RE_CREATE, REMOVE_BUILD_OPTIONS_AFTER_BUILD, REQUEST_PORT);
|
||||||
|
|
||||||
// Set environment variables user and password for Keycloak Admin used by Keycloak instance.
|
|
||||||
keycloak.setEnvVar("KC_BOOTSTRAP_ADMIN_USERNAME", serverConfig.adminUserName());
|
|
||||||
keycloak.setEnvVar("KC_BOOTSTRAP_ADMIN_PASSWORD", serverConfig.adminUserPassword());
|
|
||||||
|
|
||||||
List<String> rawOptions = new LinkedList<>();
|
|
||||||
rawOptions.add("start-dev");
|
|
||||||
|
|
||||||
//rawOptions.add("--db=dev-mem"); // TODO With dev-mem there's an issue as the H2 DB isn't stopped when restarting embedded server
|
|
||||||
rawOptions.add("--cache=local");
|
|
||||||
|
|
||||||
if (!serverConfig.features().isEmpty()) {
|
|
||||||
rawOptions.add("--features=" + String.join(",", serverConfig.features()));
|
|
||||||
}
|
|
||||||
|
|
||||||
serverConfig.options().forEach((key, value) -> rawOptions.add("--" + key + "=" + value));
|
|
||||||
|
|
||||||
databaseConfig.forEach((key, value) -> rawOptions.add("--" + key + "=" + value));
|
|
||||||
|
|
||||||
keycloak.run(rawOptions).assertStartedDevMode();
|
keycloak.run(rawOptions).assertStartedDevMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,7 @@ package org.keycloak.test.framework.server;
|
||||||
import org.keycloak.Keycloak;
|
import org.keycloak.Keycloak;
|
||||||
import org.keycloak.common.Version;
|
import org.keycloak.common.Version;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public class EmbeddedKeycloakTestServer implements KeycloakTestServer {
|
public class EmbeddedKeycloakTestServer implements KeycloakTestServer {
|
||||||
|
@ -13,29 +11,7 @@ public class EmbeddedKeycloakTestServer implements KeycloakTestServer {
|
||||||
private Keycloak keycloak;
|
private Keycloak keycloak;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(KeycloakTestServerConfig serverConfig, Map<String, String> databaseConfig) {
|
public void start(List<String> rawOptions) {
|
||||||
List<String> rawOptions = new LinkedList<>();
|
|
||||||
rawOptions.add("start-dev");
|
|
||||||
rawOptions.add("--cache=local");
|
|
||||||
|
|
||||||
if (!serverConfig.features().isEmpty()) {
|
|
||||||
rawOptions.add("--features=" + String.join(",", serverConfig.features()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serverConfig.adminUserName() != null) {
|
|
||||||
System.setProperty("keycloakAdmin", serverConfig.adminUserName());
|
|
||||||
} else {
|
|
||||||
System.getProperties().remove("keycloakAdmin");
|
|
||||||
}
|
|
||||||
if (serverConfig.adminUserPassword() != null) {
|
|
||||||
System.setProperty("keycloakAdminPassword", serverConfig.adminUserPassword());
|
|
||||||
} else {
|
|
||||||
System.getProperties().remove("keycloakAdminPassword");
|
|
||||||
}
|
|
||||||
|
|
||||||
serverConfig.options().forEach((key, value) -> rawOptions.add("--" + key + "=" + value));
|
|
||||||
databaseConfig.forEach((key, value) -> rawOptions.add("--" + key + "=" + value));
|
|
||||||
|
|
||||||
keycloak = Keycloak.builder()
|
keycloak = Keycloak.builder()
|
||||||
.setVersion(Version.VERSION)
|
.setVersion(Version.VERSION)
|
||||||
.start(rawOptions);
|
.start(rawOptions);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package org.keycloak.test.framework.server;
|
package org.keycloak.test.framework.server;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.List;
|
||||||
|
|
||||||
public interface KeycloakTestServer {
|
public interface KeycloakTestServer {
|
||||||
|
|
||||||
void start(KeycloakTestServerConfig serverConfig, Map<String, String> databaseConfig);
|
void start(List<String> rawOptions);
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.keycloak.test.framework.server;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface KeycloakTestServerConfig {
|
public interface KeycloakTestServerConfig {
|
||||||
|
@ -15,12 +14,4 @@ public interface KeycloakTestServerConfig {
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
default String adminUserName() {
|
|
||||||
return "admin";
|
|
||||||
}
|
|
||||||
|
|
||||||
default String adminUserPassword() {
|
|
||||||
return "admin";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package org.keycloak.test.framework.server;
|
package org.keycloak.test.framework.server;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.List;
|
||||||
|
|
||||||
public class RemoteKeycloakTestServer implements KeycloakTestServer {
|
public class RemoteKeycloakTestServer implements KeycloakTestServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(KeycloakTestServerConfig serverConfig, Map<String, String> databaseConfig) {
|
public void start(List<String> rawOptions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue