Skip to content

Commit

Permalink
Improve permission control of executor service proxies [API-2008] [5.…
Browse files Browse the repository at this point in the history
…2.z] (#24451)

We had a feature to perform permission control for invocations sent over
the client.

These permissions were missing from the message tasks of ExecutorService
and DurableExecutor service.

In this PR, similar to the permissions used in the
ScheduledExecutorService, I have introduced two new permissions for
`READ` and `MODIFY` operations and updated the message tasks with those.

Also, I saw that we were not enforcing permissions for the invocations
sent over the client-side ScheduledExecutorService proxy. I have fixed
that and added tests for it.

backport of #24271
  • Loading branch information
mdumandag committed May 11, 2023
1 parent bf066a9 commit 5a452df
Show file tree
Hide file tree
Showing 17 changed files with 94 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import com.hazelcast.executor.impl.operations.CancellationOperation;
import com.hazelcast.instance.impl.Node;
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.ExecutorServicePermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import java.security.Permission;
Expand Down Expand Up @@ -57,7 +59,8 @@ protected ClientMessage encodeResponse(Object response) {

@Override
public String getDistributedObjectName() {
return null;
DistributedExecutorService service = getService(getServiceName());
return service.getName(parameters.uuid);
}

@Override
Expand All @@ -67,7 +70,13 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
String name = getDistributedObjectName();
if (name == null) {
// The permission constructor expects a non-null name.
name = ExecutorServicePermission.EMPTY_EXECUTOR_NAME;
}

return new ExecutorServicePermission(name, ActionConstants.ACTION_MODIFY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import com.hazelcast.executor.impl.operations.CancellationOperation;
import com.hazelcast.instance.impl.Node;
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.ExecutorServicePermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import java.security.Permission;
Expand Down Expand Up @@ -50,7 +52,8 @@ protected ClientMessage encodeResponse(Object response) {

@Override
public String getDistributedObjectName() {
return null;
DistributedExecutorService service = getService(getServiceName());
return service.getName(parameters.uuid);
}

@Override
Expand All @@ -60,7 +63,13 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
String name = getDistributedObjectName();
if (name == null) {
// The permission constructor expects a non-null name.
name = ExecutorServicePermission.EMPTY_EXECUTOR_NAME;
}

return new ExecutorServicePermission(name, ActionConstants.ACTION_MODIFY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.hazelcast.executor.impl.DistributedExecutorService;
import com.hazelcast.instance.impl.Node;
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.ExecutorServicePermission;

import java.security.Permission;

Expand Down Expand Up @@ -55,12 +57,12 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new ExecutorServicePermission(parameters, ActionConstants.ACTION_READ);
}

@Override
public String getDistributedObjectName() {
return null;
return parameters;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.hazelcast.executor.impl.DistributedExecutorService;
import com.hazelcast.instance.impl.Node;
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.ExecutorServicePermission;

import java.security.Permission;

Expand Down Expand Up @@ -56,12 +58,12 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new ExecutorServicePermission(parameters, ActionConstants.ACTION_MODIFY);
}

@Override
public String getDistributedObjectName() {
return null;
return parameters;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.internal.serialization.Data;
import com.hazelcast.security.SecurityContext;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.ExecutorServicePermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import javax.security.auth.Subject;
Expand Down Expand Up @@ -83,7 +85,7 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new ExecutorServicePermission(parameters.name, ActionConstants.ACTION_MODIFY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.internal.serialization.Data;
import com.hazelcast.security.SecurityContext;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.ExecutorServicePermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import javax.security.auth.Subject;
Expand Down Expand Up @@ -75,7 +77,7 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new ExecutorServicePermission(parameters.name, ActionConstants.ACTION_MODIFY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.hazelcast.durableexecutor.impl.operations.DisposeResultOperation;
import com.hazelcast.instance.impl.Node;
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.DurableExecutorServicePermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import java.security.Permission;
Expand Down Expand Up @@ -57,7 +59,7 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new DurableExecutorServicePermission(parameters.name, ActionConstants.ACTION_MODIFY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.hazelcast.durableexecutor.impl.DistributedDurableExecutorService;
import com.hazelcast.instance.impl.Node;
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.DurableExecutorServicePermission;

import java.security.Permission;

Expand Down Expand Up @@ -57,7 +59,7 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new DurableExecutorServicePermission(parameters, ActionConstants.ACTION_READ);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import com.hazelcast.instance.impl.Node;
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.internal.serialization.Data;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.DurableExecutorServicePermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import java.security.Permission;
Expand Down Expand Up @@ -59,7 +61,7 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new DurableExecutorServicePermission(parameters.name, ActionConstants.ACTION_READ, ActionConstants.ACTION_MODIFY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import com.hazelcast.instance.impl.Node;
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.internal.serialization.Data;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.DurableExecutorServicePermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import java.security.Permission;
Expand Down Expand Up @@ -59,7 +61,7 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new DurableExecutorServicePermission(parameters.name, ActionConstants.ACTION_READ);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.hazelcast.durableexecutor.impl.DistributedDurableExecutorService;
import com.hazelcast.instance.impl.Node;
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.DurableExecutorServicePermission;

import java.security.Permission;

Expand Down Expand Up @@ -58,7 +60,7 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new DurableExecutorServicePermission(parameters, ActionConstants.ACTION_MODIFY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import com.hazelcast.internal.nio.Connection;
import com.hazelcast.internal.serialization.Data;
import com.hazelcast.security.SecurityContext;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.DurableExecutorServicePermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import javax.security.auth.Subject;
Expand Down Expand Up @@ -75,7 +77,7 @@ public String getServiceName() {

@Override
public Permission getRequiredPermission() {
return null;
return new DurableExecutorServicePermission(parameters.name, ActionConstants.ACTION_MODIFY);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@
import com.hazelcast.scheduledexecutor.impl.DistributedScheduledExecutorService;
import com.hazelcast.scheduledexecutor.impl.TaskDefinition;
import com.hazelcast.scheduledexecutor.impl.operations.ScheduleTaskOperation;
import com.hazelcast.security.SecurityContext;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.ScheduledExecutorPermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import javax.security.auth.Subject;
import java.security.Permission;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
Expand All @@ -42,6 +44,13 @@ public ScheduledExecutorSubmitToPartitionMessageTask(ClientMessage clientMessage
@Override
protected Operation prepareOperation() {
Callable callable = serializationService.toObject(parameters.task);
SecurityContext securityContext = clientEngine.getSecurityContext();
if (securityContext != null) {
Subject subject = endpoint.getSubject();
callable = securityContext.createSecureCallable(subject, callable);
serializationService.getManagedContext().initialize(callable);
}

TaskDefinition def = new TaskDefinition(TaskDefinition.Type.getById(parameters.type),
parameters.taskName, callable, parameters.initialDelayInMillis, parameters.periodInMillis,
TimeUnit.MILLISECONDS, isAutoDisposable());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
import com.hazelcast.scheduledexecutor.impl.DistributedScheduledExecutorService;
import com.hazelcast.scheduledexecutor.impl.TaskDefinition;
import com.hazelcast.scheduledexecutor.impl.operations.ScheduleTaskOperation;
import com.hazelcast.security.SecurityContext;
import com.hazelcast.security.permission.ActionConstants;
import com.hazelcast.security.permission.ScheduledExecutorPermission;
import com.hazelcast.spi.impl.operationservice.Operation;

import javax.security.auth.Subject;
import java.security.Permission;
import java.util.UUID;
import java.util.concurrent.Callable;
Expand All @@ -44,6 +46,13 @@ public ScheduledExecutorSubmitToTargetMessageTask(ClientMessage clientMessage, N
@Override
protected Operation prepareOperation() {
Callable callable = serializationService.toObject(parameters.task);
SecurityContext securityContext = clientEngine.getSecurityContext();
if (securityContext != null) {
Subject subject = endpoint.getSubject();
callable = securityContext.createSecureCallable(subject, callable);
serializationService.getManagedContext().initialize(callable);
}

TaskDefinition def = new TaskDefinition(TaskDefinition.Type.getById(parameters.type),
parameters.taskName, callable, parameters.initialDelayInMillis, parameters.periodInMillis,
TimeUnit.MILLISECONDS, isAutoDisposable());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.hazelcast.multimap.impl.MultiMapService;
import com.hazelcast.replicatedmap.impl.ReplicatedMapService;
import com.hazelcast.ringbuffer.impl.RingbufferService;
import com.hazelcast.scheduledexecutor.impl.DistributedScheduledExecutorService;
import com.hazelcast.sql.impl.SqlInternalService;
import com.hazelcast.topic.impl.TopicService;
import com.hazelcast.topic.impl.reliable.ReliableTopicService;
Expand Down Expand Up @@ -112,6 +113,7 @@ public final class ActionConstants {
PERMISSION_FACTORY_MAP.put(ReliableTopicService.SERVICE_NAME, ReliableTopicPermission::new);
PERMISSION_FACTORY_MAP.put(JetServiceBackend.SERVICE_NAME, (name, actions) -> new JobPermission(actions));
PERMISSION_FACTORY_MAP.put(SqlInternalService.SERVICE_NAME, SqlPermission::new);
PERMISSION_FACTORY_MAP.put(DistributedScheduledExecutorService.SERVICE_NAME, ScheduledExecutorPermission::new);
}

private ActionConstants() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

public class DurableExecutorServicePermission extends InstancePermission {

private static final int ALL = CREATE | DESTROY;
private static final int READ = 4;
private static final int MODIFY = 8;
private static final int ALL = CREATE | DESTROY | READ | MODIFY;

public DurableExecutorServicePermission(String name, String... actions) {
super(name, actions);
Expand All @@ -36,6 +38,10 @@ protected int initMask(String[] actions) {
mask |= CREATE;
} else if (ActionConstants.ACTION_DESTROY.equals(action)) {
mask |= DESTROY;
} else if (ActionConstants.ACTION_READ.equals(action)) {
mask |= READ;
} else if (ActionConstants.ACTION_MODIFY.equals(action)) {
mask |= MODIFY;
}
}
return mask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@

public class ExecutorServicePermission extends InstancePermission {

private static final int ALL = CREATE | DESTROY;
/**
* The name of the executor used when no such executor
* is found for the client invocations.
*/
public static final String EMPTY_EXECUTOR_NAME = "<EMPTY>";

private static final int READ = 4;
private static final int MODIFY = 8;
private static final int ALL = CREATE | DESTROY | READ | MODIFY;

public ExecutorServicePermission(String name, String... actions) {
super(name, actions);
Expand All @@ -36,6 +44,10 @@ protected int initMask(String[] actions) {
mask |= CREATE;
} else if (ActionConstants.ACTION_DESTROY.equals(action)) {
mask |= DESTROY;
} else if (ActionConstants.ACTION_READ.equals(action)) {
mask |= READ;
} else if (ActionConstants.ACTION_MODIFY.equals(action)) {
mask |= MODIFY;
}
}
return mask;
Expand Down

0 comments on commit 5a452df

Please sign in to comment.