This is a prerelease version.

Job Security

The Jet API allows you to upload custom code as well as access data outside of Hazelcast such as files on the device that’s running a member. As a result, it’s important to be aware of how to secure your Hazelcast member against malicious uses of the Jet API.

To secure your cluster against malicious jobs, you have the following options:

The open source distribution of Hazelcast does not include security settings. To secure your Hazelcast members against clients misusing jobs, you can only disable code uploads or the whole Jet engine.

Disabling Code Uploads

When submitting a job to a member, you have the option of uploading some of your own classes for the cluster to run with the job. This code is not subject to any client permissions that you may have set up. For example, if you restrict clients' write access to a map, the uploaded code bypasses those restrictions and can write to the map.

If you’re using Hazelcast in embedded mode, this feature is disabled by default.

To disable this feature, use the following configuration:

  • XML

  • YAML

  • Env

  • System Properties

  • Java

<jet enabled="true" resource-upload-enabled="false">
  ...
</jet>
jet:
  enabled: true
  resource-upload-enabled: false
HZ_JET_RESOURCEUPLOADENABLED=false
-Dhz.jet.resource-upload-enabled=false
Config config = new Config();
JetConfig jetConfig = config.getJetConfig();
jetConfig.setEnabled(true).setResourceUploadEnabled(false);
HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);

Disabling the Jet Engine

If you don’t plan on using the Jet engine, it’s safer to disable it. This way, your members don’t start Jet, keeping your members safe from malicious jobs.

Disabling Jet also disables code uploads and SQL queries.
If you’re using Hazelcast in embedded mode, this feature is disabled by default.

To disable this feature, use the following configuration:

  • XML

  • YAML

  • Env

  • System Properties

  • Java

<jet enabled="false">
  ...
</jet>
jet:
  enabled: false
HZ_JET_ENABLED=false
-Dhz.jet.enabled=false
Config config = new Config();
JetConfig jetConfig = config.getJetConfig();
jetConfig.setEnabled(false);
HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);

Controlling Access to Jobs

In Hazelcast Enterprise, you can restrict access to jobs, using the following client permissions:

  • Job permissions: Restrict what clients can do with jobs.

  • Connector permissions: Restrict read and write access for each connector.

Job Permissions

When the code uploads and the Jet engine are enabled, all clients are unrestricted in what they can do with jobs.

To restrict clients, you can set the following permissions:

  • 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.

  • restart: Suspend and resume a running job.

  • export-snapshot: Export the snapshot.

  • add-resources: Upload resources and classes as well as jobs to members.

    Hazelcast 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 submit action, the read action is automatically enabled as well.

Connector Permissions

By default, connectors can read and write data that you may want to keep secure.

For example, the file connector gives jobs access to all files on your members' local filesystems. As a result, a job could use this connector to read SSH keys and log them to the console.

Pipeline pipeline = Pipeline.create();
pipeline.readFrom(Sources.files("/Users/ali/.ssh"))
  .writeTo(Sinks.logger());

You can set the following permissions for each connector:

  • read: Read data from sources.

  • write: Write data to sinks.

  • all: Enable all actions.

You can also give different permissions to different folders. For example:

  • XML

  • YAML

  • Java

<connector-permission name="file:/home/user/source" principal="dev">
  <actions>
    <action>read</action>
  </actions>
</connector-permission>
<connector-permission name="file:/home/user/sink" principal="dev">
  <actions>
    <action>write</action>
  </actions>
</connector-permission>
connector:
  - name: "file:/home/user/source"
    actions:
      - action: read
connector:
  - name: "file:/home/user/sink"
    actions:
      - action: write
Config config = new Config();
SecurityConfig securityConfig = config.getSecurityConfig();
securityConfig.setEnabled(true);
securityConfig.addClientPermissionConfig(
  new PermissionConfig(PermissionConfig.PermissionType.CONNECTOR, "file:/home/user/source", "dev")
  .addAction(ActionConstants.ACTION_READ)
);
securityConfig.addClientPermissionConfig(
  new PermissionConfig(PermissionConfig.PermissionType.CONNECTOR, "file:/home/user/sink", "dev")
  .addAction(ActionConstants.ACTION_WRITE)
);
If you use the data structure connectors such as the IMap connector, you must also have certain permissions on those data structures. For example, to read from map sources, you must add the create and read permissions for those maps. If you use the IMap connector to write to map sinks, you must add the create and put permissions for those maps.

For information on how to set client permissions, see Client Security.