GridGain Developers Hub

Authentication

GridGain Community Edition authentication mechanism is based on the Apache Ignite authentication feature, which is limited to simple password-based authentication and only works with thin client/JDBC/ODBC connections.

GridGain Enterprise and Ultimate editions provide a more advanced Authentication and Authorization feature, which can be configured for cluster nodes as well as thin clients/JDBC/ODBC/GridGain Nebula connections. For example, you can use different accounts for server nodes and client nodes and configure different sets of permissions for different clients.

Ignite Authentication

You can enable Ignite Authentication by setting the authenticationEnabled property to true in the node’s configuration. This type of authentication requires persistent storage be enabled for at least one data region.

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="dataStorageConfiguration">
        <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
            <property name="defaultDataRegionConfiguration">
                <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
                    <property name="persistenceEnabled" value="true"/>
                </bean>
            </property>
        </bean>
    </property>

   <property name="authenticationEnabled" value="true"/>

</bean>
IgniteConfiguration cfg = new IgniteConfiguration();

// Ignite persistence configuration.
DataStorageConfiguration storageCfg = new DataStorageConfiguration();

// Enabling the persistence.
storageCfg.getDefaultDataRegionConfiguration().setPersistenceEnabled(true);

// Applying settings.
cfg.setDataStorageConfiguration(storageCfg);

// Enable authentication
cfg.setAuthenticationEnabled(true);

Ignite ignite = Ignition.start(cfg);
var cfg = new IgniteConfiguration
          {
              DataStorageConfiguration = new DataStorageConfiguration
              {
                  DefaultDataRegionConfiguration = new DataRegionConfiguration
                  {
                      PersistenceEnabled = true
                  }
              },
              AuthenticationEnabled = true
          };
          Ignition.Start(cfg);
This API is not presently available for C++. You can use XML configuration.

The first node that you start must have authentication enabled. Upon start-up, GridGain creates a user account with the name "ignite" and password "ignite". This account is meant to be used to create other user accounts for your needs. Then simply delete the "ignite" account.

You can manage users using the following SQL commands:

GridGain Authentication

GridGain Authentication allows you to control access to the cluster for every entity, including server and client nodes, thin clients, JDBC/ODBC and REST API clients. The feature also enables you to manage what operations the entities are allowed to perform (authorization).

How to enable authentication:

  1. The first step is to configure an authenticator that verifies the credentials of any entity trying to connect to the cluster (such as server or client nodes, thin clients, GridGain Nebula, etc.).

    GridGain supports several ways to configure an authenticator:

  2. Specify the username and password (of one of the existing users) in every node that connects to the cluster. This is done by using a security credentials provider.

  3. All applications that use thin clients, JDBC/ODBC, or REST API must provide user credentials as well.

Note that all server nodes must have the same authenticator configuration. GridGain verifies that all nodes use the same authenticator on the node start-up.

The following two sections explain how to configure the authenticator.

Passcode Authentication

The simplest way to configure authentication is to define the list of users in the node configuration. This approach consists in creating an access-control list with a set of credentials and the permissions attached to them.

In the following example, we define two users: 'server' and 'client'. The 'server' user is allowed to execute any operation. The 'client' user can only execute cache read operations. All server nodes use the 'server' user credentials, and all client nodes use the credentials of the 'client' user. Refer to the Authorization and Permissions for the full list of supported permissions.

<bean class="org.apache.ignite.plugin.security.SecurityCredentials" id="server.cred">
    <constructor-arg value="server"/>
    <constructor-arg value="password"/>
</bean>

<bean class="org.apache.ignite.plugin.security.SecurityCredentials" id="client.cred">
    <constructor-arg value="client"/>
    <constructor-arg value="password"/>
</bean>
<bean class="org.apache.ignite.configuration.IgniteConfiguration" >
    <property name="pluginConfigurations">
        <bean class="org.gridgain.grid.configuration.GridGainConfiguration">
            <property name="authenticator">
                <bean class="org.gridgain.grid.security.passcode.PasscodeAuthenticator">
                    <property name="aclProvider">
                        <bean class="org.gridgain.grid.security.passcode.AuthenticationAclBasicProvider">
                            <constructor-arg>
                                <map>
                                    <!-- server.cred credentials and associated permissions (everything is allowed) -->
                                    <entry key-ref="server.cred" value="{defaultAllow:true}"/>
                                    <!-- client.cred credentials and associated permissions (only cache reads are allowed) -->
                                    <entry key-ref="client.cred" value="{defaultAllow:false, {cache:'*',permissions:['CACHE_READ']}}"/>
                                </map>
                            </constructor-arg>
                        </bean>
                    </property>
                </bean>
            </property>

            <!-- Credentials for the current node. -->
            <property name="securityCredentialsProvider">
                <bean class="org.apache.ignite.plugin.security.SecurityCredentialsBasicProvider">
                    <constructor-arg ref="server.cred"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>
// Create security credentials objects.
SecurityCredentials serverCreds = new SecurityCredentials("server", "password");
SecurityCredentials clientCreds = new SecurityCredentials("client", "password");

// GridGain plugin configuration.
GridGainConfiguration ggCfg = new GridGainConfiguration();

// we will use simple passcode authentication
PasscodeAuthenticator authenticator = new PasscodeAuthenticator();

// Create a map for the list of credentials and permissions.
Map<SecurityCredentials, String> authMap = new HashMap<>();

// Allow all operations on server nodes.
authMap.put(serverCreds, "{defaultAllow:true}");

// Allow only cache reads on client nodes.
authMap.put(clientCreds, "{defaultAllow:false, {cache:'*', permissions:['CACHE_READ']}}");

authenticator.setAclProvider(new AuthenticationAclBasicProvider(authMap));

ggCfg.setAuthenticator(authenticator);
ggCfg.setSecurityCredentialsProvider(new SecurityCredentialsBasicProvider(serverCreds));

IgniteConfiguration igniteCfg = new IgniteConfiguration();

igniteCfg.setPluginConfigurations(ggCfg);

Ignite ignite = Ignition.start(igniteCfg);
// Provide security credentials.
SecurityCredentials serverCreds = new SecurityCredentials()
{
    Login = "server",
    Password = "password"
};

SecurityCredentials clientCreds = new SecurityCredentials()
{
    Login = "client",
    Password = "password"
};

// Create dictionary for node and client with their security credentials and permissions.
IDictionary<SecurityCredentials, ISecurityPermissionSet> authDict = new Dictionary<SecurityCredentials, ISecurityPermissionSet>();

// Allow all operations on server nodes.
authDict.Add(serverCreds, new SecurityPermissionSet()
{
    DefaultAllowAll = true
});

// Allow only cache reads on client nodes.
IDictionary<string, ICollection<SecurityPermission>> clientPermissions = new Dictionary<string, ICollection<SecurityPermission>>();
clientPermissions.Add("*", new[]
{
    SecurityPermission.CacheRead
});

authDict.Add(clientCreds, new SecurityPermissionSet()
{
    DefaultAllowAll = false,
    CachePermissions = clientPermissions
});

// GridGain plugin configuration.
var cfg = new IgniteConfiguration
{
    PluginConfigurations = new[]
    {
        new GridGainPluginConfiguration()
        {
            Authenticator = new PasscodeAuthenticator()
            {
                AclProvider = new AuthenticationAclBasicProvider()
                {
                    Acl = authDict
                }
            }
        }
    }
};
This API is not presently available for C++. You can use XML configuration.

Here is the configuration of a client node:

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="clientMode" value="true"/>
    <property name="pluginConfigurations">
        <bean class="org.gridgain.grid.configuration.GridGainConfiguration">
            <property name="securityCredentialsProvider">
                <bean class="org.apache.ignite.plugin.security.SecurityCredentialsBasicProvider">
                    <!-- Specify credentials for the current node -->
                    <constructor-arg>
                        <bean class="org.apache.ignite.plugin.security.SecurityCredentials" id="client.cred">
                            <constructor-arg value="client"/>
                            <constructor-arg value="password"/>
                        </bean>
                    </constructor-arg>
                </bean>
            </property>
        </bean>
    </property>
</bean>
SecurityCredentials clientCreds = new SecurityCredentials("client", "password");

GridGainConfiguration ggCfg = new GridGainConfiguration();

ggCfg.setSecurityCredentialsProvider(new SecurityCredentialsBasicProvider(clientCreds));

IgniteConfiguration igniteCfg = new IgniteConfiguration().setPluginConfigurations(ggCfg);

Ignite ignite = Ignition.start(igniteCfg);
This API is not presently available for C++. You can use XML configuration.

Client Certificate Authentication

If SSL is enabled, you can grant permissions based on fields of the certificate provided by the clients. When a client connects to the cluster, its certificate is validated against a predefined list of predicates. Each predicate is associated with a list of permissions. If a predicate matches the client certificate, the client is granted the associated permissions. Predicates are defined in the form of regular expressions. If the client’s certificate does not match any predicate, the client is rejected.

For example, you can define a list of permissions that are granted only if the client’s certificate subject contains "O=CustomerOrganization".

Certificate-based authentication is provided by the CertificateAuthenticator class.

In the following example, we configure SSL in the cluster and enable certificate-based client authentication. Please refer to the Authorization and Permissions for the full list of supported permissions.

<!-- This predicate will check X.509 certificate Subject DN against regular expression: -->
<bean class="org.gridgain.grid.security.certificate.SubjectRegexPredicate" id="user.predicate">
    <constructor-arg value=".*\bCN=[a-zA-Z0-9]*\b.*"/>
</bean>

<!-- This predicate will check X.509 certificate Issuer DN against different regular expression: -->
<bean class="org.gridgain.grid.security.certificate.IssuerRegexPredicate" id="devOps.predicate">
    <constructor-arg value="^OU=devOps\b"/>
</bean>
<bean class="org.apache.ignite.configuration.IgniteConfiguration" >
    <property name="pluginConfigurations">
        <bean class="org.gridgain.grid.configuration.GridGainConfiguration">
            <property name="authenticator">
                <bean class="org.gridgain.grid.security.certificate.CertificateAuthenticator">
                    <property name="permissionsJson">
                        <map>
                             <entry key-ref="user.predicate" value="{defaultAllow:false, {cache:'*',permissions:['CACHE_READ']}}"/>
                             <entry key-ref="devOps.predicate" value="{defaultAllow:true}"/>
                        </map>
                    </property>
                </bean>
            </property>
        </bean>
    </property>

    <!-- General SSL cetificate for inter-node authentication. -->
    <property name="sslContextFactory">
        <bean class="org.apache.ignite.ssl.SslContextFactory">
            <property name="keyStoreFilePath" value="keystore/node.jks"/>
            <property name="keyStorePassword" value="123456"/>
            <property name="trustStoreFilePath" value="keystore/trust.jks"/>
            <property name="trustStorePassword" value="123456"/>
         </bean>
    </property>

    <!-- Secure and enable client certificate checking for JDBC/ODBC clients. -->
    <property name="clientConnectorConfiguration">
        <bean class="org.apache.ignite.configuration.ClientConnectorConfiguration">
            <property name="sslEnabled" value="true"/>
            <property name="sslClientAuth" value="true"/>
        </bean>
    </property>

    <!-- Secure and enable client certificate validation for control.(sh,bat). -->
    <property name="connectorConfiguration">
        <bean class="org.apache.ignite.configuration.ConnectorConfiguration">
            <property name="sslEnabled" value="true"/>
            <property name="sslClientAuth" value="true"/>

            <!-- Secure and enable client certificate validation for HTTPS REST. -->
            <property name="jettyPath" value="jetty-ssl-client-auth.xml"/>
        </bean>
    </property>
</bean>
// We will use certificate authentication.
CertificateAuthenticator authenticator = new CertificateAuthenticator();

// Create a map for the list of credentials and permissions.
Map<IgnitePredicate<Certificate[]>, SecurityPermissionSet> authMap = new HashMap<>();

SecurityBasicPermissionSet permissions = new SecurityBasicPermissionSet();
permissions.setDefaultAllowAll(false);
permissions.setCachePermissions(new HashMap<String, Collection<SecurityPermission>>() {
    {
        put("*", Arrays.asList(SecurityPermission.CACHE_READ));
    }
});

// This predicate will check X.509 certificate Subject DN against a regular expression:
authMap.put(new SubjectRegexPredicate(".*\\bCN=[a-zA-Z0-9]*\\b.*"), permissions);

// This predicate will check X.509 certificate Issuer DN against a different regular expression:
authMap.put(new IssuerRegexPredicate("^OU=devOps\\b"), new AllowAllPermissionSet());

authenticator.setPermissions(authMap);

// GridGain plugin configuration.
GridGainConfiguration ggCfg = new GridGainConfiguration();
ggCfg.setAuthenticator(authenticator);

IgniteConfiguration igniteCfg = new IgniteConfiguration();

igniteCfg.setPluginConfigurations(ggCfg);

// General SSL certificate for inter-node authentication.
SslContextFactory factory = new SslContextFactory();
factory.setKeyStoreFilePath("keystore/node.jks");
factory.setKeyStorePassword("123456".toCharArray());
factory.setTrustStoreFilePath("keystore/trust.jks");
factory.setTrustStorePassword("123456".toCharArray());
igniteCfg.setSslContextFactory(factory);

// Secure and enable client certificate validation for JDBC/ODBC and thin clients.
ClientConnectorConfiguration clientConnectorCfg = new ClientConnectorConfiguration();
clientConnectorCfg.setSslEnabled(true);
clientConnectorCfg.setSslClientAuth(true);
igniteCfg.setClientConnectorConfiguration(clientConnectorCfg);

// Secure control.(sh,bat) connection and enable client certificate validation.
ConnectorConfiguration connectorCfg = new ConnectorConfiguration();
connectorCfg.setSslEnabled(true);
connectorCfg.setSslClientAuth(true);

// Secure REST and enable client certificate validation.
//connectorCfg.setJettyPath("jetty-ssl-client-auth.xml");

igniteCfg.setConnectorConfiguration(connectorCfg);

Ignite ignite = Ignition.start(igniteCfg);
This API is not presently available for C#/.NET. You can use XML configuration.
This API is not presently available for C++. You can use XML configuration.
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
    <New id="httpsCfg" class="org.eclipse.jetty.server.HttpConfiguration">
        <Set name="secureScheme">https</Set>
        <Set name="securePort"><SystemProperty name="IGNITE_JETTY_PORT" default="8443"/></Set>
        <Call name="addCustomizer">
            <Arg><New class="org.eclipse.jetty.server.SecureRequestCustomizer"/></Arg>
        </Call>
    </New>

    <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory$Server">
        <Set name="keyStorePath"><SystemProperty
                name="IGNITE_HOME" default="${IGNITE_HOME}"/>keystore/node.jks</Set>
        <Set name="keyStorePassword">123456</Set>
        <Set name="keyManagerPassword">123456</Set>
        <Set name="trustStorePath"><SystemProperty
                name="IGNITE_HOME" default="${IGNITE_HOME}"/>keystore/trust-both.jks</Set>
        <Set name="trustStorePassword">123456</Set>
        <!-- This setting is necessary for client certificate authentication: -->
        <Set name="needClientAuth">true</Set>
    </New>

    <Call name="addConnector">
        <Arg>
            <New class="org.eclipse.jetty.server.ServerConnector">
                <Arg name="server">
                    <Ref refid="Server"/>
                </Arg>
                <Arg name="factories">
                    <Array type="org.eclipse.jetty.server.ConnectionFactory">
                        <Item>
                            <New class="org.eclipse.jetty.server.SslConnectionFactory">
                                <Arg><Ref refid="sslContextFactory"/></Arg>
                                <Arg>http/1.1</Arg>
                            </New>
                        </Item>
                        <!-- This section is necessary for client certificate authentication: -->
                        <Item>
                            <New class="org.eclipse.jetty.server.HttpConnectionFactory">
                                <Arg><Ref refid="httpsCfg"/></Arg>
                            </New>
                        </Item>
                    </Array>
                </Arg>
                <Set name="host"><SystemProperty name="IGNITE_JETTY_HOST" default="localhost"/></Set>
                <Set name="port"><SystemProperty name="IGNITE_JETTY_PORT" default="8443"/></Set>
            </New>
        </Arg>
    </Call>

    <Set name="handler">
        <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
            <Set name="handlers">
                <Array type="org.eclipse.jetty.server.Handler">
                    <Item>
                        <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
                    </Item>
                </Array>
            </Set>
        </New>
    </Set>
</Configure>

Client configuration only requires enabling SSL with an appropriate certificate:

JAAS Authentication

The JAAS authenticator uses Java Authentication and Authorization Service login modules for user authentication. The configuration of the login module is specified via the -Djava.security.auth.login.config=/my/path/jaas.config system property. Refer to the JAAS Reference Guide for details.

To enable JAAS authentication, use the following configuration example:

<bean class="org.apache.ignite.plugin.security.SecurityCredentials" id="server.cred">
    <constructor-arg value="server"/>
    <constructor-arg value="password"/>
</bean>
<bean class="org.apache.ignite.configuration.IgniteConfiguration" >
    <property name="pluginConfigurations">
        <bean class="org.gridgain.grid.configuration.GridGainConfiguration">
            <property name="authenticator">
                <bean class="org.gridgain.grid.security.jaas.JaasAuthenticator"/>
            </property>

            <!-- Credentials for the current node. -->
            <property name="securityCredentialsProvider">
                <bean class="org.apache.ignite.plugin.security.SecurityCredentialsBasicProvider">
                    <constructor-arg ref="server.cred"/>
                </bean>
            </property>
        </bean>
    </property>
</bean>
GridGainConfiguration ggCfg = new GridGainConfiguration();

ggCfg.setAuthenticator(new JaasAuthenticator());

//security credentials provider for the node.  "myUser" must be authenticated by whatever mechanism you use in the jaas configuration. Otherwise, the node will not start  
ggCfg.setSecurityCredentialsProvider(new SecurityCredentialsBasicProvider(new SecurityCredentials("myUser", "password")));

IgniteConfiguration igniteCfg = new IgniteConfiguration().setPluginConfigurations(ggCfg);

Ignite ignite = Ignition.start(igniteCfg);
This API is not presently available for .NET/C#. You can use XML configuration.
This API is not presently available for C++. You can use XML configuration.

securityCredentialsProvider is a server property that enables the authentication server to provide credentials to other servers.

You can use JAAS authenticator to configure LDAP and AD Authentication.

LDAP and AD Authentication

Permissions can be assigned from permission strings in LDAP or AD records, or by looking up a role defined in the server configuration. JAAS uses the authzIdentity configuration value as a query to look up the identity to assign an authenticated user. This identity may be interpreted as a role name or as a permission string. GridGain first searches the map in the JaasBasicPermissionsProvider constructor arguments for a key, and then assigns the permissions associated with that map key. If the role map lookup fails, GridGain defaults to using the authzIdentity result as a permission string for the authenticated user.

Permissions Granted Directly from LDAP or AD

To enable LDAP authentication, follow this procedure:

  1. Configure the JAAS authenticator as explained in JAAS Authentication section.

  2. Create a config file for the LdapLoginModule. Below is an example of such a file:

    jaas.config:
    GridJaasLoginContext {
        com.sun.security.auth.module.LdapLoginModule REQUIRED
        userProvider="ldap://serverName/ou=People,dc=nodomain"
        userFilter="uid={USERNAME}"
        authzIdentity="{<ATTR_NAME_OF_GRIDGAIN_PERMISSIONS>}"
        useSSL=false
        debug=false;
    };

    Here <ATTR_NAME_OF_GRIDGAIN_PERMISSIONS> is the attribute name of the user’s LDAP entry that contains GridGain permissions in a specific format. The following example defines a set of permissions for executing tasks and operations on caches. See Authorization and Permissions for the full list of available permissions.

    {
        {
            "cache":"partitioned",
            "permissions":["CACHE_PUT", "CACHE_REMOVE", "CACHE_READ"]
        },
        {
            "cache":"*",
            "permissions":["CACHE_READ"]
        },
        {
            "task":"org.mytasks.*",
            "permissions":["TASK_EXECUTE"]
        },
        "defaultAllow":"false"
    }
  3. Start all server nodes with the following system property:

    -Djava.security.auth.login.config=/my/path/jaas.config

When started with this configuration file, the node loads the list of users and permissions from the provided LDAP server.

Role-based Authentication with Active Directory

It is often required to authenticate GridGain users based on their AD role (i.e., the authentication/authorization group they belong to). Typical requirements for a GridGain cluster running within an Active Directory domain would be as follows:

  • Every node or client application has to authenticate itself with the domain providing correct credentials of one of the user accounts.

  • Access to the cluster has to be restricted based on groups; i.e., a user can be granted a certain set of permissions if and only if that user is a member of a specific group.

Active Directory Settings

  1. Define requirements and create Active Directory groups and users to be used for access control. For example:

    • Read-only users - can read from any cache in the cluster, but can’t do updates

    • Read-write users - can both read and update data in caches

    • GridGain Nebula users - don’t have direct access to the cluster, but can use GridGain Nebula (monitoring and management tool)

    • Superusers - have full access to all cluster functions.

  2. Assign users to the groups.

On the cluster side, you need to separately configure JAAS and GridGain. The JAAS part defines how you interact with Active Directory. The GridGain part provides the actual permissions for the different groups and ties everything together.

Cluster Configuration - JAAS

GridGain assumes that every user has a special attribute in LDAP to store GridGain permissions as a JSON string (name of the attribute is provided to JAAS via the authzIdentity parameter). This does not work with the typical Active Directory structure. You want to assign permissions based on groups and roles rather than store them directly in LDAP.

Specify the userFilter parameter to search for teh user entry that is included in a particular group. Filter conditions like memberOf=GROUP_NAME mimic the "contains" operation and return true if one of the items in the memberOf collection equals the provided name.

Apply the above approach to every group one-by-one. In JAAS terms, you create multiple login modules, one for each group. Here is the full configuration:

GridJaasLoginContext {
    com.sun.security.auth.module.LdapLoginModule SUFFICIENT
    userProvider="ldap://18.218.245.71:389/CN=Users,DC=gridfoo,DC=com"
    authIdentity="{USERNAME}@gridfoo.com"
    userFilter="(&(sAMAccountName={USERNAME})(memberOf=CN=GG_CacheReadOnlyUsers,CN=Users,DC=gridfoo,DC=com))"
    authzIdentity="GG_CacheReadOnlyUsers";

    com.sun.security.auth.module.LdapLoginModule SUFFICIENT
    userProvider="ldap://18.218.245.71:389/CN=Users,DC=gridfoo,DC=com"
    authIdentity="{USERNAME}@gridfoo.com"
    userFilter="(&(sAMAccountName={USERNAME})(memberOf=CN=GG_CacheReadWriteUsers,CN=Users,DC=gridfoo,DC=com))"
    authzIdentity="GG_CacheReadWriteUsers";

    com.sun.security.auth.module.LdapLoginModule SUFFICIENT
    userProvider="ldap://18.218.245.71:389/CN=Users,DC=gridfoo,DC=com"
    authIdentity="{USERNAME}@gridfoo.com"
    userFilter="(&(sAMAccountName={USERNAME})(memberOf=CN=GG_NebulaUsers,CN=Users,DC=gridfoo,DC=com))"
    authzIdentity="GG_NebulaUsers";

    com.sun.security.auth.module.LdapLoginModule SUFFICIENT
    userProvider="ldap://18.218.245.71:389/CN=Users,DC=gridfoo,DC=com"
    authIdentity="{USERNAME}@gridfoo.com"
    userFilter="(&(sAMAccountName={USERNAME})(memberOf=CN=GG_SuperUsers,CN=Users,DC=gridfoo,DC=com))"
    authzIdentity="GG_SuperUsers";
};

The above defines four LDAP login modules, each marked as SUFFICIENT. This means that if at least one module is successful, the user is authenticated. Two common parameters are self-explanatory — userProvider and authIdentity. The userFilter and authzIdentity parameters are unique for every module, and are used to identify which group the user is part of (if any).

For every module, JAAS will go through the following process:

  1. Connect to the LDAP server and authenticate with the provided username and password.

  2. Use the userFilter search string to look for the user entry based on the username and the group name the current module is responsible for.

  3. If the above user entry exists (i.e., the user is included in the group), create a principal with the name provided in the authzIdentity parameter, and stop the process with success.

  4. If the above user entry can’t be found, move on to the next module (or fail if there are no modules left).

As a result, a successfully authenticated user is created with a principal holding the group name. This name is then passed to GridGain’s permissions provider.

Cluster Configuration - GridGain

In the GridGain configuration, enable JaasAuthenticator and use the permission provider to specify the mapping between the possible group names and the corresponding permissions. For the latter, use JaasBasicPermissionsProvider, which GridGain includes out-of-the-box.

For the four groups created earlier, the XML configuration looks like this:

<bean class="org.gridgain.grid.security.jaas.JaasAuthenticator">
    <property name="permissionsProvider">
        <bean class="org.gridgain.grid.security.jaas.JaasBasicPermissionsProvider">
            <constructor-arg>
                <map>
                    <entry key="GG_CacheReadOnlyUsers">
                        <bean class="org.apache.ignite.plugin.security.SecurityBasicPermissionSet">
                            <property name="defaultAllowAll" value="false"/>
                            <property name="cachePermissions">
                                <map>
                                    <entry key="*">
                                        <list>
                                            <value>CACHE_READ</value>
                                        </list>
                                    </entry>
                                </map>
                            </property>
                        </bean>
                    </entry>

                    <entry key="GG_CacheReadWriteUsers">
                        <bean class="org.apache.ignite.plugin.security.SecurityBasicPermissionSet">
                            <property name="defaultAllowAll" value="false"/>
                            <property name="cachePermissions">
                                <map>
                                    <entry key="*">
                                        <list>
                                            <value>CACHE_READ</value>
                                            <value>CACHE_PUT</value>
                                            <value>CACHE_REMOVE</value>
                                        </list>
                                    </entry>
                                </map>
                            </property>
                        </bean>
                    </entry>

                    <entry key="GG_NebulaUsers">
                        <bean class="org.apache.ignite.plugin.security.SecurityBasicPermissionSet">
                            <property name="defaultAllowAll" value="false"/>
                            <property name="cachePermissions">
                                <map>
                                    <entry key="*">
                                        <list>
                                            <value>ADMIN_VIEW</value>
                                            <value>ADMIN_CACHE</value>
                                            <value>ADMIN_QUERY</value>
                                            <value>ADMIN_OPS</value>
                                        </list>
                                    </entry>
                                </map>
                            </property>
                        </bean>
                    </entry>

                    <entry key="GG_SuperUsers">
                        <bean class="org.apache.ignite.plugin.security.SecurityBasicPermissionSet">
                            <property name="defaultAllowAll" value="true"/>
                        </bean>
                    </entry>
                </map>
            </constructor-arg>
        </bean>
    </property>
</bean>

In the above configuration, you set permissions for every group. For example, users included in GG_CacheReadOnlyUsers will have access to all caches, but will only be able to read the data.

Example

A basic example that demonstrates role/group-based authentication for AD users.

GridGain server node configuration (server.xml):

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
        <property name="cacheConfiguration">
            <bean class="org.apache.ignite.configuration.CacheConfiguration">
                <property name="name" value="TestCache"/>
            </bean>
        </property>

        <property name="pluginConfigurations">
            <bean class="org.gridgain.grid.configuration.GridGainConfiguration">
                <property name="authenticator">
                    <bean class="org.gridgain.grid.security.jaas.JaasAuthenticator">
                        <property name="permissionsProvider">
                            <bean class="org.gridgain.grid.security.jaas.JaasBasicPermissionsProvider">
                                <constructor-arg>
                                    <map>
                                        <entry key="GG_CacheReadOnlyUsers">
                                            <bean class="org.apache.ignite.plugin.security.SecurityBasicPermissionSet">
                                                <property name="defaultAllowAll" value="false"/>
                                                <property name="cachePermissions">
                                                    <map>
                                                        <entry key="*">
                                                            <list>
                                                                <value>CACHE_READ</value>
                                                            </list>
                                                        </entry>
                                                    </map>
                                                </property>
                                            </bean>
                                        </entry>

                                        <entry key="GG_CacheReadWriteUsers">
                                            <bean class="org.apache.ignite.plugin.security.SecurityBasicPermissionSet">
                                                <property name="defaultAllowAll" value="false"/>
                                                <property name="cachePermissions">
                                                    <map>
                                                        <entry key="*">
                                                            <list>
                                                                <value>CACHE_READ</value>
                                                                <value>CACHE_PUT</value>
                                                                <value>CACHE_REMOVE</value>
                                                            </list>
                                                        </entry>
                                                    </map>
                                                </property>
                                            </bean>
                                        </entry>

                                        <entry key="GG_NebulaUsers">
                                            <bean class="org.apache.ignite.plugin.security.SecurityBasicPermissionSet">
                                                <property name="defaultAllowAll" value="false"/>
                                                <property name="cachePermissions">
                                                    <map>
                                                        <entry key="*">
                                                            <list>
                                                                <value>ADMIN_VIEW</value>
                                                                <value>ADMIN_CACHE</value>
                                                                <value>ADMIN_QUERY</value>
                                                                <value>ADMIN_OPS</value>
                                                            </list>
                                                        </entry>
                                                    </map>
                                                </property>
                                            </bean>
                                        </entry>

                                        <entry key="GG_SuperUsers">
                                            <bean class="org.apache.ignite.plugin.security.SecurityBasicPermissionSet">
                                                <property name="defaultAllowAll" value="true"/>
                                            </bean>
                                        </entry>
                                    </map>
                                </constructor-arg>
                            </bean>
                        </property>
                    </bean>
                </property>

                <property name="securityCredentialsProvider">
                    <bean class="org.apache.ignite.plugin.security.SecurityCredentialsBasicProvider">
                        <constructor-arg>
                            <bean class="org.apache.ignite.plugin.security.SecurityCredentials">
                                <property name="login" value="GG_ServerAccount"/>
                                <property name="password" value="VeryStrongPassword123"/>
                            </bean>
                        </constructor-arg>
                    </bean>
                </property>
            </bean>
        </property>

        <property name="discoverySpi">
            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
                <property name="ipFinder">
                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
                        <property name="addresses">
                            <list>
                                <value>127.0.0.1:47500..47509</value>
                            </list>
                        </property>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
</beans>

GridGain client node configuration (client.xml):

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
        <property name="clientMode" value="true"/>

        <property name="pluginConfigurations">
            <bean class="org.gridgain.grid.configuration.GridGainConfiguration">
                <property name="securityCredentialsProvider">
                    <bean class="org.apache.ignite.plugin.security.SecurityCredentialsBasicProvider">
                        <constructor-arg>
                            <bean class="org.apache.ignite.plugin.security.SecurityCredentials">
                                <property name="login" value="user1"/>
                                <property name="password" value="p@ssw0rd"/>
                            </bean>
                        </constructor-arg>
                    </bean>
                </property>
            </bean>
        </property>

        <property name="discoverySpi">
            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
                <property name="ipFinder">
                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
                        <property name="addresses">
                            <list>
                                <value>127.0.0.1:47500..47509</value>
                            </list>
                        </property>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>
</beans>

JAAS configuration (jaas.config):

GridJaasLoginContext {
    com.sun.security.auth.module.LdapLoginModule SUFFICIENT
    userProvider="ldap://3.15.156.212:389/CN=Users,DC=gridfoo,DC=com"
    authIdentity="{USERNAME}@gridfoo.com"
    userFilter="(&(sAMAccountName={USERNAME})(memberOf=CN=GG_CacheReadOnlyUsers,CN=Users,DC=gridfoo,DC=com))"
    authzIdentity="GG_CacheReadOnlyUsers"
    useSSL=false
    debug=false;

    com.sun.security.auth.module.LdapLoginModule SUFFICIENT
    userProvider="ldap://3.15.156.212:389/CN=Users,DC=gridfoo,DC=com"
    authIdentity="{USERNAME}@gridfoo.com"
    userFilter="(&(sAMAccountName={USERNAME})(memberOf=CN=GG_CacheReadWriteUsers,CN=Users,DC=gridfoo,DC=com))"
    authzIdentity="GG_CacheReadWriteUsers"
    useSSL=false
    debug=false;

    com.sun.security.auth.module.LdapLoginModule SUFFICIENT
    userProvider="ldap://3.15.156.212:389/CN=Users,DC=gridfoo,DC=com"
    authIdentity="{USERNAME}@gridfoo.com"
    userFilter="(&(sAMAccountName={USERNAME})(memberOf=CN=GG_NebulaUsers,CN=Users,DC=gridfoo,DC=com))"
    authzIdentity="GG_NebulaUsers"
    useSSL=false
    debug=false;

    com.sun.security.auth.module.LdapLoginModule SUFFICIENT
    userProvider="ldap://3.15.156.212:389/CN=Users,DC=gridfoo,DC=com"
    authIdentity="{USERNAME}@gridfoo.com"
    userFilter="(&(sAMAccountName={USERNAME})(memberOf=CN=GG_SuperUsers,CN=Users,DC=gridfoo,DC=com))"
    authzIdentity="GG_SuperUsers"
    useSSL=false
    debug=false;
};

The server application (Server.java):

import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
import org.apache.ignite.events.EventType;
import org.apache.ignite.plugin.security.SecuritySubject;
import org.gridgain.grid.GridGain;

public class Server {
    public static void main(String[] args) {
        Ignite ignite = Ignition.start("server.xml");

        ignite.events().localListen(event -> {
            System.out.println("Authenticated subjects:");

            GridGain gg = ignite.plugin(GridGain.PLUGIN_NAME);

            for (SecuritySubject subject : gg.security().authenticatedSubjects())
                System.out.println("    " + subject.login() + ": " + subject.permissions());

            return true;
        },
        EventType.EVT_NODE_JOINED);

        IgniteCache<Integer, Integer> cache = ignite.cache("TestCache");

        for (int i = 0; i < 10; i++)
            cache.put(i, i);
    }
}

The above application uses a special user account called GG_ServerAccount, which is a member of the GG_SuperUsers group. This means that it has full access to all APIs and cluster functions. This is a general practice: although server nodes have to authenticate in the same way as clients, there is typically no need to put restrictions on them.

The client application (Client.java):

import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;

public class Client {
    public static void main(String[] args) {
        try (Ignite ignite = Ignition.start("client.xml")) {
            IgniteCache<Integer, Integer> cache = ignite.cache("TestCache");

            System.out.println("Cache value for key 5: " + cache.get(5));

            cache.put(5, 100);
        }
    }
}

The above application authenticates with the read-only account, which is created at the very beginning. Therefore, this application is only able to read the data, but not update it. Indeed, when trying to execute a cache PUT operation, it fails with an authorization error:

org.apache.ignite.plugin.security.SecurityException: Authorization failed [perm=CACHE_PUT, name=TestCache, subject=SecuritySubjectAdapter [id=60c0c45e-69a1-498f-aa9d-5aeb1c78125d, subjType=REMOTE_NODE, addr=/0:0:0:0:0:0:0:1:0, permissions=SecurityBasicPermissionSet [cachePermissions=LinkedHashMap {*=ArrayList [CACHE_READ]}, taskPermissions=HashMap {}, servicePermissions=HashMap {}, systemPermissions=null, dfltAllowAll=false], login=user1]]

In addition, the server is configured to print out a list of currently authenticated users every time a new node joins the topology. This way, you can confirm that everything is configured correctly. Here is the output after both server and client nodes are up:

Authenticated subjects:
    GG_ServerAccount: SecurityBasicPermissionSet [cachePermissions=HashMap {}, taskPermissions=HashMap {}, servicePermissions=HashMap {}, systemPermissions=null, dfltAllowAll=true]
    user1: SecurityBasicPermissionSet [cachePermissions=LinkedHashMap {*=ArrayList [CACHE_READ]}, taskPermissions=HashMap {}, servicePermissions=HashMap {}, systemPermissions=null, dfltAllowAll=false]

The example above results in a user running under the server account with all the possible permissions — that is the server node. The second user is the client, which has the CACHE_READ permission only.

Supplying Credentials in Clients

When authentication is configured in the cluster, all client applications must provide user credentials. Refer to the following pages for the information about specific clients: