Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreOn behalf of the Spring and Apache Geode communities, I am extremely pleased and excited to announce the release of Spring Data for Apache Geode 1.0.0-incubating.
You can get the bits from Maven Central by including the following dependency in either your application Maven POM or Gradle build file...
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-geode</artifactId>
<version>1.0.0.INCUBATING-RELEASE</version>
</dependency>
compile 'org.springframework.data:spring-data-geode:1.0.0.INCUBATING-RELEASE'
Including the spring-data-geode
dependency will transitively pull in all required Apache Geode artifacts so you can start building Spring applications that use Apache Geode now.
I changed the version qualifier again by removing the
APACHE-GEODE
qualification and simplifying toINCUBATING-RELEASE
. Once Apache Geode graduates, theINCUBATING
qualification will drop off as well and the version number will simply becomemajor.minor.maint.[M#|RC#|RELEASE]
.
Both Spring Data Geode 1.0.0.INCUBATING-RELEASE and Apache Geode 1.0.0-incubating release are significant for several reasons.
First and foremost, this marks the first, official GA release of Apache Geode inside the Apache Software Foundation (ASF). This is a massive step forward not only to signify the maturity of Geode, which is rooted in over a decade of production experience that is Pivotal GemFire, but also accelerates it's graduation as a Top-Level Project (TLP) inside ASF.
But, that's not all!
This release also incorporates significant changes to the security model of Apache Geode by introducing a new, Integrated Security framework (some technical details here) that not only includes secure transport (i.e. SSL) but authentication and authorization as well.
This is significant because Apache Geode is one of the few OSS IMDG options to offer Security without an Enterprise license!
One of the best things about this new feature is that it is a framework allowing different security providers to be plugged in. Out-of-the-box, Geode is built on Apache Shiro, which provides a familiar and robust way to configure security not only for Geode, but your applications as well.
Without Spring (Data Geode), Apache Geode provides its own options for configuring security.
One option is to implement the Apache Geode SecurityManager interface and set the corresponding Geode security-manager
(System) property to the fully-qualified class name. An example of this can be seen here.
But, using a property to reference a FQCN severely limits how you configure the SecurityManager
in a managed environment or test context. Per my feedback, this will be addressed in a later Geode release.
Another option is to use Apache Geode's security-shiro-init
(System) property to specify an INI configuration file located in a designated resource path supported by Apache Shiro. However, this is limiting for 2 reasons.
First, Apache Geode only supports the classpath:
resource specifier at present (also being addressed by the Geode engineering team). Second, having to learn yet another configuration file format, no matter how standard, is well, no better than XML, IMO.
Of course, Apache Shiro tries to alleviate the pain when running in a Spring context by offering this. But, there is still too much boilerplate configuration logic left to be desired.
In the spirit of making Apache Geode quick and as easy to use as possible (see my last blog post), I have been collaborating closely with the Geode engineering team to improve on the initial design and really make Integrated Security a first-class citizen in Spring Data Geode by employing many of the fundamental API and framework design concepts popularized by the Spring Framework and Spring Boot.
So, I give you the new @EnableSecurity
annotation in SDG's new Annotation-based configuration model. You have several ways in which to configure Apache Geode's security features using the annotation.
You can still reference a Geode SecurityManager
implementation by its fully-qualified class name using...
package example;
class ExampleSecurityManager
implements org.apache.geode.security.SecurityManager {
...
}
@CacheServerApplication(name = "ClassNameExample")
@EnableSecurity(securityManagerClassName = "example.ExampleSecurityManager")
class ExampleApplication {
...
}
A more detailed example can be seen in the SDG Contacts Application RI, here.
However, you must provide a default, no-arg constructor, and your Geode SecurityManager
implementation will be responsible for loading all the security authentication/authorization details upon construction; not very ideal.
Another option is to create a Proxy
implementing the Geode SecurityManager
interface, which delegates to an actual, underlying Geode SecurityManager
configured in and injected by the Spring container, or other managed environment like Pivotal CloudFoundry.
One such Proxy
implementation can been seen in the RI here, and is configured as follows...
@CacheServerApplication(name = "ProxyExample")
@EnableSecurity(securityManagerClassName =
"example.app.geode.security.SecurityManagerProxy",
useBeanFactoryLocator = true)
class ExampleApplication {
...
@Bean
JdbcSecurityRepository securityRepository(JdbcTemplate template) {
return new JdbcSecurityRepository(template);
}
@Bean
SimpleSecurityManager securityManager(
SecurityRepository<User> securityRepository) {
return new SimpleSecurityManager(securityRepository);
}
}
The SecurityMangerProxy
is constructed by Apache Geode during cache initialization. The Spring container will find the SimpleSecurityManager bean definition and inject it into the SecurityManagerProxy
.
The SecurityManagerProxy
works by leveraging another Spring feature, the BeanFactoryLocator, which is used by SDG, as mentioned in the Reference Guide (and here), to configure and auto-wire objects constructed and initialized outside of the Spring container, such as by Apache Geode.
This is useful in situations where an application object (e.g. CacheLoader) may have been defined in Geode's native cache.xml
config and needs to be auto-wired with bean(s) (e.g. DataSource
) defined in the Spring container. This also works for objects referenced in Geode (System) properties like the SecurityManager
.
The SecurityManagerProxy
must extend the LazyWiringDeclarableSupport class, which enables the Proxy
to be auto-wired by the Spring container using the BeanFactoryLocator
once Geode constructs the object. It's quite slick actually.
You can see the complete example configuration in the RI here. This also requires the useBeanFactoryLocator
attribute to be set to true on the Geode Server, Spring Boot application class, which is shown in the example above as well.
Perhaps you do not want to unnecessarily couple your application code to Geode's proprietary classes and interfaces, such as the SecurityManager
. Perhaps you just want to fully utilize Apache Shiro`s security framework.
One way to do this is to create an Apache Shiro INI configuration file and reference it in the @EnableSecurity
annotation like so...
@CacheServerApplication(name = "ProxyExample")
@EnableSecurity(shiroIniResourcePath = "my-shiro.ini")
class ExampleApplication {
...
}
Again, the Apache Shiro INI file must be on the classpath. Due to the present Apache Geode limitation, it is not possible to use other resource specifiers (e.g. file:
or url:
).
This completed example configuration can be seen here.
However, what you, as an application developer, really want to do is just define Apache Shiro Realms
as Spring beans in the Spring container to access the security meta-data needed by your application to secure Apache Geode and have Spring do all the work.
Well, SDG can do that for you too. For example...
@CacheServerApplication(name = "RealmExample")
@EnableSecurity
class ExampleApplication {
@Bean
PropertiesRealm shiroRealm() {
PropertiesRealm propertiesRealm = new PropertiesRealm();
propertiesRealm.setResourcePath("classpath:shiro.properties");
propertiesRealm.setPermissionResolver(new GeodePermissionResolver());
return propertiesRealm;
}
}
That's it; that is all you need.
Notice the Shiro PropertiesRealm uses the GeodePermissionResolver
to resolve Geode permissions. Additionally, you have the option to specify whatever resource path you choose; you are not restricted to the classpath:
only.
You are also free to define whatever Realms
(e.g. JDBC, JNDI, LDAP, etc) provided by Shiro that your application uses to access its security meta-data.
If you define more than one Shiro Realm
, you can even order them using Spring's @Order
annotation on the Realm
bean definitions, like so...
@CacheServerApplication(name = "OrderedMultiRealmExample")
@EnableSecurity
class ExampleApplication {
@Bean
@Order(1)
IniRealm iniRealm() {
IniRealm iniRealm = new IniRealm("classpath:partial-shiro.ini");
iniRealm.setPermissionResolver(new GeodePermissionResolver());
return iniRealm;
}
@Bean
@Order(2)
PropertiesRealm propertiesRealm() {
PropertiesRealm propertiesRealm = new PropertiesRealm();
propertiesRealm.setResourcePath("classpath:partial-shiro.properties");
propertiesRealm.setPermissionResolver(new GeodePermissionResolver());
return propertiesRealm;
}
}
Realm
ordering is an important factor in the authentication strategy used in Apache Shiro's Authentication Sequence.
You can can see multiple example configurations of using Shiro Realms
in the RI here.
We covered a lot of ground, but still, there is more work to do. Specifically, I intend on doing the following...
Much more is in the works, so stay tuned.
See the changelog for additional details.
As always, feedback is most welcomed and you can reach out to us in JIRA or on StackOverflow.
Thank you all! Happy coding.