Try to build a reverse proxy type configuration with Keycloak (Security Proxy edition)

What to do today

This time on the 7th day of the Keycloak Advent Calendar, we'll try Keycloak's Security Proxy.

Security Proxy is a type of simple reverse proxy (hereinafter referred to as Rivapro) server implemented in Java. The Liverpro server itself replaces Keycloak's client adapter, allowing you to protect the content you proxy to and control access by URL. It is suitable for use when the application server does not support OpenID Connect or SAML, it is difficult to install a client adapter, or the environment does not support the client adapter.

The main functions are as follows.

--HTTP (S) reverse proxy function --OpenID Connect integration with Keycloak server --Content protection for each specific path --Access control by authentication request --Allow or deny specific HTTP methods --Access control by the role of authenticated user --Deny access to specific URLs --Specify a URL that can be accessed without authentication --Information linkage of authenticated users by HTTP header

This time, I will try the procedure for protecting with Security Proxy for the original sample application of Tomcat 8.

Server configuration for operation check

The trial environment this time is like this. A demo realm has been created on the Keycloak server (see article on day 3 [https://qiita.com/tamura__246/items/4290a1035e1adcab733b)), and users with the following roles It is assumed that it exists.

FQDN OS JDK Constitution LISTEN port
kc-server.example.com CentOS 7.4.1708 OpenJDK 1.8.0.151 · Keycloak server 3.3.0.CR2 8443
kc-proxy.example.com CentOS 7.4.1708 OpenJDK 1.8.0.151 ・ Security Proxy 3.3.0.CR2
・ Tomcat 8.5.23
・ 18443(Security Proxy)
・ 8080(Tomcat)
user roll
user001 user
admin001 user,admin

In the exapmles application that comes with Tomcat, it is assumed that the following access control is applied.

proxy_acl01.jpg

The access ports to each server when checking the operation are as follows. proxy_port01.png

Keycloak server side settings

Add / configure client

  1. Log in to the Keycloak admin console.
  2. From the left menu bar, select the demo realm.
  3. Click Client on the left menu bar. A list of clients is displayed.
  4. Press the Create button in the upper right.
  5. Enter the following client settings and press the Save button. --Client ID: kc-proxy --Client protocol: openid-connect --Root URL: https://kc-proxy.example.com:18443 proxy01.png
  6. The kc-proxy setting screen will continue to be displayed. Make the following settings and press the Save button. --Access type: confidential --Valid redirect URI (first): https://kc-proxy.example.com:18443/ --Valid redirect URI (second): https://kc-proxy.example.com:18443/examples/websocket/echo.xhtml proxy02_opt.png : information_source: Valid redirect URI can also be specified by wildcard on Keycloak. However, the OIDC specification requires that it exactly match redirect_uri, so here we specify all possible URLs to redirect to. Therefore, you cannot directly transition from the unlogged-in state to the URL not specified here.
  7. Press the Credentials tab.
  8. Make a note of the value displayed as secret. proxy03.png

Security Proxy side configuration and startup

Introduction of sample application

As a sample application for checking the cooperation, install Tomcat 8.0 and start it.

cd  /tmp
wget http://ftp.tsukuba.wide.ad.jp/software/apache/tomcat/tomcat-8/v8.5.23/bin/apache-tomcat-8.5.23.tar.gz
tar zxvf apache-tomcat-8.5.23.tar.gz -C /usr/local
cd /usr/local/apache-tomcat-8.5.23/
./bin/startup.sh

Download and deploy Security Proxy

Download the Security Proxy, unzip it to / usr / local, and change it to the extracted directory.

cd  /tmp
wget https://downloads.jboss.org/keycloak/3.3.0.CR2/keycloak-proxy-3.3.0.CR2.zip
unzip keycloak-proxy-3.3.0.CR2.zip -d /usr/local
cd /usr/local/keycloak-proxy-3.3.0.CR2/

Security Proxy configuration file creation

In order to operate Security Proxy, create the following configuration file.

json:/usr/local/keycloak-proxy-3.3.0.CR2/proxy.json


{
    "target-url": "http://localhost:8080",
    "send-access-token": true,
    "bind-address": "{IP address / DNS name to bind}",
    "http-port": "18080",
    "https-port": "18443",
    "applications": [
        {
            "base-path": "/",
            "adapter-config": {
                "realm": "demo",
                "resource": "kc-proxy",
                "auth-server-url": "https://kc-server.example.com:8443/auth",
                "ssl-required" : "external",
                "credentials": {
                    "secret": "{Keycloak server-side secret value}"
                }
            },
            "constraints": [
                {
                    "pattern": "/*",
                    "authenticate": true
                },
                {
                    "pattern": "/examples/jsp/*",
                    "permit": true
                },
                {
                    "pattern": "/examples/websocket/*",
                    "roles-allowed": [
                        "admin"
                    ]
                }
            ]
        }
    ]
}

The meaning of the setting parameters in proxy.json is described below.

basic configuration

Parameter name Mandatory Description
target-url Specify the transfer destination URL of the reverse proxy.
send-access-token KEYCLOAK_ACCESS_Specifies whether to send the access token to the proxy destination with the header name TOKEN.
bind-address Specify the DNS name or IP address to bind to the socket of the proxy server. When connecting from the outside, specify a value other than the loopback address.
http-port Specify the port number to listen to as HTTP. However, whether HTTP access is allowed will be described later.adapter-configofssl-requiredof設定値に依存します。
https-port Specify the port number to listen to as HTTPS.
keystore Specify the keystore used when accepting HTTPS. If you do not specify a keystore, the automatically generated temporary self-signed server certificate will be used.
keystore-password Specify the keystore password when the keystore is specified.
key-password Specify the key password of the server certificate to be used.
buffer-size Specifies the socket buffer size of the HTTP server. Normally, the default is fine.
buffers-per-region Specifies the number of socket buffers for each region of the HTTP server. Normally, the default is fine.
io-threads Specifies the number of threads to process IO. Normally, the default is fine.
worker-threads Specifies the number of threads to process the request. Normally, the default is fine.

applications settings

Parameter name Mandatory Description
base-path Specifies the context root of the application."/"Must start with.
error-page If an error occurs(Including when access is denied)Specifies the error page to display in. base-Specify the relative path from path.
adapter-config It will be described later.

adapter-config settings

Parameter name Mandatory Description
realm Specify the realm name on the Keycloak side.
resource Client ID in the client settings on the Keycloak side(client-id)Is specified.
auth-server-url Specify the base URL on the Keycloak side.[^auth-server-url]
credentials With the access type on the Keycloak side"confidential"Required if you specify.
ssl-required Specifies whether to force access over HTTPS."all", "external", "none"Specify one of. The default is"external"Therefore, HTTP access is not allowed from the outside.

: information_source: Since there are so many adapter-config settings, only the minimum items required for operation check are listed. For other parameters, see Reference "Java Adapter Config".

setting constraint

Parameter name Mandatory Description
pattern Specify the URL pattern."/"Must start with a wildcard(*)Can only be specified at the end.
Valid patterns:/foo/bar/*and/foo/*.txt
Invalid pattern:/*/foo/*
roles-allowed This setting allows access only to users with a specific role. Multiple specifications can be specified in the array.
methods Specify the allowed HTTP method names as an array.
excluded-methods Specify the HTTP method name to deny as an array.
deny Set to true to deny access(URLs that you do not want to access via Keycoak Security Proxy, etc.)。
permit Set to true if you want to make it accessible without authentication.
permit-and-inject Set to true if you want to make it accessible without authentication. However, if it is authenticated and accessed, user information will be added to the header.
authenticate Set to true if you want access only by authentication, regardless of role.

After creating proxy.json, you can start Security Proxy from the following command.

cd /usr/local/keycloak-proxy-3.3.0.CR2/
java -jar bin/launcher.jar proxy.json

If there is no problem with the configuration file, the following startup message will be displayed.

Home directory: /usr/local/keycloak-proxy-3.3.0.CR2
11 24, 2017 6:44:37 pm org.keycloak.proxy.ProxyServerBuilder initConnections
WARN: Generating temporary SSL cert
11 24, 2017 6:44:45 pm org.xnio.Xnio <clinit>
INFO: XNIO version 3.3.6.Final
11 24, 2017 6:44:45 pm org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.3.6.Final

Operation check

URL that requires authentication

  1. Go to https://kc-proxy.example.com:18443/, which requires authentication.
  2. Since you have not logged in to Keycloak, you will be redirected to the login screen.
  3. Log in with ID / PW.
  4. The top screen of Tomcat is displayed.
  5. Go to https://kc-proxy.example.com:18443/examples/servlets/servlet/RequestHeaderExample.
  6. You can see that the Keycloak user information is linked to the HTTP header. proxy04.png

URL that does not require authentication

  1. Go to https://kc-proxy.example.com:18443/examples/jsp/, which does not require authentication.
  2. You can see that you can browse the page without authenticating. proxy05.png

URLs that require the admin role

  1. Go to https://kc-proxy.example.com:18443/examples/websocket/echo.xhtml, which requires the admin role.
  2. Log in with the ID / PW of the user who has the admin role.
  3. https://kc-proxy.example.com:18443/examples/websocket/echo.xhtml is displayed. (If you log in as a user who does not have the admin role, you will get a 403 error) proxy07.png

Summary

This time, I confirmed how to link Keycloak and Security Proxy with ID. Basically, you can check the ID linkage with Keycloak just by placing one json file for setting, so I think that it is useful as a simple operation check of the reverse proxy type.

However, there are some functional deficiencies as a reverse proxy when incorporating the Security Proxy into the system in earnest.

--Only one server can be specified as a proxy transfer destination --No access log --Cannot perform fine control like Apache (URL replacement, header replacement, load balancing, etc.) --Limited items that can be linked as HTTP headers

Therefore, when using a reverse proxy type configuration, by using "Try to build a reverse proxy type configuration with Keycloak (mod_auth_openidc edition)" that I explain in the article on the 8th day, while compensating for the above shortcomings, the reverse proxy Flexible settings are available as.

Reference material

footnote

[^ auth-server-url]: When using a self-signed server certificate for ssl connection with Keycloak server, it is necessary to import the server certificate into the Java truststore on the Security Proxy side. (Because the Security Proxy communicates directly with the Keycloak server via SSL)

Recommended Posts

Try to build a reverse proxy type configuration with Keycloak (Security Proxy edition)
Try to work with Keycloak using Spring Security SAML (Spring 5)
How to quickly create a reverse proxy that supports HTTPS with Docker
The story of making a reverse proxy with ProxyServlet
Try to build a Java development environment using Docker
[Beginner] Try to make a simple RPG game with Java ①
Build a Node-RED environment with Docker to move and understand
How to set up a proxy with authentication in Feign
Try to imitate the idea of a two-dimensional array with a one-dimensional array
How to build [TypeScript + Vue + Express + MySQL] environment with Docker ~ MySQL edition ~
Try to make a cross-platform application with JRuby (jar file generation)
Steps to build a Ruby on Rails development environment with Vagrant
How to build a little tricky with dynamic SQL query generation
[Gradle] Build a Java project with a configuration different from the convention