You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2020/12/16 13:25:15 UTC
[geode] branch develop updated: GEODE-8782: Add getPrincipal method
to FunctionContext interface (#5840)
This is an automated email from the ASF dual-hosted git repository.
jensdeppe pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new a42f89a GEODE-8782: Add getPrincipal method to FunctionContext interface (#5840)
a42f89a is described below
commit a42f89ab48aaca9aac96a34e80a9b3b2d46bcddd
Author: Jens Deppe <jd...@pivotal.io>
AuthorDate: Wed Dec 16 05:24:23 2020 -0800
GEODE-8782: Add getPrincipal method to FunctionContext interface (#5840)
- Add the ability to retrieve the Principal from the FunctionContext
when a SecurityManager is enabled.
---
.../src/main/resources/japicmp_exceptions.json | 2 +
.../FunctionExecutionWithPrincipalDUnitTest.java | 145 +++++++++++++++++++++
.../codeAnalysis/sanctionedDataSerializables.txt | 4 +-
.../geode/cache/execute/FunctionContext.java | 10 ++
.../geode/internal/cache/PartitionedRegion.java | 12 +-
.../internal/cache/PartitionedRegionDataStore.java | 4 +-
.../cache/execute/FunctionContextImpl.java | 17 +++
.../cache/execute/FunctionRemoteContext.java | 20 ++-
.../cache/execute/RegionFunctionContextImpl.java | 28 +++-
.../PartitionedRegionFunctionStreamingMessage.java | 2 +-
.../security/IntegratedSecurityService.java | 14 ++
.../internal/security/LegacySecurityService.java | 5 +
.../geode/internal/security/SecurityService.java | 2 +
.../geode/test/junit/rules/ClientCacheRule.java | 7 +-
.../internal/security/TestFunctions.java | 26 +++-
15 files changed, 279 insertions(+), 19 deletions(-)
diff --git a/buildSrc/src/main/resources/japicmp_exceptions.json b/buildSrc/src/main/resources/japicmp_exceptions.json
index 01317fc..b02a483 100755
--- a/buildSrc/src/main/resources/japicmp_exceptions.json
+++ b/buildSrc/src/main/resources/japicmp_exceptions.json
@@ -1,4 +1,6 @@
{
"Class org.apache.geode.net.SSLParameterExtension": "Old implementation exposed an internal class",
"Method org.apache.geode.net.SSLParameterExtension.init(org.apache.geode.distributed.internal.DistributionConfig)": "Old implementation exposed an internal class",
+ "Class org.apache.geode.cache.execute.FunctionContext": "Interface not intended for client applications",
+ "Method org.apache.geode.cache.execute.FunctionContext.getPrincipal()": "Interface not intended for client applications"
}
diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/execute/FunctionExecutionWithPrincipalDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/execute/FunctionExecutionWithPrincipalDUnitTest.java
new file mode 100644
index 0000000..e9d5281
--- /dev/null
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/execute/FunctionExecutionWithPrincipalDUnitTest.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package org.apache.geode.internal.cache.execute;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.distributed.ConfigurationProperties;
+import org.apache.geode.examples.SimpleSecurityManager;
+import org.apache.geode.management.internal.security.TestFunctions.ReadFunction;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.dunit.rules.SerializableFunction;
+import org.apache.geode.test.junit.rules.ClientCacheRule;
+import org.apache.geode.test.junit.rules.ServerStarterRule;
+
+public class FunctionExecutionWithPrincipalDUnitTest {
+
+ private static String PR_REGION_NAME = "partitioned-region";
+ private static String REGION_NAME = "replicated-region";
+ private static Region<String, String> replicateRegion;
+ private static Region<String, String> partitionedRegion;
+
+ private static Function<?> readFunction = new ReadFunction();
+
+ private static MemberVM locator;
+ private static MemberVM server1;
+ private static MemberVM server2;
+ private static ClientCache client;
+
+ @ClassRule
+ public static ClusterStartupRule cluster = new ClusterStartupRule();
+
+ @ClassRule
+ public static ClientCacheRule clientRule = new ClientCacheRule();
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ locator = cluster.startLocatorVM(0, x -> x
+ .withSecurityManager(SimpleSecurityManager.class));
+ int locatorPort = locator.getPort();
+
+ SerializableFunction<ServerStarterRule> startupFunction = x -> x
+ .withConnectionToLocator(locatorPort)
+ .withCredential("cluster", "cluster")
+ .withProperty(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
+ "org.apache.geode.management.internal.security.TestFunctions*");
+
+ server1 = cluster.startServerVM(1, startupFunction);
+ server2 = cluster.startServerVM(2, startupFunction);
+
+ Stream.of(server1, server2).forEach(v -> v.invoke(() -> {
+ ClusterStartupRule.getCache().createRegionFactory(RegionShortcut.REPLICATE).create(
+ REGION_NAME);
+ ClusterStartupRule.getCache().createRegionFactory(RegionShortcut.PARTITION_REDUNDANT)
+ .create(PR_REGION_NAME);
+ }));
+
+ client = clientRule
+ .withLocatorConnection(locatorPort)
+ .withCredential("data", "data")
+ .createCache();
+
+ replicateRegion = clientRule.createProxyRegion(REGION_NAME);
+ partitionedRegion = clientRule.createProxyRegion(PR_REGION_NAME);
+
+ for (int i = 0; i < 10; i++) {
+ replicateRegion.put("key-" + i, "value-" + i);
+ partitionedRegion.put("key-" + i, "value-" + i);
+ }
+ }
+
+ @Test
+ public void verifyPrincipal_whenUsingReplicateRegion_andCallingOnRegion() {
+ FunctionService.onRegion(replicateRegion)
+ .execute(readFunction)
+ .getResult();
+ }
+
+ @Test
+ public void verifyPrincipal_whenUsingPartitionedRegion_andCallingOnRegion() {
+ FunctionService.onRegion(partitionedRegion)
+ .execute(readFunction)
+ .getResult();
+ }
+
+ @Test
+ public void verifyPrincipal_whenUsingPartitionedRegion_andCallingOnRegion_withFilter() {
+ Set<String> filter = new HashSet<>();
+ filter.add("key-1");
+ filter.add("key-2");
+ filter.add("key-4");
+ filter.add("key-7");
+
+ FunctionService.onRegion(partitionedRegion)
+ .withFilter(filter)
+ .execute(readFunction)
+ .getResult();
+ }
+
+ @Test
+ public void verifyPrincipal_whenUsingPartitionedRegion_andCallingOnServer() {
+ FunctionService.onServer(partitionedRegion.getRegionService())
+ .execute(readFunction)
+ .getResult();
+ }
+
+ @Test
+ public void verifyPrincipal_whenUsingPartitionedRegion_andCallingOnServers() {
+ FunctionService.onServers(partitionedRegion.getRegionService())
+ .execute(readFunction)
+ .getResult();
+ }
+
+ @Test
+ public void verifyPrincipal_whenUsingReplicateRegion_andCallingOnServers() {
+ FunctionService.onServers(replicateRegion.getRegionService())
+ .execute(readFunction)
+ .getResult();
+ }
+
+}
diff --git a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
index 204be50..65d8796 100644
--- a/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
+++ b/geode-core/src/integrationTest/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
@@ -1297,8 +1297,8 @@ fromData,22
toData,19
org/apache/geode/internal/cache/execute/FunctionRemoteContext,2
-fromData,124
-toData,102
+fromData,145
+toData,123
org/apache/geode/internal/cache/ha/HARegionQueue$DispatchedAndCurrentEvents,2
fromData,37
diff --git a/geode-core/src/main/java/org/apache/geode/cache/execute/FunctionContext.java b/geode-core/src/main/java/org/apache/geode/cache/execute/FunctionContext.java
index bc91180..a6a779f 100755
--- a/geode-core/src/main/java/org/apache/geode/cache/execute/FunctionContext.java
+++ b/geode-core/src/main/java/org/apache/geode/cache/execute/FunctionContext.java
@@ -14,10 +14,12 @@
*/
package org.apache.geode.cache.execute;
+
import org.apache.logging.log4j.util.Strings;
import org.apache.geode.cache.Cache;
import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.internal.security.LegacySecurityService;
/**
* Defines the execution context of a {@link Function}. It is required by the
@@ -97,4 +99,12 @@ public interface FunctionContext<T1> {
return member.getId();
}
+
+ /**
+ * If available, returns the principal that has been authenticated to execute this function. This
+ * will always be null if the {@link LegacySecurityService} is in use.
+ *
+ * @return the principal that has been authenticated
+ */
+ Object getPrincipal();
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
index afafb8b..4cb63d3 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegion.java
@@ -3740,7 +3740,7 @@ public class PartitionedRegion extends LocalRegion
FunctionRemoteContext context = new FunctionRemoteContext(function,
execution.getArgumentsForMember(recip.getId()), memKeys,
FunctionExecutionNodePruner.getBucketSet(this, memKeys, false, isBucketSetAsFilter),
- execution.isReExecute(), execution.isFnSerializationReqd());
+ execution.isReExecute(), execution.isFnSerializationReqd(), getPrincipal());
recipMap.put(recip, context);
}
if (logger.isDebugEnabled()) {
@@ -3755,6 +3755,10 @@ public class PartitionedRegion extends LocalRegion
return localResultCollector;
}
+ private Object getPrincipal() {
+ return cache.getSecurityService().getPrincipal();
+ }
+
/**
* Single key execution on single node
*
@@ -3958,7 +3962,7 @@ public class PartitionedRegion extends LocalRegion
for (InternalDistributedMember recip : dest) {
FunctionRemoteContext context = new FunctionRemoteContext(function,
execution.getArgumentsForMember(recip.getId()), null, memberToBuckets.get(recip),
- execution.isReExecute(), execution.isFnSerializationReqd());
+ execution.isReExecute(), execution.isFnSerializationReqd(), getPrincipal());
recipMap.put(recip, context);
}
final LocalResultCollector<?, ?> localRC = execution.getLocalResultCollector(function, rc);
@@ -4052,7 +4056,7 @@ public class PartitionedRegion extends LocalRegion
for (InternalDistributedMember recip : memberToBuckets.keySet()) {
FunctionRemoteContext context = new FunctionRemoteContext(function,
execution.getArgumentsForMember(recip.getId()), null, memberToBuckets.get(recip),
- execution.isReExecute(), execution.isFnSerializationReqd());
+ execution.isReExecute(), execution.isFnSerializationReqd(), getPrincipal());
recipMap.put(recip, context);
}
final LocalResultCollector<?, ?> localResultCollector =
@@ -4984,7 +4988,7 @@ public class PartitionedRegion extends LocalRegion
resultSender);
FunctionRemoteContext context = new FunctionRemoteContext(function, object, routingKeys,
- bucketArray, execution.isReExecute(), execution.isFnSerializationReqd());
+ bucketArray, execution.isReExecute(), execution.isFnSerializationReqd(), getPrincipal());
HashMap<InternalDistributedMember, FunctionRemoteContext> recipMap =
new HashMap<InternalDistributedMember, FunctionRemoteContext>();
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionDataStore.java b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionDataStore.java
index 23a7487..d1d3dba 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionDataStore.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/PartitionedRegionDataStore.java
@@ -2969,7 +2969,7 @@ public class PartitionedRegionDataStore implements HasCachePerfStats {
public void executeOnDataStore(final Set localKeys, final Function function, final Object object,
final int prid, final int[] bucketArray, final boolean isReExecute,
final PartitionedRegionFunctionStreamingMessage msg, long time, ServerConnection servConn,
- int transactionID) {
+ int transactionID, Object principal) {
if (!areAllBucketsHosted(bucketArray)) {
throw new BucketMovedException(
@@ -2984,7 +2984,7 @@ public class PartitionedRegionDataStore implements HasCachePerfStats {
new RegionFunctionContextImpl(getPartitionedRegion().getCache(), function.getId(),
this.partitionedRegion, object, localKeys, ColocationHelper
.constructAndGetAllColocatedLocalDataSet(this.partitionedRegion, bucketArray),
- bucketArray, resultSender, isReExecute);
+ bucketArray, resultSender, isReExecute, principal);
FunctionStats stats = FunctionStatsManager.getFunctionStats(function.getId(), dm.getSystem());
long start = stats.startFunctionExecution(function.hasResult());
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/FunctionContextImpl.java b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/FunctionContextImpl.java
index c328b2f..c3ef8a7 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/FunctionContextImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/FunctionContextImpl.java
@@ -21,6 +21,7 @@ import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.cache.execute.RegionFunctionContext;
import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.internal.cache.InternalCache;
/**
* Context available to application functions which is passed from GemFire to {@link Function}. <br>
@@ -45,6 +46,8 @@ public class FunctionContextImpl implements FunctionContext {
private final boolean isPossDup;
+ private final Object principal;
+
public FunctionContextImpl(final Cache cache, final String functionId, final Object args,
ResultSender resultSender) {
this(cache, functionId, args, resultSender, false);
@@ -57,6 +60,14 @@ public class FunctionContextImpl implements FunctionContext {
this.args = args;
this.resultSender = resultSender;
this.isPossDup = isPossibleDuplicate;
+
+ Object tmpPrincipal = null;
+ if (cache != null) {
+ if (((InternalCache) cache).getSecurityService() != null) {
+ tmpPrincipal = ((InternalCache) cache).getSecurityService().getPrincipal();
+ }
+ }
+ this.principal = tmpPrincipal;
}
/**
@@ -89,6 +100,8 @@ public class FunctionContextImpl implements FunctionContext {
buf.append(this.functionId);
buf.append(";args=");
buf.append(this.args);
+ buf.append(";principal=");
+ buf.append(getPrincipal());
buf.append(']');
return buf.toString();
}
@@ -111,4 +124,8 @@ public class FunctionContextImpl implements FunctionContext {
return cache;
}
+ @Override
+ public Object getPrincipal() {
+ return principal;
+ }
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/FunctionRemoteContext.java b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/FunctionRemoteContext.java
index 9191a87..32d69d6 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/FunctionRemoteContext.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/FunctionRemoteContext.java
@@ -31,8 +31,6 @@ import org.apache.geode.internal.serialization.StaticSerialization;
/**
* FunctionContext for remote/target nodes
- *
- *
*/
public class FunctionRemoteContext implements DataSerializable {
@@ -50,16 +48,19 @@ public class FunctionRemoteContext implements DataSerializable {
private Function function;
+ private Object principal;
+
public FunctionRemoteContext() {}
public FunctionRemoteContext(final Function function, Object object, Set filter,
- int[] bucketArray, boolean isReExecute, boolean isFnSerializationReqd) {
+ int[] bucketArray, boolean isReExecute, boolean isFnSerializationReqd, Object principal) {
this.function = function;
this.args = object;
this.filter = filter;
this.bucketArray = bucketArray;
this.isReExecute = isReExecute;
this.isFnSerializationReqd = isFnSerializationReqd;
+ this.principal = principal;
}
@Override
@@ -84,6 +85,10 @@ public class FunctionRemoteContext implements DataSerializable {
this.bucketArray = BucketSetHelper.fromSet(bucketSet);
}
this.isReExecute = DataSerializer.readBoolean(in);
+
+ if (StaticSerialization.getVersionForDataStream(in).isNotOlderThan(KnownVersion.GEODE_1_14_0)) {
+ this.principal = DataSerializer.readObject(in);
+ }
}
@Override
@@ -103,6 +108,11 @@ public class FunctionRemoteContext implements DataSerializable {
DataSerializer.writeHashSet((HashSet) bucketSet, out);
}
DataSerializer.writeBoolean(this.isReExecute, out);
+
+ if (StaticSerialization.getVersionForDataStream(out)
+ .isNotOlderThan(KnownVersion.GEODE_1_14_0)) {
+ DataSerializer.writeObject(this.principal, out);
+ }
}
public Set getFilter() {
@@ -129,6 +139,10 @@ public class FunctionRemoteContext implements DataSerializable {
return functionId;
}
+ public Object getPrincipal() {
+ return principal;
+ }
+
@Override
public String toString() {
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/RegionFunctionContextImpl.java b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/RegionFunctionContextImpl.java
index c8d9747..f4e25e0 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/execute/RegionFunctionContextImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/execute/RegionFunctionContextImpl.java
@@ -25,6 +25,7 @@ import org.apache.geode.cache.Region;
import org.apache.geode.cache.execute.Execution;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultSender;
+import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.LocalDataSet;
/**
@@ -51,16 +52,32 @@ public class RegionFunctionContextImpl extends FunctionContextImpl
private final boolean isPossibleDuplicate;
- public RegionFunctionContextImpl(final Cache cache, final String functionId, final Region dataSet,
- final Object args, final Set<?> routingObjects,
+ private final Object principal;
+
+ public RegionFunctionContextImpl(final Cache cache, final String functionId,
+ final Region<?, ?> dataSet, final Object args, final Set<?> routingObjects,
final Map<String, LocalDataSet> colocatedLocalDataMap, int[] localBucketArray,
ResultSender<?> resultSender, boolean isPossibleDuplicate) {
+ this(cache, functionId, dataSet, args, routingObjects, colocatedLocalDataMap, localBucketArray,
+ resultSender, isPossibleDuplicate, null);
+ }
+
+ public RegionFunctionContextImpl(final Cache cache, final String functionId,
+ final Region<?, ?> dataSet, final Object args, final Set<?> routingObjects,
+ final Map<String, LocalDataSet> colocatedLocalDataMap, int[] localBucketArray,
+ ResultSender<?> resultSender, boolean isPossibleDuplicate, Object principal) {
super(cache, functionId, args, resultSender);
this.dataSet = dataSet;
this.filter = routingObjects;
this.colocatedLocalDataMap = colocatedLocalDataMap;
this.localBucketArray = localBucketArray;
this.isPossibleDuplicate = isPossibleDuplicate;
+
+ if (principal == null) {
+ this.principal = ((InternalCache) cache).getSecurityService().getPrincipal();
+ } else {
+ this.principal = principal;
+ }
setFunctionContexts();
}
@@ -107,6 +124,8 @@ public class RegionFunctionContextImpl extends FunctionContextImpl
buf.append(this.filter);
buf.append(";args=");
buf.append(getArguments());
+ buf.append(";principal=");
+ buf.append(getPrincipal());
buf.append(']');
return buf.toString();
}
@@ -144,4 +163,9 @@ public class RegionFunctionContextImpl extends FunctionContextImpl
}
return this.localBucketArray;
}
+
+ @Override
+ public Object getPrincipal() {
+ return principal;
+ }
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/PartitionedRegionFunctionStreamingMessage.java b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/PartitionedRegionFunctionStreamingMessage.java
index 23e9d4b2..52b6f98 100755
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/PartitionedRegionFunctionStreamingMessage.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/partitioned/PartitionedRegionFunctionStreamingMessage.java
@@ -100,7 +100,7 @@ public class PartitionedRegionFunctionStreamingMessage extends PartitionMessage
// if null call executeOnDataStore otherwise execute on LocalBuckets
ds.executeOnDataStore(context.getFilter(), context.getFunction(), context.getArgs(),
getProcessorId(), context.getBucketArray(), context.isReExecute(), this, startTime, null,
- 0);
+ 0, context.getPrincipal());
if (!this.replyLastMsg && context.getFunction().hasResult()) {
sendReply(getSender(), getProcessorId(), dm,
diff --git a/geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java b/geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java
index 2d1a703..eaf71ca 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/security/IntegratedSecurityService.java
@@ -127,6 +127,20 @@ public class IntegratedSecurityService implements SecurityService {
}
/**
+ * Returns the current principal if one exists or null.
+ *
+ * @return the principal
+ */
+ @Override
+ public Object getPrincipal() {
+ try {
+ return getSubject().getPrincipal();
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+ /**
* @return return a shiro subject
*/
@Override
diff --git a/geode-core/src/main/java/org/apache/geode/internal/security/LegacySecurityService.java b/geode-core/src/main/java/org/apache/geode/internal/security/LegacySecurityService.java
index d097fd9..885c515 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/security/LegacySecurityService.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/security/LegacySecurityService.java
@@ -69,6 +69,11 @@ public class LegacySecurityService implements SecurityService {
}
@Override
+ public Object getPrincipal() {
+ return null;
+ }
+
+ @Override
public Subject login(Properties credentials) {
return null;
}
diff --git a/geode-core/src/main/java/org/apache/geode/internal/security/SecurityService.java b/geode-core/src/main/java/org/apache/geode/internal/security/SecurityService.java
index 3eccdd9..89a415e 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/security/SecurityService.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/security/SecurityService.java
@@ -33,6 +33,8 @@ public interface SecurityService {
Subject getSubject();
+ Object getPrincipal();
+
Subject login(Properties credentials);
void logout();
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/junit/rules/ClientCacheRule.java b/geode-dunit/src/main/java/org/apache/geode/test/junit/rules/ClientCacheRule.java
index dbcfd8c..5befc5e 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/junit/rules/ClientCacheRule.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/junit/rules/ClientCacheRule.java
@@ -28,6 +28,7 @@ import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionService;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.client.ClientRegionFactory;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.internal.net.SocketCreatorFactory;
import org.apache.geode.security.templates.UserPasswordAuthInit;
@@ -109,8 +110,10 @@ public class ClientCacheRule extends SerializableExternalResource {
return cache;
}
- public Region createProxyRegion(String regionPath) {
- return cache.createClientRegionFactory(ClientRegionShortcut.PROXY).create(regionPath);
+ public <K, V> Region<K, V> createProxyRegion(String regionPath) {
+ ClientRegionFactory<K, V> regionFactory =
+ cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
+ return regionFactory.create(regionPath);
}
public RegionService createAuthenticatedView(String username, String password) {
diff --git a/geode-junit/src/main/java/org/apache/geode/management/internal/security/TestFunctions.java b/geode-junit/src/main/java/org/apache/geode/management/internal/security/TestFunctions.java
index 8167937..423058c 100644
--- a/geode-junit/src/main/java/org/apache/geode/management/internal/security/TestFunctions.java
+++ b/geode-junit/src/main/java/org/apache/geode/management/internal/security/TestFunctions.java
@@ -17,6 +17,7 @@ package org.apache.geode.management.internal.security;
import static org.apache.geode.security.ResourcePermission.Operation.READ;
import static org.apache.geode.security.ResourcePermission.Resource.DATA;
+import static org.assertj.core.api.Assertions.assertThat;
import java.io.Serializable;
import java.util.Collection;
@@ -27,11 +28,12 @@ import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.security.ResourcePermission;
public final class TestFunctions implements Serializable {
- public static class WriteFunction implements Function {
+ public static class WriteFunction implements Function<Object> {
public static final String SUCCESS_OUTPUT = "writeDataFunctionSucceeded";
@Override
- public void execute(FunctionContext context) {
+ public void execute(FunctionContext<Object> context) {
+ verifyPrincipal(context);
context.getResultSender().lastResult(SUCCESS_OUTPUT);
}
@@ -39,13 +41,19 @@ public final class TestFunctions implements Serializable {
public String getId() {
return "writeData";
}
+
+ @Override
+ public boolean optimizeForWrite() {
+ return true;
+ }
}
public static class ReadFunction implements Function<Object> {
public static final String SUCCESS_OUTPUT = "readDataFunctionSucceeded";
@Override
- public void execute(FunctionContext context) {
+ public void execute(FunctionContext<Object> context) {
+ verifyPrincipal(context);
context.getResultSender().lastResult(SUCCESS_OUTPUT);
}
@@ -58,5 +66,17 @@ public final class TestFunctions implements Serializable {
public String getId() {
return "readData";
}
+
+ @Override
+ public boolean optimizeForWrite() {
+ return true;
+ }
+ }
+
+ private static void verifyPrincipal(FunctionContext<Object> context) {
+ String principal = (String) context.getPrincipal();
+ assertThat(principal).as("Principal cannot be null").isNotNull();
+ assertThat(principal).startsWith("data");
+
}
}