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.

Native Client Security

Hazelcast’s Client security includes both authentication and authorization.

Authentication

The authentication mechanism works in similar way as the cluster member authentication.

To implement the client authentication, you reference a Security Realm with the authentication section defined in the <client-authentication/> element of a cluster member configuration.

The authentication configuration defines a method used to verify the client’s identity and assign its roles.

  • XML

  • YAML

<hazelcast>
    ...
    <security enabled="true">
      <realms>
          <realm name="clientRealm">
              <authentication>
                <ldap>
                    <url>ldap://corp-ldap.example.com/</url>
                    <role-mapping-attribute>cn</role-mapping-attribute>
                </ldap>
              </authentication>
          </realm>
      </realms>
      <client-authentication realm="clientRealm"/>
    </security>
    ...
</hazelcast>
xml
hazelcast:
  security:
    enabled: true
    realms:
      name: clientRealm
      authentication:
        ldap:
          url: ldap://corp-ldap.example.com/
          role-mapping-attribute: cn
    client-authentication:
      realm: clientRealm
yaml

The identity of the connecting client is defined on the client side. Usually, there are no security realms on the clients, but just identity defined directly in the security configuration:

  • XML

  • YAML

<hazelcast-client>
    ...
    <security>
      <username-password username="uid=member1,dc=example,dc=com" password="s3crEt"/>
    </security>
    ...
</hazelcast-client>
xml
hazelcast-client:
  security:
    username-password:
      username: uid=member1,dc=example,dc=com
      password: s3crEt
yaml

On the clients, you can use the same identity types as in security realms:

  • username-password

  • token

  • kerberos (may require an additional security realm definition)

  • credentials-factory

Authorization

Hazelcast client authorization is configured by a client permission policy. Hazelcast has a default permission policy implementation that uses permission configurations defined in the Hazelcast security configuration. Default policy permission checks are done against instance types (map, queue, etc.), instance names (map, queue, name, etc.), instance actions (put, read, remove, add, etc.), the client endpoint address (ClusterEndpointPrincipal) and client roles (ClusterRolePrincipal).

The default permission policy allows to use comma separated names in the principal attribute configuration.

You can define the instance and principal names as wildcards using the "*" character. See the Using Wildcards section for details.

The endpoint names can use range characters "-" and "*" as described in the Interfaces section.

  • XML

  • YAML

<hazelcast>
    ...
    <security enabled="true">
        <client-permissions>
            <!-- Principals 'admin' and 'root' from endpoint '127.0.0.1' have all permissions. -->
            <all-permissions principal="admin,root">
                <endpoints>
                    <endpoint>127.0.0.1</endpoint>
                </endpoints>
            </all-permissions>

            <!-- Principals named 'dev' from all endpoints have 'create', 'destroy',
            'put', 'read' permissions for map named 'myMap'. -->
            <map-permission name="myMap" principal="dev">
                <actions>
                    <action>create</action>
                    <action>destroy</action>
                    <action>put</action>
                    <action>read</action>
                </actions>
            </map-permission>

            <!-- All principals from endpoints '127.0.0.1' or matching to '10.10.*.*'
            have 'put', 'read', 'remove' permissions for map
            whose name matches to 'com.foo.entity.*'. -->
            <map-permission name="com.foo.entity.*">
                <endpoints>
                    <endpoint>10.10.*.*</endpoint>
                    <endpoint>127.0.0.1</endpoint>
                </endpoints>
                <actions>
                    <action>put</action>
                    <action>read</action>
                    <action>remove</action>
                </actions>
            </map-permission>

            <!-- Principals named 'dev' from endpoints matching to either
            '192.168.1.1-100' or '192.168.2.*'
            have 'create', 'add', 'remove' permissions for all queues. -->
            <queue-permission name="*" principal="dev">
                <endpoints>
                    <endpoint>192.168.1.1-100</endpoint>
                    <endpoint>192.168.2.*</endpoint>
                </endpoints>
                <actions>
                    <action>create</action>
                    <action>add</action>
                    <action>remove</action>
                </actions>
            </queue-permission>

           <!-- All principals from all endpoints have transaction permission.-->
           <transaction-permission />
       </client-permissions>
    </security>
    ...
</hazelcast>
xml
hazelcast:
  security:
    enabled: true
    client-permissions:
      on-join-operation: RECEIVE
      all:
        principal: admin,root
        endpoints:
          - 127.0.0.1
      map:
        - name: myMap
          principal: dev
          endpoints:
            - 127.0.0.1
          actions:
            - create
            - destroy
            - put
            - read
      map:
        - name: com.foo.entity
          principal: dev
          endpoints:
            - 10.10.*.*
            - 127.0.0.1
          actions:
            - put
            - read
            - remove
      queue:
        - name: "*"
          principal: dev
          endpoints:
            - 192.168.1.1-100
            - 192.168.2.*
          actions:
            - create
            - add
            - remove
      transaction:
yaml

You can also define your own policy by implementing com.hazelcast.security.IPermissionPolicy.

package com.hazelcast.security;
/**
 * IPermissionPolicy is used to determine any Subject's
 * permissions to perform a security sensitive Hazelcast operation.
 *
 */
public interface IPermissionPolicy {
  void configure( SecurityConfig securityConfig, Properties properties );

  PermissionCollection getPermissions( Subject subject,
                                       Class<? extends Permission> type );

  void destroy();
}
java

Permission policy implementations can access client-permissions that are in the configuration by using SecurityConfig.getClientPermissionConfigs() when Hazelcast calls the configure(SecurityConfig securityConfig, Properties properties) method.

The IPermissionPolicy.getPermissions(Subject subject, Class<? extends Permission> type) method is used to determine a client request that has been granted permission to perform a security-sensitive operation.

Permission policy should return a PermissionCollection containing permissions of the given type for the given Subject. The Hazelcast access controller calls PermissionCollection.implies(Permission) on returning PermissionCollection and it decides whether the current Subject has permission to access the requested resources.

Permissions

The following is the list of client permissions that can be configured on the member:

All Permission:

  • XML

  • YAML

<all-permissions principal="principal">
    <endpoints>
        ...
    </endpoints>
</all-permissions>
xml
all:
  principal: principal
  endpoints:
    - ..
yaml

Map Permission:

Actions: all, create, destroy, put, read, remove, lock, intercept, index, listen

  • XML

  • YAML

<map-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</map-permission>
xml
map:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

Queue Permission:

Actions: all, create, destroy, add, remove, read, listen

  • XML

  • YAML

<queue-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</queue-permission>
xml
queue:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

Multimap Permission:

Actions: all, create, destroy, put, read, remove, listen, lock

  • XML

  • YAML

<multimap-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
     </actions>
</multimap-permission>
xml
multimap:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

Replicated Map Permission:

Actions: all, create, destroy, put, read, remove, listen, lock, index, intercept

  • XML

  • YAML

<replicatedmap-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
     </actions>
</replicatedmap-permission>
xml
replicatedmap:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

Topic Permission:

Actions: create, destroy, publish, listen

  • XML

  • YAML

<topic-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</topic-permission>
xml
topic:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

List Permission:

Actions: all, create, destroy, add, read, remove, listen

  • XML

  • YAML

<list-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</list-permission>
xml
list:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

Set Permission:

Actions: all, create, destroy, add, read, remove, listen

  • XML

  • YAML

<set-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</set-permission>
xml
set:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

Lock Permission:

Actions: all, create, destroy, lock, read

  • XML

  • YAML

<lock-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</lock-permission>
xml
lock:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

AtomicLong Permission:

Actions: all, create, destroy, read, modify

  • XML

  • YAML

<atomic-long-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</atomic-long-permission>
xml
atomic-long:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

CountDownLatch Permission:

Actions: all, create, destroy, read, modify

  • XML

  • YAML

<countdown-latch-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</countdown-latch-permission>
xml
countdown-latch:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

FlakeIdGenerator Permission:

Actions: all, create, destroy, read, modify

  • XML

  • YAML

<flake-id-generator-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</flake-id-generator-permission>
xml
flake-id-generator:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

Semaphore Permission:

Actions: all, create, destroy, acquire, release, read

  • XML

  • YAML

<semaphore-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</semaphore-permission>
xml
semaphore:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

Executor Service Permission:

Actions: all, create, destroy

  • XML

  • YAML

<executor-service-permission name="name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</executor-service-permission>
xml
executor-service:
  - name: name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml

Transaction Permission:

  • XML

  • YAML

<transaction-permission principal="principal">
    <endpoints>
        ...
    </endpoints>
</transaction-permission>
xml
transaction:
  principal: principal
  endpoints:
    - ..
yaml

Cache Permission:

Actions: all, create, destroy, put, read, remove, listen

  • XML

  • YAML

<cache-permission name="/hz/cache-name" principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</cache-permission>
xml
cache:
  - name: /hz/cache-name
    principal: principal
    endpoints:
      - ..
    actions:
      - ..
yaml
Note The name provided in cache-permission must be the Hazelcast distributed object name corresponding to the Cache as described in the JCache - Hazelcast Instance Integration section.

User Code Deployment Permission:

Actions: all, deploy

  • XML

  • YAML

<user-code-deployment-permission principal="principal">
    <endpoints>
        ...
    </endpoints>
    <actions>
        ...
    </actions>
</user-code-deployment-permission>
xml
user-code-deployment:
  principal: principal
  endpoints:
    - ..
  actions:
    - ..
yaml

Configuration Permission:

This permission defines which client principals/endpoints are allowed to perform dynamic configuration changes, i.e., adding data structure configurations at runtime.

  • XML

  • YAML

<config-permission principal="principal">
    <endpoints>
        <endpoint>...</endpoint>
    </endpoints>
</config-permission>
xml
config:
  principal: principal
  endpoints:
    - ..
yaml

Handling Permissions When a New Member Joins

By default, the set of permissions defined in the leader member of a cluster is distributed to the newly joining members, overriding their own permission configurations, if any. However, you can configure a new member to be joined, so that it keeps its own set of permissions and even send these to the existing members in the cluster. This can be done dynamically, i.e., without needing to restart the cluster, using either one of the following configuration options:

  • the on-join-operation configuration attribute

  • the setOnJoinPermissionOperation() method

Using the above, you can choose whether a new member joining to a cluster will apply the client permissions stored in its own configuration, or use the ones defined in the cluster. The behaviors that you can specify with the configuration are RECEIVE, SEND and NONE, which are described after the examples below.

The following are the examples for both approaches on how to use them:

Declarative Configuration:

  • XML

  • YAML

<hazelcast>
    ...
    <security enabled="true">
        <client-permissions on-join-operation="SEND">
            <!-- ... -->
        </client-permissions>
    </security>
    ...
</hazelcast>
xml
hazelcast:
  security:
    enabled: true
    client-permissions:
      on-join-operation: SEND
yaml

Programmatic Configuration:

Config config = new Config();
config.getSecurityConfig()
    .setEnabled(true)
    .setOnJoinPermissionOperation(OnJoinPermissionOperationName.SEND);
java

The behaviors are explained below:

  • RECEIVE: Applies the permissions from the leader member in the cluster before join. This is the default value.

  • SEND: Doesn’t apply the permissions from the leader member before join. If the security is enabled, then it refreshes or replaces the cluster wide permissions with the ones in the new member after the join is complete. This option is suitable for the scenarios where you need to replace the cluster wide permissions without restarting the cluster.

  • NONE: Neither applies pre-join permissions, nor sends the local permissions to the other members. It means that the new member does not send its own permission definitions to the cluster, but keeps them when it joins. However, after the join, when you update the permissions in the other cluster members, those updates are also sent to the newly joining member. Therefore, this option is suitable for the scenarios where you need to elevate privileges temporarily on a single member (preferably a lite member) for a limited time period. The clients which want to use these temporary permissions have to access the cluster through this single new member, meaning that you need to disable smart routing for such clients.

    Note that, the create and destroy permissions will not work when using the NONE option, since the distributed objects need to be created/destroyed on all the members.

    The following is an example for a scenario where NONE is used:

    // temporary member, in the below case a lite member
    Config config = new Config().setLiteMember(true);
    PermissionConfig allPermission = new PermissionConfig(PermissionType.ALL, "*", null);
    config.getSecurityConfig()
      .setEnabled(true)
      .setOnJoinPermissionOperation(OnJoinPermissionOperationName.NONE)
      .addClientPermissionConfig(allPermission);
    HazelcastInstance hzLite = Hazelcast.newHazelcastInstance(config);
    
    // temporary client connecting only to the lite member
    String memberAddr = ...;
    ClientConfig clientConfig = new ClientConfig();
    clientConfig.getNetworkConfig().setSmartRouting(false)
      .addAddress(memberAddr);
    HazelcastInstance client = HazelcastClient.newHazelcastClient(clientConfig);
    
    // do operations with escalated privileges:
    client.getMap("protectedConfig").put("master.resolution", "1920");
    
    // shutdown the client and lite member
    client.shutdown();
    hzLite.shutdown();
    java