Securing Jobs

While submitting jobs, you can upload custom code that bypasses client permissions. Jobs also have access to 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 jobs.

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

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 Enterprise 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.
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 and SQL queries.

  • 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 new jobs and run new SQL queries.

  • 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 or list snapshots.

  • 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. An alternative to uploading resources and classes with a job is to add them to the member’s classpath.
  • 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 from and write to data outside of Hazelcast 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 read SSH keys and log them to the console.

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

To protect your data outside of Hazelcast, you can set the following permissions for the file, socket, JMS, and JDBC connectors:

  • read: Read data from sources.

  • write: Write data to sinks.

  • all: Enable all actions.

You can also give different permissions to different directories. 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)
);
Only connectors that access information local to the member implement permissions - namely the file and socket connector. If you use the data structure connectors such as the map 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 map connector to write to map sinks, you must add the create and put permissions for those maps.
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.

For information about client permissions, see Client Security.