RSS Feed!

Recent Posts

Recent Comments

Archive for the ‘Security’ Category

Apache with OpenSSL on Windows 2003

Wednesday, February 25th, 2009
The other day one of our SSL certificates expired. Luckily we had the replacement ready and upgrading should have been a simple, straightforward process.
Now, the part I didn't know is that Verisign had changed their intermediate certs and they were no longer signing our cert with their root cert.

Well that shouldn't be so hard to fix though since Apache (mod_ssl) has a directive for intermediate (aka chain) certificates called SSLCertificateChainFile. I just pointed it to what I thought was the correct intermediate cert, restarted Apache, pointed Firefox to the url and tada, all good. I got this intermediate cert by simply exporting from the chain of certificates you see when double clicking on your own cert and browsing to the certificate path. What a mistake this will prove to be…

But wait, when I browsed with Safari I got a nasty "this certificate was signed by an unknown authority" error message. On my iPhone same thing, the cert failed. Tried IE7, no issues. Hmm… something was wrong. So I inspected the certificate chain and I discovered that at least in Safari my ssl cert looked as if the roor cert was VeriSign Class 3 Secure Server CA rather than Class 3 Public Primary Certification Authority (which is also Verisign,Inc and has the serial number 70 BA E4 1D 10 D9 29 34 B6 38 CA 7B 03 CC BA BF).

After googling I came across an article (don't click the link) that explains how to add an intermediate cert to Microsoft's list of trusted certificates using Microsoft Management Console and lots of fiddling. Turns out I didn't really need to do that. (told you not to click the link :) )

At this point it was clear that the intermediate cert was somehow now available to all the clients. So what seemed like a logical thing to do was to see what that intermediate cert reeally looks like. Luckily there is this ssl cert checker from VeriSign. To my surprise when using it the intermediate cert was not really what I exported above. So I copied the code for the new intermediate cert and replaced the one I exported and gave it a go!

Hooray! Everything now worked.

Now what have I learned?
1. Never trust a browser to test an ssl cert. Either use openssl s_server or the applet above that verisign have built
2. Avoid Windows as a host OS for web servers. (lack of openssl, confising trusted root certificate management, etc)
3. The new cert was almost double the size of the first one. Looks like the versign intermediate cert is bundled with my cert as well. Maybe someone can clarify this?
4. Let infrastructure people handle ssl cert installation

Cheers…

Applying Acegi Security (SpringSecurity) to an existing JavaEE ap

Friday, April 11th, 2008

So I have a JavaEE application and I have to make sure that I use Acegi (called Spring Security or SS from here on) properly. I will try to go through all the steps that are required to implement SS in an existing Spring based application. I will not delve into the details of putting together a Spring Framework based application and I will not provide in-depth details of the implementation.

First of all here are the assumptions:
1. You understand what the differences between Authentication and Authorisation are.
2. You know what Form, Basic, Digest, LDAP Authentication mean.
3. You know what Annotations are and you are not in the mood to argue XML configurations vs. Annotations
4. I am not responsible if the information you found here has not solved your problem ;)

So let’s just say that there is no security in place and we need to plug SS in.


1. Adding Spring Security to the project

- copy the acegi-security-xxx.jar to your lib folder (this depends on how you have configured your project) or just include it in your build path.

- create a new xml file (i will call it ss.xml) where to put all the configuration information or copy one from the SS distribution

– import this file in your spring configuration xml (or point to it in your web.xml where you configure the contextConfigLocation)

– in the web.xml configure the Acegi Filter Chain Proxy. Then make sure the FilterToBeanProxy’s class points to the org.acegisecurity.util.FilterChainProxy (should you use FilterToBean you’ll end up writing lots and lots of xml to define the filters, but it’s your choice).

– while in the web.xml define a filter-mapping for the URIs that you want to secure. How about /* ?


All done with the web.xml You should have something like this:

[...]

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/spring-core.xml, /WEB-INF/classes/ss.xml</param-value>
</context-param>

<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

[...]


– move to the ss.xml file that i pointed to above and configure the filter. I will have different filters for web services and for the rest of the application. The order is very important so make sure you put the more specific rules first. I will also put some stuff in /notsecured that will just not be protected.

    <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/webServices/**=httpSessionContextIntegrationFilterWithASCFalse,basicProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
/notsecured/**=#NONE#
/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>

Just a few comments on what we have above: the authenticationProcessingFilter could be used to audit the logon attempts as it provides onSuccessfuAuthentication and onUnsuccessfulAuthentication methods. The exceptionTranslationFilter is responsible for detecting security exceptions thrown by the AbstractSecurityInterceptor.The filterInvocationInterceptor is needed to check web URIs.


- now it’s time to configure the authenticationProcessingFilter. Here is what it should end up looking like:

<bean id=”authenticationProcessingFilter” class=”class.that.implements.AuthenticationProcessingFilter”>
<property name=”authenticationManager”>

<ref bean=”authenticationManager”/>

</property>
<property name=”authenticationFailureUrl”>

<value>/logon.jsp?tryagain=true</value>

</property>
<property name=”filterProcessesUrl”>

<value>/j_acegi_security_check</value>

</property>
<property name=”defaultTargetUrl”>

<value>/admin/home.html</value>

</property>
<property name=”alwaysUseDefaultTargetUrl”>

<value>true</value>

</property>
</bean>


So let’s look at the properties, one at a time.


First the class that implements the processing filter can be any the AuthenticationProcessingFilter itself or your own class that extends it. You would extend it to be able to do stuff when something goes wrong for example.

The authenticationManager is responsible with delegating to its list of AuthenticationPr
oviders
to check an Authentication request. It can also be configured with a ConcurrentSessionController that manages how many session one user can have at a time.

The authenticationFailureUrl points to where the user will be redirected to in the event of an authentication failure. The request parameter tryagain is there to let you do some processing in the logon page.

The filterProcessesUrl is represents the URL that this filter responds to. In this example you can see the default value.

The defaultTargetUrl points to the URL that follows a successful authentication (unless the HttpSession attribute called ACEGI_SAVED_REQUEST_KEY points to somewhere else). Fully qualified URLs can be used too.

The alwaysUseDefaultTargetUrl just overrides the ACEGI_SAVED_REQUEST_KEY. Event if this key exists the redirect will still be made to the default target URL.


- it’s now time to configure the AuthenticationProvider (used by the authenticationManager above).


There are quite a few options here: DAO Authentication Provider, JAAS, Run-As, Form, Basic, Digest, Remember Me, LDAP, X509, CAS, Container Adapter, etc. I will only talk about the DAO Authentication Provider here. An authentication provider is basically a class that can process a specific Authentication implementation. The provider will use a a userDetailsService to retrieve the UserDetails object via the loadUserByUsername(String username) call.

The official documentations says: “The returned UserDetails is an interface that provides getters that guarantee non-null provision of basic authentication information such as the username, password, granted authorities and whether the user is enabled or disabled“. So basically the UserDetails object is what you all you need ;)

You need not do anything to this DAOAuthenticationProvider unless you have specific needs. let’s have a look at how the configuration looks like:


[...]

<bean id=”daoAuthenticationProvider” class=”org.acegisecurity.providers.dao.DaoAuthenticationProvider”>
<property name=”userDetailsService”><ref bean=”jdbcDaoService”/></property>
<property name=”saltSource”><ref bean=”saltSource”/></property>
<property name=”passwordEncoder”><ref bean=”passwordEncoder”/></property>
</bean>

[...]


The userDetailsService points to a bean that is configured to retireve user details from a database. A default database structure is available but you can override the usersByUsernameQuery and the authoritiesByUsernameQuery if you need to. Typically this should be enough:

[...]

<bean id=”jdbcDaoImpl” class=”org.acegisecurity.userdetails.jdbc.JdbcDaoImpl”>

<property name=”dataSource”>

<ref bean=”dataSource”/>

</property>

</bean>

[...]

I will not explain how to configure a dataSource here.


The saltSource is just some salt that you can add to the passwords, while the passwordEncoder (e.g. Md5PasswordEncoder) is used to encode and decode the passwords in the UserDetails object returned by the UserDetailsService.


2. The logon.jsp

When a resource that is protected is accessed, the exceptionTranslationFilter will use the authenticationEntryPoint to load the logon form (assuming that is how we configured it). So in the ss.xml there should be something like this:

[...]

<bean id=”exceptionTranslationFilter” class=”org.acegisecurity.ui.ExceptionTranslationFilter”>
<property name=”authenticationEntryPoint”><ref local=”authenticationFilterEntryPoint”/></property>
</bean>

<bean id=”authenticationFilterEntryPoint” class=”org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint”>
<property name=”loginFormUrl”>
<value>/logon.jsp</value>
</property>
<property name=”forceHttps”>
<value>false</value>
</property>
</bean>

[...]


Now these beans look quite obvious. Let me know if you want more details on this.


The logon.jsp page itself will be built around the form. Here is a simplistic approach:

<form action=”j_acegi_security_check” method=”POST”>

<input type=”text” id=”j_username” name=”j_username”>

<br />

<input type=”password” name=”j_password”>

<br />

<input type=”submit” class=”button” value=”Logon”/>

</form>


When the form is submitted, Spring Securit
y will intercept and process it.



3. Controlling the JSP output

This is where the authorization tag libraries come into play. SS’s (lol) authorization tag lib is called authz and you can find it in the >../acegi-security-x.x.x.jar/META-INF/authz.tld
The AuthorizeTag declares three attributes: ifNotGranted, ifAllGranted, ifAnyGranted. This is also the order in which they are verified. With any of the tags you can specifiy a list of comma separated ROLEs (the whitespaces are ignored). Here’s an example taken from Ben Alex’s guide:
<authz:authorize ifAllGranted=”ROLE_SUPERVISOR”>
<td>
<A HREF=”del.htm?id=<c:out value=”${contact.id}”/>”>Del</A>
</td>
</authz:authorize>Basically, if the principal (remember the UserDetails ?) doesn’t have the ROLE_SUPERVISOR then the user won’t even see the Del anchor. So, with the ifAllGranted all roles must be granted to this principal, with ifAnyGranted at least one role must be granted while with the ifNotGranted none of the roles should be granted in order to output the code enclosed by this auth:authorize tag.

I will only mention that SS also provides support for Access Control Lists via authz:accesscontrollist. Please see the official documentation for more details.


4. Secure Object Implementations

Securing the front end is not always (okay never) enough. The better way of making sure that the business objects are not available to un-authenticated users. To protect them SS uses something called MethodSecurityInterceptor.

<bean id=”bankManagerSecurity” class=”org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor”>

<property name=”validateConfigAttributes”>

<value>true</value>

</property>

<property name=”authenticationManager”>

<ref bean=”authenticationManager”/>

</property>

<property name=”accessDecisionManager”>

<ref bean=”accessDecisionManager”/>

</property>

<property name=”runAsManager”>

<ref bean=”runAsManager”/>

</property>

<property name=”objectDefinitionSource”>

<value>

org.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER

org.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER

</value>

</property>

</bean>



The important thing to look at in this example is the objectDefinitionSource. There are three ways to define with method invocations will be intercepted and checked.

1. Using a property editor

2. Using Jakarta Commons Attributes (you know, the @@SecurityConfig(“”ROLE_DUMB”) syntax…)

3. Using Java Annotations (where you will make full use of the @Secured annotation).


Here is the example from the official documentation for using java 5 style annotations:


<bean id=”attributes” class=”org.acegisecurity.annotation.SecurityAnnotationAttributes”/>

<bean id=”objectDefinitionSource” class=”org.acegisecurity.intercept.method.MethodDefinitionAttributes”>

<property name=”attributes”>

<ref local=”attributes”/>

</property>

</bean>

<bean id=”bankManagerSecurity” class=”org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor”>

<property name=”validateConfigAttributes”>

<value>false</value>

</property>

<property name=”authenticationManager”>

<ref bean=”authenticationManager”/>

</property>

<property name=”accessDecisionManager”>

<ref bean=”accessDecisionManager”/>

</property>

<property name=”runAsManager”>

<ref bean=”runAsManager”/>

</property>

<property name=”objectDefinitionSource”>

<ref bean=”objectDefinitionSource”/>

</property>

</bean>


    import org.acegisecurity.annotation.Secured;

public interface BankManager {

/**
* Delete something
*/
@Secured({"ROLE_SUPERVISOR","RUN_AS_SERVER" })
public void deleteSomething(int id);

/**
* Delete another
*/
@Secured({"ROLE_SUPERVISOR","RUN_AS_SERVER" })
public void deleteAnother(int id);
}


Please note that when using BeanNameAutoProxyCreator to create the required proxy for security, the configuration must contain the property proxyTargetClass set to true. Otherwise, the method passed to MethodSecurityInterceptor.invoke is the proxy's caller, not the proxy's target.


If you want to hear the whole story, make sure you visit Acegi Security Guide. Ben Alex has done a great job documenting this framework, the API's are not too bad either, with just a few DOCUMENT ME exceptions :)

Cheers…