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
The following commit(s) were added to refs/heads/expireAuthentication by this push: new 340e8c6 GEODE-9456, GEODE-9452: Authentication Expiration (#6721) 340e8c6 is described below commit 340e8c627ea45f06e5edaebe823b3692de8544c3 Author: Jinmei Liao <jil...@pivotal.io> AuthorDate: Fri Jul 30 12:33:54 2021 -0700 GEODE-9456, GEODE-9452: Authentication Expiration (#6721) * Add tests and throw AuthenticationExpiredException Co-authored-by: Joris Melchior <joris.melch...@gmail.com> --- .../integrationTest/resources/assembly_content.txt | 5 +- geode-core/build.gradle | 2 +- .../SecurityWithExpirationIntegrationTest.java | 66 ++++++++++++ geode-core/src/integrationTest/resources/shiro.ini | 40 ++++++++ .../cache/client/internal/OpExecutorImpl.java | 8 +- .../cache/tier/sockets/ServerConnection.java | 6 +- .../security/AuthenticationExpiredException.java | 32 ++++++ .../org/apache/geode/security/SecurityManager.java | 5 +- .../sanctioned-geode-core-serializables.txt | 2 +- .../geode/security/AuthExpirationDUnitTest.java | 112 +++++++++++++++++++++ .../geode/security/ExpirableSecurityManager.java | 56 +++++++++++ .../security/UpdatableUserAuthInitialize.java | 54 ++++++++++ .../gemstone/gemfire/OldClientSupportProvider.java | 16 ++- 13 files changed, 394 insertions(+), 10 deletions(-) diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt index c408ada..39a94f8 100644 --- a/geode-assembly/src/integrationTest/resources/assembly_content.txt +++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt @@ -929,6 +929,7 @@ javadoc/org/apache/geode/ra/package-tree.html javadoc/org/apache/geode/security/AccessControl.html javadoc/org/apache/geode/security/AuthInitialize.html javadoc/org/apache/geode/security/AuthTokenEnabledComponents.html +javadoc/org/apache/geode/security/AuthenticationExpiredException.html javadoc/org/apache/geode/security/AuthenticationFailedException.html javadoc/org/apache/geode/security/AuthenticationRequiredException.html javadoc/org/apache/geode/security/Authenticator.html @@ -975,11 +976,12 @@ lib/commons-lang3-3.12.0.jar lib/commons-logging-1.2.jar lib/commons-modeler-2.0.1.jar lib/commons-validator-1.7.jar +lib/fastutil-8.5.4.jar lib/fastutil-core-8.5.4.jar lib/fastutil-extra-8.5.4.jar -lib/fastutil-8.5.4.jar lib/findbugs-annotations-1.3.9-1.jar lib/geo-0.7.7.jar +lib/geode-apis-compatible-with-redis-0.0.0.jar lib/geode-common-0.0.0.jar lib/geode-connectors-0.0.0.jar lib/geode-core-0.0.0.jar @@ -997,7 +999,6 @@ lib/geode-membership-0.0.0.jar lib/geode-memcached-0.0.0.jar lib/geode-old-client-support-0.0.0.jar lib/geode-rebalancer-0.0.0.jar -lib/geode-apis-compatible-with-redis-0.0.0.jar lib/geode-serialization-0.0.0.jar lib/geode-tcp-server-0.0.0.jar lib/geode-unsafe-0.0.0.jar diff --git a/geode-core/build.gradle b/geode-core/build.gradle index ecb51b7..8035775 100755 --- a/geode-core/build.gradle +++ b/geode-core/build.gradle @@ -387,7 +387,7 @@ dependencies { upgradeTestRuntimeOnly(project(path: ':geode-old-versions', configuration: 'classpathsOutput')) upgradeTestRuntimeOnly(project(':geode-log4j')) - + upgradeTestRuntimeOnly(project(':geode-old-client-support')) performanceTestImplementation(project(':geode-junit')) { exclude module: 'geode-core' diff --git a/geode-core/src/integrationTest/java/org/apache/geode/management/internal/security/SecurityWithExpirationIntegrationTest.java b/geode-core/src/integrationTest/java/org/apache/geode/management/internal/security/SecurityWithExpirationIntegrationTest.java new file mode 100644 index 0000000..cb0a24f --- /dev/null +++ b/geode-core/src/integrationTest/java/org/apache/geode/management/internal/security/SecurityWithExpirationIntegrationTest.java @@ -0,0 +1,66 @@ +/* + * 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.management.internal.security; + +import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_MANAGER; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.Properties; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import org.apache.geode.internal.security.SecurityService; +import org.apache.geode.internal.security.SecurityServiceFactory; +import org.apache.geode.security.AuthenticationExpiredException; +import org.apache.geode.security.ExpirableSecurityManager; +import org.apache.geode.test.junit.categories.SecurityTest; + +@Category({SecurityTest.class}) +public class SecurityWithExpirationIntegrationTest { + + protected Properties props = new Properties(); + + protected SecurityService securityService; + + @Before + public void before() throws Exception { + props.setProperty(SECURITY_MANAGER, ExpirableSecurityManager.class.getName()); + securityService = SecurityServiceFactory.create(this.props); + } + + @After + public void after() throws Exception { + securityService.logout(); + ExpirableSecurityManager.reset(); + } + + @Test + public void testThrowAuthenticationExpiredException() { + ExpirableSecurityManager.addExpiredUser("data"); + this.securityService.login(loginCredentials("data", "data")); + assertThatThrownBy(() -> this.securityService.authorize(ResourcePermissions.DATA_READ)) + .isInstanceOf(AuthenticationExpiredException.class); + } + + private Properties loginCredentials(String username, String password) { + Properties credentials = new Properties(); + credentials.put(ResourceConstants.USER_NAME, username); + credentials.put(ResourceConstants.PASSWORD, password); + return credentials; + } +} diff --git a/geode-core/src/integrationTest/resources/shiro.ini b/geode-core/src/integrationTest/resources/shiro.ini new file mode 100644 index 0000000..a9746a5 --- /dev/null +++ b/geode-core/src/integrationTest/resources/shiro.ini @@ -0,0 +1,40 @@ +# 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. + +# the users and roles in this file needs to be kept in sync with shiro.ini +# since they are used by the same test to test ShiroUtil +# ----------------------------------------------------------------------------- +# Users and their (optional) assigned roles +# username = password, role1, role2, ..., roleN +# ----------------------------------------------------------------------------- +[users] +root = secret, admin +guest = guest, guest +regionAReader = password, readRegionA +regionAUser = password, useRegionA +dataReader = 12345, readData +reader = 12345, readAll + +# ----------------------------------------------------------------------------- +# Roles with assigned permissions +# roleName = perm1, perm2, ..., permN +# ----------------------------------------------------------------------------- +[roles] +admin = * +guest = none +readRegionA = DATA:READ:RegionA +useRegionA = *:*:RegionA +readData = DATA:READ +readAll = *:READ \ No newline at end of file diff --git a/geode-core/src/main/java/org/apache/geode/cache/client/internal/OpExecutorImpl.java b/geode-core/src/main/java/org/apache/geode/cache/client/internal/OpExecutorImpl.java index 69fb338..c5fe32a 100644 --- a/geode-core/src/main/java/org/apache/geode/cache/client/internal/OpExecutorImpl.java +++ b/geode-core/src/main/java/org/apache/geode/cache/client/internal/OpExecutorImpl.java @@ -15,6 +15,8 @@ package org.apache.geode.cache.client.internal; +import static org.apache.geode.internal.cache.tier.sockets.ServerConnection.USER_NOT_FOUND; + import java.io.IOException; import java.io.NotSerializableException; import java.net.SocketException; @@ -59,6 +61,7 @@ import org.apache.geode.internal.cache.tier.sockets.MessageTooLargeException; import org.apache.geode.internal.cache.wan.BatchException70; import org.apache.geode.internal.logging.log4j.LogMarker; import org.apache.geode.logging.internal.log4j.api.LogService; +import org.apache.geode.security.AuthenticationExpiredException; import org.apache.geode.security.AuthenticationRequiredException; import org.apache.geode.security.GemFireSecurityException; import org.apache.geode.util.internal.GeodeGlossary; @@ -740,8 +743,9 @@ public class OpExecutorImpl implements ExecutablePool { } catch (final ServerConnectivityException sce) { final Throwable cause = sce.getCause(); if ((cause instanceof AuthenticationRequiredException - && "User authorization attributes not found.".equals(cause.getMessage())) - || sce.getMessage().contains("Connection error while authenticating user")) { + && USER_NOT_FOUND.equals(cause.getMessage())) + || sce.getMessage().contains("Connection error while authenticating user") + || cause instanceof AuthenticationExpiredException) { // 2nd exception-message above is from AbstractOp.sendMessage() if (pool.getMultiuserAuthentication()) { diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/ServerConnection.java b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/ServerConnection.java index 8ee4993..5435f9b 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/ServerConnection.java +++ b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/ServerConnection.java @@ -100,6 +100,8 @@ public class ServerConnection implements Runnable { private static final String DISALLOW_INTERNAL_MESSAGES_WITHOUT_CREDENTIALS_NAME = "geode.disallow-internal-messages-without-credentials"; + public static final String USER_NOT_FOUND = "User authorization attributes not found."; + /** * When true requires some formerly credential-less messages to carry credentials. See GEODE-3249 * and ServerConnection.isInternalMessage() @@ -1774,7 +1776,7 @@ public class ServerConnection implements Runnable { logger.debug("Unexpected exception {}", npe.toString()); } if (uaa == null) { - throw new AuthenticationRequiredException("User authorization attributes not found."); + throw new AuthenticationRequiredException(USER_NOT_FOUND); } return uaa; } @@ -1818,7 +1820,7 @@ public class ServerConnection implements Runnable { logger.debug("Unexpected exception", npe); } if (uaa == null) { - throw new AuthenticationRequiredException("User authorization attributes not found."); + throw new AuthenticationRequiredException(USER_NOT_FOUND); } return uaa.getPostAuthzRequest(); diff --git a/geode-core/src/main/java/org/apache/geode/security/AuthenticationExpiredException.java b/geode-core/src/main/java/org/apache/geode/security/AuthenticationExpiredException.java new file mode 100644 index 0000000..d4ec79d --- /dev/null +++ b/geode-core/src/main/java/org/apache/geode/security/AuthenticationExpiredException.java @@ -0,0 +1,32 @@ +/* + * 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; + +/** + * This exception is thrown by the SecurityManager's authorize method to indicate that the + * authentication has expired. + */ +public class AuthenticationExpiredException extends GemFireSecurityException { + private static final long serialVersionUID = 1771792091260325297L; + + public AuthenticationExpiredException(String message) { + super(message); + } + + public AuthenticationExpiredException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/geode-core/src/main/java/org/apache/geode/security/SecurityManager.java b/geode-core/src/main/java/org/apache/geode/security/SecurityManager.java index 301b3d5..7487d5f 100644 --- a/geode-core/src/main/java/org/apache/geode/security/SecurityManager.java +++ b/geode-core/src/main/java/org/apache/geode/security/SecurityManager.java @@ -74,8 +74,11 @@ public interface SecurityManager { * @param principal The principal that's requesting the permission * @param permission The permission requested * @return true if authorized, false if not + * + * @throw AuthenticationExpiredException if the principal has expired. */ - default boolean authorize(Object principal, ResourcePermission permission) { + default boolean authorize(Object principal, ResourcePermission permission) + throws AuthenticationExpiredException { return true; } diff --git a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt index 69b6ce0..ca7686b 100644 --- a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt +++ b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt @@ -462,7 +462,6 @@ org/apache/geode/management/internal/functions/RebalanceFunction,true,1 org/apache/geode/management/internal/functions/RestoreRedundancyFunction,true,-8991672237560920252 org/apache/geode/management/internal/operation/OperationState,true,8212319653561969588,locator:java/lang/String,opId:java/lang/String,operation:org/apache/geode/management/api/ClusterManagementOperation,operationEnd:java/util/Date,operationStart:java/util/Date,result:org/apache/geode/management/runtime/OperationResult,throwable:java/lang/Throwable org/apache/geode/management/internal/web/domain/QueryParameterSource,true,34131123582155,objectName:javax/management/ObjectName,queryExpression:javax/management/QueryExp -org/apache/geode/management/internal/web/shell/MBeanAccessException,true,813768898269516238 org/apache/geode/pdx/FieldType,false,defaultSerializedValue:java/nio/ByteBuffer,defaultValue:java/lang/Object,isFixedWidth:boolean,name:java/lang/String,width:int org/apache/geode/pdx/JSONFormatter$states,false org/apache/geode/pdx/JSONFormatterException,true,1 @@ -478,6 +477,7 @@ org/apache/geode/pdx/internal/EnumInfo$PdxInstanceEnumInfo,true,7907582104525106 org/apache/geode/pdx/internal/PdxInputStream,false org/apache/geode/pdx/internal/PdxReaderImpl,true,-6094553093860427759,blobType:org/apache/geode/pdx/internal/PdxType,dis:org/apache/geode/pdx/internal/PdxInputStream org/apache/geode/security/AuthTokenEnabledComponents,false +org/apache/geode/security/AuthenticationExpiredException,true,1771792091260325297 org/apache/geode/security/AuthenticationFailedException,true,-8202866472279088879 org/apache/geode/security/AuthenticationRequiredException,true,4675976651103154919 org/apache/geode/security/GemFireSecurityException,true,3814254578203076926,cause:java/lang/Throwable 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 new file mode 100644 index 0000000..117cc77 --- /dev/null +++ b/geode-core/src/upgradeTest/java/org/apache/geode/security/AuthExpirationDUnitTest.java @@ -0,0 +1,112 @@ +/* + * 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.apache.geode.distributed.ConfigurationProperties.SECURITY_MANAGER; +import static org.apache.geode.test.version.VersionManager.CURRENT_VERSION; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.RestoreSystemProperties; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionShortcut; +import org.apache.geode.cache.client.ClientCache; +import org.apache.geode.cache.client.ClientRegionFactory; +import org.apache.geode.cache.client.ClientRegionShortcut; +import org.apache.geode.test.dunit.rules.ClientVM; +import org.apache.geode.test.dunit.rules.ClusterStartupRule; +import org.apache.geode.test.junit.categories.SecurityTest; +import org.apache.geode.test.junit.rules.ServerStarterRule; +import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory; + +@Category({SecurityTest.class}) +@RunWith(Parameterized.class) +@Parameterized.UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class) +public class AuthExpirationDUnitTest { + + @Parameterized.Parameter + public String clientVersion; + + @Parameterized.Parameters(name = "{0}") + public static Collection<String> data() { + // only test the current version and the latest released version + return Arrays.asList(CURRENT_VERSION, "1.13.3"); + } + + @Rule + public ClusterStartupRule lsRule = new ClusterStartupRule(); + + + @Rule + public RestoreSystemProperties restore = new RestoreSystemProperties(); + + @Rule + public ServerStarterRule server = new ServerStarterRule() + .withProperty(SECURITY_MANAGER, ExpirableSecurityManager.class.getName()) + .withRegion(RegionShortcut.REPLICATE, "region"); + + @After + public void after() { + // make sure after each test, the values of the ExpirationManager are reset + ExpirableSecurityManager.reset(); + } + + @Test + public void clientShouldReAuthenticateWhenCredentialExpiredAndOperationSucceed() + throws Exception { + int serverPort = server.getPort(); + ClientVM clientVM = lsRule.startClientVM(0, clientVersion, + c -> c.withProperty(SECURITY_CLIENT_AUTH_INIT, UpdatableUserAuthInitialize.class.getName()) + .withPoolSubscription(true) + .withServerConnection(serverPort)); + + clientVM.invoke(() -> { + ClientCache clientCache = ClusterStartupRule.getClientCache(); + UpdatableUserAuthInitialize.setUser("user1"); + ClientRegionFactory clientRegionFactory = + clientCache.createClientRegionFactory(ClientRegionShortcut.PROXY); + Region region = clientRegionFactory.create("region"); + region.put(0, "value0"); + }); + + // expire the current user + ExpirableSecurityManager.addExpiredUser("user1"); + + // do a second put, if this is successful, it means new credentials are provided + clientVM.invoke(() -> { + UpdatableUserAuthInitialize.setUser("user2"); + ClientCache clientCache = ClusterStartupRule.getClientCache(); + Region region = clientCache.getRegion("region"); + region.put(1, "value1"); + }); + + // 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); + } + +} 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 new file mode 100644 index 0000000..fc1021d --- /dev/null +++ b/geode-junit/src/main/java/org/apache/geode/security/ExpirableSecurityManager.java @@ -0,0 +1,56 @@ +/* + * 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 java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.geode.examples.SimpleSecurityManager; + +/** + * this is a test security manager that will authenticate credentials when username matches the + * password. It will authorize all operations. It keeps a list of expired users, and will throw + * AuthenticationExpiredException if the user is in that list. This security manager is usually used + * with NewCredentialAuthInitialize. + * + * make sure to call reset after each test to clean things up. + */ +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(); + + @Override + public boolean authorize(Object principal, ResourcePermission permission) { + if (EXPIRED_USERS.contains(principal)) { + throw new AuthenticationExpiredException("User authentication expired."); + } + // always authorized + return true; + } + + public static void addExpiredUser(String user) { + EXPIRED_USERS.add(user); + } + + public static Set<String> getExpiredUsers() { + return EXPIRED_USERS; + } + + public static void reset() { + EXPIRED_USERS.clear(); + } +} diff --git a/geode-junit/src/main/java/org/apache/geode/security/UpdatableUserAuthInitialize.java b/geode-junit/src/main/java/org/apache/geode/security/UpdatableUserAuthInitialize.java new file mode 100644 index 0000000..0a0e6b4 --- /dev/null +++ b/geode-junit/src/main/java/org/apache/geode/security/UpdatableUserAuthInitialize.java @@ -0,0 +1,54 @@ +/* + * 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 java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.geode.distributed.DistributedMember; + +/** + * this is used in conjunction with ExpirableSecurityManager. It will create a new set of + * credentials every time getCredentials are called, and they will always be authenticated + * and authorized by the ExpirableSecurityManager. + * + * make sure reset is called after each test to clean things up. + */ +public class UpdatableUserAuthInitialize implements AuthInitialize { + // use static field for ease of testing since there is only one instance of this in each VM + private static final AtomicReference<String> user = new AtomicReference<>(); + + @Override + public Properties getCredentials(Properties securityProps, DistributedMember server, + boolean isPeer) throws AuthenticationFailedException { + Properties credentials = new Properties(); + credentials.put("security-username", user.get()); + credentials.put("security-password", user.get()); + return credentials; + } + + public static String getUser() { + return user.get(); + } + + public static void setUser(String newValue) { + user.set(newValue); + } + + public static void reset() { + user.set(null); + } +} diff --git a/geode-old-client-support/src/main/java/com/gemstone/gemfire/OldClientSupportProvider.java b/geode-old-client-support/src/main/java/com/gemstone/gemfire/OldClientSupportProvider.java index ccf3c1a..581fc98 100644 --- a/geode-old-client-support/src/main/java/com/gemstone/gemfire/OldClientSupportProvider.java +++ b/geode-old-client-support/src/main/java/com/gemstone/gemfire/OldClientSupportProvider.java @@ -14,6 +14,8 @@ */ package com.gemstone.gemfire; +import static org.apache.geode.internal.cache.tier.sockets.ServerConnection.USER_NOT_FOUND; + import java.io.DataInput; import java.io.DataOutput; import java.util.Map; @@ -27,6 +29,8 @@ import org.apache.geode.internal.cache.tier.sockets.OldClientSupportService; import org.apache.geode.internal.serialization.KnownVersion; import org.apache.geode.internal.serialization.VersionedDataOutputStream; import org.apache.geode.management.internal.beans.CacheServiceMBeanBase; +import org.apache.geode.security.AuthenticationExpiredException; +import org.apache.geode.security.AuthenticationRequiredException; import org.apache.geode.util.internal.GeodeGlossary; import com.gemstone.gemfire.cache.execute.EmtpyRegionFunctionException; @@ -121,11 +125,21 @@ public class OldClientSupportProvider implements OldClientSupportService { if (theThrowable == null) { return theThrowable; } + + String className = theThrowable.getClass().getName(); + + // backward compatibility for authentication expiration + if (clientVersion.isOlderThan(KnownVersion.GEODE_1_15_0)) { + if (className.equals(AuthenticationExpiredException.class.getName())) { + return new AuthenticationRequiredException(USER_NOT_FOUND); + } + } + if (clientVersion.isNotOlderThan(KnownVersion.GFE_90)) { return theThrowable; } - String className = theThrowable.getClass().getName(); + // this class has been renamed, so it cannot be automatically translated // during java deserialization