Skip to content

Instantly share code, notes, and snippets.

@drmalex07
Last active April 21, 2020 10:58
Show Gist options
  • Select an option

  • Save drmalex07/2061338f6645f3536bd399fb37b6a98f to your computer and use it in GitHub Desktop.

Select an option

Save drmalex07/2061338f6645f3536bd399fb37b6a98f to your computer and use it in GitHub Desktop.
Setup Keycloak. #keycloak

Setup Keycloak (5.0)

This is a checklist of steps to be taken to setup the identity server (in standalone mode). We assume that keycloak is installed under /usr/local/keycloak (so all paths will be relative to this).

1. Add module for PostgreSQL database

Under modules/org/postgresql/main we must place:

  • module.xml: descriptor for the module
  • postgresql-*.jar: the actual JAR for the PostgreSQL JDBC driver

The module.xml should contain something like:

<?xml version="1.0" ?>
<module xmlns="urn:jboss:module:1.3" name="org.postgresql">
    <resources>
        <resource-root path="postgresql-9.4.1208.jar"/>
    </resources>
    <dependencies>
        <module name="javax.api"/>
        <module name="javax.transaction.api"/>
    </dependencies>
</module>

2. Edit configuration

To setup keycloak in standalone mode, edit standalone/configuration/standalone.xml.

2.1. Configure keystore

A JKS (or PKCS12) keystore is needed to hold our keys, and it must contain a private-key entry named as server. Edit the corresponding XML fragment:

xmlstarlet sel \
   -N x=urn:jboss:domain:9.0 \
   -t -c 'x:server/x:management/x:security-realms/x:security-realm[@name="ApplicationRealm"]/x:server-identities/x:ssl/x:keystore' \
   standalone/configuration/standalone.xml

An example content:

<keystore path="server.jks" relative-to="jboss.server.config.dir" keystore-password="secret" alias="server" key-password="secret"/>

2.2. Configure datasource

Add a driver pointing PostgreSQL module. Edit the XML fragment for drivers and add one <driver> fragment:

xmlstarlet sel \
  -N x=urn:jboss:domain:9.0 -N d=urn:jboss:domain:datasources:5.0 \
  -t -c 'x:server/x:profile/d:subsystem/d:datasources/d:drivers' \
  standalone/configuration/standalone.xml

The result should be like this:

<drivers xmlns="urn:jboss:domain:datasources:5.0">
  <driver name="h2" module="com.h2database.h2">
    <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
  </driver>
  <driver name="postgresql" module="org.postgresql">
    <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
  </driver>
</drivers>

Now, configure the datasource to use the PostgreSQL driver. Edit the corresponding XML fragment:

xmlstarlet sel \
  -N x=urn:jboss:domain:9.0 -N d=urn:jboss:domain:datasources:5.0 \
  -t -c 'x:server/x:profile/d:subsystem/d:datasources/d:datasource[@pool-name="KeycloakDS"]'
  standalone/configuration/standalone.xml 

An example content:

<datasource xmlns="urn:jboss:domain:datasources:5.0" jndi-name="java:jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true" use-java-context="true">
  <connection-url>${env.database_url}</connection-url>
  <driver>postgresql</driver>
  <pool>
    <max-pool-size>20</max-pool-size>
  </pool>
  <security>
    <user-name>${env.database_username}</user-name>
    <password>${env.database_password}</password>
  </security>
</datasource>

2.3. Configure listen interfaces

Generally, we must restrict the interface where management service listens to. The main web application can listen to everything (but we can later narrow access to admin console).

Edit the XML fragment:

xmlstarlet sel \
  -N x=urn:jboss:domain:9.0 \
  -t -c 'x:server/x:interfaces' \
  standalone/configuration/standalone.xml

An example content:

<interfaces xmlns="urn:jboss:domain:9.0">
  <interface name="management">
    <inet-address value="127.0.0.1"/>
  </interface>
  <interface name="public">
    <inet-address value="0.0.0.0"/>
  </interface>
</interfaces>

2.4. Filter access to admin console (opt)

We usually want to restrict access to admin console to some private network. This is performed by adding a servlet filter to Undertow servlet container.

Edit the corresponding XML fragment (add a filter definition under filters and a filter-ref under host):

xmlstarlet sel \
   -N x=urn:jboss:domain:9.0 -N s=urn:jboss:domain:undertow:8.0 \
   -t -c 'x:server/x:profile/s:subsystem' 
   standalone/configuration/standalone.xml

An example allowing access only to network 10.17.4.0/24:

<subsystem xmlns="urn:jboss:domain:undertow:8.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other">
  <buffer-cache name="default"/>
  <server name="default-server">
    <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
    <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
    <host name="default-host" alias="localhost">
      <location name="/" handler="welcome-content"/>
      <http-invoker security-realm="ApplicationRealm"/>
      <filter-ref name="ipAccess"/>
    </host>
  </server>
  <servlet-container name="default">
    <jsp-config/>
    <websockets/>
  </servlet-container>
  <handlers>
    <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
  </handlers>
  <filters>
    <!-- Filter access to admin console -->
    <expression-filter name="ipAccess" expression="path-prefix('/auth/admin') -> ip-access-control(acl={'10.17.4.0/24 allow'})"/>
  </filters>
</subsystem>

3. Add i18n data for theme (opt)

Edit themes/base/{account,admin,email,login}/theme.properties and add language code (e.g. el) under locales property.

Add translated messages for target language (here el) under themes/base/{account,admin,email,login}/messages/messages_el.properties

Do not forget a header line of # encoding: UTF-8 on each messages_XY.properties file.

Do not forget to enable internationalization under Realm Settings > Themes in the admin console.

4. Add administrator

Use ./bin/add-user-keycloak.sh to add a first (administrative) user to the system.

5. Edit welcome (opt)

Edit welcome-content/index.html to provide a landing page (e.g redirect to the login page /auth/realms/demo/account for a specific realm)

6. Add as systemd service

Create /etc/default/keycloak to provide an enviroment file for keycloak service. The variables provided here as foo=bar can be substituted in standalone/configuration/standalone.xml as ${env.foo}.

An example woule be:

database_url=jdbc:postgresql://localhost/keycloak
database_username=keycloak
database_password=secret

Create the service unit file under /etc/systemd/system/keycloak.service:

[Unit]
Description=Keycloak Identity Server
After=syslog.target network.target

[Service]
Type=simple
EnvironmentFile=/etc/default/keycloak
User=ubuntu
Group=ubuntu
ExecStart=/usr/local/keycloak/bin/standalone.sh
TimeoutStartSec=600
TimeoutStopSec=600

[Install]
WantedBy=multi-user.target

Enable service:

sudo systemctl enable keycloak.service 

7. Configure fail2ban

See https://gist.github.com/drmalex07/3eba8b98d0ac4a1e821e8e721b3e1816

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment