This recipe describes how to deploy this example servlet to an OpenShift environment that is providing SSO capabilities using Keycloak (Red Hat SSO).
A simpler version that shows how to deploy the app using templates, but without using Keycloak for authentication can be found here.
The OpenRiskNet environment is planned to provide SSO capabilites using Keycloak. So to use this for authentication the Tomcat container needs to be configured with a valve that performs the authentication. This value recognises that the user is not signed in and redirects to Keycloak where the user enters their username and password. If successful the user is redirected back to Tomcat with a JSON Web Token containing the credentials, including an access token and a list of roles the user has. This time Tomcat accepts the user as being authorised and passes the request through to the servlet webapp.
To configure this we need to add various things to the Tomcat configuration.
- The Keycloak adapter jar files that need to go in the $CATALINA_HOME/lib directory
- Updates to server.xml and context.xml in $CATALINA_HOME/conf
- Updates to web.xml in $CATALINA_HOME/webapps/ROOT/WEB-INF
- Add keycloak.json to $CATALINA_HOME/webapps/ROOT/WEB-INF
These files are in this directory and will need editing if you are not using the standard set up which is:
- Base domain name of
prod.openrisknet.org - Keycloak found at
https://sso.prod.openrisknet.org - Keycloak realm of
openrisknet - User requires role of
standard-user
The Dockerfile that builds the image is ../../Dockerfile-keycloak. Note: the Dockerfile that is used to build the standard version is generated by the gradle build and so is not in git.
To build the image first make sure that the war file is built and then build and push the image:
$ ./gradlew war
<snip>
$ docker build -t tdudgeon/hello-example-servlet -f Dockerfile-keycloak .
<snip>
$ docker push tdudgeon/hello-example-servlet
<snip>
Create an OpenShift environment as follows:
- Create OpenShift nodes according to standard recipes (e.g. here) and set up DNS.
- Create an openrisknet-infra project
- Deploy Keycloak to the openrisknet-infra project according to the standard recipe.
- Deploy the ACME controller to the openrisknet-infra project according to the standard recipe.
- Set up permissions as described in the basic recipe to allow containers to be run as a specified user.
- Create the client configuration in Keycloak's openrisknet realm (note: openshift/keycloak/hello-servlet-client.json can be used as a template).
- Create a user with
standard-userrole in the openrisknet realm.
First create a new project for the app.
oc new-project example-servlet
The servlet needs to authenticate against the realm in Keycloak. To do this a client needs to be created in the realm.
This can be done manually, but we want to automate this. The keycloak-client-create.yaml template can be used to do this.
This template works in both the project with Keycloak and the project with the servlet and does the following:
- Generates a random secret that is used to identify the client.
- Creates a ConfigMap in the Keycloak project that contains a shell script that does the client registration.
- Runs a job that runs a pod with a Centos container that executes the shell script, using credentials provided in a secret.
- Creates a ConfigMap in the servlet project containing the configuration information that Tomcat needs (keycloak.json and context.xml).
The template has a number of parameters that can be specified. If not running on the OpenRiskNet production site some of these will need to be specified.
In the keycloak project (e.g. openrisknet-infra) as a user with edit privs in both projects (e.g. admin) run the template:
$ oc process -f keycloak-client-create.yaml | oc create -f -
configmap "hello-servlet-sso-config" created
configmap "hello-servlet-client-creator" created
job "hello-servlet-client-creator" created
Check in the Keycloak realm to confirm that the hello-servlet client has been added.
Check in the example-servlet project to confirm that the hello-servlet-sso-config ConfigMap has been created.
We are now ready to deply the application.
Switch to the example-servlet project.
Review the deploy.yaml file with respect to your environment. You will need to specify some paramters when deploying if you are not deploying to the OpenRiskNet production site. Deploy with something like this:
$ oc process -f deploy.yaml -p APPLICATION_DOMAIN=hello-servlet.prod.openrisknet.org -p GREETING=Hiya | oc create -f -
deploymentconfig "hello-servlet" created
service "hello-servlet" created
route "hello-servlet" created
Change the APPLICATION_DOMAIN and GREETING parameters accordingly to get a suitable host name for your app and a customised greeting.
Try to access it and you will see the Keycloak login prompt.
Login as the user you created in the openrisknet realm.
You should see the customised greeting message, something like this: Hiya user1.
The route has TLS configured, but a trusted certificate is not used by default. Edit the route YAML to deploy a trusted Let's Encrypt certificate using the ACME Controller.
metadata:
annotations:
kubernetes.io/tls-acme: 'true'
Note: if you re-run this process remember to delete all the artifacts that were created, including the client in Keycloak.
The keycloak.json file specifies "disable-trust-manager": true. This is to allow non trusted certificates to be used.
For production use certificates will be trusted and this parameter must be removed or set to false.
Logging in Tomcat is set to log messages for the Keycloak adapter at the FINE level.
This is useful for debugging but should be turned off for production use.
Look at the logging.properties file as an example.
Allow a logout URL to be configured and displayed in the servlet response.