You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2021/08/23 16:11:35 UTC
[geode] 03/03: GEODE-9521: Add test to cover multi-servers scenario for re-authentic… (#6782)
This is an automated email from the ASF dual-hosted git repository.
jinmeiliao pushed a commit to branch expireAuthentication
in repository https://gitbox.apache.org/repos/asf/geode.git
commit 5bbd1c9e33b130f0ae0eec77bf7316681a457714
Author: Jinmei Liao <ji...@pivotal.io>
AuthorDate: Mon Aug 23 08:58:40 2021 -0700
GEODE-9521: Add test to cover multi-servers scenario for re-authentic… (#6782)
---
.../geode/security/AuthExpirationDUnitTest.java | 65 +++++-----
.../AuthExpirationMultiServerDUnitTest.java | 136 +++++++++++++++++++++
.../geode/security/ExpirableSecurityManager.java | 29 +++--
3 files changed, 194 insertions(+), 36 deletions(-)
diff --git a/geode-core/src/upgradeTest/java/org/apache/geode/security/AuthExpirationDUnitTest.java b/geode-core/src/upgradeTest/java/org/apache/geode/security/AuthExpirationDUnitTest.java
index 0aae286..8c8eaff 100644
--- a/geode-core/src/upgradeTest/java/org/apache/geode/security/AuthExpirationDUnitTest.java
+++ b/geode-core/src/upgradeTest/java/org/apache/geode/security/AuthExpirationDUnitTest.java
@@ -48,8 +48,8 @@ import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactor
@RunWith(Parameterized.class)
@Parameterized.UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class)
public class AuthExpirationDUnitTest {
- static RegionService regionService0;
- static RegionService regionService1;
+ static RegionService user0Service;
+ static RegionService user1Service;
@Parameterized.Parameter
public String clientVersion;
@@ -110,9 +110,14 @@ public class AuthExpirationDUnitTest {
// all put operation succeeded
Region<Object, Object> region = server.getCache().getRegion("/region");
- assertThat(ExpirableSecurityManager.getExpiredUsers().size()).isEqualTo(1);
- assertThat(ExpirableSecurityManager.getExpiredUsers().contains("user1")).isTrue();
assertThat(region.size()).isEqualTo(2);
+ Map<String, List<String>> authorizedOps = ExpirableSecurityManager.getAuthorizedOps();
+ Map<String, List<String>> unAuthorizedOps = ExpirableSecurityManager.getUnAuthorizedOps();
+ assertThat(authorizedOps.keySet().size()).isEqualTo(2);
+ assertThat(authorizedOps.get("user1")).asList().containsExactly("DATA:WRITE:region:0");
+ assertThat(authorizedOps.get("user2")).asList().containsExactly("DATA:WRITE:region:1");
+ assertThat(unAuthorizedOps.keySet().size()).isEqualTo(1);
+ assertThat(unAuthorizedOps.get("user1")).asList().containsExactly("DATA:WRITE:region:1");
}
@Test
@@ -125,48 +130,52 @@ public class AuthExpirationDUnitTest {
.withServerConnection(serverPort));
clientVM.invoke(() -> {
- UpdatableUserAuthInitialize.setUser("serviceUser0");
+ UpdatableUserAuthInitialize.setUser("user0");
ClientCache clientCache = ClusterStartupRule.getClientCache();
- assert clientCache != null;
clientCache.createClientRegionFactory(ClientRegionShortcut.PROXY).create("region");
Properties userSecurityProperties = new Properties();
userSecurityProperties.put(SECURITY_CLIENT_AUTH_INIT,
UpdatableUserAuthInitialize.class.getName());
- regionService0 = clientCache.createAuthenticatedView(userSecurityProperties);
- Region<Object, Object> region = regionService0.getRegion("/region");
+ user0Service = clientCache.createAuthenticatedView(userSecurityProperties);
+ Region<Object, Object> region = user0Service.getRegion("/region");
region.put(0, "value0");
- UpdatableUserAuthInitialize.setUser("serviceUser1");
+ UpdatableUserAuthInitialize.setUser("user1");
userSecurityProperties.put(SECURITY_CLIENT_AUTH_INIT,
UpdatableUserAuthInitialize.class.getName());
- regionService1 = clientCache.createAuthenticatedView(userSecurityProperties);
- region = regionService1.getRegion("/region");
+ user1Service = clientCache.createAuthenticatedView(userSecurityProperties);
+ region = user1Service.getRegion("/region");
region.put(1, "value1");
});
- ExpirableSecurityManager.addExpiredUser("serviceUser1");
+ ExpirableSecurityManager.addExpiredUser("user1");
clientVM.invoke(() -> {
- Region<Object, Object> region = regionService1.getRegion("/region");
- UpdatableUserAuthInitialize.setUser("serviceUser2");
- region.put(2, "value2");
-
- region = regionService0.getRegion("/region");
- region.put(3, "value3");
- regionService0.close();
- regionService1.close();
+
+ Region<Object, Object> region = user0Service.getRegion("/region");
+ region.put(2, "value3");
+
+ UpdatableUserAuthInitialize.setUser("user1_extended");
+ region = user1Service.getRegion("/region");
+ region.put(3, "value2");
+
+ user0Service.close();
+ user1Service.close();
});
Region<Object, Object> region = server.getCache().getRegion("/region");
- assertThat(ExpirableSecurityManager.getExpiredUsers().size()).isEqualTo(1);
- assertThat(ExpirableSecurityManager.getExpiredUsers().contains("serviceUser1")).isTrue();
- Map<Object, List<ResourcePermission>> authorizedOps =
- ExpirableSecurityManager.getAuthorizedOps();
- assertThat(authorizedOps.size()).isEqualTo(3);
- assertThat(authorizedOps.get("serviceUser0").size()).isEqualTo(2);
- assertThat(authorizedOps.get("serviceUser1").size()).isEqualTo(1);
- assertThat(authorizedOps.get("serviceUser2").size()).isEqualTo(1);
assertThat(region.size()).isEqualTo(4);
+
+ Map<String, List<String>> authorizedOps = ExpirableSecurityManager.getAuthorizedOps();
+ assertThat(authorizedOps.keySet().size()).isEqualTo(3);
+ assertThat(authorizedOps.get("user0")).asList().containsExactly("DATA:WRITE:region:0",
+ "DATA:WRITE:region:2");
+ assertThat(authorizedOps.get("user1")).asList().containsExactly("DATA:WRITE:region:1");
+ assertThat(authorizedOps.get("user1_extended")).asList().containsExactly("DATA:WRITE:region:3");
+
+ Map<String, List<String>> unAuthorizedOps = ExpirableSecurityManager.getUnAuthorizedOps();
+ assertThat(unAuthorizedOps.keySet().size()).isEqualTo(1);
+ assertThat(unAuthorizedOps.get("user1")).asList().containsExactly("DATA:WRITE:region:3");
}
}
diff --git a/geode-core/src/upgradeTest/java/org/apache/geode/security/AuthExpirationMultiServerDUnitTest.java b/geode-core/src/upgradeTest/java/org/apache/geode/security/AuthExpirationMultiServerDUnitTest.java
new file mode 100644
index 0000000..0dbc8ac
--- /dev/null
+++ b/geode-core/src/upgradeTest/java/org/apache/geode/security/AuthExpirationMultiServerDUnitTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.security;
+
+import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_CLIENT_AUTH_INIT;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.categories.SecurityTest;
+import org.apache.geode.test.junit.rules.ClientCacheRule;
+
+@Category({SecurityTest.class})
+public class AuthExpirationMultiServerDUnitTest implements Serializable {
+ public static final String REPLICATE_REGION = "replicateRegion";
+ public static final String PARTITION_REGION = "partitionRegion";
+ private MemberVM locator, server1, server2;
+ private int locatorPort;
+
+ @Rule
+ public ClusterStartupRule lsRule = new ClusterStartupRule();
+
+ @Rule
+ public ClientCacheRule clientCacheRule = new ClientCacheRule();
+
+ @Before
+ public void setup() {
+ locator = lsRule.startLocatorVM(0, l -> l.withSecurityManager(ExpirableSecurityManager.class));
+ locatorPort = locator.getPort();
+ server1 = lsRule.startServerVM(1, s -> s.withSecurityManager(ExpirableSecurityManager.class)
+ .withCredential("test", "test")
+ .withRegion(RegionShortcut.REPLICATE, REPLICATE_REGION)
+ .withRegion(RegionShortcut.PARTITION, PARTITION_REGION)
+ .withConnectionToLocator(locatorPort));
+ server2 = lsRule.startServerVM(2, s -> s.withSecurityManager(ExpirableSecurityManager.class)
+ .withCredential("test", "test")
+ .withRegion(RegionShortcut.REPLICATE, REPLICATE_REGION)
+ .withRegion(RegionShortcut.PARTITION, PARTITION_REGION)
+ .withConnectionToLocator(locatorPort));
+ }
+
+ @Test
+ public void clientReAuthenticationWorksOnMultipleServers() throws Exception {
+ UpdatableUserAuthInitialize.setUser("user1");
+ clientCacheRule
+ .withProperty(SECURITY_CLIENT_AUTH_INIT, UpdatableUserAuthInitialize.class.getName())
+ .withPoolSubscription(true)
+ .withServerConnection(server1.getPort());
+ clientCacheRule.createCache();
+ Region<Object, Object> region1 = clientCacheRule.createProxyRegion(REPLICATE_REGION);
+ Region<Object, Object> region2 = clientCacheRule.createProxyRegion(PARTITION_REGION);
+ region1.put("0", "value0");
+ region2.put("0", "value0");
+
+ expireUserOnAllVms("user1");
+
+ UpdatableUserAuthInitialize.setUser("user2");
+ region1.put("1", "value1");
+ region2.put("1", "value1");
+
+ // locator only validates peer
+ locator.invoke(() -> {
+ Map<String, List<String>> authorizedOps = ExpirableSecurityManager.getAuthorizedOps();
+ assertThat(authorizedOps.keySet().contains("test")).isTrue();
+ assertThat(authorizedOps.keySet().size()).isEqualTo(1);
+ Map<String, List<String>> unAuthorizedOps = ExpirableSecurityManager.getUnAuthorizedOps();
+ assertThat(unAuthorizedOps.keySet().size()).isEqualTo(0);
+ });
+
+ // client is connected to server1, server1 gets all the initial contact,
+ // authorization checks happens here
+ server1.invoke(() -> {
+ Map<String, List<String>> authorizedOps = ExpirableSecurityManager.getAuthorizedOps();
+ assertThat(authorizedOps.get("user1")).asList().containsExactlyInAnyOrder(
+ "DATA:WRITE:replicateRegion:0", "DATA:WRITE:partitionRegion:0");
+ assertThat(authorizedOps.get("user2")).asList().containsExactlyInAnyOrder(
+ "DATA:WRITE:replicateRegion:1", "DATA:WRITE:partitionRegion:1");
+ Map<String, List<String>> unAuthorizedOps = ExpirableSecurityManager.getUnAuthorizedOps();
+ assertThat(unAuthorizedOps.get("user1")).asList()
+ .containsExactly("DATA:WRITE:replicateRegion:1");
+ });
+
+ // server2 performs no authorization checks
+ server2.invoke(() -> {
+ Map<String, List<String>> authorizedOps = ExpirableSecurityManager.getAuthorizedOps();
+ Map<String, List<String>> unAuthorizedOps = ExpirableSecurityManager.getUnAuthorizedOps();
+ assertThat(authorizedOps.size()).isEqualTo(0);
+ assertThat(unAuthorizedOps.size()).isEqualTo(0);
+ });
+
+ MemberVM.invokeInEveryMember(() -> {
+ InternalCache cache = ClusterStartupRule.getCache();
+ Region<Object, Object> serverRegion1 = cache.getRegion(REPLICATE_REGION);
+ assertThat(serverRegion1.size()).isEqualTo(2);
+ Region<Object, Object> serverRegion2 = cache.getRegion(PARTITION_REGION);
+ assertThat(serverRegion2.size()).isEqualTo(2);
+ }, server1, server2);
+
+ MemberVM.invokeInEveryMember(() -> {
+ ExpirableSecurityManager.reset();
+ UpdatableUserAuthInitialize.reset();
+ }, locator, server1, server2);
+ }
+
+ private void expireUserOnAllVms(String user) {
+ MemberVM.invokeInEveryMember(() -> {
+ ExpirableSecurityManager.addExpiredUser(user);
+ }, locator, server1, server2);
+ }
+
+
+}
diff --git a/geode-junit/src/main/java/org/apache/geode/security/ExpirableSecurityManager.java b/geode-junit/src/main/java/org/apache/geode/security/ExpirableSecurityManager.java
index 5c4d177..59a8b4cb 100644
--- a/geode-junit/src/main/java/org/apache/geode/security/ExpirableSecurityManager.java
+++ b/geode-junit/src/main/java/org/apache/geode/security/ExpirableSecurityManager.java
@@ -35,20 +35,18 @@ public class ExpirableSecurityManager extends SimpleSecurityManager {
// use static field for ease of testing since there is only one instance of this in each VM
// we only need ConcurrentHashSet here, but map is only construct available in the library
private static final Set<String> EXPIRED_USERS = ConcurrentHashMap.newKeySet();
- private static final Map<Object, List<ResourcePermission>> AUTHORIZED_OPS =
+ private static final Map<String, List<String>> AUTHORIZED_OPS =
+ new ConcurrentHashMap<>();
+ private static final Map<String, List<String>> UNAUTHORIZED_OPS =
new ConcurrentHashMap<>();
@Override
public boolean authorize(Object principal, ResourcePermission permission) {
if (EXPIRED_USERS.contains((String) principal)) {
+ addToMap(UNAUTHORIZED_OPS, principal, permission);
throw new AuthenticationExpiredException("User authentication expired.");
}
- List<ResourcePermission> permissions = AUTHORIZED_OPS.get(principal);
- if (permissions == null) {
- permissions = new ArrayList<>();
- }
- permissions.add(permission);
- AUTHORIZED_OPS.put(principal, permissions);
+ addToMap(AUTHORIZED_OPS, principal, permission);
// always authorized
return true;
@@ -62,12 +60,27 @@ public class ExpirableSecurityManager extends SimpleSecurityManager {
return EXPIRED_USERS;
}
- public static Map<Object, List<ResourcePermission>> getAuthorizedOps() {
+ public static Map<String, List<String>> getAuthorizedOps() {
return AUTHORIZED_OPS;
}
+ public static Map<String, List<String>> getUnAuthorizedOps() {
+ return UNAUTHORIZED_OPS;
+ }
+
+ private static void addToMap(Map<String, List<String>> maps, Object user,
+ ResourcePermission permission) {
+ List<String> list = maps.get(user);
+ if (list == null) {
+ list = new ArrayList<>();
+ }
+ list.add(permission.toString());
+ maps.put(user.toString(), list);
+ }
+
public static void reset() {
EXPIRED_USERS.clear();
AUTHORIZED_OPS.clear();
+ UNAUTHORIZED_OPS.clear();
}
}