A newer version of IMDG is available.

View latest

Want to try Hazelcast Platform?

We’ve combined the in-memory storage of IMDG with the stream processing power of Jet to bring you the all new Hazelcast Platform.

Security Realms

Hazelcast IMDG 4.0 introduces a new security configuration: security realms. Realms allow configuring JAAS authentication and/or own identity independently on the module which consumes this configuration. The realm is a named configuration and other modules just reference it by name.

  • XML

  • YAML

    <security enabled="true">
        <realms>
            <realm name="realm1">
                <authentication>
                    <jaas>
                        <login-module class-name="com.hazelcast.examples.MyRequiredLoginModule" usage="REQUIRED">
                            <properties>
                                <property name="property">value</property>
                            </properties>
                        </login-module>
                    </jaas>
                </authentication>
                <identity>
                    <credentials-factory class-name="com.hazelcast.examples.MyCredentialsFactory">
                        <properties>
                            <property name="property">value</property>
                        </properties>
                    </credentials-factory>
                </identity>
            </realm>
        </realms>
        <member-authentication realm="realm1"/>
        <client-authentication realm="realm1"/>
    </security>
  security:
    enabled: true
    realms:
      - name: realm1
        authentication:
          jaas:
            - class-name: com.hazelcast.examples.MyRequiredLoginModule
              usage: REQUIRED
              properties:
                property: value
        identity:
          credentials-factory:
            class-name: com.hazelcast.examples.MyCredentialsFactory
            properties:
              property: value
    member-authentication:
      realm: realm1
    client-authentication:
      realm: realm1

Authentication Configuration

There are several types of authentication configuration available in a security realm. The realm cannot have more than one authentication method specified.

The following are the available authentication types:

  • jaas: It allows defining JAAS login module stacks.

  • ldap: It verifies PasswordCredentials against an LDAP server.

  • kerberos: It verifies the Kerberos token provided in TokenCredentials.

  • tls: It verifies that the TLS mutual authentication was used in the incoming connection and the peer’s certificate chain is available.

JAAS Authentication Type

The <jaas> authentication configuration is the most flexible form of the authentication configuration, but it requires knowledge of JAAS login modules and related concepts. It allows using custom login modules and ordering them in a login module stack.

The following is a sample configuration which authenticates against an LDAP server or database as a fallback:

  • XML

  • YAML

            <realm name="jaasRealm">
                <authentication>
                    <jaas>
                        <login-module class-name="com.examples.LdapLoginModule" usage="SUFFICIENT">
                            <properties>
                                <property name="url">ldap://corp-ldap/</property>
                            </properties>
                        </login-module>
                        <login-module class-name="com.examples.DatabaseLoginModule" usage="SUFFICIENT">
                            <properties>
                                <property name="type">ora18</property>
                                <property name="host">corp-db</property>
                                <property name="table">USERS</property>
                            </properties>
                        </login-module>
                    </jaas>
                </authentication>
            </realm>
    realms:
      - name: jaasRealm
        authentication:
          jaas:
            - class-name: com.examples.LdapLoginModule
              usage: SUFFICIENT
              properties:
                url: ldap://corp-ldap
            - class-name: com.examples.DatabaseLoginModule
              usage: SUFFICIENT
              properties:
                type: ora18
                host: corp-db
                table: USERS

For more details, see the JAAS authentication section.

LDAP Authentication Type

LDAP servers are one of the most popular identity stores in companies. They can track information about the organization structure, users, groups, servers and configurations.

Hazelcast supports authentication and authorization against LDAP servers. The authentication verifies the provided name and password. The authorization part allows to map roles to the authenticated user.

The password verification during the authentication is possible by:

  • making a new LDAP bind operation with the given name and password

  • using a separate "admin connection" to verify the provided password against an LDAP object attribute.

The LDAP authentication allows also a role mapping. As there are more ways how roles can be mapped in the LDAP, Hazelcast provides several approaches to retrieve them:

  • attribute: The role name is stored as an attribute in the object representing the identity.

  • direct mapping: The identity object contains an attribute with reference to the role object(s).

  • reverse mapping: The role objects having a reference to the identity object are searched.

The direct and reverse mapping modes also allow a role search recursion.

Table 1. LDAP Configuration Options

Option Name

Default Value

Description

url

URL of the LDAP server. The value is configured as the JNDI environment property, i.e., java.naming.provider.url.

socket-factory-class-name

Socket factory class name. The factory can be used for fine grained configuration of the TLS protocol on top of the LDAP protocol, i.e., ldaps scheme.

parse-dn

false

If set to true, it treats the value of role-mapping-attribute as a DN and extracts only the role-name-attribute values as role names. If set to false, the whole value of role-mapping-attribute is used as a role name.

This option is only used when the role-mapping-mode option has the value attribute.

role-context

LDAP Context in which assigned roles are searched, e.g., ou=Roles,dc=hazelcast,dc=com.

This option is only used when the role-mapping-mode option has the value reverse.

role-filter

([role-mapping-attribute]={MEMBERDN})

LDAP search string which usually contains a placeholder {MEMBERDN} to be replaced by the provided login name, e.g., (member={MEMBERDN}).

If the role search recursion is enabled (see role-recursion-max-depth), the {MEMBERDN} is replaced by role DNs in the recurrent searches.

This option is only used when the role-mapping-mode option has the value reverse.

role-mapping-attribute

Name of the LDAP attribute which contains either the role name or role DN.

This option is used when the role-mapping-mode option has the value attribute or direct. If the mapping mode is reverse, the value is used in role-filter default value.

role-mapping-mode

attribute

Role mapping mode. It can have one of the following values:

  • attribute: The user object in the LDAP contains directly role name in the given attribute. Role name can be parsed from a DN string when parse-dn=true No additional LDAP query is done to find assigned roles.

  • direct: The user object contains an attribute with DN(s) of assigned role(s). Role object(s) is/are loaded from the LDAP and the role name is retrieved from its attributes. Role search recursion can be enabled for this mode.

  • reverse: The role objects are located by executing an LDAP search query with the given role-filter. In this case, the role object usually contains attributes with DNs of the assigned users. Role search recursion can be enabled for this mode.

role-name-attribute

This option may refer to a name of LDAP attribute within the role object which contains the role name in case of direct and reverse role mapping mode. It may also refer to the attribute name within X.500 name stored in role-mapping-attribute when role-mapping-mode=attribute and parse-dn=true.

role-recursion-max-depth

1

Sets the maximum depth of role search recursion. The default value 1 means the role search recursion is disabled.

This option is only used when the role-mapping-mode option has value direct or reverse.

role-search-scope

subtree

LDAP search scope used for role-filter search. It can have one of the following values:

  • subtree: Searches for objects in the given context and its subtree.

  • one-level: Searches just one-level under the given context.

  • object: Searches (or tests) just for the context object itself (if it matches the filter criteria).

This option is only used when the role-mapping-mode option has the value reverse.

user-name-attribute

uid

LDAP attribute name whose value is used as a name in ClusterIdentityPrincipal added to the JAAS Subject.

system-user-dn

Admin account DN. If configured, then the following are true:

  • For the user and role object, search queries are used an admin connection instead of the "user" one created by LDAP bind with provided credentials.

  • LDAP authentication doesn’t expect the full user DN to be provided as a login name. It rather expects names like "jduke" than "uid=jduke,ou=Engineering,o=Hazelcast,dc=com";

  • The admin connection allows verifying the provided user credentials against a value defined in the password-attribute option.

system-user-password

Admin’s password (for system-user-dn account).

system-authentication

simple

Name of the authentication mechanism used for the admin LDAP connection. It’s used as a value for JNDI environment property Context#SECURITY_AUTHENTICATION. You can specify GSSAPI to authenticate with the Kerberos protocol.

password-attribute

Credentials verification is done by the new LDAP binds by default. Nevertheless, the password can be stored in a non-default LDAP attribute, and in this case use password-attribute to configure against which LDAP attribute (within the user object) is the provided password compared during the login. As a result, if the password-attribute option is provided, then the extra LDAP bind to verify credentials is not done and passwords are just compared within the Hazelcast code after retrieving the user object from LDAP server.

This option is only used when the admin connection is configured, i.e., when system-user-dn or system-authentication is defined.

user-context

LDAP context in which the user objects are searched, e.g., ou=Users,dc=hazelcast,dc=com.

This option is only used when the admin connection is configured, i.e., when system-user-dn or system-authentication is defined.

user-filter

(uid={login})

LDAP search string for retrieving the user objects based on the provided login name. It usually contains a placeholder substring {login} which is replaced by the provided login name.

This option is only used when the admin connection is configured, i.e., when system-user-dn or system-authentication is defined.

user-search-scope

subtree

LDAP search scope used for user-filter search. It can have one of the following values:

  • subtree: Searches for objects in the given context and its subtree.

  • one-level: Searches just one-level under the given context.

  • object: Searches (or tests) just for the context object itself (if it matches the filter criteria).

This option is only used when the admin connection is configured, i.e., when system-user-dn or system-authentication is defined.

skip-authentication

false

Flag which allows disabling password verification and only takes care about filling HazelcastPrincipal instances into the Subject.

This option is only used when the admin connection is configured, i.e., when system-user-dn or system-authentication is defined.

security-realm

If specified, given realm name is used for authentication of a (temporary) Subject which is then used for doing LDAP queries.

This option is only used when the admin connection is configured, i.e., when system-user-dn or system-authentication is defined.

Detailed logging for LDAP authentication can be enabled by configuring a more verbose logger level for the com.hazelcast.security package as described in the Security Debugging section.

TLS Protected LDAP Server Connections

The LDAP authentication type supports TLS protected connections to LDAP servers, i.e., the ldaps protocol scheme. The TLS is handled on the Java runtime side (JNDI API and URL handlers).

When using TLS, the LDAP provider will, by default, use the socket factory, javax.net.ssl.SSLSocketFactory for creating a TLS socket to communicate with the server, using the default JSSE configuration. By default, the server’s certificate is validated against Java default CA certificate store and hostname in LDAPs URL is verified against the name(s) in the server certificate. The behavior can be controlled globally by using javax.net.ssl.* properties. Here is an example:

java -Djavax.net.ssl.trustStore=/opt/hazelcast.truststore \
  -Djavax.net.ssl.trustStorePassword=123456 \
  -Djavax.net.ssl.keyStore=/opt/hazelcast.keystore \
  -Djavax.net.ssl.keyStorePassword=123456 \
  ...

There can be also properties specific to vendor or Java version allowing more fine-grained control. Here is an example on disabling host name validation:

-Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true

When even more control is necessary, you can implement your own SSLSocketFactory and use its class name as the value in the ldap authentication option socket-factory-class-name.

Here is an example custom socket factory class:

package security.ldap;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.KeyStore;
import java.security.SecureRandom;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

public class CustomSSLSocketFactory extends SSLSocketFactory {

    private static final SocketFactory INSTANCE = new CustomSSLSocketFactory();

    /**
     * JNDI uses this method when creating {@code ldaps} connections.
     */
    public static SocketFactory getDefault() {
        return INSTANCE;
    }

    private SSLSocketFactory delegate;

    public CustomSSLSocketFactory() {
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            try (FileInputStream fis = new FileInputStream("/opt/ldap.truststore")) {
                trustStore.load(fis, "S3cr3t".toCharArray());
            }
            TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmFactory.init(trustStore);
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, tmFactory.getTrustManagers(), new SecureRandom());
            delegate = sc.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return delegate.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return delegate.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket arg0, String arg1, int arg2, boolean arg3) throws IOException {
        return delegate.createSocket(arg0, arg1, arg2, arg3);
    }

    @Override
    public Socket createSocket(String arg0, int arg1) throws IOException {
        return delegate.createSocket(arg0, arg1);
    }

    @Override
    public Socket createSocket(InetAddress arg0, int arg1) throws IOException {
        return delegate.createSocket(arg0, arg1);
    }

    @Override
    public Socket createSocket(String arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
        return delegate.createSocket(arg0, arg1, arg2, arg3);
    }

    @Override
    public Socket createSocket(InetAddress arg0, int arg1, InetAddress arg2, int arg3) throws IOException {
        return delegate.createSocket(arg0, arg1, arg2, arg3);
    }
}

The authentication configuration could look like as follows:

  • XML

  • YAML

            <realm name="ldapsRealm">
                <authentication>
                    <ldap>
                        <url>ldaps://ldapserver.acme.com</url>
                        <socket-factory-class-name>security.ldap.CustomSSLSocketFactory</socket-factory-class-name>
                        <role-mapping-attribute>cn</role-mapping-attribute>
                    </ldap>
                </authentication>
            </realm>
    realms:
      - name: ldapsRealm
        authentication:
          ldap:
             url: ldaps://ldapserver.acme.com
             socket-factory-class-name: security.ldap.CustomSSLSocketFactory
             role-mapping-attribute: cn

The LDAP authentication is backed by the JNDI API in Java. It has also the failover support. You can configure multiple space-separated URLs in the <url> option:

  • XML

  • YAML

            <realm name="ldapFallbackRealm">
                <authentication>
                    <ldap>
                        <url>ldap://ldap-master.example.com ldap://ldap-backup.example.com</url>
                    </ldap>
                </authentication>
            </realm>
    realms:
      - name: ldapFallbackRealm
        authentication:
          ldap:
             url: ldap://ldap-master.example.com ldap://ldap-backup.example.com

Kerberos Authentication Type

The Kerberos authentication protocol is one of the standard solutions for single sign-on (SSO). It’s well established in many companies. Hazelcast supports Kerberos authentication as an Enterprise feature and it also provides Kerberos integration to LDAP-based authorization.

The Kerberos support in Hazelcast has 2 configuration parts: identity and authentication. The identity part is responsible for retrieving the service ticket from Kerberos KDC (Key Distribution Center). The authentication part verifies the service tickets.

Default Service principal names for Hazelcast members are in the form hz/address@REALM, e.g., hz/192.168.1.1@ACME.COM.

Before a service ticket is issued, the client side of the connection has to be authenticated, which means the TGT (Ticket Granting Ticket) is present in the Subject.

Hazelcast delegates the TGT retrieval to vendor specific Krb5LoginModule implementations (find the correct login module and its options in your Java documentation). On the Hazelcast side, the security-ream property allows referencing another realm with Krb5LoginModule configured.

  • Sample Kerberos Identity Configuration XML

  • YAML

<realm name="kerberosRealm">
    <identity>
        <kerberos>
            <realm>ACME.COM</realm>
            <security-realm>krb5Initiator</security-realm>
        </kerberos>
    </identity>
</realm>
<realm name="krb5Initiator">
    <authentication>
        <jaas>
            <login-module class-name="com.sun.security.auth.module.Krb5LoginModule" usage="REQUIRED">
                <properties>
                    <property name="useTicketCache">true</property>
                    <property name="doNotPrompt">true</property>
                </properties>
            </login-module>
        </jaas>
    </authentication>
</realm>
  realms:
    - name: kerberosRealm
        identity:
          kerberos:
            realm: ACME.COM
            security-realm: krb5Initiator
    - name: krb5Initiator
        authentication:
          jaas:
            class-name: com.sun.security.auth.module.Krb5LoginModule
              properties:
                useTicketCache: true
                doNotPrompt: true

The <kerberos> identity configuration has the following properties:

Table 2. The <kerberos> Identity Configuration Options
Property name Default value Description

spn

Allows configuring static Service Principal Name (SPN). It’s meant for use cases where all the members share a single Kerberos identity.

service-name-prefix

"hz/"

Defines the prefix of SPN. By default the member’s principal name (for which this credentials factory asks the service ticket) is in the form "[servicePrefix][memberIpAddress]@[REALM]", e.g., "hz/192.168.1.1@ACME.COM".

realm

Kerberos realm name, e.g., "ACME.COM".

security-realm

Security realm name in the Hazelcast configuration used for Kerberos authentication. The authentication configuration in the referenced security realm will be used to fill the Subject with the Kerberos credentials, e.g., TGT.

use-canonical-hostname

false

Flag which controls if canonical hostnames should be used instead of IP addresses in generated Service Principal names. This property is only used when Service Principal name is not static, i.e., when spn option is not configured).

principal

Kerberos principal name. This is a helper option which can be used together with the keytabFile to replace the security-realm configuration.

We don’t recommend using this property in production!

keytabFile

Path to a keytab file with the current principal’s secrets. This is a helper option which can be used together with the principal to replace the security-realm configuration.

We don’t recommend using this property in production!

The authenticating part on the server side is able to accept the Kerberos tickets and verify them. Again the Kerberos authentication is delegated to another realm with the Kerberos login module configured.

  • Sample Kerberos Identity Configuration XML

  • YAML

<realm name="kerberosRealm">
    <authentication>
        <kerberos>
            <security-realm>krb5Acceptor</security-realm>
        </kerberos>
    </authentication>
</realm>
<realm name="krb5Acceptor">
    <authentication>
        <jaas>
            <login-module class-name="com.sun.security.auth.module.Krb5LoginModule" usage="REQUIRED">
                <properties>
                    <property name="isInitiator">false</property>
                    <property name="useTicketCache">false</property>
                    <property name="doNotPrompt">true</property>
                    <property name="useKeyTab">true</property>
                    <property name="storeKey">true</property>
                    <property name="principal">hz/192.168.1.1@ACME.COM</property>
                    <property name="keyTab">/opt/member1.keytab</property>
                </properties>
            </login-module>
        </jaas>
    </authentication>
</realm>
    realms:
      name: kerberosRealm
        authentication:
          kerberos:
            security-realm: krb5Acceptor
      name: krb5Acceptor
        authentication:
          jaas:
            - class-name: com.sun.security.auth.module.Krb5LoginModule
              usage: REQUIRED
              properties:
                isInitiator: false
                useTicketCache: false
                doNotPrompt: true
                useKeyTab: true
                storeKey: true
                principal: hz/192.168.1.1@ACME.COM
                keyTab: /opt/member1.keytab

The krb5Acceptor realm configuration in the snippet only loads the Kerberos secrets from a keytab file and it doesn’t authenticate against a KDC.

Table 3. The <kerberos> Authentication Configuration Options
Property name Default value Description

relax-flags-check

false

Allows disabling some of the checks on the incoming token, e.g., passes authentication even if the mutual authentication is required by the token.

use-name-without-realm

false

When set to true, then the Kerberos realm part is removed from the authenticated name, e.g., "jduke@ACME.COM" becomes just "jduke".

security-realm

Security realm name in the Hazelcast configuration used for Kerberos authentication. The authentication configuration in the referenced security realm will be used to fill the Subject with the Kerberos credentials, e.g., Keytab.

principal

Kerberos principal name. This is a helper option which can be used together with the keytabFile to replace the security-realm configuration.

We don’t recommend using this property in production!

keytabFile

Path to a keytab file with the current principal’s secrets. This is a helper option which can be used together with the principal to replace the security-realm configuration.

We don’t recommend using this property in production!

The GssApiLoginModule (implementing Kerberos authentication) derives from the abstract ClusterLoginModule. As a result the <kerberos> configuration supports the common options, too: skip-identity, skip-endpoint and skip-role.

  • The Kerberos authentication in Hazelcast is only able to validate connections on the server side. It doesn’t support mutual authentication.

  • The Generic Security Services API (GSS-API) is not used for protecting (wrapping) the messages after the authentication, e.g., encryption, integrity checks. It’s only used for accepting tokens.

  • The token itself is not protected against Man-in-the-Middle (MITM) attacks. If an attacker is able to eavesdrop the token and use it before the original sender, then the attacker succeeds with the authentication but the original sender won’t.

    • There is a replay protection in Java which caches the already used tokens.

    • Java Kerberos implementation accepts the token for 5 minutes (by default) from its creation.

  • Time has to be synchronized on the machines where the Kerberos is used.

If you are running Hazelcast in an untrusted network with a MITM attack risk, then enable encryption on Hazelcast protocols to prevent stealing the token.

Kerberos and LDAP integration

The Kerberos authentication allows loading role mapping information from an LDAP server (usually the one backing the Kerberos KDC server, too). Therefore the <ldap> authentication configuration is also available as sub-configuration of the <kerberos> authentication.

  • Sample Kerberos Identity Configuration XML

  • YAML

<realm name="kerberosRealm">
    <authentication>
        <kerberos>
            <skip-role>true</skip-role>
            <security-realm>krb5Acceptor</security-realm>
            <ldap>
                <url>ldap://ldap.hazelcast.com</url>
                <system-authentication>GSSAPI</system-authentication>
                <role-mapping-attribute>memberOf</role-mapping-attribute>
                <security-realm>krb5Initiator</security-realm>
                <user-filter>(krb5PrincipalName=\{login})</user-filter>
                <skip-authentication>true</skip-authentication>
            </ldap>
        </kerberos>
    </authentication>
</realm>
    realms:
      - name: kerberosRealm
        authentication:
          kerberos:
            skip-role: true
            security-realm: krb5Acceptor
            ldap:
              url: ldap://ldap.hazelcast.com
              system-authentication: GSSAPI
              security-realm: krb5Initiator
              skip-authentication: true
              user-filter: "(krb5PrincipalName=\{login})"
              role-mapping-attribute: memberOf
The Kerberos-LDAP integration doesn’t support credentials delegation, i.e., reusing client’s ticket for accessing the LDAP. It only allows using the member’s Kerberos credentials to authenticate into the LDAP.

Simplified Kerberos Configuration

To simplify the Kerberos configuration process for new users, Hazelcast allows skipping Krb5LoginModule JAAS configuration within separate security realms. Instead it’s possible to define the principal and keytabFile options in the kerberos identity and authentication configurations. If these options are used instead of the security-realm, then a new temporary realm is generated on the fly during the authentication.

  • Sample Kerberos Identity Configuration XML

  • YAML

<hz:realm name="simpleKerberosRealm">
    <hz:authentication>
        <hz:kerberos>
            <hz:principal>hz/127.0.0.1@HAZELCAST.COM</hz:principal>
            <hz:keytab-file>/opt/localhost.keytab</hz:keytab-file>
        </hz:kerberos>
    </hz:authentication>
    <hz:identity>
        <hz:kerberos>
            <hz:realm>HAZELCAST.COM</hz:realm>
            <hz:principal>hz/127.0.0.1@HAZELCAST.COM</hz:principal>
            <hz:keytab-file>/opt/localhost.keytab</hz:keytab-file>
        </hz:kerberos>
    </hz:identity>
</hz:realm>
    realms:
      - name: simpleKerberosRealm
        authentication:
          kerberos:
            principal: hz/127.0.0.1@HAZELCAST.COM
            keytab-file: /opt/localhost.keytab
        identity:
          kerberos:
            realm: HAZELCAST.COM
            principal: hz/127.0.0.1@HAZELCAST.COM
            keytab-file: /opt/localhost.keytab

A warning is logged during the first usage of the simplified configuration form. It includes the generated configuration, so you can use it as a starting point to define the full Kerberos configuration. An example warning log is shown below:

12:37:41,187  WARN [KerberosCredentialsFactory] Using generated Kerberos initiator
realm configuration is not intended for production use. It's recommended
to properly configure the Krb5LoginModule manually to fit your needs.
Following configuration was generated from provided keytab and principal properties:
<realm name="krb5Initiator">
  <authentication>
    <jaas>
      <login-module class-name="com.sun.security.auth.module.Krb5LoginModule" usage="REQUIRED">
        <properties>
          <property name="isInitiator">true</property>
          <property name="useKeyTab">true</property>
          <property name="refreshKrb5Config">true</property>
          <property name="doNotPrompt">true</property>
          <property name="storeKey">true</property>
          <property name="keyTab">/opt/localhost.keytab</property>
          <property name="principal">hz/127.0.0.1@HAZELCAST.COM</property>
        </properties>
      </login-module>
    </jaas>
  </authentication>
</realm>

TLS Authentication Type

Hazelcast is able to protect network communication using TLS. The TLS mutual authentication is also supported. It means not only the server side identifies itself to a client side (member, client, REST client, etc.), but also the client side needs to prove its identity by using a TLS (X.509) certificate.

The tls authentication type verifies within the JAAS authentication that the incoming connection already authenticated the client’s TLS certificate. A ClusterIdentityPrincipal uses the subject DN (distinguished name) from the client’s TLS certificate.

This authentication type is able to parse a role name from the client’s certificate subject DN. The <tls> element has an attribute, roleAttribute, which specifies a part of DN to be used as a role name.

  • XML

  • YAML

            <realm name="tlsRealm">
                <authentication>
                    <tls roleAttribute="cn" />
                </authentication>
            </realm>
realms:
  name: tlsRealm
    authentication:
      tls:
        roleAttribute: cn

This tls authentication uses cn attribute from the subject DN as the role name. If the subject DN in the certificate is cn=admin,ou=Devs,o=Hazelcast for instance, then the following Principals are added:

  • ClusterIdentityPrincipal: CN=admin,OU=Devs,O=Hazelcast

  • ClusterRolePrincipal: admin

  • ClusterEndpointPrincipal: [remote address of the connecting party]

Identity Configuration

The Identity configuration allows defining own Credentials. These Credentials are used to authenticate to other systems.

Available identity configuration types are as follows:

  • username-password: Defines a new PasswordCredentials object.

  • token: Defines a new TokenCredentials object.

  • kerberos: Defines the Kerberos identity which uses the service tickets stored in the TokenCredentials object.

  • credentials-factory: Configures the factory class which creates the Credentials objects.

Credentials

One of the key elements in Hazelcast security is the Credentials object, which represents evidence of the identity (member or client). The content of Credentials object is verified during the authentication. Credentials is an interface which extends Serializable.

public interface Credentials extends Serializable {
    String getName();
}

There are two subtype interfaces which simplify the Credentials usage. The subtypes reflect data provided in the client authentication messages:

  • Name and password (com.hazelcast.security.PasswordCredentials)

  • Byte array token (com.hazelcast.security.TokenCredentials)

The interfaces have the following forms:

public interface PasswordCredentials extends Credentials {
    String getPassword();
}
public interface TokenCredentials extends Credentials {
  byte[] getToken();

  default Data asData() {
      return new HeapData(getToken());
  }
}

The Credentials instance can be retrieved in the login modules by handling a CredentialsCallback.

Here is an example:

            CredentialsCallback credcb = new CredentialsCallback();
            try {
                callbackHandler.handle(new Callback[] { credcb });
            } catch (IOException | UnsupportedCallbackException e) {
                throw new LoginException("Unable to retrieve credetials");
            }
            Credentials credentials = credcb.getCredentials();
            if (credentials instanceof PasswordCredentials) {
                PasswordCredentials passwordCredentials = (PasswordCredentials) credentials;
                if (expectedName.equals(credentials.getName())
                        && expectedPassword.equals(passwordCredentials.getPassword())) {
                    name = credentials.getName();
                    addRole(name);
                    return true;
                }
            }
            throw new FailedLoginException("Credentials verification failed.");

Password Credentials

A PasswordCredentials implementation can be configured as a simple identity representation. It is configured by the <username-password/> XML configuration element as shown below:

  • XML

  • YAML

        <realms>
            <realm name="passwordRealm">
                <identity>
                    <username-password username="member1" password="s3crEt" />
                </identity>
            </realm>
        </realms>
        <member-authentication realm="passwordRealm" />
realms:
  name: passwordRealm
    identity:
      username-password:
        username: member1
        password: s3crEt
member-authentication:
  realm: passwordRealm

The equivalent programmatic configuration is shown below:

        RealmConfig realmConfig = new RealmConfig()
                .setUsernamePasswordIdentityConfig("member1", "s3crEt");
        config.getSecurityConfig().setMemberRealmConfig("passwordRealm", realmConfig);

Token Credentials

TokenCredentials instances are also simply configurable for identity representation. The <token/> XML configuration element allows using either plain ASCII tokens or Base64 encoded values. Its optional argument encoding can have either base64 or none (default) as its value.

The following two realms define the same token value - bytes of the "Hazelcast" string:

  • XML

  • YAML

            <realm name="tokenRealm1">
                <identity>
                    <token>Hazelcast</token>
                </identity>
            </realm>
            <realm name="tokenRealm2">
                <identity>
                    <token encoding="base64">SGF6ZWxjYXN0</token>
                </identity>
            </realm>
realms:
  - name: tokenRealm1
      identity:
        token:
          value: Hazelcast
  - name: tokenRealm2
      identity:
        token:
          encoding: base64
          value: SGF6ZWxjYXN0

The equivalent programmatic configuration is as follows:

        TokenIdentityConfig tokenConfig = new TokenIdentityConfig("Hazelcast".getBytes(StandardCharsets.US_ASCII));
        RealmConfig realmConfig = new RealmConfig().setTokenIdentityConfig(tokenConfig);

Kerberos Identity

The kerberos identity type is used to retrieve Kerberos service tickets to access a member with the kerberos authentication type configured. The resulting tickets are TokenCredentials instances. Read more about kerberos identity in the Kerberos authentication section.

Credentials Factory

The most flexible way to define the Credentials objects is using a custom credential factory. It is an implementation of com.hazelcast.security.ICredentialsFactory interface. Its newCredentials() method is the one which provides credentials.

The XML configuration uses <credentials-factory> element to define the factory class.

The behavior of credential factories can be controlled by specifying factory properties. The properties are provided in the init(Properties) method.

A sample configuration is shown below:

  • XML

  • YAML

            <realm name="credentialsFactoryRealm">
                <identity>
                    <credentials-factory class-name="com.examples.TOTPCredentialsFactory">
                        <properties>
                            <property name="seed">3132333435363738393031323334353637383930</property>
                        </properties>
                    </credentials-factory>
                </identity>
            </realm>
realms:
  name: credentialsFactoryRealm
    identity:
      credentials-factory:
        class-name: com.examples.TOTPCredentialsFactory
        properties:
          seed: 3132333435363738393031323334353637383930

Security Realms on the Client Side

Hazelcast IMDG 4.1 introduces a limited support of security realms in native clients. The configuration allows specifying JAAS login modules which can be referenced from the Kerberos identity configuration.

  • XML

  • YAML

<security>
    <kerberos>
        <realm>ACME.COM</realm>
        <security-realm>krb5Initiator</security-realm>
    </kerberos>
    <realms>
        <realm name="krb5Initiator">
            <authentication>
                <jaas>
                    <login-module class-name="com.sun.security.auth.module.Krb5LoginModule" usage="REQUIRED">
                        <properties>
                            <property name="useTicketCache">true</property>
                            <property name="doNotPrompt">true</property>
                        </properties>
                    </login-module>
                </jaas>
            </authentication>
        </realm>
    </realms>
</security>
security:
  kerberos:
    realm: ACME.COM
    security-realm: krb5Initiator
    realms:
      name: krb5Initiator
        authentication:
          jaas:
            class-name: com.sun.security.auth.module.Krb5LoginModule
            usage: REQUIRED
            properties:
              useTicketCache: true
              doNotPrompt: true