-
1. Re: Securing access to JNDI tree
gavinho Nov 23, 2004 11:07 AM (in response to jcasp)Yes, I am also looking for this topic. Anyway has update about it?
-
3. Re: Securing access to JNDI tree
gavinho Nov 29, 2004 4:43 AM (in response to jcasp)"scott.stark@jboss.org" wrote:
http://www.jboss.org/wiki/Wiki.jsp?page=XMBeansforSecurity
I followed the examples but encountered "NoSuchMethodException" when startup JBoss. The problem is JBoss startup sequence tried to use org.jboss.mx.server.MBeanInvoker interface to lookup a constructor for my Interceptor.
Can any one help?
Here is the output from startup log
=======================org.jboss.mx.interceptors.JNDISecurityInterceptor java.lang.NoSuchMethodException: org.jboss.mx.interceptors.JNDISecurityInterceptor.<init>(org.jboss.mx.server.MBeanInvoker) at java.lang.Class.getConstructor0(Class.java:1929) at java.lang.Class.getConstructor(Class.java:1019) at org.jboss.mx.modelmbean.ModelMBeanInvoker.getInterceptors(ModelMBeanInvoker.java:552) at org.jboss.mx.modelmbean.ModelMBeanInvoker.configureInterceptorStack(ModelMBeanInvoker.java:458) at org.jboss.mx.modelmbean.XMBean.configureInterceptorStack(XMBean.java:360) at org.jboss.mx.modelmbean.ModelMBeanInvoker.invokePreRegister(ModelMBeanInvoker.java:350) at org.jboss.mx.server.AbstractMBeanInvoker.preRegister(AbstractMBeanInvoker.java:539) at org.jboss.mx.server.registry.BasicMBeanRegistry.invokePreRegister(BasicMBeanRegistry.java:644) at org.jboss.mx.server.registry.BasicMBeanRegistry.registerMBean(BasicMBeanRegistry.java:199) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at org.jboss.mx.server.ReflectedDispatcher.dispatch(ReflectedDispatcher.java:60) at org.jboss.mx.server.Invocation.dispatch(Invocation.java:61) at org.jboss.mx.server.Invocation.dispatch(Invocation.java:53) at org.jboss.mx.server.Invocation.invoke(Invocation.java:86) at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:185) at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:473) at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:1018) at org.jboss.mx.server.MBeanServerImpl.registerMBean(MBeanServerImpl.java:981) at org.jboss.mx.server.MBeanServerImpl.createMBean(MBeanServerImpl.java:318) at org.jboss.system.ServiceCreator.install(ServiceCreator.java:152) at org.jboss.system.ServiceConfigurator.internalInstall(ServiceConfigurator.java:149) at org.jboss.system.ServiceConfigurator.install(ServiceConfigurator.java:114) at org.jboss.system.ServiceController.install(ServiceController.java:198) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at org.jboss.mx.server.ReflectedDispatcher.dispatch(ReflectedDispatcher.java:60) at org.jboss.mx.server.Invocation.dispatch(Invocation.java:61)
What I did was,
1. compile the following class
=====================package org.jboss.mx.interceptors; imports ignored public final class JNDISecurityInterceptor extends AbstractInterceptor { private static Logger log = Logger.getLogger(JNDISecurityInterceptor.class); private static final Principal READER_ROLE = new SimplePrincipal("JNDIReader"); private static final Principal WRITER_ROLE = new SimplePrincipal("JNDIWriter"); private String securityDomain; private SubjectSecurityManager authMgr; private RealmMapping roleMgr; public JNDISecurityInterceptor() { super("JNDI Security Interceptor"); } public String getSecurityDomain() { return securityDomain; } public void setSecurityDomain(String securityDomain) throws Exception { log.info("setSecurityDomain: "+securityDomain); this.securityDomain = securityDomain; InitialContext ctx = new InitialContext(); this.authMgr = (SubjectSecurityManager) ctx.lookup(securityDomain); this.roleMgr = (RealmMapping) ctx.lookup(securityDomain); } // Interceptor overrides ----------------------------------------- public Object invoke(Invocation invocation) throws InvocationException { String opName = invocation.getName(); log.info("invoke, opName="+opName); // If this is not the invoke(Invocation) op just pass it along if( opName == null || opName.equals("invoke") == false ) return invocation.nextInterceptor().invoke(invocation); Object[] args = invocation.getArgs(); org.jboss.invocation.Invocation invokeInfo = (org.jboss.invocation.Invocation) args[0]; // There must be a valid security manager if( authMgr == null || roleMgr == null ) { String msg = "No security mgr configured, check securityDomain: "+securityDomain; throw new SecurityException(msg); } // Get the security context passed from the client Principal principal = invokeInfo.getPrincipal(); Object credential = invokeInfo.getCredential(); if( authMgr.isValid(principal, credential) == false ) { String msg = "Failed to authenticate principal: "+principal; throw new SecurityException(msg); } HashSet methodRoles = new HashSet(); Method method = invokeInfo.getMethod(); boolean isRead = isReadMethod(method); if( isRead == true ) methodRoles.add(READER_ROLE); else methodRoles.add(WRITER_ROLE); if( roleMgr.doesUserHaveRole(principal, methodRoles) == false ) { String msg = "Failed to authorize subject: "+authMgr.getActiveSubject() + " principal: " + principal + " for access roles:" + methodRoles; throw new SecurityException(msg); } // Let the invocation go return invocation.nextInterceptor().invoke(invocation); } private boolean isReadMethod(Method method) { boolean isRead = true; String name = method.getName(); String name = method.getName(); isRead = name.equals("lookup") || name.equals("list") || name.equals("listBindings"); return isRead; } }
2. modified the mbean declaration for NamingService in ~/conf/jboss-service.xml
===================================<mbean code="org.jboss.naming.NamingService" name="jboss:service=Naming" xmbean-dd="xmdesc/NamingService-xmbean.xml" > <!-- other attributes omitted --> </mbean>
3. create file ~/conf/xmdesc/NamingService-xmbean.xml
======================================<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mbean PUBLIC "-//JBoss//DTD JBOSS XMBEAN 1.1//EN" "http://www.jboss.org/j2ee/dtd/jboss_xmbean_1_0.dtd" [ ATTLIST interceptor securityDomain CDATA #IMPLIED ]> <mbean> <description>A deployment of the standard JBoss JNDI naming servr that employs custom interceptors to add security </description> <descriptors> <interceptors> <interceptor code="org.jboss.mx.interceptors.JNDISecurityInterceptor" securityDomain="java:/jaas/jmx-console"/> </interceptors> </descriptors> <class>org.jboss.naming.NamingService</class> <constructor> <description>The default constructor</description> <name>NamingService</name> </constructor> <attribute access="read-only" getMethod="getMethodMap"> <name>MethodMap</name> <type>java.util.Map</type> </attribute> <attribute access="read-write" getMethod="getPort" setMethod="setPort"> <name>Port</name> <type>int</type> </attribute> <attribute access="read-write" getMethod="getInstallGlobalService" setMethod="setInstallGlobalService"> <name>InstallGlobalService</name> <type>boolean</type> </attribute> <!-- Operations --> <operation> <description>The start lifecycle operation</description> <name>start</name> </operation> <operation> <description>The stop lifecycle operation</description> <name>stop</name> </operation> <operation> <description>The detyped lifecycle operation (for internal use only)</description> <name>jbossInternalLifecycle</name> <parameter> <description>The lifecycle operation</description> <name>method</name> <type>java.lang.String</type> </parameter> <return-type>void</return-type> </operation> <operation> <description>The generic invocation operation used by detached invokers to route requests to the service </description> <name>invoke</name> <parameter> <description>The Naming interface method invocation encapsulation </description> <name>invocation</name> <type>org.jboss.invocation.Invocation</type> </parameter> <return-type>java.lang.Object</return-type> </operation> </mbean>
-
4. Re: Securing access to JNDI tree
starksm64 Nov 29, 2004 12:45 PM (in response to jcasp)That is an irrelevant debug level msg simply saying the interceptor does not have a ctor that takes an MBeanInvoker. The default ctor will be used instead.
-
5. Re: Securing access to JNDI tree
gavinho Dec 1, 2004 4:13 AM (in response to jcasp)Yeah, the ctor not found message is not fatal. I managed to start JBoss successfully with the interceptor attached. But I am still interesting to know how can we remove such noisy message.
I tested using a external client program to do JNDI lookup but the invoke() method of interceptor had not being called for security checking as expected.
I can only see the invoke method being called serveral times during JBoss startup.
8-( -
6. Re: Securing access to JNDI tree
gavinho Dec 2, 2004 1:49 AM (in response to jcasp)Browsed thru the source codes. The interceptor as described in URL:
http://www.jboss.org/wiki/Wiki.jsp?page=XMBeansforSecurity
only intercept calls to object org.jboss.naming.NamingService
But according to the class diagram in URL
http://docs.jboss.org/jbossas/admindevel326/html/ch3.chapter.html#ch3.jbossns.fig
JNDI client only interact with object org.jnp.server.NamingServer thru
interface org.jnp.interfaces.Name, the interceptor will not be called,
hence the access control still will not in place.
Am I right? -
7. Re: Securing access to JNDI tree
starksm64 Dec 2, 2004 12:23 PM (in response to jcasp)No. The org.jnp.interfaces.Naming interface is the interface exposed by the NamingService xmbean. All Naming interface invocations ultimately go through the NamingService xmbean and its associated interceptors.
-
8. Re: Securing access to JNDI tree
gavinho Dec 2, 2004 9:41 PM (in response to jcasp)"scott.stark@jboss.org" wrote:
No. The org.jnp.interfaces.Naming interface is the interface exposed by the NamingService xmbean. All Naming interface invocations ultimately go through the NamingService xmbean and its associated interceptors.
Browsed thru the source code tree jboss-3.2.5-src\naming but I really can't find out how invocations on Naming interface get thru the NamingService xmbean and its associated interceptors.
Can you provide some more hints? -
9. Re: Securing access to JNDI tree
starksm64 Dec 3, 2004 12:26 AM (in response to jcasp)Ok, I see your confusion now and its due to not showing how to expose the NamingService via the detached invoker framework as a Naming proxy. Go reread the wiki which I have updated to show all of the details for changing the conf/jboss-service.xml NamingService to use a custom security interceptor. You will have to use 3.2.6+ for this to work correctly as you need to be able to replace the bootstrap proxy with the detached invoker proxy so that all externali jndi lookups are routed to the NamingService.invoke(Invocation) operation.
http://www.jboss.org/wiki/Wiki.jsp?page=XMBeansforSecurity -
10. Re: Securing access to JNDI tree
gavinho Dec 6, 2004 9:34 PM (in response to jcasp)Great, I have set up access control to JNDI tree. Thx.