The goal of this project is to create a simple Spring Boot REST API, called simple-service, and secure it with Keycloak. The API users will be loaded from OpenLDAP server. Furthermore, we will start Mesos / Marathon environment, so that we can deploy Keycloak and simple-service in it.
-
Spring BootJava Web application that exposes two endpoints:/api/public: endpoint that can be access by anyone, it is not secured;/api/private: endpoint that can just be accessed by users that provides aJWTtoken issued byKeycloakand the token must contain the roleUSER.
A new directory called /var/lib must be added to Docker File Sharing resources. For it, follow the steps below
- Go to Docker Desktop and open
Preferences...>Resources>File Sharing - Add
/var/lib - Click
Apply & Restartbutton
-
Open a terminal and make sure you are in
springboot-mesos-marathon-keycloak-openldaproot folder -
Export to an environment variable called
HOST_IPthe machine ip addressexport HOST_IP=$(ipconfig getifaddr en0) -
Run the following command
docker-compose up -dWarning: mesos-slave Docker container is not running, see issues
-
Wait for Docker containers to be up and running. To check it, run
docker-compose ps
| Service | URL |
|---|---|
| Mesos | http://localhost:5050 |
| Marathon | http://localhost:8090 |
The LDIF file that we will use, springboot-mesos-marathon-keycloak-openldap/ldap/ldap-mycompany-com.ldif, contains already a pre-defined structure for mycompany.com. Basically, it has 2 groups (developers and admin) and 4 users (Bill Gates, Steve Jobs, Mark Cuban and Ivan Franchin). Besides, it's defined that Bill Gates, Steve Jobs and Mark Cuban belong to developers group and Ivan Franchin belongs to admin group.
Bill Gates > username: bgates, password: 123
Steve Jobs > username: sjobs, password: 123
Mark Cuban > username: mcuban, password: 123
Ivan Franchin > username: ifranchin, password: 123
To import those users to OpenLDAP
- In a terminal, make sure you are in
springboot-mesos-marathon-keycloak-openldaproot folder - Run the following script
./import-openldap-users.sh
-
In a terminal, make sure you are in
springboot-mesos-marathon-keycloak-openldaproot folder -
Run the following script to build
simple-serviceDocker Image./docker-build.sh
-
In a terminal and inside
springboot-mesos-marathon-keycloak-openldaproot folder, runcurl -X POST \ -H "Content-type: application/json" \ -d @./marathon/keycloak.json \ http://localhost:8090/v2/apps -
Open
Marathonwebsite and wait forKeycloakto be healthy -
You can monitor
Keycloakdeployment logs onMesoswebsite- On
Active Taskssection, find the taskkeycloakand click onSandbox(last link on the right) - Click on
stdout - A window will open showing the logs at real-time
- On
When Keycloak is deployed to Marathon, it's assigned a host and port to it. There are two ways to obtain it
-
Running the following command in a terminal
KEYCLOAK_HOST_PORT="$(curl -s http://localhost:8090/v2/apps/keycloak | jq -r '.app.tasks[0].host'):$(curl -s http://localhost:8090/v2/apps/keycloak | jq '.app.tasks[0].ports[0]')" echo $KEYCLOAK_HOST_PORT -
Using
Marathonwebsite
Keycloak can be configured by running a script or manually. For manual configuration check Configure Keycloak Manually. Below, it's explained to configure by running a script.
-
In a terminal, make sure you are in
springboot-mesos-marathon-keycloak-openldaproot folder -
Run the following script
./init-keycloak.sh $KEYCLOAK_HOST_PORTThis script creates
company-servicesrealm,simple-serviceclient,USERclient role,ldapfederation and the usersbgatesandsjobswith the roleUSERassigned.
-
Update the property
env.keycloak.auth-server-urlthat is present inmarathon/simple-service.json, informingKeycloakaddress -
In a terminal and inside
springboot-mesos-marathon-keycloak-openldaproot folder, runcurl -X POST http://localhost:8090/v2/apps \ -H "Content-type: application/json" \ -d @./marathon/simple-service.json -
Open
Marathonwebsite and wait forsimple-serviceto be healthy. You can monitorsimple-servicedeployment logs onMesoswebsite -
The figure below shows
keycloakandsimple-servicerunning onMarathon
When simple-service is deployed in Marathon, it's assigned to it a host and port. There are two ways to obtain it
-
Running the following command in a terminal
SIMPLE_SERVICE_HOST_PORT="$(curl -s http://localhost:8090/v2/apps/simple-service | jq -r '.app.tasks[0].host'):$(curl -s http://localhost:8090/v2/apps/simple-service | jq '.app.tasks[0].ports[0]')" echo $SIMPLE_SERVICE_HOST_PORT -
Using
Marathon
-
In a terminal, make sure you have the environment variables
KEYCLOAK_HOST_PORTandSIMPLE_SERVICE_HOST_PORTwith the host and port ofKeycloakandsimple-servicerespectively -
Try to access
GET /api/publicendpointcurl -i "http://$SIMPLE_SERVICE_HOST_PORT/api/public"It should return
HTTP/1.1 200 It is public. -
Access
GET /api/privateendpoint (without authentication)curl -i "http://$SIMPLE_SERVICE_HOST_PORT/api/private"It should return
HTTP/1.1 302Here, the application is trying to redirect the request to an authentication link.
-
Get
bgatesaccess tokenBGATES_ACCESS_TOKEN=$(curl -s -X POST \ "http://$KEYCLOAK_HOST_PORT/realms/company-services/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=bgates" \ -d "password=123" \ -d "grant_type=password" \ -d "client_id=simple-service" | jq -r .access_token) echo $BGATES_ACCESS_TOKEN -
Access
GET /api/privateendpoint this time, informing the access tokencurl -i -H "Authorization: Bearer $BGATES_ACCESS_TOKEN" "http://$SIMPLE_SERVICE_HOST_PORT/api/private"It should return
HTTP/1.1 200 bgates, it is private.
-
Go to
Marathonand clicksimple-serviceapplication -
In the next page, click the
gearsymbol and then onDestroy -
Confirm the destruction of the application
-
Do the same for
keycloakapplication -
Go to a terminal and, inside
springboot-mesos-marathon-keycloak-openldaproot folder, rundocker-compose down -v docker rm -v $(docker ps -a -f status=exited -f status=created -q)
-
To remove the Docker image created in this project, go to a terminal and, inside
springboot-mesos-marathon-keycloak-openldaproot folder, run the script below./remove-docker-images.sh -
Mac Users
Remove
/var/libadded to DockerFile Sharingresources- Go to Docker Desktop and open
Preferences...>Resources>File Sharing - Remove
/var/libby clicking the-(minus) icon - Click
Apply & Restartbutton
- Go to Docker Desktop and open
The Docker container mesos-slave is not running. The log says
I0306 19:13:13.388301 34109 main.cpp:366] Version: 1.5.2
I0306 19:13:13.388335 34109 main.cpp:369] Git tag: 1.5.2
I0306 19:13:13.388352 34109 main.cpp:373] Git SHA: 3088295d4156eb58d092ad9b3529b85fd33bd36e
I0306 19:13:13.390044 34109 resolver.cpp:69] Creating default secret resolver
E0306 19:13:13.390632 34109 main.cpp:498] EXIT with status 1: Failed to create a containerizer: Could not create DockerContainerizer: Failed to create docker: Failed to find a mounted cgroups hierarchy for the 'cpu' subsystem; you probably need to mount cgroups manually

