From ca0776d9778d8390ed34389d8a522a1b7c13bc74 Mon Sep 17 00:00:00 2001 From: John Blum Date: Mon, 24 Jul 2017 18:18:52 -0700 Subject: [PATCH] DATAGEODE-24 - Enable the AutoConfiguredAuthenticationConfigurationIntegrationTests.clientAuthenticatesWithServer() test case. --- ...ConfiguredAuthenticationConfiguration.java | 47 +++++---- ...toConfiguredAuthenticationInitializer.java | 10 +- ...AbstractGeodeSecurityIntegrationTests.java | 95 +++++++++---------- ...yManagerGeodeSecurityIntegrationTests.java | 25 +---- ...ticationConfigurationIntegrationTests.java | 22 ++--- .../annotation/TestSecurityManager.java | 65 ++++++++----- .../ClientServerIntegrationTestsSupport.java | 31 ++++-- 7 files changed, 158 insertions(+), 137 deletions(-) diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfiguration.java index 66b175ee..9d2527ee 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfiguration.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfiguration.java @@ -16,19 +16,18 @@ package org.springframework.data.gemfire.config.annotation; -import java.util.Map; import java.util.Optional; import java.util.Properties; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.data.gemfire.config.annotation.support.AutoConfiguredAuthenticationInitializer; -import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport; -import org.springframework.data.gemfire.util.PropertiesBuilder; import org.springframework.util.StringUtils; /** @@ -40,9 +39,11 @@ import org.springframework.util.StringUtils; * @author John Blum * @see java.util.Properties * @see org.apache.geode.security.AuthInitialize + * @see org.springframework.context.annotation.Bean * @see org.springframework.context.annotation.Condition * @see org.springframework.context.annotation.Conditional * @see org.springframework.context.annotation.Configuration + * @see org.springframework.context.annotation.Import * @see org.springframework.core.env.Environment * @see org.springframework.data.gemfire.config.annotation.EnableBeanFactoryLocator * @see org.springframework.data.gemfire.config.annotation.support.AutoConfiguredAuthenticationInitializer @@ -51,9 +52,10 @@ import org.springframework.util.StringUtils; * @since 2.0.0 */ @Configuration -@EnableBeanFactoryLocator +@Import(BeanFactoryLocatorConfiguration.class) @Conditional(AutoConfiguredAuthenticationConfiguration.AutoConfiguredAuthenticationCondition.class) -public class AutoConfiguredAuthenticationConfiguration extends EmbeddedServiceConfigurationSupport { +@SuppressWarnings("unused") +public class AutoConfiguredAuthenticationConfiguration { protected static final String AUTO_CONFIGURED_AUTH_INIT_STATIC_FACTORY_METHOD = AutoConfiguredAuthenticationInitializer.class.getName().concat(".newAuthenticationInitializer"); @@ -61,29 +63,34 @@ public class AutoConfiguredAuthenticationConfiguration extends EmbeddedServiceCo protected static final String SECURITY_CLIENT_AUTH_INIT = "security-client-auth-init"; protected static final String SECURITY_PEER_AUTH_INIT = "security-peer-auth-init"; - /* (non-Javadoc) */ - @Override - protected Class getAnnotationType() { - return EnableSecurity.class; + @Bean + public ClientCacheConfigurer authenticationCredentialsSettingClientCacheConfigurer(Environment environment) { + return (beanName, beanFactory) -> setAuthenticationCredentials(beanFactory.getProperties(), environment); + } + + @Bean + public PeerCacheConfigurer authenticationCredentialsSettingPeerCacheConfigurer(Environment environment) { + return (beanName, beanFactory) -> setAuthenticationCredentials(beanFactory.getProperties(), environment); } /* (non-Javadoc) */ - @Override - protected Properties toGemFireProperties(Map annotationAttributes) { + private void setAuthenticationCredentials(Properties gemfireProperties, Environment environment) { - return Optional.of(PropertiesBuilder.create()) - .filter(builder -> isMatch(environment())) - .map(builder -> builder - .setProperty(SECURITY_CLIENT_AUTH_INIT, AUTO_CONFIGURED_AUTH_INIT_STATIC_FACTORY_METHOD) - .setProperty(SECURITY_PEER_AUTH_INIT, AUTO_CONFIGURED_AUTH_INIT_STATIC_FACTORY_METHOD)) - .map(PropertiesBuilder::build) - .orElse(null); + Optional.ofNullable(gemfireProperties) + .filter(properties -> isMatch(environment)) + .ifPresent(properties -> { + properties.setProperty(SECURITY_CLIENT_AUTH_INIT, AUTO_CONFIGURED_AUTH_INIT_STATIC_FACTORY_METHOD); + properties.setProperty(SECURITY_PEER_AUTH_INIT, AUTO_CONFIGURED_AUTH_INIT_STATIC_FACTORY_METHOD); + }); } /* (non-Javadoc) */ private static boolean isMatch(Environment environment) { - return StringUtils.hasText(environment.getProperty( - AutoConfiguredAuthenticationInitializer.SDG_SECURITY_USERNAME_PROPERTY)); + + return Optional.ofNullable(environment) + .map(env -> env.getProperty(AutoConfiguredAuthenticationInitializer.SDG_SECURITY_USERNAME_PROPERTY)) + .map(StringUtils::hasText) + .isPresent(); } public static class AutoConfiguredAuthenticationCondition implements Condition { diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/support/AutoConfiguredAuthenticationInitializer.java b/src/main/java/org/springframework/data/gemfire/config/annotation/support/AutoConfiguredAuthenticationInitializer.java index 0dd0472a..6e5c1dff 100644 --- a/src/main/java/org/springframework/data/gemfire/config/annotation/support/AutoConfiguredAuthenticationInitializer.java +++ b/src/main/java/org/springframework/data/gemfire/config/annotation/support/AutoConfiguredAuthenticationInitializer.java @@ -35,6 +35,8 @@ public class AutoConfiguredAuthenticationInitializer extends AbstractAuthInitial public static final String SECURITY_USERNAME_PROPERTY = "security-username"; public static final String SECURITY_PASSWORD_PROPERTY = "security-password"; + protected static final Properties NO_PARAMETERS = new Properties(); + /** * Factory method used to construct a new instance of {@link AutoConfiguredAuthenticationInitializer}. * @@ -42,7 +44,13 @@ public class AutoConfiguredAuthenticationInitializer extends AbstractAuthInitial * @see org.springframework.data.gemfire.config.annotation.support.AutoConfiguredAuthenticationInitializer */ public static AutoConfiguredAuthenticationInitializer newAuthenticationInitializer() { - return new AutoConfiguredAuthenticationInitializer(); + + AutoConfiguredAuthenticationInitializer authenticationInitializer = + new AutoConfiguredAuthenticationInitializer(); + + authenticationInitializer.init(NO_PARAMETERS); + + return authenticationInitializer; } /* (non-Javadoc) */ diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/AbstractGeodeSecurityIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/AbstractGeodeSecurityIntegrationTests.java index 076bb6b9..15ad4902 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/AbstractGeodeSecurityIntegrationTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/AbstractGeodeSecurityIntegrationTests.java @@ -18,9 +18,6 @@ package org.springframework.data.gemfire.config.annotation; import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; import java.io.IOException; import java.io.Serializable; @@ -35,7 +32,6 @@ import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.PostConstruct; import javax.annotation.Resource; -import org.apache.geode.LogWriter; import org.apache.geode.cache.CacheLoader; import org.apache.geode.cache.CacheLoaderException; import org.apache.geode.cache.GemFireCache; @@ -43,17 +39,12 @@ import org.apache.geode.cache.LoaderHelper; import org.apache.geode.cache.Region; import org.apache.geode.cache.client.ClientRegionShortcut; import org.apache.geode.cache.client.ServerOperationException; -import org.apache.geode.distributed.DistributedMember; -import org.apache.geode.security.AuthInitialize; -import org.apache.geode.security.AuthenticationFailedException; import org.apache.geode.security.NotAuthorizedException; import org.apache.geode.security.ResourcePermission; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.FixMethodOrder; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runners.MethodSorters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,6 +54,7 @@ import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Profile; import org.springframework.data.gemfire.LocalRegionFactoryBean; import org.springframework.data.gemfire.client.ClientRegionFactoryBean; +import org.springframework.data.gemfire.config.annotation.support.AbstractAuthInitialize; import org.springframework.data.gemfire.process.ProcessWrapper; import org.springframework.data.gemfire.test.support.ClientServerIntegrationTestsSupport; import org.springframework.data.gemfire.util.CollectionUtils; @@ -80,10 +72,15 @@ import lombok.RequiredArgsConstructor; * Abstract base test class for implementing Apache Geode Integrated Security Integration Tests. * * @author John Blum + * @see java.security.Principal + * @see java.util.Properties * @see org.junit.FixMethodOrder * @see org.junit.Test * @see lombok * @see org.apache.geode.cache.GemFireCache + * @see org.apache.geode.cache.Region + * @see org.springframework.data.gemfire.config.annotation.support.AbstractAuthInitialize + * @see org.springframework.data.gemfire.process.ProcessWrapper * @see org.springframework.data.gemfire.test.support.ClientServerIntegrationTestsSupport * @since 1.0.0 */ @@ -106,6 +103,7 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer @BeforeClass public static void runGeodeServer() throws IOException { + String geodeSecurityProfile = System.getProperty(GEODE_SECURITY_PROFILE_PROPERTY); if (StringUtils.hasText(geodeSecurityProfile)) { @@ -114,13 +112,17 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer } protected static ProcessWrapper runGeodeServer(String geodeSecurityProfile) throws IOException { - Assert.hasText(geodeSecurityProfile, String.format("The '%s' System property must be set", + + Assert.hasText(geodeSecurityProfile, String.format("[%s] System property is required", GEODE_SECURITY_PROFILE_PROPERTY)); + String debugEndpoint = Boolean.getBoolean(DEBUGGING_ENABLED_PROPERTY) ? DEBUG_ENDPOINT : null; + geodeServerProcess = run(GeodeServerConfiguration.class, String.format("-Dgemfire.log-file=%s", logFile()), String.format("-Dgemfire.log-level=%s", logLevel(TEST_GEMFIRE_LOG_LEVEL)), - String.format("-Dspring.profiles.active=apache-geode-server,%s", geodeSecurityProfile)); + String.format("-Dspring.profiles.active=apache-geode-server,%s", geodeSecurityProfile), + debugEndpoint); waitForServerToStart(CACHE_SERVER_HOST, CACHE_SERVER_PORT); @@ -133,9 +135,6 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer stop(geodeServerProcess); } - @Rule - public ExpectedException exception = ExpectedException.none(); - @Resource(name = "Echo") private Region echo; @@ -147,45 +146,24 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer assertThat(echo.get("two")).isEqualTo("four"); } - @Test + @Test(expected = NotAuthorizedException.class) public void unauthorizedUser() { - assertThat(echo.get("one")).isEqualTo("one"); - - exception.expect(ServerOperationException.class); - exception.expectCause(is(instanceOf(NotAuthorizedException.class))); - exception.expectMessage(containsString("analyst not authorized for DATA:WRITE:Echo:two")); - - echo.put("two", "four"); - } - - protected static abstract class AuthInitializeSupport implements AuthInitialize { - - /** - * @inheritDoc - */ - @Override - public void init(LogWriter systemLogger, LogWriter securityLogger) throws AuthenticationFailedException { + try { + assertThat(echo.get("one")).isEqualTo("one"); + echo.put("two", "four"); } + catch (ServerOperationException expected) { + assertThat(expected).hasMessageContaining("analyst not authorized for DATA:WRITE:Echo:two"); + assertThat(expected).hasCauseInstanceOf(NotAuthorizedException.class); - /** - * @inheritDoc - */ - @Override - public Properties getCredentials(Properties securityProperties, DistributedMember server, boolean isPeer) - throws AuthenticationFailedException { - - return getCredentials(securityProperties); + throw (NotAuthorizedException) expected.getCause(); } - - /** - * @inheritDoc - */ - @Override - public void close() { + finally { + assertThat(echo).doesNotContainKey("two"); } } - public static class GeodeClientAuthInitialize extends AuthInitializeSupport { + public static class GeodeClientAuthInitialize extends AbstractAuthInitialize { protected static final User ANALYST = User.newUser("analyst").with("p@55w0rd"); protected static final User SCIENTIST = User.newUser("scientist").with("w0rk!ng4u"); @@ -203,11 +181,10 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer this.user = user; } - /** - * @inheritDoc - */ + /* (non-Javadoc) */ @Override - public Properties getCredentials(Properties securityProperties) { + protected Properties doGetCredentials(Properties securityProperties) { + User user = getUser(); return new PropertiesBuilder() @@ -226,19 +203,23 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer */ @Override public String toString() { + User user = getUser(); + return String.format("%1$s:%2$s", user.getName(), user.getCredentials()); } } @ClientCacheApplication(name = "GeodeSecurityIntegrationTestsClient", logLevel = TEST_GEMFIRE_LOG_LEVEL, servers = { @ClientCacheApplication.Server(port = CACHE_SERVER_PORT) }) - @EnableAuth(clientAuthenticationInitializer = "org.springframework.data.gemfire.config.annotation.AbstractGeodeSecurityIntegrationTests$GeodeClientAuthInitialize.create") + @EnableAuth(clientAuthenticationInitializer = + "org.springframework.data.gemfire.config.annotation.AbstractGeodeSecurityIntegrationTests$GeodeClientAuthInitialize.create") @Profile("apache-geode-client") static class GeodeClientConfiguration { @Bean("Echo") ClientRegionFactoryBean echoRegion(GemFireCache gemfireCache) { + ClientRegionFactoryBean echoRegion = new ClientRegionFactoryBean<>(); echoRegion.setCache(gemfireCache); @@ -268,6 +249,7 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer @Bean("Echo") LocalRegionFactoryBean echoRegion(GemFireCache gemfireCache) { + LocalRegionFactoryBean echoRegion = new LocalRegionFactoryBean<>(); echoRegion.setCache(gemfireCache); @@ -279,7 +261,9 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer } CacheLoader echoCacheLoader() { + return new CacheLoader() { + @Override public String load(LoaderHelper helper) throws CacheLoaderException { return helper.getKey(); @@ -314,6 +298,7 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer /* (non-Javadoc) */ public boolean hasPermission(ResourcePermission permission) { + for (Role role : this) { if (role.hasPermission(permission)) { return true; @@ -346,13 +331,17 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer /* (non-Javadoc) */ public User with(String credentials) { + this.credentials = credentials; + return this; } /* (non-Javadoc) */ public User with(Role... roles) { + Collections.addAll(this.roles, roles); + return this; } } @@ -370,6 +359,7 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer /* (non-Javadoc) */ public boolean hasPermission(ResourcePermission permission) { + for (ResourcePermission thisPermission : this) { if (thisPermission.implies(permission)) { return true; @@ -383,6 +373,7 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer * @inheritDoc */ @Override + @SuppressWarnings("all") public Iterator iterator() { return Collections.unmodifiableSet(this.permissions).iterator(); } @@ -397,7 +388,9 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer /* (non-Javadoc) */ public Role with(ResourcePermission... permissions) { + Collections.addAll(this.permissions, permissions); + return this; } } diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests.java index 29894639..10a9e215 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests.java @@ -58,7 +58,8 @@ public class ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests extends Abs } @Configuration - @EnableSecurity(securityManagerClassName = "org.springframework.data.gemfire.config.annotation.ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests$TestGeodeSecurityManager") + @EnableSecurity(securityManagerClassName = + "org.springframework.data.gemfire.config.annotation.ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests$TestGeodeSecurityManager") @Profile(GEODE_SECURITY_MANAGER_PROPERTY_CONFIGURATION_PROFILE) public static class ApacheGeodeSecurityManagerConfiguration { } @@ -87,28 +88,11 @@ public class ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests extends Abs Set users = new HashSet<>(Arrays.asList(root, scientist, analyst, guest)); default User findBy(String username) { - return users.stream().filter((user) -> user.getName().equals(username)).findFirst().get(); + return users.stream().filter((user) -> user.getName().equals(username)).findFirst().orElse(null); } } - public static abstract class GeodeSecurityManagerSupport implements org.apache.geode.security.SecurityManager { - - /** - * @inheritDoc - */ - @Override - public void init(Properties securityProps) { - } - - /** - * @inheritDoc - */ - @Override - public void close() { - } - } - - public static class TestGeodeSecurityManager extends GeodeSecurityManagerSupport { + public static class TestGeodeSecurityManager implements org.apache.geode.security.SecurityManager { private final GeodeSecurityRepository securityRepository; @@ -121,6 +105,7 @@ public class ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests extends Abs */ @Override public Object authenticate(Properties credentials) throws AuthenticationFailedException { + String username = credentials.getProperty(SECURITY_USERNAME_PROPERTY); String password = credentials.getProperty(SECURITY_PASSWORD_PROPERTY); diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfigurationIntegrationTests.java b/src/test/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfigurationIntegrationTests.java index 9c94d8d2..84194cad 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfigurationIntegrationTests.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/AutoConfiguredAuthenticationConfigurationIntegrationTests.java @@ -31,7 +31,6 @@ import org.apache.geode.cache.client.ClientRegionShortcut; import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -50,6 +49,7 @@ import org.springframework.mock.env.MockPropertySource; * @author John Blum * @since 1.0.0 */ +@SuppressWarnings("unused") public class AutoConfiguredAuthenticationConfigurationIntegrationTests extends ClientServerIntegrationTestsSupport { private static final int PORT = 42124; @@ -64,7 +64,8 @@ public class AutoConfiguredAuthenticationConfigurationIntegrationTests extends C gemfireServerProcess = run(TestGemFireServerConfiguration.class, String.format("-Dgemfire.name=%1$s", asApplicationName(AutoConfiguredAuthenticationConfigurationIntegrationTests.class))); - waitForServerToStart("localhost", PORT); + Optional.ofNullable(gemfireServerProcess) + .ifPresent(server -> waitForServerToStart("localhost", PORT)); } @AfterClass @@ -78,7 +79,7 @@ public class AutoConfiguredAuthenticationConfigurationIntegrationTests extends C } private ConfigurableApplicationContext newApplicationContext(PropertySource testPropertySource, - Class... annotatedClasses) { + Class... annotatedClasses) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); @@ -94,9 +95,8 @@ public class AutoConfiguredAuthenticationConfigurationIntegrationTests extends C } @Test - @Ignore @SuppressWarnings("unchecked") - public void clientAuthenticatedWithServer() { + public void clientAuthenticatesWithServer() { MockPropertySource testPropertySource = new MockPropertySource() .withProperty("spring.data.gemfire.security.username", SECURITY_USERNAME) @@ -109,11 +109,13 @@ public class AutoConfiguredAuthenticationConfigurationIntegrationTests extends C Region echo = this.applicationContext.getBean("Echo", Region.class); + assertThat(echo.get("Hello")).isEqualTo("Hello"); assertThat(echo.get("TEST")).isEqualTo("TEST"); + assertThat(echo.get("Good-Bye")).isEqualTo("Good-Bye"); } @EnableSecurity - @ClientCacheApplication(servers = @ClientCacheApplication.Server(port = PORT)) + @ClientCacheApplication(logLevel = TEST_GEMFIRE_LOG_LEVEL, servers = @ClientCacheApplication.Server(port = PORT)) static class TestGemFireClientConfiguration { @Bean("Echo") @@ -129,16 +131,12 @@ public class AutoConfiguredAuthenticationConfigurationIntegrationTests extends C } } - @CacheServerApplication(port = PORT) + @CacheServerApplication(logLevel = TEST_GEMFIRE_LOG_LEVEL, port = PORT) @EnableSecurity(securityManagerClassName = "org.springframework.data.gemfire.config.annotation.TestSecurityManager") static class TestGemFireServerConfiguration { public static void main(String[] args) { - - ConfigurableApplicationContext applicationContext = - new AnnotationConfigApplicationContext(TestGemFireServerConfiguration.class); - - applicationContext.registerShutdownHook(); + runSpringApplication(TestGemFireServerConfiguration.class, args); } @Bean("Echo") diff --git a/src/test/java/org/springframework/data/gemfire/config/annotation/TestSecurityManager.java b/src/test/java/org/springframework/data/gemfire/config/annotation/TestSecurityManager.java index 0f8ae926..0015b5d8 100644 --- a/src/test/java/org/springframework/data/gemfire/config/annotation/TestSecurityManager.java +++ b/src/test/java/org/springframework/data/gemfire/config/annotation/TestSecurityManager.java @@ -16,16 +16,19 @@ package org.springframework.data.gemfire.config.annotation; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.springframework.data.gemfire.config.annotation.TestSecurityManager.TestPrincipal.newPrincipal; +import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException; import java.security.Principal; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.geode.security.AuthenticationFailedException; -import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; /** * The {@link TestSecurityManager} class is an Apache Geode / Pivotal GemFire @@ -34,17 +37,18 @@ import org.springframework.util.ObjectUtils; * @author John Blum * @see java.security.Principal * @see java.util.Properties + * @see javax.security.auth.Subject * @see org.apache.geode.security.SecurityManager * @since 2.0.0 */ public final class TestSecurityManager implements org.apache.geode.security.SecurityManager { + public static final String SECURITY_USERNAME = "testUser"; + public static final String SECURITY_PASSWORD = "&t35t9@55w0rd!"; + public static final String SECURITY_USERNAME_PROPERTY = "security-username"; public static final String SECURITY_PASSWORD_PROPERTY = "security-password"; - public static final String SECURITY_USERNAME = "testUser"; - public static final String SECURITY_PASSWORD = "testP@55w0rd"; - private final ConcurrentMap authorizedUsers; public TestSecurityManager() { @@ -52,34 +56,49 @@ public final class TestSecurityManager implements org.apache.geode.security.Secu this.authorizedUsers.putIfAbsent(SECURITY_USERNAME, SECURITY_PASSWORD); } + protected Map getAuthorizedUsers() { + return Collections.unmodifiableMap(this.authorizedUsers); + } + @Override - public Object authenticate(Properties properties) throws AuthenticationFailedException { + public Object authenticate(Properties credentials) throws AuthenticationFailedException { - String username = properties.getProperty(SECURITY_USERNAME_PROPERTY); - String password = properties.getProperty(SECURITY_PASSWORD_PROPERTY); + String username = credentials.getProperty(SECURITY_USERNAME_PROPERTY); + String password = credentials.getProperty(SECURITY_PASSWORD_PROPERTY); - return validateIdentified(isIdentified(username, password) ? newPrincipal(username) : null, username); + return Optional.ofNullable(identify(username, password)).orElseThrow(() -> + new AuthenticationFailedException(String.format("User [%s] is not authorized", username))); + } + + private Principal identify(String username, String password) { + return (isIdentified(username, password) ? newPrincipal(username) : null); } private boolean isIdentified(String username, String password) { - return ObjectUtils.nullSafeEquals(this.authorizedUsers.get(String.valueOf(username)), password); + + return Optional.ofNullable(username) + .filter(StringUtils::hasText) + .map(user -> getAuthorizedUsers().get(user)) + .map(userPassword -> userPassword.equals(password)) + .orElse(false); } - private Principal newPrincipal(String username) { + public static final class TestPrincipal implements java.security.Principal, java.io.Serializable { - Principal mockPrincipal = mock(Principal.class, username); + private final String name; - when(mockPrincipal.getName()).thenReturn(username); - - return mockPrincipal; - } - - private Principal validateIdentified(Principal principal, String username) { - - if (principal == null) { - throw new AuthenticationFailedException(String.format("User [%s] is not valid", username)); + public static TestPrincipal newPrincipal(String username) { + return new TestPrincipal(username); } - return principal; + public TestPrincipal(String name) { + this.name = Optional.ofNullable(name).filter(StringUtils::hasText) + .orElseThrow(() -> newIllegalArgumentException("Name is required")); + } + + @Override + public String getName() { + return this.name; + } } } diff --git a/src/test/java/org/springframework/data/gemfire/test/support/ClientServerIntegrationTestsSupport.java b/src/test/java/org/springframework/data/gemfire/test/support/ClientServerIntegrationTestsSupport.java index 32605e9f..da4192ab 100644 --- a/src/test/java/org/springframework/data/gemfire/test/support/ClientServerIntegrationTestsSupport.java +++ b/src/test/java/org/springframework/data/gemfire/test/support/ClientServerIntegrationTestsSupport.java @@ -27,6 +27,7 @@ import java.net.ServerSocket; import java.net.Socket; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -58,13 +59,15 @@ public class ClientServerIntegrationTestsSupport { protected static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(30); protected static final long DEFAULT_WAIT_INTERVAL = 500L; // milliseconds + protected static final String DEBUG_ENDPOINT = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"; + protected static final String DEBUGGING_ENABLED_PROPERTY = "spring.data.gemfire.debugging.enabled"; protected static final String DEFAULT_HOSTNAME = "localhost"; protected static final String DIRECTORY_DELETE_ON_EXIT_PROPERTY = "spring.data.gemfire.directory.delete-on-exit"; protected static final String GEMFIRE_CACHE_SERVER_PORT_PROPERTY = "spring.data.gemfire.cache.server.port"; protected static final String GEMFIRE_LOG_FILE = "gemfire-server.log"; - protected static final String GEMFIRE_LOG_FILE_PROPERTY = "spring.data.gemfire.gemfire.log.file"; + protected static final String GEMFIRE_LOG_FILE_PROPERTY = "spring.data.gemfire.log.file"; protected static final String GEMFIRE_LOG_LEVEL = "warning"; - protected static final String GEMFIRE_LOG_LEVEL_PROPERTY = "spring.data.gemfire.gemfire.log.level"; + protected static final String GEMFIRE_LOG_LEVEL_PROPERTY = "spring.data.gemfire.log.level"; protected static final String PROCESS_RUN_MANUAL_PROPERTY = "spring.data.gemfire.process.run-manual"; protected static final String SYSTEM_PROPERTIES_LOG_FILE = "system-properties.log"; protected static final String TEST_GEMFIRE_LOG_LEVEL = "warning"; @@ -87,6 +90,7 @@ public class ClientServerIntegrationTestsSupport { /* (non-Javadoc) */ protected static File createDirectory(File directory) { + assertThat(directory.isDirectory() || directory.mkdirs()) .as(String.format("Failed to create directory [%s]", directory)).isTrue(); @@ -99,6 +103,7 @@ public class ClientServerIntegrationTestsSupport { /* (non-Javadoc) */ protected static int findAvailablePort() throws IOException { + ServerSocket serverSocket = null; try { @@ -232,17 +237,19 @@ public class ClientServerIntegrationTestsSupport { /* (non-Javadoc) */ protected static boolean stop(ProcessWrapper process, long duration) { - if (process != null) { - process.stop(duration); - if (process.isNotRunning() && isDeleteDirectoryOnExit()) { - FileSystemUtils.deleteRecursive(process.getWorkingDirectory()); - } + return Optional.ofNullable(process) + .map(it -> { - return process.isRunning(); - } + it.stop(duration); - return true; + if (it.isNotRunning() && isDeleteDirectoryOnExit()) { + FileSystemUtils.deleteRecursive(it.getWorkingDirectory()); + } + + return it.isRunning(); + }) + .orElse(true); } /* (non-Javadoc) */ @@ -262,10 +269,13 @@ public class ClientServerIntegrationTestsSupport { /* (non-Javadoc) */ protected static boolean waitForServerToStart(final String host, final int port, long duration) { + return ThreadUtils.timedWait(duration, DEFAULT_WAIT_INTERVAL, new ThreadUtils.WaitCondition() { + AtomicBoolean connected = new AtomicBoolean(false); public boolean waiting() { + Socket socket = null; try { @@ -291,6 +301,7 @@ public class ClientServerIntegrationTestsSupport { @SuppressWarnings("all") protected static boolean waitOn(Condition condition, long duration) { + long timeout = (System.currentTimeMillis() + duration); try {