Quantcast
Channel: Eyal Lupu Java Blog
Viewing all articles
Browse latest Browse all 53

Dynamic Configuration of Acegi's JBoss JAAS Container Adapter

$
0
0

Hi, long time (as always...) , this time about Acegi.

Environment

  • JBoss 4.0.5 (ejb3 configuration)

  • acegi – 1.0.3

Introduction

Spring frameworks is one of the most popular application frameworks used today. Acegi is a security solution “with a particular emphasis on applications that use Spring” (quote from Acegi's site). Acegi gives us a framework to perform Authentication and Authorization. In here I'm going to focus on Acegi's Container Adapter Authentication.

The container adapter authentication is the way Acegi integrates with the container used to host the application. Since I focus on authentication here lets assume that the only authorization used is the container authorization (using the @RolesAllowed, @RunAs, context.isCallerInRole(), and so on). Using the container adapter the container obtains the user credentials from Acegi – the adapter role is to authenticate the user and return to the container a user object which matches the container requirements (usually a Subject/Principal). The container Adapter (at least for JBoss) is actually a JAAS login module, which authenticate using Acegi providers and populates the subject in the layout which JBoss expects it to do.

In my example I have an Acegi security context which defines the users, a sample bean which is allowed to be executed only by users in a specific role, a JBoss dynamic login configuration Mbean, and a client.

Why?

Everything shown in this blog entry can be written very easily, and the configuration can be found on Acegi's documentation (here).But there is one important difference: on Acegi's documentation we are required to copy Acegi, Spring, and some other utility jars into the server's lib folder (${JBOSS_HOME}/server/{config}/lib. Which means that:

  1. To change the version of the Spring, Acegi or any other library used by the authentication we have to restart the server

  2. When looking for a class deployed both in the application and in the server's lib folder the class version in the application scope will be ignored (there are ways to workaround it but then you start to fight with JBoss....”JBoss makes possible for applications to share classes. JBoss 3.x does that by default. JBoss 4.0 does this for the"standard" configuration, but maintains class namespace isolation between applications for its "default" configuration. JBoss 4.0.1 reverts to the 3.x convention.” - taken from JBoss wiki)

And (back to Acegi's documentation) the security realm is define in the central login-config.xml file (${JBOSS_HOME}/server/{config}/conf/login-config.xml).

  1. An external configuration to your application – one more file to configure during deployment

  2. Requires server restart on change

In my sample I use JBoss' DynamicLoginConfig MBean which means that the security realm is defined during the application deployment automatically by JBoss, and the utility jars can be taken from the deployment unit (ear file) and can be easily hot swapped (BTW they can still be shared by applications – notice the scoping)

The EJB

Very simple:

import java.security.Principal;

import javax.annotation.Resource;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Remote;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;

import eyallupu.ejbsample.common.Echo;

@Remote(Echo.class) @Stateless(name="echo") @RolesAllowed("admins") 
public class EchoImpl implements Echo {
	@Resource SessionContext ctx;

	public String echo(String s) {
	
		Principal p =  ctx.getCallerPrincipal();
		System.out.println("Principal is: " + p.getName());
		return s;
	}

}

For our sample the only issue to notice is the use of the @RolesAllowed annotation. It means that if the application is configured to use a security manager (using the<security-domain> element in jboss.xml or jboss-web.xml) the security interceptor will verify, on each invocation of a bean method, that the principal of the current request belongs to the“admins” role.

The EAR and the SAR files

The ear file has the following layout

root
    |
   +--- ejb3 module (sample-app.jar)
    |
   +--- sar module (dynamic-login-config.sar)
    |             |
    |            +---META-INF
    |             |          |
    |             |          +----- jboss-service.xml
    |             |          +----- sample-login-config.xml
    |             +--- beanRefFactory.xml
    |             +--- acegisecurity.xml
    |
   +---META-INF
               |
              +---- application.xml
              +---- jboss-app.xml



The jboss-app.xml defines the security domain of the application (as mentioned above), the dynamic login module configuration is done on the SAR (JBoss'ServiceARchive) module. The SAR defines the dynamic login module and contains the Acegi configuration file. Here is the content of my jboss-service.xml:

<server><mbean code="org.jboss.security.auth.login.DynamicLoginConfig"
       name="sample-app:service=DynamicLoginConfig,domain=sampleAppDomain"><!-- The Attribute AuthConfig point to the login configuration file used by the dynamic 
               login configuration loader
       --><attribute name="AuthConfig">META-INF/sample-login-config.xml</attribute><!-- The service which supports dynamic processing of login-config.xml
          configurations.
       --><depends optional-attribute-name="LoginConfigService">
          jboss.security:service=XMLLoginConfig</depends><!-- Optionally specify the security mgr service to use when
          this service is stopped to flush the auth caches of the domains
          registered by this service.
       --><depends optional-attribute-name="SecurityManagerService">
          jboss.security:service=JaasSecurityManager</depends></mbean></server>



For those of you who are familiar with SAR files the above file is obvious, for the others here is the idea: I define a managed bean (MBean) with the type of org.jboss.security.auth.login.DynamicLoginConfig, this one depends on other two MBeans (the <depends> element), and it has one attribute (property), the “AuthConfig” attribute, which defines which resource holds the configuration to dynamically load, in my case the sample-login-config.xml file. Here it is:

<?xml version='1.0'?><!DOCTYPE policy PUBLIC "-//JBoss//DTD JBOSS Security Config 3.0//EN" "http://www.jboss.org/j2ee/dtd/security_config.dtd"><policy><application-policy name="sampleAppDomain"><authentication><login-module code="org.acegisecurity.adapters.jboss.JbossAcegiLoginModule" flag="required"><module-option name="singletonId">	springRealm	</module-option><module-option name="key">foobar</module-option><module-option name="authenticationManager">authenticationManager</module-option></login-module></authentication></application-policy></policy>


This is a standard JBoss login configuration file which uses one login module – the AcegiLoginModule (the only login module on this configuration). From here down the rest of the configuration is as defined in the Acegidocumentation– the beanRefFactory.xml, and acegisecurity.xml files are both included in the SAR. There is only one additional change – the libraries that Acegi uses (like Spring, aopalliance, acegi-security-jboss, etc.) are all included within the EAR file, there is no need to deploy the libraries into the server's lib folder. When including the utility jars in the EAR file * don't forget* to reference the jars using the Class-Path manifest attribute in the the SAR's manifest.

That's all, now we have an Acegi authentication, which can be dynamicallyloaded by JBoss, and doesn't require any deployment to the server's lib folder, or any changes to the master login configuration file.

Some References


Viewing all articles
Browse latest Browse all 53

Latest Images

Trending Articles





Latest Images