Thursday, March 22, 2007

JBoss 4 Security: Setup LdapLoginModule + ClientLoginModule





Contents:

1) Project Structure
2) File: build.xml
3) Files: resources/*
4) Files: resources/ldif/*
5) Files: resources/META-INF/*
6) Files: resources/server-config/*
7) Files: src/com/aniplan/securityfilestore/client/*
8) Files: src/com/aniplan/securityfilestore/server/iface/*
9) Files: src/com/aniplan/securityfilestore/server/impl/*




--------------------
1) Project Structure
--------------------

[./SecurityLdapStore/]:

build/
resources/
src/
build.xml

------------------
2) File: build.xml
------------------

[build.xml]:

<?xml version="1.0" encoding="UTF-8"?>

<project name="SecurityLdapStore" default="ejbear" basedir=".">


<property environment="env" />

<property name="src.dir" value="${basedir}/src" />
<property name="resources.dir" value="${basedir}/resources" />
<property name="build.dir" value="${basedir}/build" />
<property name="classes.dir" value="${build.dir}/classes" />

<property name="jboss.home" value="${env.JBOSS_HOME}" />
<property name="jboss.deploy" value="${jboss.home}/server/default/deploy" />

<property name="ejbjar.name" value="${ant.project.name}.jar" />
<property name="ejbear.name" value="${ant.project.name}.ear" />
<property name="client.jar.name" value="${ant.project.name}Client.jar" />


<fail message="Can not find environment variable JBOSS_HOME">
<condition>
<not>
<isset property="env.JBOSS_HOME" />
</not>
</condition>
</fail>


<path id="classpath">
<pathelement location="${classes.dir}" />
<!-- So that we can get jndi.properties for InitialContext -->
<pathelement location="${resources.dir}" />

<fileset dir="${jboss.home}/lib">
<include name="**/*.jar" />
</fileset>

<fileset dir="${jboss.home}/server/default/lib">
<include name="**/*.jar" />
</fileset>

<fileset dir="${jboss.home}/server/default/deploy/ejb3.deployer">
<include name="*.jar" />
</fileset>

<fileset dir="${jboss.home}/server/default/deploy/jboss-aop-jdk50.deployer">
<include name="*.jar" />
</fileset>
</path>


<target name="clean">
<delete dir="${classes.dir}" />
<delete dir="${build.dir}" />
</target>


<target name="prepare">
<mkdir dir="${build.dir}" />
<mkdir dir="${classes.dir}" />
</target>


<target name="compile" depends="prepare">
<javac destdir="${classes.dir}" debug="on" failonerror="off"
optimize="off" includes="**/*.java" encoding="utf-8">
<src path="${src.dir}" />
<classpath refid="classpath" />
</javac>
</target>


<target name="ejbjar" depends="compile">
<jar jarfile="${build.dir}/${ejbjar.name}">
<manifest>
<attribute name="Built-By" value="${user.name}" />
<attribute name="Built-Date" value="${TODAY}" />
</manifest>

<fileset dir="${classes.dir}">
<include name="**/server/iface/*.class" />
<include name="**/server/impl/*.class" />
</fileset>

<fileset dir="${resources.dir}">
<include name="**/ejb-jar.xml" />
<include name="**/jboss.xml" />
</fileset>

</jar>

<jar jarfile="${build.dir}/${client.jar.name}">
<manifest>
<attribute name="Built-By" value="${user.name}" />
<attribute name="Built-Date" value="${TODAY}" />
</manifest>

<fileset dir="${classes.dir}">
<include name="**/client/*.class" />
</fileset>

<fileset dir="${resources.dir}">
<include name="jndi.properties" />
<include name="log4j.xml" />
</fileset>

</jar>
</target>


<target name="ejbear" depends="ejbjar">

<ear destfile="${build.dir}/${ejbear.name}"
appxml="${resources.dir}/META-INF/application.xml">
<manifest>
<attribute name="Built-By" value="${server.builder}" />
<attribute name="Built-Date" value="${TODAY}" />
</manifest>

<fileset dir="${build.dir}">
<include name="${ejbjar.name}" />
</fileset>
</ear>
</target>


<target name="undeploy">
<delete file="${jboss.deploy}/${ejbear.name}" />
</target>


<target name="deploy" depends="ejbear">
<copy file="${build.dir}/${ejbear.name}" todir="${jboss.deploy}" />
</target>


<target name="run" depends="ejbear">
<java fork="true" classname="com.aniplan.securityldapstore.client.ConsoleClient"
classpathref="classpath">
<jvmarg value="-Djava.security.manager" />
<jvmarg value="-Djava.security.policy=resources/client.policy" />
<jvmarg value="-Djava.security.auth.login.config=resources/auth.conf" />
<classpath path="${client.jar.name}" />
</java>
</target>


</project>

---------------------
3) Files: resources/*
---------------------

[auth.conf]:

client {
org.jboss.security.ClientLoginModule required;
};

[client.policy]:

grant {
permission java.security.AllPermission;
};

[jndi.properties]:

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost

--------------------------
4) Files: resources/ldap/*
--------------------------

[aniplan-sample.ldif]:

version: 1
dn: dc=aniplan,dc=com
ObjectClass: dcObject
ObjectClass: organization
ObjectClass: top
dc: aniplan
o: Aniplan

dn: ou=People,dc=aniplan,dc=com
ObjectClass: organizationalUnit
ObjectClass: top
ou: People

dn: uid=root3,ou=People,dc=aniplan,dc=com
ObjectClass: uidObject
ObjectClass: person
ObjectClass: top
cn: ZGS Admin
sn: Root
uid: root3
userpassword:: cm9vdHB3ZA==

dn: uid=user3,ou=People,dc=aniplan,dc=com
ObjectClass: uidObject
ObjectClass: person
ObjectClass: top
cn: ZGS User
sn: User
uid: user3
userpassword:: dXNlcnB3ZA==

dn: ou=Roles,dc=aniplan,dc=com
ObjectClass: organizationalUnit
ObjectClass: top
ou: Roles

dn: cn=FullAccess,ou=Roles,dc=aniplan,dc=com
ObjectClass: groupOfNames
ObjectClass: top
cn: FullAccess
description: the ZGS Admin Group
member: uid=root3,ou=People,dc=aniplan,dc=com

dn: cn=NotFullAccess,ou=Roles,dc=aniplan,dc=com
ObjectClass: groupOfNames
ObjectClass: top
cn: NotFullAccess
description: the ZGS User group
member: uid=user3,ou=People,dc=aniplan,dc=com

------------------------------
5) Files: resources/META-INF/*
------------------------------

[application.xml]:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC
"-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN"
"http://java.sun.com/dtd/application_1_3.dtd">

<application>
<display-name>SecurityLdapStore</display-name>
<module>
<ejb>SecurityLdapStore.jar</ejb>
</module>
</application>

[ejb-jar.xml]:

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar>
<assembly-descriptor>

<security-role>
<description>FullAccess Role</description>
<role-name>FullAccess</role-name>
</security-role>

<security-role>
<description>NotFullAccess Role</description>
<role-name>NotFullAccess</role-name>
</security-role>

<method-permission>
<role-name>FullAccess</role-name>
<method>
<ejb-name>ServerAgentBean</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>

<method-permission>
<role-name>NotFullAccess</role-name>
<role-name>FullAccess</role-name>
<method>
<ejb-name>ServerAgentBean</ejb-name>
<method-name>checkAccessLevel1</method-name>
</method>
</method-permission>

<method-permission>
<unchecked/>
<method>
<ejb-name>ServerAgentBean</ejb-name>
<method-name>checkAccessLevel3</method-name>
</method>
</method-permission>

</assembly-descriptor>
</ejb-jar>

[jboss.xml]:

<?xml version="1.0" encoding="UTF-8"?>
<jboss>
<security-domain>SecurityLdapStoreDomain</security-domain>
</jboss>

-----------------------------------
6) Files: resources/server-config/*
-----------------------------------

[login-config.xml]:

<policy>
<application-policy name = "SecurityLdapStoreDomain">
<authentication>
<login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="required">
<module-option name="java.naming.factory.initial">
com.sun.jndi.ldap.LdapCtxFactory
</module-option>
<module-option name="java.naming.provider.url">
ldap://localhost:10389/
</module-option>
<module-option name="java.naming.security.authentication">
simple
</module-option>
<module-option name="principalDNPrefix">
uid=
</module-option>
<module-option name="principalDNSuffix">
,ou=People,dc=aniplan,dc=com
</module-option>
<module-option name="rolesCtxDN">
ou=Roles,dc=aniplan,dc=com
</module-option>
<!-- <module-option name="userRolesCtxDNAttributeName"></module-option> -->
<module-option name="uidAttributeID">
member
</module-option>
<module-option name="matchOnUserDN">
true
</module-option>
<module-option name="roleAttributeID">
cn
</module-option>
<module-option name="roleAttributeIsDN">
fasle
</module-option>
</login-module>
</authentication>
</application-policy>
</policy>

[server.xml]:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="examplePartitionConfiguration"
class="org.apache.directory.server.core.partition.impl. \
btree.MutableBTreePartitionConfiguration">
<property name="name" value="aniplan.com" />
<property name="cacheSize" value="100"/>
<property name="suffix" value="o=aniplan.com" />
<property name="optimizerEnabled" value="true" />
<property name="synchOnWrite" value="true" />
<property name="contextEntry">
<value>
objectClass: organization
objectClass: top
o: aniplan.com
</value>
</property>
</bean>
</beans>

----------------------------------------------------
7) Files: src/com/aniplan/securityldapstore/client/*
----------------------------------------------------

[ConsoleClient.java]:

package com.aniplan.securityldapstore.client;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import org.jboss.security.auth.callback.UsernamePasswordHandler;

import com.aniplan.securityldapstore.server.iface.*;

public class ConsoleClient {

private String loginName = "user3";
private String loginPassword = "userpwd";

public static void main(String[] args) {
ConsoleClient client = new ConsoleClient();
client.run();
System.out.println("done.");
}

private Context getInitialContext()
throws javax.naming.NamingException {
return new javax.naming.InitialContext();
}

private void setupSecuriry() throws LoginException, NamingException {
UsernamePasswordHandler loginHandler =
new UsernamePasswordHandler(
loginName, loginPassword.toCharArray());


final LoginContext loginContext =
new LoginContext("client", loginHandler);

System.out.println("login begin");
loginContext.login();
System.out.println("login end");
}

public ConsoleClient() {
// void
}

public void run() {
try {
setupSecuriry();
//
System.out.println("lookup begin");
ServerAgentRemoteIF bean = (ServerAgentRemoteIF)
getInitialContext().lookup(ServerAgentRemoteIF.JNDI_NAME);
System.out.println("lookup end");
//
System.out.println("call checkAccessLevel3");
System.out.println(bean.checkAccessLevel3());
System.out.println("call checkAccessLevel1");
System.out.println(bean.checkAccessLevel1());
System.out.println("call checkAccessLevel2");
System.out.println(bean.checkAccessLevel2());
}
catch (Exception e) {
e.printStackTrace();
}
}

}

----------------------------------------------------------
8) Files: src/com/aniplan/securityldapstore/server/iface/*
----------------------------------------------------------

[ServerAgentIF.java]:

package com.aniplan.securityldapstore.server.iface;

public interface ServerAgentIF extends java.io.Serializable {
String checkAccessLevel1();
String checkAccessLevel2();
String checkAccessLevel3();
}

[ServerAgentLocalIF.java]:

package com.aniplan.securityldapstore.server.iface;

public interface ServerAgentLocalIF extends ServerAgentIF {
String JNDI_NAME = "com.aniplan.securityldapstore.server/ServerAgent/local";
}

[ServerAgentRemoteIF.java]:

package com.aniplan.securityldapstore.server.iface;

public interface ServerAgentRemoteIF extends ServerAgentIF {
String JNDI_NAME = "com.aniplan.securityldapstore.server/ServerAgent/remote";
}

---------------------------------------------------------
9) Files: src/com/aniplan/securityldapstore/server/impl/*
---------------------------------------------------------

[ServerAgentBean.java]:

package com.aniplan.securityldapstore.server.impl;

import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;

import org.jboss.annotation.ejb.LocalBinding;
import org.jboss.annotation.ejb.RemoteBinding;

import com.aniplan.securityldapstore.server.iface.ServerAgentLocalIF;
import com.aniplan.securityldapstore.server.iface.ServerAgentRemoteIF;

@Stateless
@Local(ServerAgentLocalIF.class)
@Remote(ServerAgentRemoteIF.class)
@LocalBinding(jndiBinding = ServerAgentLocalIF.JNDI_NAME)
@RemoteBinding(jndiBinding = ServerAgentRemoteIF.JNDI_NAME)
public class ServerAgentBean
implements ServerAgentLocalIF, ServerAgentRemoteIF
{
private static final long serialVersionUID = 1L;

public String checkAccessLevel1() {
return "Level 1 Ok.";
}
public String checkAccessLevel2() {
return "Level 2 Ok.";
}
public String checkAccessLevel3() {
return "Level 3 Ok.";
}

}




%%

No comments: