Fwd'ing to security newsgroup

-------- Original Message --------
Subject: Client accessing MBeanHome for more than one domain receives
SecurityException
Date: 4 Mar 2004 07:27:33 -0800
From: Dinesh Bhat
Reply-To: Dinesh Bhat
Organization: BEA NEWS SITE
Newsgroups: weblogic.developer.interest.management


Hi,

When a client accesses MBeans of more than one domains (Weblogic 8.1)
that have
different passwords, it receives a SecurityException. This occurs when
the MBeanHome
for each domain is looked up at initialization and reused for each
request ( to
access MBeans ). The security exception does not occur if the MBeanHome
for each
domain is looked up for each request. On initial review, this behavoir
seems inconsistent.

Looking up the MBeanHome for each request may introduce a significant
overhead.
I am not sure if concurrent lookups would also cause the same problem.
I have read on another post that we can work around this problem by
establishing
a trust relationship between the servers, but this may not be feasible
when one
is monitoring a lot of servers and the overhead of configuration may be
an issue.

I have attached code that can reproduce the problem.

Please advise on the correct approach.

Thanks

Dinesh Bhat
Panacya Inc.


import java.util.ArrayList;
import java.util.Set;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Hashtable;

import javax.management.MBeanServer;
import javax.naming.Context;

import weblogic.jndi.Environment;
import weblogic.management.MBeanHome;

/**
* This class reproduces the Security Exception that is caused when a client tries to access
* MBeans of more than one domain with different weblogic passwords. Here is the stacktrace of the
* exception
*
* java.lang.SecurityException: [Security:090398]Invalid Subject: principals=[weblogic, Administrators]
at weblogic.rjvm.BasicOutboundRequest.sendReceive(Bas icOutboundRequest.java:108)
at weblogic.rmi.internal.BasicRemoteRef.invoke(BasicR emoteRef.java:138)
at weblogic.management.internal.AdminMBeanHomeImpl_81 1_WLStub.getDomainName(Unknown Source)
at WLSecurityTest.getWeblogicInfo(WLSecurityTest.java :140)
at WLSecurityTest.runTest(WLSecurityTest.java:75)
at WLSecurityTest.(WLSecurityTest.java:66)
at WLSecurityTest.main(WLSecurityTest.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at com.intellij.rt.execution.application.AppMain.main (Unknown Source)
Caused by: java.lang.SecurityException: [Security:090398]Invalid Subject: principals=[weblogic, Administrators]
at weblogic.security.service.SecurityServiceManager.s eal(SecurityServiceManager.java:682)
at weblogic.rjvm.MsgAbbrevInputStream.getSubject(MsgA bbrevInputStream.java:181)
at weblogic.rmi.internal.BasicServerRef.acceptRequest (BasicServerRef.java:814)
at weblogic.rmi.internal.BasicServerRef.dispatch(Basi cServerRef.java:299)
at weblogic.rjvm.RJVMImpl.dispatchRequest(RJVMImpl.ja va:920)
at weblogic.rjvm.RJVMImpl.dispatch(RJVMImpl.java:841)
at weblogic.rjvm.ConnectionManagerServer.handleRJVM(C onnectionManagerServer.java:222)
at weblogic.rjvm.ConnectionManager.dispatch(Connectio nManager.java:794)
at weblogic.rjvm.t3.T3JVMConnection.dispatch(T3JVMCon nection.java:570)
at weblogic.socket.NTSocketMuxer.processSockets(NTSoc ketMuxer.java:105)
at weblogic.socket.SocketReaderRequest.execute(Socket ReaderRequest.java:32)
at weblogic.kernel.ExecuteThread.execute(ExecuteThrea d.java:197)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.ja va:170)
*
* Note: the exception is caused only when the MBeanHome for each domain is cached and used for subsequent
* transactions. The exception does not occur if the MBeanHome for each domain is looked up for each transaction. This
* would significant overhead in practice. Also the transactions across the various domains occurs serially, hence
* the effect of concurrent lookups has to be tested.
*
* Usage:
* This class has been tested with weblogic 8.1
* The class needs weblogic.jar in its classpath
* One can specify the weblogic details as System properties. The properties need to be specified in
* the following format:
* wls.host.n, wls.userId.n, wls.password.n where n is the weblogix instance number. Also specify
* the boolean system property reconnect.each.iteration to toggle between reconnecting or not reconnecting
* for each iteration. When not reconnecting for each iteration, the MBeanHome is reused and the Security Exception
* occurs.
*
* Following is the example of system properties
* -Dwls.host.0=localhost:7001 -Dwls.userId.0=weblogic -Dwls.password.0=weblogic
* -Dwls.host.1=localhost:7011 -Dwls.userId.1=weblogic -Dwls.password.1=weblogic1
* -Dwls.host.2=localhost:7021 -Dwls.userId.2=weblogic -Dwls.password.2=weblogic2
* -Dreconnect.each.iteration=false
*/
public class WLSecurityTest
{
ArrayList wlsDetailsList = new ArrayList();
HashMap connectionMap = new HashMap();

public static void main(String[] args)
{
try
{
WLSecurityTest wlSecurityTest = new WLSecurityTest();
}
catch (Exception e)
{
e.printStackTrace();
}
}

/**
* Constructor
* @throws Exception
*/
public WLSecurityTest() throws Exception
{
int noOfTries = 10;
getWLSDetails();

for( int i=0; i <= noOfTries; i++)
{
runTest();
}
}

/**
* Runs the test
*/
private void runTest()
{
for (int i = 0; i < wlsDetailsList.size(); i++)
{
WLSDetails wlsDetails = (WLSDetails) wlsDetailsList.get(i);
getWeblogicInfo(wlsDetails);
}
}

/**
* Get Weblogic details from System properties
* @throws Exception
*/
private void getWLSDetails() throws Exception
{
wlsDetailsList = new ArrayList();
String hostKeyTmpl = "wls.host";
String userIdKeyTmpl = "wls.userId";
String passwordKeyTmpl = "wls.password";
boolean done = false;
for (int i = 0; !done; i++)
{
WLSDetails wlsDetails = new WLSDetails();
String hostKey = hostKeyTmpl + "." + Integer.toString(i);
String userIdKey = userIdKeyTmpl + "." + Integer.toString(i);
String passwordKey = passwordKeyTmpl + "." + Integer.toString(i);

wlsDetails.hostName = System.getProperty(hostKey);

done = (wlsDetails.hostName == null) || (wlsDetails.hostName.length() == 0);
if (!done)
{
wlsDetails.userId = System.getProperty(userIdKey);
wlsDetails.password = System.getProperty(passwordKey);
connect(wlsDetails);
wlsDetailsList.add(wlsDetails);
}
}
}

/**
* Lookup the MBeanHome for the specified weblogic server
* @param wlsDetails
* @throws Exception
*/
public synchronized void connect(WLSecurityTest.WLSDetails wlsDetails) throws Exception
{
Context ctx = null;
MBeanHome mbHomeLocal = null;
try
{
Environment env = new Environment();
env.setProviderUrl("t3://" + wlsDetails.hostName);
env.setSecurityPrincipal(wlsDetails.userId);
env.setSecurityCredentials(wlsDetails.password);
Hashtable hashtable = env.getProperties();
System.out.println(hashtable.toString());
ctx = env.getInitialContext();
wlsDetails._mBeanHome = (MBeanHome) ctx.lookup(MBeanHome.ADMIN_JNDI_NAME);

}
catch (Exception e)
{
e.printStackTrace();
}
}

/**
* Gets weblogic information using MBeans
* @param wlsDetails
*/
public synchronized void getWeblogicInfo(WLSDetails wlsDetails)
{
try
{
boolean reconnectEachIteration =
Boolean.getBoolean("reconnect.each.iteration");
if( (reconnectEachIteration) || ((wlsDetails._mBeanHome == null) && (!reconnectEachIteration) ))
{
connect(wlsDetails);
}
MBeanHome mbHomeLocal = wlsDetails._mBeanHome;

String domainName = mbHomeLocal.getDomainName();
Set allMBeans = mbHomeLocal.getAllMBeans();
System.out.println("Size: " + allMBeans.size());
Set clusterMBeans = mbHomeLocal.getMBeansByType("Cluster", domainName);
System.out.println(clusterMBeans);
MBeanServer mBeanServer = mbHomeLocal.getMBeanServer();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}

/**
* Class that holds weblogic server details
*/
class WLSDetails
{
String hostName = "";

String userId = "";

String password = "";

MBeanHome _mBeanHome = null;

}
}