Posts Tagged ‘spring security

24
Sep
09

Integration of Spring Security into Grails – plugin approach 3

In this post, as mentioned earlier, I will explain how my spring security 2.0.5 ACL (access control list) enhancement of the acegi security plugin 0.5.1 for Grails can be configured. My work bases on Stephan February’s solution for the 0.3 plugin version and acegi security. Apart from the implementation changes within the plugin, the plugin configuration only has minor changes. This is the reason why it is strongly advised to read Stephan’s blog post before continuing with this article as I will only mention major differences between the configuration of his plugin version and mine.

One difference in my version is the possibility of applying ACLs to method parameters (see 2.1 for an example):

For this to work custom voters have to be defined. A custom definition for the example of Stephan’s blog post looks as follows:

springSecACLVoters = [ //this map must be called 'springSecACLVoters'
			aclReportWriteVoter: [// custom beanName
			domainObjectClass: 'Report', // which type of domainclass will be secured
			roleName: 'ACL_REPORT_WRITE', // under which name the voter should be referenced later? Must start with 'ACL_'
			permissions: [ org.springframework.security.acls.domain.BasePermission.ADMINISTRATION,
			org.springframework.security.acls.domain.BasePermission.WRITE] // which concrete permissions will be checked if 'ACL_REPORT_WRITE' is specified
			],
			aclReportDeleteVoter: [
			domainObjectClass: 'Report',
			roleName: 'ACL_REPORT_DELETE',
			permissions: [ org.springframework.security.acls.domain.BasePermission.DELETE]			
			]
	]

I added comments in the corresponding lines to describe the single options in detail. As you can see more than one voter can be defined as long as the map name is ‘springSecACLVoters’ and the map is defined in SecurityConfig.groovy. Please note that if you do not need method parameter checking with ACLs you can simply omit the map configuration of voters.

Aside from the definition of custom voters and for applying ACLs to method parameters I added three other options to SecurityConfig.groovy:

useAcl = true // defaults to false, optional
aclClassIdentityQuery="SELECT @@IDENTITY" // this query is for MySQL, default is 'identity()' for hsqldb, optional
aclSidIdentityQuery="SELECT @@IDENTITY" // this query is for MySQL, default is 'identity()' for hsqldb, optional

If you want to use ACL extensions in general useAcl must be specified and set to “true”. Furthermore the enhancement uses the default JdbcMutableAclService implementation of Spring. For this reason you must have the possibility to change its identity queries (look here) to match your database. This can be done with the two corresponding options. The code snippet above shows working example values for hsqldb and MySQL.

Apart from feature and configuration changes the infrastructure of the plugin did also undergo a change since Stephan’s version: Because of the move of the ACL domain classes into the plugin domain directory the Gant target “CreateAclDomains” is no longer needed.

Therewith the description of the plugin configuration is complete. Some issues however remain to be done:

  1. Calling of acl security functionality when using ‘run-app’ may raise a class not found exception which will not be raised when ‘run-war’ is used. I have to examine this more precisely and eventually file a bug report.
  2. Test cases should be developed before a possible integration of the code into the main acegi security plugin tree. I am in contact with Burt Beckwith to get this working.
  3. I have to upload the code to the GRAILSPLUGINS-723 JIRA task so that Burt Beckwith can decide on a possible integration into the acegi plugin version control tree. I will do this within the next week as I am very busy at the moment.

I hope this helps somebody
Feedback is greatly appreciated

Regards,
Phillip

Jump to other parts of this series:

19
Sep
09

Integration of Spring Security into Grails – plugin approach 1

This blog post describes problems and challenges when porting Stephan February’s solution from acegi security and acegiSecurityPlugin 0.3 to acegiSecurityPlugin 0.5.1 and Spring Security 2.0.5.

One issue was the fact that the whole API names changed from acegi security to spring security and that few api calls changed. Also the libraries had to be changed to work with Spring Security 2.0.5. In this case the grails maven project of the “Spring Way” mentioned before was of great help because maven’s calculated dependencies could simply be copied to the plugin. In this way all Java method.invocation errors went away magically :-). Regrettably the domain classes of Stephan’s solution could not be used any further because the whole schema had changed from Acegi security to Spring Security. That is why I decided to continue the usage of the standard JDBCMutableAclService of Spring in combination with a simple Spring bean which controls the deletion and creation of schemata with plain SQL commands.

Apart from these issues I learned to work with the Grails plugin and the Spring Security API and digged deeper into interceptor technology, expando meta classes, the Grails Bean Builder DSL and Spring Security as a whole.

I already mentioned that our Image Site makes use of very fine grained permission control for which reason it was not acceptable to us that Stephan’s solution did not support applying ACLs (Access Control Lists) to method parameters. For example this could turn out to be very useful if a user wants to delete an image and the deletion method is able to check whether the user has the correct permission on the given image object. This is the reason why I tried to implement applying ACLs to method parameters. Details of the implementation and arising problems will be subject to my next blog post.

Regards,
Phillip

Jump to other parts of this series:

19
Sep
09

Integration of Spring Security into Grails – Spring approach

In the last post of the security layer we decided to integrate Spring Domain Object Security the ‘Spring Way’ into our Grails application. This means that I tried to integrate the security concept without implementing or enhancing Grails or the acegi security plugin. Testable functionality was provided by the contact sample application of Spring Security. This was achieved by using a plain spring configuration file which was referenced from grails-app/config/spring/resources.xml

As we planned to use MySQL as our datasource several changes had to be done to the default configuration. First I needed to provide a different database schema which luckily could be found on Jim Bernatowicz’ Website. Apart from this the identity queries of Spring’s JdbcMutableAclService had to be adapted like this to support MySQL:

<bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
    <constructor-arg ref="dataSource"/>
    <constructor-arg ref="lookupStrategy"/>
    <constructor-arg ref="aclCache"/>
    <property name="classIdentityQuery" value="SELECT @@IDENTITY"/>
    <property name="sidIdentityQuery" value="SELECT @@IDENTITY"/>	
</bean>

Another problem I faced was that grails run:app threw errors when trying to find some security classes. Strange to say grails run:war worked perfectly. As we did not need grails:run-app functionality I decided to postpone this problem.

Apart from these issues this solution worked, but only for Java classes. An integration of Groovy classes into Spring like http://www.javabeat.net/articles/46-integrating-spring-and-groovy-1.html seemed heavy weighted and cumbersome to me. For this reason and with more Spring Security insight I decided to look deeper into the plugin approach of Stephan February and port it to the version 0.5.1 of the acegi-security plugin which will be part of the next blog post.

Regards,
Phillip

Jump to other parts of this series:

19
Sep
09

The Decision

As you probably already know when reading this blog our project consists of building an image managing website based on Grails with fine grained access control.  Therefore we need access control not only on role level but on object level. This means that we have to define access rights for a dynamic set of roles each with a dynamic set of users. UserA e.g. may have ReadRights on ImageA but AdminRights on ImageB and UserB may have ReadRights on ImageB but AdminRights on ImageA. In this case a role based approach needs to define a role for each combination of permission and image. Because normal role based approaches are not developed for millions of roles we needed a different approach.

As we did not have enough time to implement a whole security system by ourself we decided to look into Spring Security which we had in mind because of the acegi security plugin for grails. Spring Security has several advantages which were for us in short:

  • very flexible because security access can be defined on method level
  • LDAP, RemeberMe and OpenID authentication
  • long history (acegi security base) and thus a hopefully stable approach

Because of the use case mentioned in the beginning of this post the basic role based approach in “normal” Spring Security was not enough. Domain object security however seemed to be exactly what we needed.  Some reasons for using domain object security in our case are:

  • For each domain object instance (eg picture number 23) it is possible to define an own ACL (Access Control List) which contains ACEs (Access Control Entries). This way each object instance has its own list of principals (users) which again have its own permissions (read, write, etc.)
  • White and black ACEs are supported (either restrict or enhance permissions)
  • Furthermore inheritance of ACLs is supported
  • Performance -> “one of the main capabilities of the Spring Security ACL module is providing a high-performance way of retrieving ACLs”

The only problem seemed to be that the Acegi Security Plugin for Grails did not support domain object security and that is why we decided to integrate Spring Security the spring-way into grails. How I solved this will be mentioned in the next post.

Regards,

Phillip

Jump to other parts of this series: