Covering J2EE Security and WebLogic Topics

Good primer on web security

Christian Heilmann wrote a nice post on web security topics. He gives an overview of the following attacks:

He also provides some practical tips for being safer on the web (as a user) and things you can do on your server and in your applications to be more secure. Neither his tips nor the article itself are about WebLogic but certainly most of the information isĀ  relevant to any server and a good reminder in any case.

Maven and the Tyranny of a WebLogic Installation

Can you stand another post on Maven and WebLogic? I can’t but I thought I’d document this anyway… ;-)

I decided to revisit the problem outlined in Maven and WebLogicMBeanMaker in WebLogic 9/10 wherein you need to have an installation of WebLogic on the machine where you build your security provider. To refresh your memory if you read that post, the problem is that weblogic.jar uses relative paths to find other jars and thus defeats Maven’s dependency mechanism.

I came up with a solution that precludes having to have WebLogic installed but it still doesn’t use artifacts in the repository. Rather, it’s a hack but at least it’s a portable hack.

The solution is to have a directory that contains the required WebLogic jars in the required hierarchy. Here’s the directory structure and subset of files you need from the WLS 9.x installation:

./common/lib/apache_xbean.jar
./server/lib/ant/ant.jar
./server/lib/cssapi.jar
./server/lib/cssimpl.jar
./server/lib/mbeantypes
./server/lib/mbeantypes/wlManagementImplSource.jar
./server/lib/mbeantypes/wlManagementMBean.jar
./server/lib/mbeantypes/wlSecurityProviders.jar
./server/lib/mbeantypes/xacmlSecurityProviders.jar
./server/lib/schema/weblogic-domain-binding.jar
./server/lib/weblogic.jar
./server/lib/xbean.jar

I made a directory to contain the directories and files above and then used that high level directory in the pom like this:

<dependency>
  <groupId>weblogic</groupId>
  <artifactId>weblogic<artifactId>
  <version>9.2.0</version>
  <scope>system</scope>
  <systemPath>C:/WLS920/server/lib/weblogic.jar</systemPath></dependency>

<dependency>
  <groupId>weblogic</groupId>
  <artifactId>wlManagementMBean</artifactId>
  <version>9.2.0<version>
  <scope>system</scope>
<systemPath>C:/WLS920/server/lib/mbeantypes/wlManagementMBean.jar</systemPath>
</dependency>

<dependency>
  <groupId>weblogic</groupId>
  <artifactId>xmlbeans</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>C:/WLS920/server/lib/xbean.jar</systemPath>
</dependency>

As long as your WebLogicMBeanMaker tasks use “maven.compile.classpath” in the classpath then it should work like a champ.

Being freed from the tyranny of a WebLogic installation is a relief and lends itself to painless builds on a continuous integration server, for example.

Obviously, this solution is for WLS 9 (is anyone still using that?) but providers built this way also work in WLS 10.

WebLogic 10 Active Directory Authentication Provider Bug

Reader Cobbie Behrend emailed with a bug he noticed in the Active Directory authentication provider in WebLogic 10. He writes:

“The class that handles AD authentication has a small bug in it that causes authentication to fail [at a later time] after someone logs in incorrectly. During authentication the AD provider binds twice using the same LDAP connection, once with the username password being authenticated, and once with the credentials supplied when you configure the LDAP provider. If authentication fails, the second binding doesn’t happen, and the unauthenticated LDAP connection is returned to the internal LDAP connection pool. This poses a problem when later trying to authenticate and the unauthenticated LDAP connection is retrieved from the pool (you get a stack trace from netscape LDAP classes telling you that the connection has not been bound).

Below is the nested stack trace that you get from WebLogic. The really confusing part when you try to figure this one out is that the point of failure changes, as it all depends on when the bogus connection is being used… also if you are using the same AD user for WebLogic configuration of LDAP, and for testing your application (typical bad development behavior), you don’t notice that the connection is bogus when you turn security logging on. So below the failure is at getDNForUser, but I’ve also seen it happen getting the group members of a group (when testing using a different user).”

netscape.ldap.LDAPException: error result (1); 00000000: LdapErr: DSID-0C090627, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece
at netscape.ldap.LDAPConnection.checkMsg(Unknown Source)
at netscape.ldap.LDAPConnection.checkSearchMsg(Unknown Source)
at netscape.ldap.LDAPConnection.search(Unknown Source)
at weblogic.security.providers.authentication.LDAPAtnDelegate.getDNForUser(LDAPAtnDelegate.java:3310)
at weblogic.security.providers.authentication.LDAPAtnDelegate.authenticate(LDAPAtnDelegate.java:3180)
at weblogic.security.providers.authentication.LDAPAtnLoginModuleImpl.login(LDAPAtnLoginModuleImpl.java:200)
at com.bea.common.security.internal.service.LoginModuleWrapper$1.run(LoginModuleWrapper.java:110)
at java.security.AccessController.doPrivileged(Native Method)
at com.bea.common.security.internal.service.LoginModuleWrapper.login(LoginModuleWrapper.java:106)
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:585)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
at com.bea.common.security.internal.service.JAASLoginServiceImpl.login(JAASLoginServiceImpl.java:93)
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:585)
at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
at $Proxy11.login(Unknown Source)
at weblogic.security.service.internal.WLSJAASLoginServiceImpl$ServiceImpl.login(Unknown Source)
at com.bea.common.security.internal.service.JAASAuthenticationServiceImpl.authenticate(JAASAuthenticationServiceImpl.java:82)
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:585)
at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
at $Proxy32.authenticate(Unknown Source)
at weblogic.security.service.PrincipalAuthenticator.authenticate(Unknown Source)
at weblogic.servlet.security.internal.SecurityModule.checkAuthenticate(SecurityModule.java:256)
at weblogic.servlet.security.internal.SecurityModule.checkAuthenticate(SecurityModule.java:205)
at weblogic.servlet.security.internal.FormSecurityModule.processJSecurityCheck(FormSecurityModule.java:245)
at weblogic.servlet.security.internal.FormSecurityModule.checkUserPerm(FormSecurityModule.java:200)
at weblogic.servlet.security.internal.FormSecurityModule.checkAccess(FormSecurityModule.java:91)
at weblogic.servlet.security.internal.ServletSecurityManager.checkAccess(ServletSecurityManager.java:82)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2076)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2046)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1366)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:200)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:172)

Cobbie points out that you don’t even see the stack trace above unless you enable authentication debugging. He says, “In the console you must set environment -> servers -> AdminServer -> Logging -> Advanced -> Severity Level to debug. To turn on security logging you have to change environment -> servers -> AdminServer -> Debug -> WebLogic -> security -> atn -> DebugSecurityAtn to enabled.”

Cobbie contacted Oracle and received a patch but it doesn’t seem to be a “normal” one in that it was not given a unique name like most patches. Instead, Oracle sent him a new cssWlSecurityProviders.jar file via email.

Cobbie notes:

“The patch works, but only if you have “Use Retrieved User Name as Principal” set to false. If a user sets “Use Retrieved User Name as Principal” property to true the connection should be returned to the pool for the retrieved user (something that was also fixed by this patch).

This works great if a correct password is passed in. However if incorrect credentials are passed in and you have “Use Retrieved User Name as Principal” set to true, you have the same issue as before. The unauthenticated connection gets added to the LDAP connection pool, and future attempts to use it fail.

It appears that there still is no check to confirm that the connection is authenticated before the connection is returned to the pool (or from the pool).”

Hopefully, this post will spare others the troubleshooting effort when they encounter this subtle bug.

Thanks Cobbie!

Maven and WebLogicMBeanMaker in WebLogic 9/10

In WebLogicMBeanMaker and Maven I wrote about how to use WebLogicMBeanMaker 8.1 in a Maven 2 build. Even though WebLogicMBeanMaker is documented as a two-step process, the Maven build process allowed us to skip the second step by relying upon Maven’s packaging mechanism. All was well at the time…

Of course, if you have a security provider in WebLogic 8.1 you’re probably going to migrate it to WebLogic 9 or 10 eventually, right? Unfortunately, the old build process is no longer sufficient and you’ll have to make some changes. First, I’ll describe the problem and then show the solution.

Home is where WebLogic is

If you use a POM similar to the one presented in WebLogicMBeanMaker and Maven but with WebLogic 9+ dependencies (note that wlManagement.jar changed to wlManagementMBean.jar in WLS 9), you’ll get the following error:

[java] Compiling inline
[java] WLMaker-SubProcess: : Exception in thread "main" java.lang.ExceptionInInitializerError
[java] WLMaker-SubProcess: :       at java.lang.Class.forName0(Native Method)
[java] WLMaker-SubProcess: :       at java.lang.Class.forName(Class.java:164)
[java] WLMaker-SubProcess: :       at weblogic.management.commo.BeanGenDriver.getManagementTempDir(BeanGenDriver.java:76)
[java] WLMaker-SubProcess: :       at weblogic.management.commo.BeanGenDriver.main(BeanGenDriver.java:118)
[java] WLMaker-SubProcess: : Caused by: java.lang.RuntimeException: error in finding weblogic.Home
[java] WLMaker-SubProcess: :       at weblogic.Home.getInstance(Home.java:90)
[java] WLMaker-SubProcess: :       at weblogic.Home.getPath(Home.java:96)
[java] WLMaker-SubProcess: :       at weblogic.management.bootstrap.BootStrap.init(BootStrap.java:108)
[java] WLMaker-SubProcess: :       at weblogic.management.bootstrap.BootStrap.(BootStrap.java:87)
[java] WLMaker-SubProcess: :       ... 4 more
[java] WLMaker-SubProcess: : Stopped draining WLMaker-SubProcess:
[java] BeanGen code generation failed
[java] WLMaker-SubProcess: : Stopped draining WLMaker-SubProcess:

“Error in finding weblogic.Home” is the only thing of value in the exception, but what’s that about? Running setDomainEnv before running Maven didn’t help.

As it turns out, the WebLogic dependencies are location-dependent in some fashion. Simply having weblogic.jar and wlManagementMBean.jar in your Maven repository is not sufficient. While setting a weblogic.home system property has potential, I didn’t have any success with the approach. What did work for me is to use the WebLogic installation directory even though it is less than ideal. Here’s how I configured my dependencies in the POM:

<dependency>
  <groupId>weblogic</groupId>
  <artifactId>weblogic</artifactId>
  <version>9.1.0</version>
  <scope>system</scope>
  <systemPath>C:/bea910/weblogic91/server/lib/weblogic.jar</systemPath>
</dependency>
    
<dependency>
  <groupId>weblogic</groupId>
  <artifactId>wlManagementMBean</artifactId>
  <version>9.1.0</version>
  <scope>system</scope>
  <systemPath>C:/bea910/weblogic91/server/lib/mbeantypes/wlManagementMBean.jar</systemPath>
</dependency>

Essentially, I changed the scope from “provided” to “system” and added the systemPath element which points to the jar in the WebLogic installation directory. I left the hard-coded paths for illustration but you’ll probably want to use properties, instead.

Using the system scope solves the home problem and your provider will build without error. It won’t actually work, but your build was successful so what more could you want? ;-) Seriously, that problem will be solved in the next section, but for completeness, I’d like to point out something in case someone knows a better solution than using a WebLogic installation directory. After all, I’d much rather use the Maven repository and I’m guessing you would, too.

Here’s something I discovered:

If you run

java -classpath C:\bea910\weblogic91\server\lib\weblogic.jar weblogic.Home

you get

C:/bea910/weblogic91/server

If you do the same thing against your repository’s weblogic.jar like this

java -classpath “C:\Documents and Settings\MSF\.m2\repository\weblogic\weblogic\9.1.0\weblogic-9.1.0.jar” weblogic.Home

you get

Exception in thread "main" java.lang.RuntimeException: error in finding weblogic.Home
        at weblogic.Home.getInstance(Home.java:90)
        at weblogic.Home.getHome(Home.java:105)
        at weblogic.Home.main(Home.java:113)

I’m not sure what it means or how to leverage the information but it seems to be the root of the problem. I got tired of messing with it but if you have an idea, please comment.

Moving right along…

Scheming Minds

As I mentioned above, you should now have a JAR file for your provider. If you copy it to the mbeantypes directory and start WebLogic, though, you’ll find that your provider doesn’t show up in WebLogic console. Very annoying, indeed.

As it turns out, our pals at BEA are messing with our heads. Starting with WebLogic 9, you need to dance the MBeanMaker Two-Step because the second phase — which just jarred the provider in the past — now creates schema files among other things. No schema files means no recognition of your provider by WebLogic.

Fortunately, the solution is pretty simple since you just need to run WebLogicMBeanMaker twice to get all of the required artifacts. Here’s my updated POM snippet:

<!-- Run WebLogicMBeanMaker to build the authentication provider --> 
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <executions>
    <execution>
      <id>WebLogicMBeanMaker</id>
      <phase>generate-sources</phase>
      <configuration>
        <tasks>

          <echo>Building Authentication provider with WebLogicMBeanMaker...</echo>

          <!-- Ensure that WebLogicMBeanMaker starts from a clean slate -->
          <delete dir="${project.build.directory}/generated-sources"/>

          <path id="gen.path">
            <pathelement path="${project.build.directory}\generated-sources\main\java"/>
            <path refid="maven.compile.classpath"/>
          </path>

          <!-- Copy ZAuthenticator.xml to the generated source directory or it won't work -->
          <copy file="${basedir}/conf/ZAuthenticator.xml" todir="${project.build.directory}/generated-sources/main/java"/> 
                
          <!-- Build the MDF (mbean definition file) for the authenticator -->
          <java classname="weblogic.management.commo.WebLogicMBeanMaker" fork="true" failonerror="true">
            <jvmarg line="-Dfiles=${project.build.directory}/generated-sources/main/java 
                          -DMDF=${basedir}/conf/ZAuthenticator.xml 
                          -DcreateStubs=true -Dverbose=true "/>
            <classpath>
              <path refid="gen.path"/>
            </classpath>
          </java>

          <!-- Build the MJF (mbean jar file) for the authenticator . Also 
               generates a set of XML binding classes and a schema. -->
          <java classname="weblogic.management.commo.WebLogicMBeanMaker" fork="true" failonerror="true">
            <jvmarg line="-Dfiles=${project.build.directory}/generated-sources/main/java 
                          -DMJF=${basedir}/conf/ZAuthenticator -Dverbose=true "/>
                                
            <classpath>
              <path refid="gen.path"/>
            </classpath>
          </java>

          <!-- Copy meta-data files to the target/classes directory so they get jarred -->
          <copy todir="${project.build.directory}/classes">
            <fileset dir="${basedir}/conf">
              <include name="**/*.xml"/> <!-- ZAuthenticator.xml -->
              <include name="**/*.dtd"/> <!-- commo.dtd --> 
            </fileset>
            <fileset dir="${project.build.directory}/generated-sources/main/java">
              <exclude name="**/*.java"/>
            </fileset>
          </copy>

          <echo>Building Authentication provider with WebLogicMBeanMaker. DONE!</echo>
        </tasks>

 	  <!-- Add the generated sources to the Maven source directory list -->
        <sourceRoot>${project.build.directory}/generated-sources/main/java</sourceRoot>
      </configuration>

      <goals>
        <goal>run</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Now, in addition to the original files, your jar should contain roughly a dozen more files, half of which are XSB files. Your provider should now be recognized by WebLogic after you copy the jar to mbeantypes and restart WebLogic.

Can you handle more good news? The same build configuration works in WebLogic 10.

Update: Alex Rykov figured out how to handle the Weblogic home problem. Check it out here.

XSS and Web Frameworks

Matt Raible recently blogged about Java Web Frameworks and XSS. The post and the comments are well worth reading. It’s easy to think (hope!) that a framework will automatically escape output to prevent XSS and give no more thought to it. As Matt’s post shows, you really need to know how your chosen framework deals with the issue.

If you use Struts 2 or WebWork be sure to read the post and update your libraries.

How to Protect Against CSRF Attacks

In Unconventional Warfare, I took a somewhat whimsical approach to describing the challenges of application security today. While the analogy was fun, the message was quite serious. The take-away was that we as developers need to know more about the latest techniques used to subvert our applications.

With this post, I’m going to show you a simple but eye-opening CSRF exploit against WebLogic console. We’ll add a user to your WebLogic security realm without any outward indication that it happened.

Before we go on, it’s important to know what CSRF is. CSRF stands for Cross-Site Request Forgery. Essentially, a malicious website takes advantage of another website’s trust in the user.

I’m just learning about vulnerabilities like CSRF but it occurred to me that administrators would be likely targets for such attacks. Could I compromise my WebLogic server? Turns out I could, and it took about five minutes for me to figure out how to add a user with CSRF. The significance of this paragraph is that someone who has a cursory knowledge of CSRF can cause considerable damage.

As I researched CSRF for this post, I learned that administrators have always been targeted. Also, there are many different ways to pull off the attack and it might be a multi-step process with Cross-Site Scripting (XSS) thrown in for good measure. It’s my intention that my simple demonstration of CSRF will stoke your interest in the subject enough to start defending against these attacks. I’ll supply some techniques for avoiding CSRF vulnerabilities in your applications as well as how to protect your WebLogic console.

OK, time for the demo. You’ll need the following things if you want to try this for yourself:

  • A WebLogic 8.1 domain running on your local machine (I tested against 8.1.4)
  • Your domain has to have the default realm name (myrealm)
  • Your domain has to have the default authenticator named DefaultAuthenticator
  • Your server needs to run on port 80 or 7001

That’s it. You can just take the defaults when you configure the domain and everything will be as required.

With the pre-requisites in place, let’s add the user. Perform these steps:

  1. Fire up WebLogic
  2. Sign into the console
  3. In the same browser session as your console, navigate to my CSRF demo page

See the helpful web page? Now, go back to the console and examine your users. Did you add the user named SpongebobWasHere? I didn’t think so…

The user SpongebobWasHere was added by a CSRF exploit

Perhaps you are wary of going to my demo attack page. I don’t blame you. Security researcher sites don’t display “Best viewed with telnet to port 80″ simply for the humor of it. Assuming you don’t want to telnet you have two other choices for seeing the user get added:

  1. Save the link to your machine, examine the contents, and then load that downloaded page in your browser when you’re satisfied that it’s safe
  2. Go to the URL below by copying and pasting it into your browser (I had to add spaces to get the long text to wrap so you’ll have to remove them)

http://localhost:7001/console/actions/security/DoCreateUserAction? cancelAction=%2Factions%2Fsecurity%2FListUsersAction%3F scopeMBean%3DSecurity%253AName%253Dmyrealm&realm= Security%3AName%3Dmyrealm&continueAction=%2Factions%2F security%2FDoEditUserAction%3FcancelAction%3D%252Factions %252Fsecurity%252FListUsersAction%253FscopeMBean%253DSecurity %25253AName%25253Dmyrealm%26realm%3DSecurity%253AName %253Dmyrealm%26provider%3DSecurity%253AName%253D myrealmDefaultAuthenticator&provider=Security%3AName%3D myrealmDefaultAuthenticator& wl_control_weblogic_management_security_User_Name= SpongebobWasHere&wl_control_weblogic_management_security_User_Password =password&dependentPassword_wl_control_weblogic_management_ security_User_Password=password

Change the port as required.

By the way, the URL above is the only “active” ingredient in the demo page. It serves as the source of an IMG tag. Essentially, the IMG tag issues a GET against the server running on localhost at the specified port. All of the parameters in the URL were gleaned from the HTML source of the console Add User page. The interesting stuff is at the end where I specifed the username and passwords.

The reason this exploit works is that the request to your WebLogic server came from YOUR browser. With YOUR cookies. In fact, if auditing is turned on, it looks like YOU did it.

So, there it is — a quick and easily understandable CSRF attack. I’m amazed at the ease with which this was done. Granted, I made several assumptions when crafting the URL regarding the names of things. Changing any one name would have defeated this particular attack, but a determined attacker might have employed other techniques to learn the names.

Protecting WebLogic Console from CSRF Exploits

Since WebLogic 8.1 console is vulnerable to CSRF, one solution is to change the name of the console. Another is to undeploy the console and use the scripting tools, instead. Hiding behind a firewall is not an option. Non-routable IPs are exploitable as you can see from the use of “localhost” in the URL above.

Yet another solution is to log out of the console before browsing anywhere else. This is probably a good habit for anything you need to log in to such as your bank’s web site.

What’s the likelihood that someone would do this particular exploit? Not very likely, but I believe it is possible even if your server is not on localhost. For example, an attacker might check your browser history and notice you’ve been to http://192.168.1.143/console. Hmmm…

Now, I don’t mean to pick on WebLogic console. From what I’ve read, MANY applications are vulnerable to CSRF. BEA might have fixed the problem in 9.x because I wasn’t able to duplicate my success there. So, either they fixed it or I didn’t craft the URL correctly.

Protecting Your Applications from CSRF Exploits

How can you prevent CSRF attacks in your applications? I was hoping you would ask!

First, know that checking the referrer or doing POST instead of GET won’t save you. To have a shot at preventing a CSRF attack, consider the following techniques:

  • Set a short session timeout
  • Use a token for forms
  • Re-authenticate the user or use a CAPTCHA for each important action
  • Have no XSS vulnerabilities

For more information, check out the sources below. From this list you can see that it’s a tall order to prevent CSRF attacks. However, the various techniques add up to hopefully raise the bar high enough to require a skilled attacker. That’s probably the best you can hope for since a skilled attacker will probably get in, anyway.

Further Reading

As I said earlier, I’m just learning this stuff and know enough to whip up the simple demo you’ve seen here. I encourage you to read more about this issue because there are excellent resources out there describing it much better than I can. Here’s a starter set:

Find WebLogic MBeans with Ease

There was an old woman who lived in a shoe
She had so many MBeans she didn’t know what to do
– With apologies to Mother Goose

It’s hard to deny that MBeans are incredibly useful for accessing configuration and runtime data. But with so many MBeans in an application server, it’s also incredibly hard to find the needle in the haystack.

Whether you’re looking for an MBean type, a particular attribute, or the bean that goes along with a known value (domain name, for example), how do you quickly find it? I’ve already posted one trick I use for finding MBeans via the audit log. In this post, I’ll show you my bestest trick of all for finding WebLogic MBeans. I’d like to fancy myself as an Evil Genius(TM) but it’s actually quite obvious. Here we go…

The weblogic.Admin utility has several commands such as GET and QUERY. You can find MBeans by type, name, or name pattern which is useful if you already have an idea of what you want. The following command uses weblogic.Admin to print all MBeans and their attributes to the command console:

java weblogic.Admin -username weblogic -password weblogic -url t3://localhost:80 query -pretty -pattern *:*

Substitute your username, password, and URL and you’ll get a ton of output. Here’s a representative snippet:

MBeanName: "Security:Name=myrealmDefaultAuthenticator"
	ControlFlag: REQUIRED
	Description: WebLogic Authentication Provider
	EnableGroupMembershipLookupHierarchyCaching: false
	GroupHierarchyCacheTTL: 60
	GroupMembershipSearching: unlimited
	MaxGroupHierarchiesInCache: 100
	MaxGroupMembershipSearchLevel: 0
	MinimumPasswordLength: 8
	ProviderClassName: weblogic.security.providers. \
authentication.DefaultAuthenticationProviderImpl
	Realm: Security:Name=myrealm
	SupportedExportConstraints: users|groups
	SupportedExportFormats: DefaultAtn
	SupportedImportConstraints: 
	SupportedImportFormats: DefaultAtn
	UseRetrievedUserNameAsPrincipal: false
	Version: 1.0

By the way, if you’ve never used weblogic.Admin before, you must first run the setEnv (or setDomainEnv) script in your domain directory to set up environment variables and paths.

Now, that output is all well and good but it might not make finding things any easier. Time for a little redirection, my friend:

java weblogic.Admin -username weblogic -password weblogic -url t3://localhost:80 query -pretty -pattern *:* > MBeans.txt

This time, the output goes into the MBeans.txt file. You can use this file to do automated searches. When you search, you’ll get MBean names, attribute names, and attribute values. Wanna search with RegEx? More power to you! <evil-genius>Muuwhaahaaaahaaa!</evil-genius>

Anyway, like I said, it’s fairly obvious but very useful. Mother Goose’s old woman would be proud of how we spanked those MBeans soundly and sent them to bed.

Epilogue

weblogic.Admin was deprecated in WebLogic 9. It’s still there and works, but it’s being phased out in favor of WLST. I don’t know of a quick way to use WLST to dump MBeans to a file. However, WLST is clearly powerful enough to write a script that does it. I haven’t pursued a solution in WLST because I cheat and use the deprecated weblogic.Admin to dump MBeans to a file. Please don’t tell…

If anyone knows how to use WLST to the same effect, please post a comment and share the solution with everyone. Thanks!

WebLogicMBeanMaker and Maven

This article illustrates a method of integrating WebLogicMBeanMaker (WebLogic 8.1) into a Maven 2 build.

UPDATE: Joel posted a comment with a much better solution than the one presented in this post. Essentially, adding

<copy file=”${basedir}/conf/ZAuthenticator.xml” todir=”${project.build.directory}/generated-sources/main/java”/>

before the call to WebLogicMBeanMaker prevents you from having to run it twice. Thanks, Joel!

If you’ve ever created a Weblogic security provider, you’ve used the WebLogicMBeanMaker utility. It generates source code for adapting your provider definition to the requirements of the WebLogic security framework. It also compiles some of the classes and can optionally JAR the entire package.

Maven is a project management and build system from Apache. I was lured by its Siren song of dependency management, project comprehension, site building capability, and a promise of less complicated build files. Unbeknownst to me, I set out on an adventure that would make Odysseus himself proud.

Refactoring my Ant file into separate projects started out smoothly enough. Creating separate web application and utility jar projects was quite liberating and I was pleased at the relative simplicity. Then I set about to Mavenize the security provider piece. I should have
borrowed some of Odysseus’ beeswax because I ran head-first into the rocks.

There’s no WebLogicMBeanMaker plugin for Maven but Maven does sport the handy maven-antrun-plugin. This plugin allows you to run Ant snippets within Maven. So, I copied the appropriate parts of the Ant script and did a little tweaking where required. With high hopes I ran "mvn clean compile" and was rewarded with a failed build for my optimism. This was a result that would occur time and time again as I’d check the web, tweak, and try again.

At the time of this writing, the web has a miniscule amount of content on WebLogicMBeanMaker and Maven. As it turns out, most of my flailing was caused by my own stupidity, but one issue remains. I eventually got around the problem but the solution is U-G-L-Y. Regardless, I’m posting the build file snippet here in the hopes that it might help someone.

The following script uses WebLogicMBeanMaker to generate the sources. I don’t care about the class files it makes (in fact I delete them) because I want to use Maven to control compilation so that I can be specific about the compiler version. The generated source tree is added to Maven’s source tree for compilation. Finally, I don’t use WebLogicMBeanMaker to JAR the provider because I let Maven handle that as well.

Here’s the snippet:

<!-- Run WebLogicMBeanMaker to build the authentication provider --> 
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <executions>
    <execution>
      <phase>generate-sources</phase>
      <configuration>
        <tasks>

          <!-- IMPORTANT NOTE: When the WebLogicMbeanMaker is run from
               a clean state, eveything works up until a class not found
               error against ZAuthenticatorMBI even though it's there.
               No real clue about why... However, it will work if 
               WebLogicMBeanMaker is run a second time (not from a clean
               slate).
                                    
               Thus, the workaround is to run WebLogicMBeanMaker twice. 
               The first one's failonerror attribute is set to false and the 
               second is set to true to catch any errors. -->

          <echo>Building Authentication provider with WebLogicMBeanMaker...</echo>
          <echo/>
          <echo>*** IGNORE THE CLASSNOTFOUND FOR ZAuthenticatorMBI ***</echo>
          <echo/>

          <!-- Ensure that WebLogicMBeanMaker starts from a clean slate -->
          <delete dir="${project.build.directory}/generated-sources"/>

          <path id="gen.path">
            <pathelement path=
              "${project.build.directory}\generated-sources\main\java"/>
            <path refid="maven.compile.classpath"/>
          </path>

          <!-- Build the MDF (mbean definition file) for the authenticator -->
          <java classname="weblogic.management.commo.WebLogicMBeanMaker" 
                fork="true" failonerror="false">
            <jvmarg 
              line="-Dfiles=${project.build.directory}/generated-sources/main/java 
                    -DMDF=${basedir}/conf/ZAuthenticator.xml 
                    -DcreateStubs=true -Dverbose=true "/>
            <classpath>
              <path refid="gen.path"/>
            </classpath>
          </java>

          <java classname="weblogic.management.commo.WebLogicMBeanMaker" 
                fork="true" failonerror="true">
            <jvmarg 
              line="-Dfiles=${project.build.directory}/generated-sources/main/java 
                    -DMDF=${basedir}/conf/ZAuthenticator.xml 
                    -DcreateStubs=true -Dverbose=true "/>
            <classpath>
              <path refid="gen.path"/>
            </classpath>
          </java>

          <!-- Move the generated Java source files to the appropriate spot -->
          <move todir=
            "${project.build.directory}/generated-sources/main/java/com/z/provider">
            <fileset dir="${project.build.directory}/generated-sources/main/java">
              <include name="**/*.java"/>        
              <exclude name="**/*MBI.java"/>
            </fileset>
          </move>

          <!-- Delete the class files created by WebLogicMBeanMaker -->
          <delete>
            <fileset dir="${project.build.directory}/generated-sources" 
                     includes="**/*.class"/>
          </delete>

          <!-- Copy meta-data files to the target/classes directory so they 
               get jarred -->
          <copy todir="${project.build.directory}/classes">
            <fileset dir="${basedir}/conf">
              <include name="**/*.xml"/> <!-- ZAuthenticator.xml -->
              <include name="**/*.dtd"/> <!-- commo.dtd --> 
            </fileset>
            <fileset dir="${project.build.directory}/generated-sources/main/java">
              <include name="**/*.mbi"/> <!-- ZAuthenticator.mbi -->
            </fileset>
          </copy>

          <echo/>
          <echo>*** IGNORE THE CLASSNOTFOUND FOR ZAuthenticatorMBI ***</echo>
          <echo/>
          <echo>Building Authentication provider with WebLogicMBeanMaker. DONE!</echo>
        </tasks>
        
        <!-- Add the generated sources to the Maven source directory list -->
        <sourceRoot>${project.build.directory}/generated-sources/main/java</sourceRoot>
      </configuration>

      <goals>
        <goal>run</goal>
      </goals>
    </execution>
  </executions>
</plugin>

This script is very similar to the one presented in the WebLogic documentation. My ugly kludge is to run WebLogicMBeanMaker twice. Yep, the first time it fails at a certain point and the second time it works like a champ. Here’s part of the ouput when it fails:

[java] Creating the MBI file…
[java] Could not create MBI.
[java] java.lang.ClassNotFoundException: ZAuthenticatorMBI

The class is there regardless of what the error says. I’ve manipulated my classpath a million times trying to fix this silliness. I’m sure it’s probably something really stupid that I’m missing. Wouldn’t be the first time. But for now, I’ll just let it be and get on with my life. If you know the answer, please comment and let me know.

I almost forgot to mention that for me, the jury is still out on Maven. However, I’ve dusted myself off after smashing into the rocks and can now enjoy the Siren song for the time being, at least. Just add some reporting plugins and run "mvn site". That’s pretty nifty. Oh, and that dependency management piece is very nice. No beeswax required.

 

Bookmark this page on del.icio.us