DATAGEODE-55 - Adapt to Apache Geode Integrated Security Framework changes.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user