DATAGEODE-55 - Adapt to Apache Geode Integrated Security Framework changes.

This commit is contained in:
John Blum
2017-11-11 16:13:37 -08:00
parent ca5585293c
commit 6fc39d0095
7 changed files with 41 additions and 70 deletions

View File

@@ -18,9 +18,8 @@
package org.springframework.data.gemfire.config.annotation;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import java.lang.reflect.Field;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -28,7 +27,6 @@ import java.util.Map;
import java.util.Optional;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.internal.security.SecurityService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.Realm;
@@ -36,6 +34,7 @@ import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
@@ -44,13 +43,12 @@ import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.OrderComparator;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.config.annotation.support.AbstractAnnotationConfigSupport;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.data.gemfire.util.SpringUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
/**
* The {@link ApacheShiroSecurityConfiguration} class is a Spring {@link Configuration @Configuration} component
@@ -86,7 +84,7 @@ public class ApacheShiroSecurityConfiguration extends AbstractAnnotationConfigSu
* @see org.springframework.data.gemfire.config.annotation.EnableSecurity
*/
@Override
protected Class getAnnotationType() {
protected Class<? extends Annotation> getAnnotationType() {
return EnableSecurity.class;
}
@@ -120,6 +118,14 @@ public class ApacheShiroSecurityConfiguration extends AbstractAnnotationConfigSu
return (ListableBeanFactory) getBeanFactory();
}
@Bean
public BeanFactoryPostProcessor shiroGemFireBeanFactoryPostProcessor() {
return configurableListableBeanFactory ->
SpringUtils.addDependsOn(configurableListableBeanFactory.getBeanDefinition("gemfireCache"),
"shiroSecurityManager");
}
/**
* {@link Bean} definition to define, configure and register an Apache Shiro Spring
* {@link LifecycleBeanPostProcessor} to automatically call lifecycle callback methods
@@ -157,29 +163,16 @@ public class ApacheShiroSecurityConfiguration extends AbstractAnnotationConfigSu
* with the Apache Shiro security framework but Apache Geode security could not be enabled.
* @see org.apache.shiro.mgt.SecurityManager
* @see #registerSecurityManager(org.apache.shiro.mgt.SecurityManager)
* @see #enableApacheGeodeSecurity()
* @see #resolveRealms()
* @see #registerSecurityManager(org.apache.shiro.mgt.SecurityManager)
* @see #enableApacheGeodeSecurity()
*/
@Bean
public org.apache.shiro.mgt.SecurityManager shiroSecurityManager(GemFireCache gemfireCache) {
public org.apache.shiro.mgt.SecurityManager shiroSecurityManager() {
org.apache.shiro.mgt.SecurityManager shiroSecurityManager = null;
List<Realm> realms = resolveRealms();
if (!realms.isEmpty()) {
shiroSecurityManager = registerSecurityManager(new DefaultSecurityManager(realms));
if (!enableApacheGeodeSecurity()) {
throw newIllegalStateException("Failed to enable security services in %s",
GemfireUtils.apacheGeodeProductName());
}
}
return shiroSecurityManager;
return Optional.ofNullable(resolveRealms())
.filter(realms -> !realms.isEmpty())
.map(realms -> new DefaultSecurityManager(realms))
.map(this::registerSecurityManager)
.orElse(null);
}
/**
@@ -198,7 +191,9 @@ public class ApacheShiroSecurityConfiguration extends AbstractAnnotationConfigSu
protected List<Realm> resolveRealms() {
try {
Map<String, Realm> realmBeans = getListableBeanFactory().getBeansOfType(Realm.class, false, true);
Map<String, Realm> realmBeans = getListableBeanFactory().getBeansOfType(Realm.class,
false, false);
List<Realm> realms = new ArrayList<>(CollectionUtils.nullSafeMap(realmBeans).values());
@@ -231,40 +226,6 @@ public class ApacheShiroSecurityConfiguration extends AbstractAnnotationConfigSu
return securityManager;
}
/**
* Sets the Apache Geode, Integrated Security {@link SecurityService} property {@literal isIntegratedSecurity}
* to {@literal true} to indicate that Apache Geode security is enabled.
*
* @return a boolean value indicating whether Apache Geode's Integrated Security framework services
* were successfully enabled.
* @see org.apache.geode.internal.security.SecurityService#getSecurityService()
*/
protected boolean enableApacheGeodeSecurity() {
SecurityService securityService = SecurityService.getSecurityService();
if (securityService != null) {
String isIntegratedSecurityFieldName = "isIntegratedSecurity";
Field isIntegratedSecurity = ReflectionUtils.findField(securityService.getClass(),
isIntegratedSecurityFieldName, Boolean.class);
isIntegratedSecurity = Optional.ofNullable(isIntegratedSecurity).orElseGet(() ->
ReflectionUtils.findField(securityService.getClass(), isIntegratedSecurityFieldName, Boolean.TYPE));
if (isIntegratedSecurity != null) {
ReflectionUtils.makeAccessible(isIntegratedSecurity);
ReflectionUtils.setField(isIntegratedSecurity, securityService, Boolean.TRUE);
return true;
}
}
return false;
}
/**
* A Spring {@link Condition} to determine whether the user has included (declared) the 'shiro-spring' dependency
* on their application's classpath, which is necessary for configuring Apache Shiro to secure Apache Geode

View File

@@ -47,8 +47,11 @@ import org.springframework.context.annotation.Import;
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Import({ ApacheShiroSecurityConfiguration.class, AutoConfiguredAuthenticationConfiguration.class,
GeodeIntegratedSecurityConfiguration.class })
@Import({
ApacheShiroSecurityConfiguration.class,
AutoConfiguredAuthenticationConfiguration.class,
GeodeIntegratedSecurityConfiguration.class
})
@UsesGemFireProperties
@SuppressWarnings({ "unused" })
public @interface EnableSecurity {

View File

@@ -17,6 +17,7 @@
package org.springframework.data.gemfire.config.annotation;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Properties;
@@ -47,7 +48,7 @@ public class GeodeIntegratedSecurityConfiguration extends EmbeddedServiceConfigu
* @see org.springframework.data.gemfire.config.annotation.EnableSecurity
*/
@Override
protected Class getAnnotationType() {
protected Class<? extends Annotation> getAnnotationType() {
return EnableSecurity.class;
}

View File

@@ -141,6 +141,7 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer
@Test
@DirtiesContext
public void authorizedUser() {
assertThat(echo.get("one")).isEqualTo("one");
assertThat(echo.put("two", "four")).isNull();
assertThat(echo.get("two")).isEqualTo("four");
@@ -148,11 +149,13 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer
@Test(expected = NotAuthorizedException.class)
public void unauthorizedUser() {
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);
@@ -233,9 +236,9 @@ public abstract class AbstractGeodeSecurityIntegrationTests extends ClientServer
@CacheServerApplication(name = "GeodeSecurityIntegrationTestsServer", logLevel = TEST_GEMFIRE_LOG_LEVEL,
port = CACHE_SERVER_PORT)
@Import({
ApacheShiroIniGeodeSecurityIntegrationTests.ApacheShiroIniConfiguration.class,
ApacheShiroRealmGeodeSecurityIntegrationTests.ApacheShiroRealmConfiguration.class,
ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests.ApacheGeodeSecurityManagerConfiguration.class
ApacheShiroIniSecurityIntegrationTests.ApacheShiroIniConfiguration.class,
ApacheShiroRealmSecurityIntegrationTests.ApacheShiroRealmConfiguration.class,
ApacheGeodeSecurityManagerSecurityIntegrationTests.ApacheGeodeSecurityManagerConfiguration.class
})
@Profile("apache-geode-server")
public static class GeodeServerConfiguration {

View File

@@ -47,7 +47,7 @@ import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = AbstractGeodeSecurityIntegrationTests.GeodeClientConfiguration.class)
@ActiveProfiles("apache-geode-client")
public class ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests extends AbstractGeodeSecurityIntegrationTests {
public class ApacheGeodeSecurityManagerSecurityIntegrationTests extends AbstractGeodeSecurityIntegrationTests {
protected static final String GEODE_SECURITY_MANAGER_PROPERTY_CONFIGURATION_PROFILE =
"geode-security-manager-property-configuration";
@@ -59,7 +59,7 @@ public class ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests extends Abs
@Configuration
@EnableSecurity(securityManagerClassName =
"org.springframework.data.gemfire.config.annotation.ApacheGeodeSecurityManagerGeodeSecurityIntegrationTests$TestGeodeSecurityManager")
"org.springframework.data.gemfire.config.annotation.ApacheGeodeSecurityManagerSecurityIntegrationTests$TestGeodeSecurityManager")
@Profile(GEODE_SECURITY_MANAGER_PROPERTY_CONFIGURATION_PROFILE)
public static class ApacheGeodeSecurityManagerConfiguration {
}

View File

@@ -37,7 +37,7 @@ import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = AbstractGeodeSecurityIntegrationTests.GeodeClientConfiguration.class)
@ActiveProfiles("apache-geode-client")
public class ApacheShiroIniGeodeSecurityIntegrationTests extends AbstractGeodeSecurityIntegrationTests {
public class ApacheShiroIniSecurityIntegrationTests extends AbstractGeodeSecurityIntegrationTests {
protected static final String SHIRO_INI_CONFIGURATION_PROFILE = "shiro-ini-configuration";

View File

@@ -41,7 +41,7 @@ import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = AbstractGeodeSecurityIntegrationTests.GeodeClientConfiguration.class)
@ActiveProfiles("apache-geode-client")
public class ApacheShiroRealmGeodeSecurityIntegrationTests extends AbstractGeodeSecurityIntegrationTests {
public class ApacheShiroRealmSecurityIntegrationTests extends AbstractGeodeSecurityIntegrationTests {
protected static final String SHIRO_REALM_CONFIGURATION_PROFILE = "shiro-realm-configuration";
@@ -58,9 +58,12 @@ public class ApacheShiroRealmGeodeSecurityIntegrationTests extends AbstractGeode
@Bean
public PropertiesRealm shiroRealm() {
PropertiesRealm propertiesRealm = new PropertiesRealm();
propertiesRealm.setResourcePath("classpath:shiro.properties");
propertiesRealm.setPermissionResolver(new GeodePermissionResolver());
return propertiesRealm;
}
}