20 July 2016

Karaf JDBC JAAS Module

Karaf relys on JAAS for user authentication. JAAS makes it possible to plugin multiple modules for this purpose. By default Karaf will use the karaf realm with a JAAS module getting its user and role information from a property file: runtime/etc/users.properties

In this blog post I will show you how to use the Karaf JAAS console commands and how to setup a JDBC module to authenticate against a database.

All code was tested on Karaf version 4.0.3 respectively Talend ESB version 6.1.1

JDBC Setup

Register Datasource

At first you need to install the Karaf JDBC feature:
karaf@trun()> feature:install jdbc
karaf@trun()> feature:install pax-jdbc-h2
Check all available DataSourceFactory:
karaf@trun()> service:list DataSourceFactory
 osgi.jdbc.driver.version = 1.3.172
 osgi.jdbc.driver.class = org.h2.Driver
 osgi.jdbc.driver.name = H2
 service.id = 453
 service.bundleid = 360
 service.scope = singleton
Provided by :
 H2 Database Engine (360)

 osgi.jdbc.driver.class = org.h2.Driver
 service.id = 454
 service.bundleid = 360
 service.scope = singleton
Provided by :
 H2 Database Engine (360)
Next you can create a new Datasource:
karaf@root()> jdbc:ds-create -dn H2 -url "jdbc:h2:file:C:/Talend/6.1.1/db/users" -u sa -p secret users
With the -dn H2 option you define a datasource of type H2. Alternative you could also use generic, oracle, mysql, postgres, derby, hsql as your datasource type. Please make sure to install also the matching jdbc pax feature for your datasource type.
The -u sa option defines the datasource username. Finally users is the datasource name.

Add sample data

jdbc:execute users CREATE TABLE users ( username VARCHAR(255) PRIMARY KEY NOT NULL, password VARCHAR(255) NOT NULL );
jdbc:execute users CREATE TABLE roles ( username VARCHAR(255) NOT NULL, role VARCHAR(255) NOT NULL, PRIMARY KEY (username,role) );
jdbc:execute users INSERT INTO users values('alice','e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4');
jdbc:execute users INSERT INTO roles values('alice','manager');
Validate your input:
karaf@trun()> jdbc:query users SELECT * FROM roles
manager | alice

JAAS Console Commands

Karaf provides some nice console commands to manage your JAAS realms.

List JAAS realms with assigned modules

karaf@trun()> jaas:realm-list
Index | Realm Name | Login Module Class Name
1     | karaf      | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
2     | karaf      | org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule
3     | karaf      | org.apache.karaf.jaas.modules.audit.FileAuditLoginModule
4     | karaf      | org.apache.karaf.jaas.modules.audit.EventAdminAuditLoginModule

List users and assigned roles

karaf@trun()> jaas:realm-manage --realm karaf

karaf@trun()> jaas:user-list
User Name | Group      | Role
tadmin    | admingroup | admin
tadmin    | admingroup | manager
tadmin    | admingroup | viewer
tadmin    | admingroup | systembundles
tadmin    |            | sl_admin
tesb      | admingroup | admin
tesb      | admingroup | manager
tesb      | admingroup | viewer
tesb      | admingroup | systembundles
tesb      |            | sl_maintain
karaf     | admingroup | admin
karaf     | admingroup | manager
karaf     | admingroup | viewer
karaf     | admingroup | systembundles

karaf@trun()> jaas:cancel

Adding a user

karaf@trun()> jaas:realm-manage --realm karaf
karaf@trun()> jaas:user-add alice secret
karaf@trun()> jaas:update
If you execute "List users" again you will see alice added to the realm. You will also find alice added to the users.properties file.

Register JDBC JAAS Module

Create a file db_jaas.xml within the deploy folder of your karaf installation:
<?xml version="1.0" encoding="UTF-8"?>
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for additional information regarding copyright ownership.
    The ASF licenses this file to You under the Apache License, Version 2.0
    (the "License"); you may not use this file except in compliance with
    the License.  You may obtain a copy of the License at
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"

    <!-- Allow usage of System properties, especially the karaf.base property -->
    <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>

    <!-- AdminConfig property place holder for the org.apache.karaf.jaas  -->
    <cm:property-placeholder persistent-id="org.apache.karaf.jaas.db" update-strategy="reload">
            <cm:property name="encryption.name" value="basic"/>
            <cm:property name="encryption.enabled" value="true"/>
            <!--cm:property name="encryption.prefix" value="{CRYPT}"/>
            <cm:property name="encryption.suffix" value="{CRYPT}"/-->
            <cm:property name="encryption.algorithm" value="SHA1"/>
            <cm:property name="encryption.encoding" value="hexadecimal"/>
            <cm:property name="detailed.login.exception" value="false"/>
            <cm:property name="audit.file.enabled" value="true"/>
            <cm:property name="audit.file.file" value="$[karaf.data]/security/audit.log"/>
            <cm:property name="audit.eventadmin.enabled" value="true"/>
            <cm:property name="audit.eventadmin.topic" value="org/apache/karaf/login"/>

    <jaas:config name="karaf" rank="10">

        <jaas:module className="org.apache.karaf.jaas.modules.jdbc.JDBCLoginModule" flags="required">
            datasource = osgi:javax.sql.DataSource/(osgi.jndi.service.name=users)
            query.password = SELECT PASSWORD FROM USERS WHERE USERNAME=?
            query.role = SELECT ROLE FROM ROLES WHERE USERNAME=?
            insert.user = INSERT INTO USERS VALUES(?,?)
            insert.role = INSERT INTO ROLES VALUES(?,?)
            delete.user = DELETE FROM USERS WHERE USERNAME=?
            delete.role = DELETE FROM ROLES WHERE USERNAME=? AND ROLE=?
            delete.roles = DELETE FROM ROLES WHERE USERNAME=?
            encryption.enabled = ${encryption.enabled}
            encryption.name = ${encryption.name}
            encryption.algorithm = ${encryption.algorithm}
            encryption.encoding = ${encryption.encoding}
            detailed.login.exception = ${detailed.login.exception}
        <jaas:module className="org.apache.karaf.jaas.modules.audit.FileAuditLoginModule" flags="optional">
            enabled = ${audit.file.enabled}
            file = ${audit.file.file}
        <jaas:module className="org.apache.karaf.jaas.modules.audit.EventAdminAuditLoginModule" flags="optional">
            enabled = ${audit.eventadmin.enabled}
            topic = ${audit.eventadmin.topic}

By adding a configuration file org.apache.karaf.jaas.db.cfg to your etc folder you will be able to update the configuration of your jaas bundle during runtime.
encryption.enabled = true
encryption.name = basic
encryption.algorithm = SHA1
encryption.encoding = hexadecimal
detailed.login.exception = false
Now you can login to Karaf via SSH with you alice DB user.
ssh -p 8101 alice@localhost
Password will be a: secret