Client Security
To protect your members from a malicious client, you can allow them to identify clients and restrict their permissions to access either data in data structures or features such as user code deployment.
To allow members to identify clients, set up client authentication.
To allow members to restrict client permissions, set up client authorization.
Authenticating Clients
To implement the client authentication, reference a Security Realm with the authentication section defined in the client-authentication setting of a cluster member's 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>
hazelcast:
security:
enabled: true
realms:
name: clientRealm
authentication:
ldap:
url: ldap://corp-ldap.example.com/
role-mapping-attribute: cn
client-authentication:
realm: clientRealm
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>
hazelcast-client:
security:
username-password:
username: uid=member1,dc=example,dc=com
password: s3crEt
On the clients, you can use the same identity types as in security realms:
username-passwordtokenkerberos(may require an additional security realm definition)credentials-factory
Authorizing Clients
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, 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.
Unless part of the role name, do not include spaces when adding names to the principal attribute.
Hazelcast does not automatically remove spaces in role names. If you include spaces that are not part of the name, permission is not granted to the intended role.
For example, if you configure permissions for the admin and devel roles using principal=" admin ,devel", the admin role is not granted the permission.
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 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>
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:
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();
}
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
This permission grants clients access to all data and features.
- XML
- YAML
<all-permissions principal="principal">
<endpoints>
...
</endpoints>
</all-permissions>
all:
principal: principal
endpoints:
- ..
Management Permission
This permission defines which client principals/endpoints are allowed to perform management tasks. Here, the client we mention is the one that is used by Hazelcast Management Center when it connects to the clusters. To learn more about this client, see Cluster Connections.
- XML
- YAML
<management-permission principal="mcadmin">
<endpoints>
...
</endpoints>
</management-permission>
management:
- principal: mcadmin
endpoints:
- ..
Map Permission
Actions: all, create, destroy, index, intercept, listen, lock, put, read, remove
- XML
- YAML
<map-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</map-permission>
map:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Queue Permission
Actions: add, all, create, destroy, listen, read, remove
- XML
- YAML
<queue-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</queue-permission>
queue:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Multimap Permission
Actions: all, create, destroy, listen, lock, put, read, remove
- XML
- YAML
<multimap-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</multimap-permission>
multimap:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Replicated Map Permission
Actions: all, create, destroy, index, intercept, listen, lock, put, read, remove
- XML
- YAML
<replicatedmap-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</replicatedmap-permission>
replicatedmap:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Topic Permission
Actions: create, destroy, listen, publish
- XML
- YAML
<topic-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</topic-permission>
topic:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Reliable Topic Permission
Actions: create, destroy, listen, publish
- XML
- YAML
<reliable-topic-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</reliable-topic-permission>
reliable-topic:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
List Permission
Actions: add, all, create, destroy, listen, read, remove
- XML
- YAML
<list-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</list-permission>
list:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Set Permission
Actions: add, all, create, destroy, listen, read, remove
- XML
- YAML
<set-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</set-permission>
set:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Ringbuffer Permission
Actions: add, put, read, create, destroy
- XML
- YAML
<ring-buffer-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</ring-buffer-permission>
ring-buffer:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Lock Permission
Actions: all, create, destroy, lock, read
- XML
- YAML
<lock-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</lock-permission>
lock:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
AtomicLong Permission
Actions: all, create, destroy, modify, read
- XML
- YAML
<atomic-long-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</atomic-long-permission>
atomic-long:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
AtomicReference Permission
Actions: all, create, destroy, modify, read
- XML
- YAML
<atomic-reference-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</atomic-reference-permission>
atomic-reference:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
CountDownLatch Permission
Actions: all, create, destroy, modify, read
- XML
- YAML
<countdown-latch-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</countdown-latch-permission>
countdown-latch:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
FlakeIdGenerator Permission
Actions: all, create, destroy, modify, read
- XML
- YAML
<flake-id-generator-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</flake-id-generator-permission>
flake-id-generator:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Semaphore Permission
Actions: all, acquire, create, destroy, read, release
- XML
- YAML
<semaphore-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</semaphore-permission>
semaphore:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Executor Service Permission
Actions: all, create, destroy
- XML
- YAML
<executor-service-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</executor-service-permission>
executor-service:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Durable Executor Service Permission
Actions: all, create, destroy
- XML
- YAML
<durable-executor-service-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</durable-executor-service-permission>
durable-executor-service:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Scheduled Executor Service Permission
Actions: all, create, destroy, read, modify
- XML
- YAML
<scheduled-executor-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</scheduled-executor-permission>
scheduled-executor:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Cardinality Estimator Permission
Actions: all, create, destroy, read, modify
- XML
- YAML
<cardinality-estimator-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</cardinality-estimator-permission>
cardinality-estimator:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
PN Counter Permission
Actions: all, create, destroy, read, modify
- XML
- YAML
<pn-counter-permission name="name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</pn-counter-permission>
pn-counter:
- name: name
principal: principal
endpoints:
- ..
actions:
- ..
Transaction Permission
- XML
- YAML
<transaction-permission principal="principal">
<endpoints>
...
</endpoints>
</transaction-permission>
transaction:
principal: principal
endpoints:
- ..
Cache Permission
Actions: all, create, destroy, listen, put, read, remove
- XML
- YAML
<cache-permission name="/hz/cache-name" principal="principal">
<endpoints>
...
</endpoints>
<actions>
...
</actions>
</cache-permission>
cache:
- name: /hz/cache-name
principal: principal
endpoints:
- ..
actions:
- ..
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>
user-code-deployment:
principal: principal
endpoints:
- ..
actions:
- ..
Configuration Permission
This permission defines which client principals/endpoints are allowed to add data structure configurations at runtime.
- XML
- YAML
<config-permission principal="principal">
<endpoints>
<endpoint>...</endpoint>
</endpoints>
</config-permission>
config:
principal: principal
endpoints:
- ..
Job Permission
Actions:
-
submit: Submit a new job, without uploading resources. -
cancel: Cancel a running job. -
read: Get or list information about a job (by ID or name) such as job configuration, job status, and submission time.warningWhen you query a streaming source with SQL, Hazelcast runs that query as a job. As a result, clients with the
readpermission for jobs can see the SQL query and any parameters. -
restart: Suspend and resume a running job. -
export-snapshot: Export or read snapshots. -
add-resources: Upload resources and classes as well as jobs to members.warningHazelcast cannot check permissions in code that's uploaded with a job, If you enable this permission, clients can upload custom code that ignores any configured permissions.
-
all: Enable all actions.
All actions for job permissions also enable the read action. For example if you enable the create action, the read action is automatically enabled as well.
- XML
- YAML
<job-permission principal="principal">
<actions>
<action>...</action>
</actions>
</job-permission>
job:
- principal: "principal"
actions:
- ..
Connector Permission
You can give permissions to the following connectors:
- File
- Socket
Actions:
read: Read data from sources.write: Write data to sinks.all: Enable all actions.
- XML
- YAML
<!-- It is currently only possible to give access to a whole directory, not to a single file. -->
<connector-permission name="file:directory_name">
<actions>
<action>...</action>
</actions>
</connector-permission>
<connector-permission name="socket:host:port">
<actions>
<action>...</action>
</actions>
</connector-permission>
connector:
- name: "file:directory_name"
actions:
- ..
connector:
- name: "socket:host:port"
actions:
- ..
To protect external systems from being reached by external connectors (JDBC, Mongo, S3, …), use other means than Hazelcast client permissions. Traditionally, this is done by enabling authentication on the external system and/or setting up firewall rules.
SQL Permission
You can give clients permission to use the following SQL statements:
CREATE MAPPINGDROP MAPPINGCREATE INDEXCREATE VIEWDROP VIEWCREATE DATA CONNECTIONDROP DATA CONNECTIONSHOW RESOURCES
Actions:
create: Use theCREATE MAPPINGstatement to create new mappings or replace existing ones.destroy: Use theDROP MAPPINGstatement to delete mappings.create-index: Use theCREATE INDEXstatement to create a new index for a map.create-view: Use theCREATE VIEWstatement to create new views or replace existing ones.drop-view: Use theDROP VIEWstatement to delete an existing view.create-dataconnection: Use theCREATE DATA CONNECTIONstatement to create new data connections or replace existing ones.drop-dataconnection: Use theDROP DATA CONNECTIONstatement to delete data connections.view-dataconnection: Use theSHOW RESOURCESstatement to view the resources and data types accessible via data connections.all: Enable all actions.
To apply permissions to certain mappings or data connections, provide their names in the name attribute. Or, you can apply permissions to all mappings and data connections using the * wildcard.
- XML
- YAML
<sql-permission name="mapping_name">
<actions>
<action>create</action>
<action>destroy</action>
</actions>
</sql-permission>
<sql-permission name="*">
<actions>
<action>create</action>
<action>destroy</action>
</actions>
</sql-permission>
<sql-permission name="data_connection_name">
<actions>
<action>drop-dataconnection</action>
<action>view-dataconnection</action>
</actions>
</sql-permission>
sql:
- name: "mapping_name"
actions:
- create
- destroy
sql:
- name: "*"
actions:
- create
- destroy
sql:
- name: "data_connection_name"
actions:
- drop-dataconnection
- view-dataconnection
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, without needing to restart the cluster, using either one of the following configuration options:
- the
on-join-operationconfiguration 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>
hazelcast:
security:
enabled: true
client-permissions:
on-join-operation: SEND
Programmatic Configuration:
Config config = new Config();
config.getSecurityConfig()
.setEnabled(true)
.setOnJoinPermissionOperation(OnJoinPermissionOperationName.SEND);
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
createanddestroypermissions will not work when using theNONEoption, since the distributed objects need to be created/destroyed on all the members.The following is an example for a scenario where
NONEis used:java// temporary member, in the below case a lite memberConfig 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 memberString 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 memberclient.shutdown();hzLite.shutdown();