Chapter 2. Securing the Container

Abstract

The Red Hat JBoss Fuse container is secured using JAAS. By defining JAAS realms, you can configure the mechanism used to retrieve user credentials. You can also refine access to the container's administrative interfaces by changing the default roles.

2.1. JAAS Authentication

Abstract

The Java Authentication and Authorization Service (JAAS) provides a general framework for implementing authentication in a Java application. The implementation of authentication is modular, with individual JAAS modules (or plug-ins) providing the authentication implementations.
For background information about JAAS, see the JAAS Reference Guide.

2.1.1. Default JAAS Realm

Overview

This section describes how to manage user data for the default JAAS realm in a standalone container.

Default JAAS realm

The Red Hat JBoss Fuse container has a predefined JAAS realm, the karaf realm, which is used by default to secure all aspects of the container.

How to integrate an application with JAAS

You can use the karaf realm in your own applications. Simply configure karaf as the name of the JAAS realm that you want to use.

Default JAAS login modules

When you start JBoss Fuse for the first time, the container is configured as a standalone container and uses the karaf default realm. In this default configuration, the karaf realm deploys four JAAS login modules, which are enabled simultaneously. To see the deployed login modules, enter the jaas:realms console command, as follows:
JBossFuse:karaf@root> jaas:realms
Index Realm  Module Class                                                                    
    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
Important
In a standalone container, both the properties login module and the public key login module are enabled. When JAAS authenticates a user, it tries first of all to authenticate the user with the properties login module. If that fails, it then tries to authenticate the user with the public key login module. If that module also fails, an error is raised.
Note
The FileAuditLoginModule login module and the EventAdminAuditLoginModule login module are used to record an audit trail of successful and failed login attempts. These login modules do not authenticate users.

Configuring users in the properties login module

The properties login module is used to store username/password credentials in a flat file format. To create a new user in the properties login module, open the InstallDir/etc/users.properties file using a text editor and add a line with the following syntax:
Username=Password[,UserGroup|Role][,UserGroup|Role]...
For example, to create the jdoe user with password, topsecret, and role, Administrator, you could create an entry like the following:
jdoe=topsecret,Administrator
Where the Administrator role gives full administrative privileges to the jdoe user.

Configuring user groups in the properties login module

Instead of (or in addition to) assigning roles directly to users, you also have the option of adding users to user groups in the properties login module. To create a user group in the properties login module, open the InstallDir/etc/users.properties file using a text editor and add a line with the following syntax:
_g_\:GroupName=Role1,Role2,...
For example, to create the admingroup user group with the roles, SuperUser and Administrator, you could create an entry like the following:
_g_\:admingroup=SuperUser,Administrator
You could then add the majorclanger user to the admingroup, by creating the following user entry:
majorclanger=secretpass,_g_:admingroup

Configuring the public key login module

The public key login module is used to store SSH public key credentials in a flat file format. To create a new user in the public key login module, open the InstallDir/etc/keys.properties file using a text editor and add a line with the following syntax:
Username=PublicKey[,UserGroup|Role][,UserGroup|Role]...
For example, you can create the jdoe user with the Administrator role by adding the following entry to the InstallDir/etc/keys.properties file (on a single line):
jdoe=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7
gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnfqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCX
YFCPFSMLzLKSuYKi64QL8Fgc9QAAAnEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6Ewo
FhO3zwkyjMim4TwWeotifI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACB
AKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53Jj7uyk31drV2qxhIOsLDC9dGCWj4
7Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,Administrator
Important
Do not insert the entire contents of an id_rsa.pub file here. Insert just the block of symbols which represents the public key itself.

Configuring user groups in the public key login module

Instead of (or in addition to) assigning roles directly to users, you also have the option of adding users to user groups in the public key login module. To create a user group in the public key login module, open the InstallDir/etc/keys.properties file using a text editor and add a line with the following syntax:
_g_\:GroupName=Role1,Role2,...
For example, to create the admingroup user group with the roles, SuperUser and Administrator, you could create an entry like the following:
_g_\:admingroup=SuperUser,Administrator
You could then add the jdoe user to the admingroup, by creating the following user entry:
jdoe=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7
gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnfqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCX
YFCPFSMLzLKSuYKi64QL8Fgc9QAAAnEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6Ewo
FhO3zwkyjMim4TwWeotifI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACB
AKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53Jj7uyk31drV2qxhIOsLDC9dGCWj4
7Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,_g_:admingroup

Encrypting the stored passwords

By default, passwords are stored in the InstallDir/etc/users.properties file in plaintext format. To protect the passwords in this file, you must set the file permissions of the users.properties file so that it can be read only by administrators. To provide additional protection, you can optionally encrypt the stored passwords using a message digest algorithm.
To enable the password encryption feature, edit the InstallDir/etc/org.apache.karaf.jaas.cfg file and set the encryption properties as described in the comments. For example, the following settings would enable basic encryption using the MD5 message digest algorithm:
encryption.enabled = true
encryption.name = basic
encryption.prefix = {CRYPT}
encryption.suffix = {CRYPT}
encryption.algorithm = MD5
encryption.encoding = hexadecimal
Note
The encryption settings in the org.apache.karaf.jaas.cfg file are applied only to the default karaf realm in a standalone container. The have no effect on a Fabric container and no effect on a custom realm.
For more details about password encryption, see Section 2.1.8, “Encrypting Stored Passwords”.

Overriding the default realm

If you want to customise the JAAS realm, the most convenient approach to take is to override the default karaf realm by defining a higher ranking karaf realm. This ensures that all of the Red Hat JBoss Fuse security components switch to use your custom realm. For details of how to define and deploy custom JAAS realms, see Section 2.1.2, “Defining JAAS Realms”.

2.1.2. Defining JAAS Realms

Overview

When defining a JAAS realm in the OSGi container, you cannot put the definitions in a conventional JAAS login configuration file. Instead, the OSGi container uses a special jaas:config element for defining JAAS realms in a blueprint configuration file. The JAAS realms defined in this way are made available to all of the application bundles deployed in the container, making it possible to share the JAAS security infrastructure across the whole container.

Namespace

The jaas:config element is defined in the http://karaf.apache.org/xmlns/jaas/v1.0.0 namespace. When defining a JAAS realm you will need to include the line shown in Example 2.1, “JAAS Blueprint Namespace”.

Example 2.1. JAAS Blueprint Namespace

xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"

Configuring a JAAS realm

The syntax for the jaas:config element is shown in Example 2.2, “Defining a JAAS Realm in Blueprint XML”.

Example 2.2. Defining a JAAS Realm in Blueprint XML

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0">

    <jaas:config name="JaasRealmName"
                 [rank="IntegerRank"]>
        <jaas:module className="LoginModuleClassName"
                     [flags="[required|requisite|sufficient|optional]"]>
            Property=Value
            ...
        </jaas:module>
        ...
        <!-- Can optionally define multiple modules -->
        ...
    </jaas:config>

</blueprint>
The elements are used as follows:
jaas:config
Defines the JAAS realm. It has the following attributes:
  • name—specifies the name of the JAAS realm.
  • rank—specifies an optional rank for resolving naming conflicts between JAAS realms . When two or more JAAS realms are registered under the same name, the OSGi container always picks the realm instance with the highest rank. If you decide to override the default realm, karaf, you should specify a rank of 100 or more, so that it overrides all of the previously installed karaf realms (in the context of Fabric, you need to override the default ZookeeperLoginModule, which has a rank of 99).
jaas:module
Defines a JAAS login module in the current realm. jaas:module has the following attributes:
  • className—the fully-qualified class name of a JAAS login module. The specified class must be available from the bundle classloader.
  • flags—determines what happens upon success or failure of the login operation. Table 2.1, “Flags for Defining a JAAS Module” describes the valid values.

    Table 2.1. Flags for Defining a JAAS Module

    ValueDescription
    requiredAuthentication of this login module must succeed. Always proceed to the next login module in this entry, irrespective of success or failure.
    requisiteAuthentication of this login module must succeed. If success, proceed to the next login module; if failure, return immediately without processing the remaining login modules.
    sufficientAuthentication of this login module is not required to succeed. If success, return immediately without processing the remaining login modules; if failure, proceed to the next login module.
    optionalAuthentication of this login module is not required to succeed. Always proceed to the next login module in this entry, irrespective of success or failure.
The contents of a jaas:module element is a space separated list of property settings, which are used to initialize the JAAS login module instance. The specific properties are determined by the JAAS login module and must be put into the proper format.
Note
You can define multiple login modules in a realm.

Converting standard JAAS login properties to XML

Red Hat JBoss Fuse uses the same properties as a standard Java login configuration file, however Red Hat JBoss Fuse requires that they are specified slightly differently. To see how the Red Hat JBoss Fuse approach to defining JAAS realms compares with the standard Java login configuration file approach, consider how to convert the login configuration shown in Example 2.3, “Standard JAAS Properties”, which defines the PropertiesLogin realm using the Red Hat JBoss Fuse properties login module class, PropertiesLoginModule:

Example 2.3. Standard JAAS Properties

PropertiesLogin {
    org.apache.activemq.jaas.PropertiesLoginModule required
        org.apache.activemq.jaas.properties.user="users.properties"
        org.apache.activemq.jaas.properties.group="groups.properties";
};
The equivalent JAAS realm definition, using the jaas:config element in a blueprint file, is shown in Example 2.4, “Blueprint JAAS Properties”.

Example 2.4. Blueprint JAAS Properties

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

  <jaas:config name="PropertiesLogin">
    <jaas:module flags="required" 
      className="org.apache.activemq.jaas.PropertiesLoginModule">
        org.apache.activemq.jaas.properties.user=users.properties
        org.apache.activemq.jaas.properties.group=groups.properties
    </jaas:module>
  </jaas:config>

</blueprint>
Important
You do not use double quotes for JAAS properties in the blueprint configuration.

Example

Red Hat JBoss Fuse also provides an adapter that enables you to store JAAS authentication data in an X.500 server. Example 2.5, “Configuring a JAAS Realm” defines the LDAPLogin realm to use Red Hat JBoss Fuse's LDAPLoginModule class, which connects to the LDAP server located at ldap://localhost:10389.

Example 2.5. Configuring a JAAS Realm

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

  <jaas:config name="LDAPLogin" rank="200">
    <jaas:module flags="required" 
      className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule">
        initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
        connection.username=uid=admin,ou=system
        connection.password=secret
        connection.protocol=
        connection.url = ldap://localhost:10389
        user.base.dn = ou=users,ou=system
        user.filter = (uid=%u)
        user.search.subtree = true
        role.base.dn = ou=users,ou=system
        role.filter = (uid=%u)
        role.name.attribute = ou
        role.search.subtree = true
        authentication = simple
    </jaas:module>
  </jaas:config>
</blueprint>
For a detailed description and example of using the LDAP login module, see Section 2.1.7, “JAAS LDAP Login Module”.

2.1.3. JAAS Properties Login Module

Overview

The JAAS properties login module stores user data in a flat file format (where the stored passwords can optionally be encrypted using a message digest algorithm). The user data can either be edited directly, using a simple text editor, or managed using the jaas:* console commands.
For example, a standalone container uses the JAAS properties login module by default and stores the associated user data in the InstallDir/etc/users.properties file.

Supported credentials

The JAAS properties login module authenticates username/password credentials, returning the list of roles associated with the authenticated user.

Implementation classes

The following classes implement the JAAS properties login module:
org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
Implements the JAAS login module.
org.apache.karaf.jaas.modules.properties.PropertiesBackingEngineFactory
Must be exposed as an OSGi service. This service makes it possible for you to manage the user data using the jaas:* console commands from the Apache Karaf shell (see chapter "JAAS Console Commands" in "Console Reference").

Options

The JAAS properties login module supports the following options:
users
Location of the user properties file.

Format of the user properties file

The user properties file is used to store username, password, and role data for the properties login module. Each user is represented by a single line in the user properties file, where a line has the following form:
Username=Password[,UserGroup|Role][,UserGroup|Role]...
User groups can also be defined in this file, where each user group is represented by a single line in the following format:
_g_\:GroupName=Role1[,Role2]...
For example, you can define the users, bigcheese and guest, and the user groups, admingroup and guestgroup, as follows:
# Users
bigcheese=cheesepass,_g_:admingroup
guest=guestpass,_g_:guestgroup

# Groups
_g_\:admingroup=SuperUser,Administrator
_g_\:guestgroup=Monitor

Sample Blueprint configuration

The following Blueprint configuration shows how to define a new karaf realm using the properties login module, where the default karaf realm is overridden by setting the rank attribute to 200:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
  xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

  <type-converters>
    <bean class="org.apache.karaf.jaas.modules.properties.PropertiesConverter"/>
  </type-converters>

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

  <jaas:config name="karaf" rank="200">
    <jaas:module flags="required"
className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule">
        users= $[karaf.base]/etc/users.properties
    </jaas:module>
  </jaas:config>

  <!-- The Backing Engine Factory Service for the PropertiesLoginModule -->
  <service interface="org.apache.karaf.jaas.modules.BackingEngineFactory">
    <bean class="org.apache.karaf.jaas.modules.properties.PropertiesBackingEngineFactory"/>
  </service>

</blueprint>
Remember to export the BackingEngineFactory bean as an OSGi service, so that the jaas:* console commands can manage the user data.

2.1.4. JAAS OSGi Config Login Module

Overview

The JAAS OSGi config login modules leverages the OSGi Config Admin Service to store user data. This login module is fairly similar to the JAAS properties login module (for example, the syntax of the user entries is the same), but the mechanism for retrieving user data is based on the OSGi Config Admin Service.
The user data can be edited directly by creating a corresponding OSGi configuration file, etc/PersistentID.cfg or using any method of configuration that is supported by the OSGi Config Admin Service. The jaas:* console commands are not supported, however.

Supported credentials

The JAAS OSGi config login module authenticates username/password credentials, returning the list of roles associated with the authenticated user.

Implementation classes

The following classes implement the JAAS OSGi config login module:
org.apache.karaf.jaas.modules.osgi.OsgiConfigLoginModule
Implements the JAAS login module.
Note
There is no backing engine factory for the OSGi config login module, which means that this module cannot be managed using the jaas:* console commands.

Options

The JAAS OSGi config login module supports the following options:
pid
The persistent ID of the OSGi configuration containing the user data. In the OSGi Config Admin standard, a persistent ID references a set of related configuration properties.

Location of the configuration file

The location of the configuration file follows the usual convention where the configuration for the persistent ID, PersistentID, is stored in the following file:
InstallDir/etc/PersistentID.cfg

Format of the configuration file

The PersistentID.cfg configuration file is used to store username, password, and role data for the OSGi config login module. Each user is represented by a single line in the configuration file, where a line has the following form:
Username=Password[,Role][,Role]...
Note
User groups are not supported in the JAAS OSGi config login module.

Sample Blueprint configuration

The following Blueprint configuration shows how to define a new karaf realm using the OSGi config login module, where the default karaf realm is overridden by setting the rank attribute to 200:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
  xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

  <jaas:config name="karaf" rank="200">
    <jaas:module flags="required"
className="org.apache.karaf.jaas.modules.osgi.OsgiConfigLoginModule">
        pid = org.jboss.example.osgiconfigloginmodule
    </jaas:module>
  </jaas:config>

</blueprint>
In this example, the user data will be stored in the file, InstallDir/etc/org.jboss.example.osgiconfigloginmodule.cfg, and it is not possible to edit the configuration using the jaas:* console commands.

2.1.5. JAAS Public Key Login Module

Overview

The JAAS public key login module stores user data in a flat file format, which can be edited directly using a simple text editor. The jaas:* console commands are not supported, however.
For example, a standalone container uses the JAAS public key login module by default and stores the associated user data in the InstallDir/etc/keys.properties file.

Supported credentials

The JAAS public key login module authenticates SSH key credentials. When a user tries to log in, the SSH protocol uses the stored public key to challenge the user. The user must possess the corresponding private key in order to answer the challenge. If login is successful, the login module returns the list of roles associated with the user.

Implementation classes

The following classes implement the JAAS public key login module:
org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule
Implements the JAAS login module.
Note
There is no backing engine factory for the public key login module, which means that this module cannot be managed using the jaas:* console commands.

Options

The JAAS public key login module supports the following options:
users
Location of the user properties file for the public key login module.

Format of the keys properties file

The keys.properties file is used to store username, public key, and role data for the public key login module. Each user is represented by a single line in the keys properties file, where a line has the following form:
Username=PublicKey[,UserGroup|Role][,UserGroup|Role]...
Where the PublicKey is the public key part of an SSH key pair (typically found in a user's home directory in ~/.ssh/id_rsa.pub in a UNIX system).
For example, to create the user jdoe with the Administrator role, you would create an entry like the following:
jdoe=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7
gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnfqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCX
YFCPFSMLzLKSuYKi64QL8Fgc9QAAAnEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6Ewo
FhO3zwkyjMim4TwWeotifI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACB
AKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53Jj7uyk31drV2qxhIOsLDC9dGCWj4
7Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,Administrator
Important
Do not insert the entire contents of the id_rsa.pub file here. Insert just the block of symbols which represents the public key itself.
User groups can also be defined in this file, where each user group is represented by a single line in the following format:
_g_\:GroupName=Role1[,Role2]...

Sample Blueprint configuration

The following Blueprint configuration shows how to define a new karaf realm using the public key login module, where the default karaf realm is overridden by setting the rank attribute to 200:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
  xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

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

  <jaas:config name="karaf" rank="200">
    <jaas:module flags="required"
className="org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule">
        users = $[karaf.base]/etc/keys.properties
    </jaas:module>
  </jaas:config>

</blueprint>
In this example, the user data will be stored in the file, InstallDir/etc/keys.properties, and it is not possible to edit the configuration using the jaas:* console commands.

2.1.6. JAAS JDBC Login Module

Overview

The JAAS JDBC login module enables you to store user data in a database back-end, using Java Database Connectivity (JDBC) to connect to the database. Hence, you can use any database that supports JDBC to store your user data. To manage the user data, you can use either the native database client tools or the jaas:* console commands (where the backing engine uses configured SQL queries to perform the relevant database updates).
You can combine multiple login modules with each login module providing both the authentication and authorization components. For example, you can combine default PropertiesLoginModule with JDBCLoginModule to ensure access to the system.
Note
User groups are not supported in the JAAS JDBC login module.

Supported credentials

The JAAS JDBC Login Module authenticates username/password credentials, returning the list of roles associated with the authenticated user.

Implementation classes

The following classes implement the JAAS JDBC Login Module:
org.apache.karaf.jaas.modules.jdbc.JDBCLoginModule
Implements the JAAS login module.
org.apache.karaf.jaas.modules.jdbc.JDBCBackingEngineFactory
Must be exposed as an OSGi service. This service makes it possible for you to manage the user data using the jaas:* console commands from the Apache Karaf shell (see chapter "JAAS Console Commands" in "Console Reference").

Options

The JAAS JDBC login module supports the following options:
datasource
The JDBC data source, specified either as an OSGi service or as a JNDI name. You can specify a data source's OSGi service using the following syntax:
osgi:ServiceInterfaceName[/ServicePropertiesFilter]
The ServiceInterfaceName is the interface or class that is exported by the data source's OSGi service (usually javax.sql.DataSource).
Because multiple data sources can be exported as OSGi services in a container, it is usually necessary to specify a filter, ServicePropertiesFilter, to select the particular data source that you want. Filters on OSGi services are applied to the service property settings and follow a syntax that is borrowed from LDAP filter syntax.
query.password
The SQL query that retrieves the user's password. The query can contain a single question mark character, ?, which is substituted by the username at run time.
query.role
The SQL query that retrieves the user's roles. The query can contain a single question mark character, ?, which is substituted by the username at run time.
insert.user
The SQL query that creates a new user entry. The query can contain two question marks, ?, characters: the first question mark is substituted by the username and the second question mark is substituted by the password at run time.
insert.role
The SQL query that adds a role to a user entry. The query can contain two question marks, ?, characters: the first question mark is substituted by the username and the second question mark is substituted by the role at run time.
delete.user
The SQL query that deletes a user entry. The query can contain a single question mark character, ?, which is substituted by the username at run time.
delete.role
The SQL query that deletes a role from a user entry. The query can contain two question marks, ?, characters: the first question mark is substituted by the username and the second question mark is substituted by the role at run time.
delete.roles
The SQL query that deletes multiple roles from a user entry. The query can contain a single question mark character, ?, which is substituted by the username at run time.

Example of setting up a JDBC login module

To set up a JDBC login module, perform the following main steps:

Create the database tables

Before you can set up the JDBC login module, you must set up a users table and a roles table in the backing database to store the user data. For example, the following SQL commands show how to create a suitable users table and roles table:
CREATE TABLE users (
  username VARCHAR(255) NOT NULL,
  password VARCHAR(255) NOT NULL,
  PRIMARY KEY (username)
);
CREATE TABLE roles (
  username VARCHAR(255) NOT NULL,
  role VARCHAR(255) NOT NULL,
  PRIMARY KEY (username,role)
);
The users table stores username/password data and the roles table associates a username with one or more roles.

Create the data source

To use a JDBC datasource with the JDBC login module, the correct approach to take is to create a data source instance and export the data source as an OSGi service. The JDBC login module can then access the data source by referencing the exported OSGi service. For example, you could create a MySQL data source instance and expose it as an OSGi service (of javax.sql.DataSource type) using code like the following in a Blueprint file:
<blueprint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <bean id="mysqlDatasource"
        class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
    <property name="serverName" value="localhost"></property>
    <property name="databaseName" value="DBName"></property>
    <property name="port" value="3306"></property>
    <property name="user" value="DBUser"></property>
    <property name="password" value="DBPassword"></property>
  </bean>

  <service id="mysqlDS" interface="javax.sql.DataSource" 
        ref="mysqlDatasource">
    <service-properties>
        <entry key="osgi.jndi.service.name" value="jdbc/karafdb"/>
    </service-properties>
  </service>
</blueprint>
The preceding Blueprint configuration should be packaged and installed in the container as an OSGi bundle.

Specify the data source as an OSGi service

After the data source has been instantiated and exported as an OSGi service, you are ready to configure the JDBC login module. In particular, the datasource option of the JDBC login module can reference the data source's OSGi service using the following syntax:
osgi:javax.sql.DataSource/(osgi.jndi.service.name=jdbc/karafdb)
Where javax.sql.DataSource is the interface type of the exported OSGi service and the filter, (osgi.jndi.service.name=jdbc/karafdb), selects the particular javax.sql.DataSource instance whose osgi.jndi.service.name service property has the value, jdbc/karafdb.
For example, you can use the following Blueprint configuration to override the karaf realm with a JDBC login module that references the sample MySQL data source:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
  xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

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

  <jaas:config name="karaf" rank="200">
    <jaas:module flags="required" 
      className="org.apache.karaf.jaas.modules.jdbc.JDBCLoginModule">
        datasource = osgi:javax.sql.DataSource/(osgi.jndi.service.name=jdbc/karafdb)
        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=?
    </jaas:module>
  </jaas:config>

  <!-- The Backing Engine Factory Service for the JDBCLoginModule -->
  <service interface="org.apache.karaf.jaas.modules.BackingEngineFactory">
    <bean class="org.apache.karaf.jaas.modules.jdbc.JDBCBackingEngineFactory"/>
  </service>

</blueprint>
Note
The SQL statements shown in the preceding configuration are in fact the default values of these options. Hence, if you create user and role tables consistent with these SQL statements, you could omit the options settings and rely on the defaults.
In addition to creating a JDBCLoginModule, the preceding Blueprint configuration also instantiates and exports a JDBCBackingEngineFactory instance, which enables you to manage the user data using the jaas:* console commands.

2.1.7. JAAS LDAP Login Module

Overview

The JAAS LDAP login module enables you to store user data in an LDAP database. To manage the stored user data, use a standard LDAP client tool. The jaas:* console commands are not supported.
For more details about using LDAP with Red Hat JBoss Fuse see Chapter 9, LDAP Authentication Tutorial.
Note
User groups are not supported in the JAAS LDAP login module.
Important
In a Fuse Fabric, the Zookeeper login module must always be enabled. Hence, if you want to enable the LDAP login module in a Fabric, both the Zookeeper login module and the LDAP login module must be enabled. See Section 9.4, “Enable LDAP Authentication in the OSGi Container” for details.

Supported credentials

The JAAS LDAP Login Module authenticates username/password credentials, returning the list of roles associated with the authenticated user.

Implementation classes

The following classes implement the JAAS LDAP Login Module:
org.apache.karaf.jaas.modules.ldap.LDAPLoginModule
Implements the JAAS login module. It is preloaded in the container, so you do not need to install its bundle.
Note
There is no backing engine factory for the LDAP Login Module, which means that this module cannot be managed using the jaas:* console commands.

Options

The JAAS LDAP login module supports the following options:
authentication
Specifies the authentication method used when binding to the LDAP server. Valid values are
  • simple—bind with user name and password authentication, requiring you to set the connection.username and connection.password properties.
  • none—bind anonymously. In this case the connection.username and connection.password properties can be left unassigned.
Note
The connection to the directory server is used only for performing searches. In this case, an anonymous bind is often preferred, because it is faster than an authenticated bind (but you would also need to ensure that the directory server is sufficiently protected, for example by deploying it behind a firewall).
connection.url
Specifies specify the location of the directory server using an ldap URL, ldap://Host:Port. You can optionally qualify this URL, by adding a forward slash, /, followed by the DN of a particular node in the directory tree. To enable SSL security on the connection, you need to specify the ldaps: scheme in the URL—for example, ldaps://Host:Port. You can also specify multiple URLs, as a space-separated list, for example:
connection.url=ldap://10.0.0.153:2389 ldap://10.10.178.20:389
connection.username
Specifies the DN of the user that opens the connection to the directory server. For example, uid=admin,ou=system.
connection.password
Specifies the password that matches the DN from connection.username. In the directory server, the password is normally stored as a userPassword attribute in the corresponding directory entry.
context.com.sun.jndi.ldap.connect.pool
If true, enables connection pooling for LDAP connections. Default is false.
context.com.sun.jndi.ldap.connect.timeout
Specifies the timeout for creating a TCP connection to the LDAP server, in units of milliseconds. We recommend that you set this property explicitly, because the default value is infinite, which can result in a hung connection attempt.
context.com.sun.jndi.ldap.read.timeout
Specifies the read timeout for an LDAP operation, in units of milliseconds. We recommend that you set this property explicitly, because the default value is infinite.
context.java.naming.referral
An LDAP referral is a form of indirection supported by some LDAP servers. The LDAP referral is an entry in the LDAP server which contains one or more URLs (usually referencing a node or nodes in another LDAP server). The context.java.naming.referral property can be used to enable or disable referral following. It can be set to one of the following values:
  • follow to follow the referrals (assuming it is supported by the LDAP server),
  • ignore to silently ignore all referrals,
  • throw to throw a PartialResultException whenever a referral is encountered.
disableCache
The user and role caches can be disabled by setting this property to true. Default is false.
initial.context.factory
Specifies the class of the context factory used to connect to the LDAP server. This must always be set to com.sun.jndi.ldap.LdapCtxFactory.
role.base.dn
Specifies the DN of the subtree of the DIT to search for role entries. For example, ou=groups,ou=system.
role.filter
Specifies the LDAP search filter used to locate roles. It is applied to the subtree selected by role.base.dn. For example, (member=uid=%u). Before being passed to the LDAP search operation, the value is subjected to string substitution, as follows:
  • %u is replaced by the user name extracted from the incoming credentials, and
  • %dn is replaced by the RDN of the corresponding user in the LDAP server (which was found by matching against the user.filter filter).
  • %fqdn is replaced by the DN of the corresponding user in the LDAP server (which was found by matching against the user.filter filter).
role.mapping
Specifies the mapping between LDAP groups and JAAS roles. If no mapping is specified, the default mapping is for each LDAP group to map to the corresponding JAAS role of the same name. The role mapping is specified with the following syntax:
ldap-group=jaas-role(,jaas-role)*(;ldap-group=jaas-role(,jaas-role)*)*
Where each LDAP group, ldap-group, is specified by its Common Name (CN). Note that the role.mapping option must be set to a non-empty value.
For example, given the LDAP groups, admin, devop, and tester, you could map them to JAAS roles, as follows:
role.mapping=admin=Administrator;devop=Administrator,Deployer;tester=Monitor
Since JBoss Fuse 6.3.0 R4, it is also possible to specify an LDAP group using its full Distinguished Name (DN). For example:
role.mapping=cn=admin,ou=groups,dc=example,dc=org=Administrator;cn=admin,ou=otherGroups,dc=example,dc=org=Administrator,Deployer
role.name.attribute
Specifies the attribute type of the role entry that contains the name of the role/group. If you omit this option, the role search feature is effectively disabled. For example, cn.
role.search.subtree
Specifies whether the role entry search scope includes the subtrees of the tree selected by role.base.dn. If true, the role lookup is recursive (SUBTREE). If false, the role lookup is performed only at the first level (ONELEVEL).
ssl
Specifies whether the connection to the LDAP server is secured using SSL. If connection.url starts with ldaps:// SSL is used regardless of this property.
ssl.provider
Specifies the SSL provider to use for the LDAP connection. If not specified, the default SSL provider is used.
ssl.protocol
Specifies the protocol to use for the SSL connection. You must set this property to TLSv1, in order to prevent the SSLv3 protocol from being used (POODLE vulnerability).
ssl.algorithm
Specifies the algorithm used by the trust store manager. For example, PKIX.
ssl.keystore
The ID of the keystore that stores the LDAP client's own X.509 certificate (required only if SSL client authentication is enabled on the LDAP server). The keystore must be deployed using a jaas:keystore element (see the section called “Sample configuration for Apache DS”).
ssl.keyalias
The keystore alias of the LDAP client's own X.509 certificate (required only if there is more than one certificate stored in the keystore specified by ssl.keystore).
ssl.truststore
The ID of the keystore that stores trusted CA certificates, which are used to verify the LDAP server's certificate (the LDAP server's certificate chain must be signed by one of the certificates in the truststore). The keystore must be deployed using a jaas:keystore element.
user.base.dn
Specifies the DN of the subtree of the DIT to search for user entries. For example, ou=users,ou=system.
user.filter
Specifies the LDAP search filter used to locate user credentials. It is applied to the subtree selected by user.base.dn. For example, (uid=%u). Before being passed to the LDAP search operation, the value is subjected to string substitution, as follows:
  • %u is replaced by the user name extracted from the incoming credentials.
user.search.subtree
Specifies whether the user entry search scope includes the subtrees of the tree selected by user.base.dn. If true, the user lookup is recursive (SUBTREE). If false, the user lookup is performed only at the first level (ONELEVEL).

Sample configuration for Apache DS

The following Blueprint configuration shows how to define a new karaf realm using the LDAP login module, where the default karaf realm is overridden by setting the rank attribute to 200, and the LDAP login module connects to an Apache Directory Server:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
  xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

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

    <jaas:module className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule" flags="sufficient">
      debug=true

      <!-- LDAP Configuration -->
      initialContextFactory=com.sun.jndi.ldap.LdapCtxFactory
<!--  multiple LDAP servers can be specified as a space separated list of URLs -->
      connection.url=ldap://10.0.0.153:2389 ldap://10.10.178.20:389

<!--  authentication=none -->
      authentication=simple
      connection.username=cn=Directory Manager
      connection.password=directory

      <!-- User Info -->
      user.base.dn=dc=redhat,dc=com
      user.filter=(&amp;(objectClass=InetOrgPerson)(uid=%u))
      user.search.subtree=true

      <!-- Role/Group Info-->
      role.base.dn=dc=redhat,dc=com
      role.name.attribute=cn
<!-- 
      The 'dc=redhat,dc=com' used in the role.filter
      below is the user.base.dn.
-->
<!--      role.filter=(uniquemember=%dn,dc=redhat,dc=com) -->
      role.filter=(&amp;(objectClass=GroupOfUniqueNames)(UniqueMember=%fqdn))
      role.search.subtree=true

<!-- role mappings - a ';' separated list -->
      role.mapping=JBossAdmin=admin;JBossMonitor=Monitor,viewer

<!-- LDAP context properties -->
      context.com.sun.jndi.ldap.connect.timeout=5000
      context.com.sun.jndi.ldap.read.timeout=5000

<!-- LDAP connection pooling -->
<!-- http://docs.oracle.com/javase/jndi/tutorial/ldap/connect/pool.html -->
<!-- http://docs.oracle.com/javase/jndi/tutorial/ldap/connect/config.html -->
     context.com.sun.jndi.ldap.connect.pool=true

<!-- How are LDAP referrals handled? 

     Can be `follow`, `ignore` or `throw`.  Configuring `follow` may not work on all LDAP servers, `ignore` will 
     silently ignore all referrals, while `throw` will throw a partial results exception if there is a referral.
-->
     context.java.naming.referral=ignore

<!-- SSL configuration -->
     ssl=false
     ssl.protocol=SSL
<!-- matches the keystore/truststore configured below -->
     ssl.truststore=ks
     ssl.algorithm=PKIX
<!-- The User and Role caches can be disabled - 6.3.0 179 and later -->
     disableCache=true
    </jaas:module>
  </jaas:config>

  <!-- Location of the SSL truststore/keystore 
  <jaas:keystore name="ks" path="file:///${karaf.home}/etc/ldap.truststore" keystorePassword="XXXXXX" />
-->
</blueprint>
Note
In order to enable SSL, you must remember to use the ldaps scheme in the connection.url setting.
Important
You must set ssl.protocol to TLSv1, in order to protect against the Poodle vulnerability (CVE-2014-3566)

Filter settings for different directory servers

The most significant differences between directory servers arise in connection with setting the filter options in the LDAP login module. The precise settings depend ultimately on the organisation of your DIT, but the following table gives an idea of the typical role filter settings required for different directory servers:
Directory ServerTypical Filter Settings
389-DS
Red Hat DS
user.filter=(&amp;(objectClass=InetOrgPerson)(uid=%u))
role.filter=(uniquemember=%fqdn)
MS Active Directory
user.filter=(&amp;(objectCategory=person)(samAccountName=%u))
role.filter=(uniquemember=%fqdn)
Apache DS
user.filter=(uid=%u)
role.filter=(member=uid=%u)
OpenLDAP
user.filter=(uid=%u)
role.filter=(member:=uid=%u)
Note
In the preceding table, the & symbol (representing the logical And operator) is escaped as &amp; because the option settings will be embedded in a Blueprint XML file.

2.1.8. Encrypting Stored Passwords

Overview

By default, the JAAS login modules store passwords in plaintext format. Although you can (and should) protect such data by setting file permissions appropriately, you can provide additional protection to passwords by storing them in an obscured format (using a message digest algorithm).
Red Hat JBoss Fuse provides a set of options for enabling password encryption, which can be combined with any of the JAAS login modules (except the public key login module, where it is not needed).
Important
Although message digest algorithms are difficult to crack, they are not invulnerable to attack (for example, see the Wikipedia article on cryptographic hash functions). Always use file permissions to protect files containing passwords, in addition to using password encryption.

Options

You can optionally enable password encryption for JAAS login modules by setting the following login module properties. To do so, either edit the InstallDir/etc/org.apache.karaf.jaas.cfg file or deploy your own blueprint file as described in the section called “Example of a login module with Jasypt encryption”.
encryption.enabled
Set to true, to enable password encryption.
encryption.name
Name of the encryption service, which has been registered as an OSGi service.
encryption.prefix
Prefix for encrypted passwords.
encryption.suffix
Suffix for encrypted passwords.
encryption.algorithm
Specifies the name of the encryption algorithm—for example, MD5 or SHA-1. You can specify one of the following encryption algorithms:
  • MD2
  • MD5
  • SHA-1
  • SHA-256
  • SHA-384
  • SHA-512
encryption.encoding
Encrypted passwords encoding: hexadecimal or base64.
encryption.providerName (Jasypt only)
Name of the java.security.Provider instance that is to provide the digest algorithm.
encryption.providerClassName (Jasypt only)
Class name of the security provider that is to provide the digest algorithm
encryption.iterations (Jasypt only)
Number of times to apply the hash function recursively.
encryption.saltSizeBytes (Jasypt only)
Size of the salt used to compute the digest.
encryption.saltGeneratorClassName (Jasypt only)
Class name of the salt generator.
role.policy
Specifies the policy for identifying role principals. Can have the values, prefix or group.
role.discriminator
Specifies the discriminator value to be used by the role policy.

Encryption services

There are two encryption services provided by JBoss Fuse:
You can also create your own encryption service. To do so, you need to:
  • implement interface org.apache.karaf.jaas.modules.EncryptionService
  • and expose your implementation as OSGI service.
Following listing shows, how jasypt encryption service is exposed to OSGI container.
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

    <service interface="org.apache.karaf.jaas.modules.EncryptionService">
        <service-properties>
            <entry key="name" value="jasypt" />
        </service-properties>
        <bean class="org.apache.karaf.jaas.jasypt.impl.JasyptEncryptionService"/>
    </service>
    ...
</blueprint>

Basic encryption service

The basic encryption service is installed in the standalone container by default and you can reference it by setting the encryption.name property to the value, basic. In the basic encryption service, the message digest algorithms are provided by the SUN security provider (the default security provider in the Oracle JDK).

Jasypt encryption

By default, the Jasypt encryption service is installed on standalone JBoss Fuse, but not on standalone JBoss A-MQ. To install it on JBoss A-MQ, install the jasypt-encryption feature, using the following console command:
JBossA-MQ:karaf@root> features:install jasypt-encryption
This command installs the requisite Jasypt bundles and exports Jasypt encryption as an OSGi service, so that it is available for use by JAAS login modules. To access the Jasypt encryption service, set the encryption.name property to the value, jasypt.
For more information about Jasypt encryption, see the Jasypt documentation.

Example of a login module with Jasypt encryption

Assuming that you have already installed the jasypt-encryption feature, you could deploy a properties login module with Jasypt encryption using the following Blueprint configuration:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
  xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
  xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

  <type-converters>
      <bean class="org.apache.karaf.jaas.modules.properties.PropertiesConverter"/>
  </type-converters>

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

  <jaas:config name="karaf" rank="200">
      <jaas:module flags="required" 
className="org.apache.karaf.jaas.modules.properties.PropertiesLoginModule">
        users = $[karaf.base]/etc/users.properties
        encryption.enabled = true
        encryption.name = jasypt
        encryption.algorithm = SHA-256
        encryption.encoding = base64
        encryption.iterations = 100000
        encryption.saltSizeBytes = 16
      </jaas:module>
  </jaas:config>

  <!-- The Backing Engine Factory Service for the PropertiesLoginModule -->
  <service interface="org.apache.karaf.jaas.modules.BackingEngineFactory">
      <bean class="org.apache.karaf.jaas.modules.properties.PropertiesBackingEngineFactory"/>
  </service>
  
  <!-- Enable automatic encryption of all user passwords 
    in InstallDir/etc/users.properties file. 
    No login required to activate. 
    Encrypted passwords appear in the 
    InstallDir/etc/users.properties file as values enclosed 
    by {CRYPT}...{CRYPT} prefix/suffix pairs -->
  
  <bean init-method="init" destroy-method="destroy"
class="org.apache.karaf.jaas.modules.properties.AutoEncryptionSupport">
    <argument>
      <map>
        <entry key="org.osgi.framework.BundleContext" 
              value-ref="blueprintBundleContext"/>
        <entry key="users" value="$[karaf.base]/etc/users.properties"/>
        <entry key="encryption.name" value="jasypt"/>
        <entry key="encryption.enabled" value="true"/>
        <entry key="encryption.prefix" value="{CRYPT}"/>
        <entry key="encryption.suffix" value="{CRYPT}"/>
        <entry key="encryption.algorithm" value="SHA-256"/>
        <entry key="encryption.encoding" value="base64"/>
        <entry key="encryption.iterations" value="100000"/>
        <entry key="encryption.saltSizeBytes" value="16"/>
      </map>
    </argument>
  </bean>

</blueprint>