mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 15:02:05 -03:30
[Test Framework] Ability to run Keycloak test server with HTTPS (#42616)
* Ability to run Keycloak test server with HTTPS Closes: #34486 Signed-off-by: Simon Vacek <simonvacky@email.cz> # Conflicts: # test-framework/core/src/main/java/org/keycloak/testframework/CoreTestFrameworkExtension.java # test-framework/core/src/main/java/org/keycloak/testframework/server/KeycloakServerConfigBuilder.java # Conflicts: # test-framework/core/src/main/java/org/keycloak/testframework/CoreTestFrameworkExtension.java * PR review fixes Signed-off-by: Simon Vacek <simonvacky@email.cz> * Split keystore into truststore and keystore Signed-off-by: Simon Vacek <simonvacky@email.cz> --------- Signed-off-by: Simon Vacek <simonvacky@email.cz>
This commit is contained in:
parent
54e8c87860
commit
ae7c2d29e8
@ -154,6 +154,11 @@ public class ClusteredKeycloakServer implements KeycloakServer {
|
||||
return getManagementBaseUrl(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTlsEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getBasePort(int index) {
|
||||
return containers[index].getMappedPort(REQUEST_PORT);
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import org.keycloak.testframework.events.EventsSupplier;
|
||||
import org.keycloak.testframework.events.SysLogServerSupplier;
|
||||
import org.keycloak.testframework.http.HttpClientSupplier;
|
||||
import org.keycloak.testframework.http.HttpServerSupplier;
|
||||
import org.keycloak.testframework.https.CertificatesSupplier;
|
||||
import org.keycloak.testframework.injection.Supplier;
|
||||
import org.keycloak.testframework.realm.ClientSupplier;
|
||||
import org.keycloak.testframework.realm.RealmSupplier;
|
||||
@ -47,7 +48,8 @@ public class CoreTestFrameworkExtension implements TestFrameworkExtension {
|
||||
new HttpClientSupplier(),
|
||||
new HttpServerSupplier(),
|
||||
new InfinispanExternalServerSupplier(),
|
||||
new SimpleHttpSupplier()
|
||||
new SimpleHttpSupplier(),
|
||||
new CertificatesSupplier()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ package org.keycloak.testframework.admin;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.KeycloakBuilder;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
@ -17,6 +18,13 @@ public class AdminClientFactory {
|
||||
delegateSupplier = () -> KeycloakBuilder.builder().serverUrl(serverUrl);
|
||||
}
|
||||
|
||||
AdminClientFactory(String serverUrl, SSLContext sslContext) {
|
||||
delegateSupplier = () ->
|
||||
KeycloakBuilder.builder()
|
||||
.serverUrl(serverUrl)
|
||||
.resteasyClient(Keycloak.getClientProvider().newRestEasyClient(null, sslContext, false));
|
||||
}
|
||||
|
||||
public AdminClientBuilder create() {
|
||||
return new AdminClientBuilder(this, delegateSupplier.get());
|
||||
}
|
||||
|
||||
@ -1,17 +1,27 @@
|
||||
package org.keycloak.testframework.admin;
|
||||
|
||||
import org.keycloak.testframework.annotations.InjectAdminClientFactory;
|
||||
import org.keycloak.testframework.https.ManagedCertificates;
|
||||
import org.keycloak.testframework.injection.InstanceContext;
|
||||
import org.keycloak.testframework.injection.RequestedInstance;
|
||||
import org.keycloak.testframework.injection.Supplier;
|
||||
import org.keycloak.testframework.server.KeycloakServer;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
public class AdminClientFactorySupplier implements Supplier<AdminClientFactory, InjectAdminClientFactory> {
|
||||
|
||||
@Override
|
||||
public AdminClientFactory getValue(InstanceContext<AdminClientFactory, InjectAdminClientFactory> instanceContext) {
|
||||
KeycloakServer server = instanceContext.getDependency(KeycloakServer.class);
|
||||
return new AdminClientFactory(server.getBaseUrl());
|
||||
|
||||
if (!server.isTlsEnabled()) {
|
||||
return new AdminClientFactory(server.getBaseUrl());
|
||||
} else {
|
||||
ManagedCertificates managedCert = instanceContext.getDependency(ManagedCertificates.class);
|
||||
SSLContext sslContext = managedCert.getClientSSLContext();
|
||||
return new AdminClientFactory(server.getBaseUrl(), sslContext);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,14 +1,18 @@
|
||||
package org.keycloak.testframework.http;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.keycloak.testframework.annotations.InjectHttpClient;
|
||||
import org.keycloak.testframework.https.ManagedCertificates;
|
||||
import org.keycloak.testframework.injection.InstanceContext;
|
||||
import org.keycloak.testframework.injection.LifeCycle;
|
||||
import org.keycloak.testframework.injection.RequestedInstance;
|
||||
import org.keycloak.testframework.injection.Supplier;
|
||||
import org.keycloak.testframework.server.KeycloakServer;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
|
||||
public class HttpClientSupplier implements Supplier<HttpClient, InjectHttpClient> {
|
||||
@ -17,6 +21,19 @@ public class HttpClientSupplier implements Supplier<HttpClient, InjectHttpClient
|
||||
public HttpClient getValue(InstanceContext<HttpClient, InjectHttpClient> instanceContext) {
|
||||
HttpClientBuilder builder = HttpClientBuilder.create();
|
||||
|
||||
KeycloakServer server = instanceContext.getDependency(KeycloakServer.class);
|
||||
if (server.isTlsEnabled()) {
|
||||
ManagedCertificates managedCerts = instanceContext.getDependency(ManagedCertificates.class);
|
||||
|
||||
SSLContext sslContext = managedCerts.getClientSSLContext();
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
|
||||
sslContext,
|
||||
SSLConnectionSocketFactory.getDefaultHostnameVerifier()
|
||||
);
|
||||
|
||||
builder.setSSLSocketFactory(sslSocketFactory);
|
||||
}
|
||||
|
||||
if (!instanceContext.getAnnotation().followRedirects()) {
|
||||
builder.disableRedirectHandling();
|
||||
}
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
package org.keycloak.testframework.https;
|
||||
|
||||
import org.keycloak.testframework.injection.InstanceContext;
|
||||
import org.keycloak.testframework.injection.LifeCycle;
|
||||
import org.keycloak.testframework.injection.RequestedInstance;
|
||||
import org.keycloak.testframework.injection.Supplier;
|
||||
import org.keycloak.testframework.injection.SupplierOrder;
|
||||
|
||||
public class CertificatesSupplier implements Supplier<ManagedCertificates, InjectCertificates> {
|
||||
|
||||
@Override
|
||||
public ManagedCertificates getValue(InstanceContext<ManagedCertificates, InjectCertificates> instanceContext) {
|
||||
return new ManagedCertificates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LifeCycle getDefaultLifecycle() {
|
||||
return LifeCycle.GLOBAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean compatible(InstanceContext<ManagedCertificates, InjectCertificates> a, RequestedInstance<ManagedCertificates, InjectCertificates> b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int order() {
|
||||
return SupplierOrder.BEFORE_KEYCLOAK_SERVER;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package org.keycloak.testframework.https;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface InjectCertificates {
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
package org.keycloak.testframework.https;
|
||||
|
||||
import org.apache.http.ssl.SSLContextBuilder;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.common.crypto.CryptoIntegration;
|
||||
import org.keycloak.common.crypto.CryptoProvider;
|
||||
import org.keycloak.common.util.KeystoreUtil;
|
||||
import org.keycloak.crypto.def.DefaultCryptoProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
public class ManagedCertificates {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ManagedCertificates.class);
|
||||
|
||||
private final CryptoProvider cryptoProvider;
|
||||
|
||||
private KeyStore serverKeyStore;
|
||||
private KeyStore clientsTrustStore;
|
||||
|
||||
private final static Path KEYSTORES_DIR = Path.of(System.getProperty("java.io.tmpdir"));
|
||||
private final static Path SERVER_KEYSTORE_FILE_PATH = KEYSTORES_DIR.resolve("kc-testing-server-keystore.jks");
|
||||
private final static Path CLIENTS_TRUSTSTORE_FILE_PATH = KEYSTORES_DIR.resolve("kc-testing-clients-truststore.jks");
|
||||
|
||||
private final static char[] PASSWORD = "password".toCharArray();
|
||||
|
||||
private final static String PRV_KEY_ENTRY = "prvKey";
|
||||
public final static String CERT_ENTRY = "cert";
|
||||
|
||||
|
||||
public ManagedCertificates() throws ManagedCertificatesException {
|
||||
if (!CryptoIntegration.isInitialised()) {
|
||||
CryptoIntegration.setProvider(new DefaultCryptoProvider());
|
||||
}
|
||||
cryptoProvider = CryptoIntegration.getProvider();
|
||||
initServerCerts();
|
||||
}
|
||||
|
||||
public String getKeycloakServerKeyStorePath() {
|
||||
return SERVER_KEYSTORE_FILE_PATH.toString();
|
||||
}
|
||||
|
||||
public String getKeycloakServerKeyStorePassword() {
|
||||
return String.valueOf(PASSWORD);
|
||||
}
|
||||
|
||||
public KeyStore getClientTrustStore() {
|
||||
return clientsTrustStore;
|
||||
}
|
||||
|
||||
public X509Certificate getKeycloakServerCertificate() {
|
||||
try {
|
||||
return (X509Certificate) serverKeyStore.getCertificate(CERT_ENTRY);
|
||||
} catch (KeyStoreException e) {
|
||||
throw new ManagedCertificatesException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public SSLContext getClientSSLContext() {
|
||||
try {
|
||||
return SSLContextBuilder.create()
|
||||
.loadTrustMaterial(clientsTrustStore, null)
|
||||
.build();
|
||||
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
|
||||
throw new ManagedCertificatesException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void initServerCerts() throws ManagedCertificatesException {
|
||||
try {
|
||||
serverKeyStore = cryptoProvider.getKeyStore(KeystoreUtil.KeystoreFormat.JKS);
|
||||
clientsTrustStore = cryptoProvider.getKeyStore(KeystoreUtil.KeystoreFormat.JKS);
|
||||
|
||||
if (Files.exists(SERVER_KEYSTORE_FILE_PATH) && Files.exists(CLIENTS_TRUSTSTORE_FILE_PATH)) {
|
||||
LOGGER.debugv("Existing Server KeyStore files found in {0}", KEYSTORES_DIR);
|
||||
|
||||
loadKeyStore(serverKeyStore, SERVER_KEYSTORE_FILE_PATH, PASSWORD);
|
||||
loadKeyStore(clientsTrustStore, CLIENTS_TRUSTSTORE_FILE_PATH, PASSWORD);
|
||||
} else {
|
||||
LOGGER.debugv("Generating Server KeyStore files in {0}", KEYSTORES_DIR);
|
||||
|
||||
generateKeystore(serverKeyStore, clientsTrustStore, "localhost");
|
||||
// store the generated keystore and truststore in a temp folder
|
||||
try (FileOutputStream fos = new FileOutputStream(SERVER_KEYSTORE_FILE_PATH.toFile())) {
|
||||
serverKeyStore.store(fos, PASSWORD);
|
||||
}
|
||||
try (FileOutputStream fos = new FileOutputStream(CLIENTS_TRUSTSTORE_FILE_PATH.toFile())) {
|
||||
clientsTrustStore.store(fos, PASSWORD);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ManagedCertificatesException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadKeyStore(KeyStore keyStore, Path keyStorePath, char[] keyStorePasswd) throws NoSuchAlgorithmException, IOException, CertificateException {
|
||||
try (FileInputStream fis = new FileInputStream(keyStorePath.toFile())) {
|
||||
keyStore.load(fis, keyStorePasswd);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateKeystore(KeyStore keyStore, KeyStore trustStore, String subject) throws NoSuchAlgorithmException, NoSuchProviderException, CertificateException, IOException, KeyStoreException, Exception {
|
||||
keyStore.load(null);
|
||||
trustStore.load(null);
|
||||
|
||||
KeyPair keyPair = generateKeyPair();
|
||||
X509Certificate cert = generateX509CertificateCertificate(keyPair, subject);
|
||||
|
||||
keyStore.setCertificateEntry(CERT_ENTRY, cert);
|
||||
trustStore.setCertificateEntry(CERT_ENTRY, cert);
|
||||
keyStore.setKeyEntry(PRV_KEY_ENTRY, keyPair.getPrivate(), PASSWORD, new X509Certificate[]{cert});
|
||||
}
|
||||
|
||||
private KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
|
||||
return cryptoProvider.getKeyPairGen("RSA").generateKeyPair();
|
||||
}
|
||||
|
||||
private X509Certificate generateX509CertificateCertificate(KeyPair keyPair, String subject) throws Exception {
|
||||
// generate a v1 certificate
|
||||
X509Certificate caCert = cryptoProvider.getCertificateUtils().generateV1SelfSignedCertificate(keyPair, subject);
|
||||
|
||||
// generate a v3 certificate
|
||||
return cryptoProvider.getCertificateUtils().generateV3Certificate(keyPair, keyPair.getPrivate(), caCert, subject);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package org.keycloak.testframework.https;
|
||||
|
||||
public class ManagedCertificatesException extends RuntimeException {
|
||||
public ManagedCertificatesException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@ -2,9 +2,10 @@ package org.keycloak.testframework.server;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.testframework.infinispan.InfinispanServer;
|
||||
import org.keycloak.testframework.config.Config;
|
||||
import org.keycloak.testframework.database.TestDatabase;
|
||||
import org.keycloak.testframework.https.ManagedCertificates;
|
||||
import org.keycloak.testframework.infinispan.InfinispanServer;
|
||||
import org.keycloak.testframework.injection.AbstractInterceptorHelper;
|
||||
import org.keycloak.testframework.injection.InstanceContext;
|
||||
import org.keycloak.testframework.injection.LifeCycle;
|
||||
@ -48,6 +49,12 @@ public abstract class AbstractKeycloakServerSupplier implements Supplier<Keycloa
|
||||
ServerConfigInterceptorHelper interceptor = new ServerConfigInterceptorHelper(instanceContext.getRegistry());
|
||||
command = interceptor.intercept(command, instanceContext);
|
||||
|
||||
if (command.tlsEnabled()) {
|
||||
ManagedCertificates managedCert = instanceContext.getDependency(ManagedCertificates.class);
|
||||
command.option("https-key-store-file", managedCert.getKeycloakServerKeyStorePath());
|
||||
command.option("https-key-store-password", managedCert.getKeycloakServerKeyStorePassword());
|
||||
}
|
||||
|
||||
command.log().fromConfig(Config.getConfig());
|
||||
|
||||
getLogger().info("Starting Keycloak test server");
|
||||
|
||||
@ -14,7 +14,6 @@ import java.util.regex.Pattern;
|
||||
public class DistributionKeycloakServer implements KeycloakServer {
|
||||
|
||||
private static final boolean MANUAL_STOP = true;
|
||||
private static final boolean ENABLE_TLS = false;
|
||||
private static final boolean RE_CREATE = false;
|
||||
private static final boolean REMOVE_BUILD_OPTIONS_AFTER_BUILD = false;
|
||||
private static final int REQUEST_PORT = 8080;
|
||||
@ -22,6 +21,7 @@ public class DistributionKeycloakServer implements KeycloakServer {
|
||||
private RawKeycloakDistribution keycloak;
|
||||
|
||||
private final boolean debug;
|
||||
private boolean enableTls = false;
|
||||
|
||||
public DistributionKeycloakServer(boolean debug) {
|
||||
this.debug = debug;
|
||||
@ -29,7 +29,8 @@ public class DistributionKeycloakServer implements KeycloakServer {
|
||||
|
||||
@Override
|
||||
public void start(KeycloakServerConfigBuilder keycloakServerConfigBuilder) {
|
||||
keycloak = new RawKeycloakDistribution(false, MANUAL_STOP, ENABLE_TLS, RE_CREATE, REMOVE_BUILD_OPTIONS_AFTER_BUILD, REQUEST_PORT, new LoggingOutputConsumer());
|
||||
enableTls = keycloakServerConfigBuilder.tlsEnabled();
|
||||
keycloak = new RawKeycloakDistribution(false, MANUAL_STOP, false, RE_CREATE, REMOVE_BUILD_OPTIONS_AFTER_BUILD, REQUEST_PORT, new LoggingOutputConsumer());
|
||||
|
||||
// RawKeycloakDistribution sets "DEBUG_SUSPEND", not "DEBUG" when debug is passed to constructor
|
||||
if (debug) {
|
||||
@ -54,12 +55,25 @@ public class DistributionKeycloakServer implements KeycloakServer {
|
||||
|
||||
@Override
|
||||
public String getBaseUrl() {
|
||||
return "http://localhost:8080";
|
||||
if (isTlsEnabled()) {
|
||||
return "https://localhost:8443";
|
||||
} else {
|
||||
return "http://localhost:8080";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getManagementBaseUrl() {
|
||||
return "http://localhost:9000";
|
||||
if (isTlsEnabled()) {
|
||||
return "https://localhost:9000";
|
||||
} else {
|
||||
return "http://localhost:9000";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTlsEnabled() {
|
||||
return enableTls;
|
||||
}
|
||||
|
||||
private static final class LoggingOutputConsumer implements OutputConsumer {
|
||||
|
||||
@ -15,10 +15,12 @@ public class EmbeddedKeycloakServer implements KeycloakServer {
|
||||
|
||||
private Keycloak keycloak;
|
||||
private Path homeDir;
|
||||
private boolean enableTls = false;
|
||||
|
||||
@Override
|
||||
public void start(KeycloakServerConfigBuilder keycloakServerConfigBuilder) {
|
||||
Keycloak.Builder builder = Keycloak.builder().setVersion(Version.VERSION);
|
||||
enableTls = keycloakServerConfigBuilder.tlsEnabled();
|
||||
|
||||
for(Dependency dependency : keycloakServerConfigBuilder.toDependencies()) {
|
||||
builder.addDependency(dependency.getGroupId(), dependency.getArtifactId(), "");
|
||||
@ -61,11 +63,24 @@ public class EmbeddedKeycloakServer implements KeycloakServer {
|
||||
|
||||
@Override
|
||||
public String getBaseUrl() {
|
||||
return "http://localhost:8080";
|
||||
if (isTlsEnabled()) {
|
||||
return "https://localhost:8443";
|
||||
} else {
|
||||
return "http://localhost:8080";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getManagementBaseUrl() {
|
||||
return "http://localhost:9001";
|
||||
if (isTlsEnabled()) {
|
||||
return "https://localhost:9001";
|
||||
} else {
|
||||
return "http://localhost:9001";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTlsEnabled() {
|
||||
return enableTls;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,4 +9,6 @@ public interface KeycloakServer {
|
||||
String getBaseUrl();
|
||||
|
||||
String getManagementBaseUrl();
|
||||
|
||||
boolean isTlsEnabled();
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ public class KeycloakServerConfigBuilder {
|
||||
private final Set<Path> configFiles = new HashSet<>();
|
||||
private CacheType cacheType = CacheType.LOCAL;
|
||||
private boolean externalInfinispan = false;
|
||||
private boolean tlsEnabled = false;
|
||||
|
||||
private KeycloakServerConfigBuilder(String command) {
|
||||
this.command = command;
|
||||
@ -99,6 +100,16 @@ public class KeycloakServerConfigBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public KeycloakServerConfigBuilder tlsEnabled(boolean enabled) {
|
||||
tlsEnabled = enabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean tlsEnabled() {
|
||||
return tlsEnabled ;
|
||||
}
|
||||
|
||||
|
||||
public KeycloakServerConfigBuilder cacheConfigFile(String resourcePath) {
|
||||
try {
|
||||
Path p = Paths.get(Objects.requireNonNull(getClass().getResource(resourcePath)).toURI());
|
||||
|
||||
@ -2,6 +2,7 @@ package org.keycloak.testframework.server;
|
||||
|
||||
import io.quarkus.maven.dependency.Dependency;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
@ -10,8 +11,11 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class RemoteKeycloakServer implements KeycloakServer {
|
||||
|
||||
private boolean enableTls = false;
|
||||
|
||||
@Override
|
||||
public void start(KeycloakServerConfigBuilder keycloakServerConfigBuilder) {
|
||||
enableTls = keycloakServerConfigBuilder.tlsEnabled();
|
||||
if (!verifyRunningKeycloak()) {
|
||||
printStartupInstructions(keycloakServerConfigBuilder);
|
||||
waitForStartup();
|
||||
@ -24,12 +28,25 @@ public class RemoteKeycloakServer implements KeycloakServer {
|
||||
|
||||
@Override
|
||||
public String getBaseUrl() {
|
||||
return "http://localhost:8080";
|
||||
if (isTlsEnabled()) {
|
||||
return "https://localhost:8443";
|
||||
} else {
|
||||
return "http://localhost:8080";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getManagementBaseUrl() {
|
||||
return "http://localhost:9000";
|
||||
if (isTlsEnabled()) {
|
||||
return "https://localhost:9000";
|
||||
} else {
|
||||
return "http://localhost:9000";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTlsEnabled() {
|
||||
return enableTls;
|
||||
}
|
||||
|
||||
private void printStartupInstructions(KeycloakServerConfigBuilder keycloakServerConfigBuilder) {
|
||||
@ -70,6 +87,10 @@ public class RemoteKeycloakServer implements KeycloakServer {
|
||||
return true;
|
||||
} catch (ConnectException e) {
|
||||
return false;
|
||||
} catch (SSLException ignored) {
|
||||
// if the kc server is running with https, it is not this class' responsibility to check the certificate
|
||||
// we're just checking that keycloak is running
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@ -0,0 +1,97 @@
|
||||
package org.keycloak.test.examples;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.testframework.annotations.InjectAdminClient;
|
||||
import org.keycloak.testframework.annotations.InjectHttpClient;
|
||||
import org.keycloak.testframework.annotations.InjectKeycloakUrls;
|
||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.testframework.https.InjectCertificates;
|
||||
import org.keycloak.testframework.https.ManagedCertificates;
|
||||
import org.keycloak.testframework.oauth.OAuthClient;
|
||||
import org.keycloak.testframework.oauth.annotations.InjectOAuthClient;
|
||||
import org.keycloak.testframework.server.KeycloakServerConfig;
|
||||
import org.keycloak.testframework.server.KeycloakServerConfigBuilder;
|
||||
import org.keycloak.testframework.server.KeycloakUrls;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateNotYetValidException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
@KeycloakIntegrationTest(config = TlsEnabledTest.TlsEnabledServerConfig.class)
|
||||
public class TlsEnabledTest {
|
||||
|
||||
@InjectHttpClient
|
||||
HttpClient httpClient;
|
||||
|
||||
@InjectOAuthClient
|
||||
OAuthClient oAuthClient;
|
||||
|
||||
@InjectAdminClient
|
||||
Keycloak adminClient;
|
||||
|
||||
@InjectCertificates
|
||||
ManagedCertificates managedCertificates;
|
||||
|
||||
@InjectKeycloakUrls
|
||||
KeycloakUrls keycloakUrls;
|
||||
|
||||
|
||||
@Test
|
||||
public void testCertSupplier() throws KeyStoreException {
|
||||
Assertions.assertNotNull(managedCertificates);
|
||||
|
||||
KeyStore trustStore = managedCertificates.getClientTrustStore();
|
||||
Assertions.assertNotNull(trustStore);
|
||||
|
||||
X509Certificate cert = managedCertificates.getKeycloakServerCertificate();
|
||||
Assertions.assertNotNull(cert);
|
||||
Assertions.assertEquals(cert.getSerialNumber(), ((X509Certificate) trustStore.getCertificate(ManagedCertificates.CERT_ENTRY)).getSerialNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCertDetails() throws CertificateNotYetValidException, CertificateExpiredException {
|
||||
X509Certificate cert = managedCertificates.getKeycloakServerCertificate();
|
||||
|
||||
cert.checkValidity();
|
||||
Assertions.assertEquals("CN=localhost", cert.getSubjectX500Principal().getName());
|
||||
Assertions.assertEquals("CN=localhost", cert.getIssuerX500Principal().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpClient() throws IOException {
|
||||
URL baseUrl = keycloakUrls.getBaseUrl();
|
||||
Assertions.assertEquals("https", baseUrl.getProtocol());
|
||||
|
||||
HttpGet req = new HttpGet(baseUrl.toString());
|
||||
HttpResponse resp = httpClient.execute(req);
|
||||
Assertions.assertEquals(200, resp.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdminClient() {
|
||||
adminClient.realm("default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOAuthClient() {
|
||||
Assertions.assertTrue(oAuthClient.doWellKnownRequest().getTokenEndpoint().startsWith("https://"));
|
||||
}
|
||||
|
||||
|
||||
public static class TlsEnabledServerConfig implements KeycloakServerConfig {
|
||||
|
||||
@Override
|
||||
public KeycloakServerConfigBuilder configure(KeycloakServerConfigBuilder config) {
|
||||
return config.tlsEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user