NOTE: This article might be being revised continuously because of new insights.
This blog describes how I created a couple of Docker images to demonstrate Keycloak.
Important in this blog is that the whole process will be described. I attended a couple of keycloak sessions during Javaone this year and during these sessions the illusion was created that adding Keycloak as the security provider for your application is very easy and almost non-invasive for your code.
What they did not tell you that configuring a server that could use keycloak was not as trivial.
This blog will also expose a java web application with rest end-points to show how the auth works.
- I will use usernames and passwords in this document as this is a demo blog. Be sure to change the relevant stuff if you want to use it for realzlike :-) I will not say so again.
- This demo has done on a Mac and the commands will reflect that. You might have to do some translating if you are on another OS. Sorry will not be fixed
The whole idea is to setup Keycloak as a separate server as a kind of “Security as a service” solution.
This is the setup I choose:
- Get a docker data volume for my database values
- jboss/keycloak-postgres docker image to serve as the keycloak security server / service
- Tune a postgress docker image to serve as db for the keycloak server
- jboss/wildfly docker image as the base for the application server. This images will be adjusted to enable keycloak as security provider.
- put it all behind an apache proxy in a production environment.
Time to maybe read more here about what the following commands mean.
If you are not interested in accessing the ivonet-postgres-data with external tools, then you can eliminate the -p parameter from the ivonet-keycloak-postgres command.
As you might have noticed I gave the external port 15432. I did this because on my production environment I already have a native postgres running and am migrating slowly.
So now we have a setup that might work :-)
lets try it out and enter the following in the terminal:
You should now see something like this:
NOTE: the default username and password is admin and admin.
So now we have a keycloak auth server up and running. it is time to get another instance of wildfly and make it keycloak enabled. This is the part not mentioned in the sessions I followed and what stumped me in the beginning. On my local machene I mostly use Glassfish as my EE development environment and I could not get the sample apps to work… After a couple of hours I started thinking for real :-) and doing some reading and it actually made sense that it didn’t work. I was so focuessed on the demo I saw that I didn’t realize that glassfish != wildfly and that something might have to be done to get stuff working.
Wel as you may have guessed you actually do need something else. Wildfly is the obvious choise because jboss is the major contributor to keycloak. You need an adaptor installed on the server, because you want the EE container to recognize keycloak as a security provider.
JBoss provides a docker image for that to but as of the time of this writing it was in wildfly 9.0.1.Final and on keycloak 1.5.0.Final and the most current versions are 9.0.2.Final for wildfly and 1.6.1.Final for keycloak so I upgraded from the latest default wildfly image.
The power of docker is to make adjustments gradually and modularly and so I did that too…
- first upgraded to wildfly with the admin console enabled
- now build it:
docker build --tag ivonet/wildfly-admin .
- I also pushed it to de docker repository because I intent to reuse it for development purposes
- add to this admin enabled wildfly by adding the keycloak adapter
See this Dockerfile for the one I used to build my own version of Wilfly with the keycloak adapter installed.
- build it:
docker build --tag ivonet/wildfly-admin-keycloak-adapter .
- push it to the repo for reuse:
- As you can see this images is extended from ivonet/wildfly-admin that was just created.
- it sets an environment variable for the keycloak version
- it changes the workdir
- it fetches (curl) the correct adapter from internet and un-tars’ it
- changes workdir again
- changes the standalone.xml file at the appropriate points in the file with the sed command to activate the security provider module/adapter
- expose the standard port and the admin console port
This Dockerfile is of course the product of some trial and error I had to find out if the install was correct. This part will not be explained here, but if you want more input on this subject, drop me a line.
This image is again a base for more because now it is time to write an app and deploy it.
I’ve made a screencast with a basic talk about Keycloak explaining a lot of the above text.
Well I found out very soon that all of the above was great but didn’t work very wel in production.
My production environment is an Ubuntu Linux distribution and I access all my sites through Apache2 VirtualHost configurations. Apache is my front proxy and directs all based on servername resolves and ports.
When trying to put my keycloak docker construction as described above behind an Apache ProxyPass construction it all went to pieces. As we are talking about a security solution it seems kinda important to do all through https. So I went to letsencrypt and got myself a certificate and proxypassed my content to the inner docker endpoint. The trouble was that when talking secure (https) I got all kinds of error messages about “Mixed content” and stuff was blocked by the browser(s). Solving this was way more hassle than I expected and took my about two evenings of googling and reading to fix.
First I had to create a custom Dockerfile based on the jboss/keycloak-postgres image to change a few settings in the standalone.xml of that distribution. These settings can be found in the documentation but are not easy to find.
and replace the current image with my own
On build machine:
Notice that now I get the ivonet/keycloak-postgres and not the jboss/keycloak-postgres.
Then I had to make changes to the Apache config:
Now I have no mixed content messages anymore and a certificate that is not self signed. Great stuff.
Hopefully I’m ready for the next step.
This command is quite involved and will do:
- run the jboss/keycloak-postgres image
- naming it ivonet-keycloak-backup but will be removed after quit
- map the current host folder to the image folder /backup
- link ivonet-keycloak-postgres to the postgres image
- start keycloak with a couple of keycloak specific parameters telling it to extract the realmName=IvoNet to a singleFile
The extraction will take place and after that the server is still running. You can quit it by pressing
Now you will see a file in the current folder named something like:
This is a file you can import as a ream in Keycloak.
Now you can even make it more efficient:
Next time you can just run:
and it will create the the json file at the location you ran the command. Now I think that you can change these commands to suit your needs. e.g. when you always want to backup to a specific host location you can replace $(pwd) with a local folder.
Configuring Keycloak for production based on docker and all was not as easy as I was made to believe. I learned a lot though and that’s why I love doing this stuff so much.
Hope you get stuff working a but faster than I did with the help provided here.