Tuesday 5 May 2020

Installing Keycloak using Docker with Nginx as Reverse proxy

I wanted to test setting up an on premise identity provider and see if I can build my own SSO solution.
Found that the easiest way to do this is to use Keycloak.
Keycloak is a feature rich identity access management system that supports various integration protocols, among those, SAML 2.0 and OpenID connect.

Keycloak can also connect to existing IDPs and LDAP user directories to allow more flexible setups.

To install Keycloak using you can download it from its official download page: https://www.keycloak.org/downloads or use a docker image.
To use docker, we need to pull the official image from the official docker repo:

docker pull jboss/keycloak

Once we have the image, you can run keycloak using below simple docker run:

docker run -p 8080:8080 -p 8443:8443 jboss/keycloak
docker exec <CONTAINER> /opt/jboss/keycloak/bin/add-user-keycloak.sh -u <USERNAME> -p <PASSWORD>

This will start keycloak and expose port 8080 and 8443 to the docker host, then using docker exec, we run the script add-user-keycloak.sh to add an admin user.

In our use case here, we will start keycloak using a bigger set of options to allow it to  interact with a docker network, import a realm, that was saved from a previous setup, add admin user directly from docker run command and add reverse proxy forwarding options.

But first, we create a docker bridge network:

[root@Fingon ~]# docker network create  --subnet=172.28.0.0/16 --gateway=172.28.0.1 dcnet


And then the docker run script looks like this:

docker run \
-e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin \
-e PROXY_ADDRESS_FORWARDING=true \
-e KEYCLOAK_IMPORT=/tmp/realm-export.json \
-v /tmp/realm-export.json:/tmp/realm-export.json \
--network dcnet \
--hostname keycloak2 \
--ip 172.28.0.13 \
--add-host fingon:172.17.0.1 \
--add-host fingon:172.28.0.1 \
--add-host dcnode2:172.28.0.12 \
--add-host dcnode1:172.28.0.11 \
--add-host keycloak2:172.28.0.13 \
--dns 8.8.4.4 \
--dns 8.8.8.8 \
--dns 172.28.0.1 \
--name="keycloak2" -d -p 8181:8080 -p 9443:8443 jboss/keycloak



And once the container us up, we can see it with docker ps:

[root@Fingon ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                            NAMES                                                                                                                
3402c1b4163e        jboss/keycloak      "/opt/jboss/tools/do…"   21 hours ago        Up 3 seconds        0.0.0.0:8181->8080/tcp, 0.0.0.0:9443->8443/tcp   keycloak2                                                                                                            
[root@Fingon ~]#



We can now access keycloak from host machine using the URL http://localhost:8181/auth/ or https://localhost:9443/auth/

To expose keycloak to outside network and use proper SSL configuration, we then need to use a reverse proxy, in this case we use Nginx.

The Nigix configuration will look like this:

[root@Fingon nginx]# cat nginx.conf
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" "$http_authorization"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        return 301 https://fingon$request_uri;
    }

# Settings for a TLS enabled server.
#
    server {
        listen       443 ssl http2 default_server;
        listen       [::]:443 ssl http2 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        ssl_certificate "/root/cert.crt";
        ssl_certificate_key "/root/key.key";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }
               
        location /auth/ {
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Forwarded-Server $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_pass http://localhost:8181/auth/;

        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

}

[root@Fingon nginx]#


Now the UI looks like below:




You can access keycloak on https only using the URL https://fingon/auth.
Any requests to http will be redirected to https.
On Nginx, we need to set the host, x-forwarded-for and x-forwarded-proto headers so that keycloak identifies it is working behind a reverse proxy and does a proper redirection.
More information can be found in keycloak documentation.

Now we are ready to do more keycloak configurations ☺











No comments:

Post a Comment