While writing a few Integration tests(ITs), I ran into a scenario where my test had to make a few calls to the SSL enabled custom keycloak container. I had to communicate over HTTPS with the keycloak container since HTTP was disabled. I also wanted my tests to be compatible with any future customizations to the keycloak image. The keycloak image was using a self-signed certificate.
For the test code to be able to communicate with SSL enabled container, it was imperative that we either add code in our test to manage SSL issues(usually creating a Keystore programmatically) or worse install the self-signed certificate in the test code’s JVM.
Handling SSL in the test code would have been an added nuisance. With the intent of keeping the test code to only deal with the functionality under test(and not the infrastructure), I tried out using haproxy to handle ssl connection. The below picture outlines the basic implementation –
Keystore shared volume
A self-signed certificate was generated and placed onto a shared docker volume. Keycloak and Haproxy containers were made to refer to this shared Keystore volume.
Haproxy configuration – The configuration routes the HTTP traffic to HTTPS endpoint for keycloak i.e. keycloak-backend configuration will encrypt the outgoing traffic to keycloak with the same certificate(present on the shared volume) which is recognized by the keycloak container.
#---------------------------------------------------------------------
# Keycloak
#---------------------------------------------------------------------
frontend integration-tests-keycloak
bind *:8444
mode http
default_backend keycloak-backend
backend keycloak-backend
mode http
# https backend
server keycloak keycloak:8444 check ca-file /test-keystore/integration-tests.pem ssl
In conclusion, SSL management stays out of the test code and is only limited to the test infrastructure. Infrastructure here refers to docker maven plugin https://github.com/fabric8io/docker-maven-plugin
Haproxy image configuration
haproxy
${project.artifactId}-haproxy:${project.version}
${dockerHubPublic}/library/haproxy:2.2.3
/
${project.basedir}/src/test/config/haproxy
usr/local/etc/haproxy
unix
haproxy.cfg
${keycloak.proxy.port}:8444
keycloak
keystore
Keycloak image configuration
keycloak
${docker-image-registry}custom-keycloak-base:1.8.0-SNAPSHOT
${keycloak.https.port}:8444
POSTGRES
postgres
5432
${postgres.db}
Keycloak
${postgres.user}
${postgres.pass}
${keycloak.admin.username}
${keycloak.admin.password}
integration-tests.p12
integration-tests.pem
integration-tests-alias
changeit
DEBUG
DEBUG
keystore
postgres
postgres
https://${docker.host.address}:${keycloak.https.port}/auth/realms/master
true
500
Keystore image configuration
keystore
${project.artifactId}-keystore:${project.version}
${dockerHubPublic}/library/java:8
mkdir /test-keystore
$JAVA_HOME/bin/keytool -genkey -noprompt -alias integration-tests-alias -dname "CN=myname, OU=myorganisational.unit, O=myorganisation, L=mycity, S=myprovince, C=GB" -keystore /test-keystore/integration-tests.jks -storepass changeit -keypass changeit -keyalg RSA
$JAVA_HOME/bin/keytool -importkeystore -srckeystore /test-keystore/integration-tests.jks -srcstorepass changeit -deststorepass changeit -srckeypass changeit -destkeypass changeit -destkeystore /test-keystore/integration-tests.p12 -srcalias integration-tests-alias -srcstoretype jks -deststoretype pkcs12
openssl pkcs12 -in /test-keystore/integration-tests.p12 -out /test-keystore/integration-tests.pem -password pass:changeit
/test-keystore