Covering J2EE Security and WebLogic Topics

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.

Friendlier Navigation Syntax in WLST

In WLST (WebLogic Scripting Tool), how many times have you wished you didn’t have to type the parentheses or quotes when navigating MBeans? For me, I wished for that every time. πŸ˜‰

Fortunately, WLST designer Satya Ghattu lets us in on a little secret. Simply enter easeSyntax() while in online mode and you can drop the parentheses and quotes when navigating. Using Satya’s examples:

cd(β€œ/Servers/testServer”)

turns into the friendlier

cd /Servers/testServer

Thanks for the tip, Satya!

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!

The WebLogic Administration Port

Is your WebLogic console available to anyone on the Internet? A quick Google search might be eye-opening:

http://www.google.com/search?q=%22Administration+Console%22+%22Sign+in%22+WebLogic+inurl:%22console%22&hl=en&filter=0

If you try this search you’ll see approximately two pages of exposed consoles. A colleague I showed this to pondered: “How many still use weblogic/weblogic?” Good question. Scary, too.

Simon Vans-Colina wrote “Competitive Intelligence Gathering with Google” wherein he discusses two ways of gleaning which server a site is using. He demonstrated how to search for stacktraces which give very obvious clues as well as the console searching technique shown above.

It’s also important to realize that the results from the search above only found the unfortunate sites whose links were published in some way for Google to find them. Regardless of the search results, someone could go directly to your site and slap a “/console” on the end of your domain to see what happens.

These problems aren’t new and they’re not limited to WebLogic, of course. Any server software that exposes a web-based administration application is fair game. Blogging apps, CMS’s, you name it — they all expose an admin app. If you’re lucky, your application will provide some way to restrict access to the administrative functionality. This post is about securing WebLogic’s console.

You have two choices if you don’t want your server caught with its pants down:

  1. Disable the console application
  2. Use the administration port

Disabling the console application is a bit extreme. If you do that you can only administer your server with weblogic.Admin, WLST, or a custom JMX client. That all seems a bit too inconvenient so the second option is the way to go and will be described below.

Enabling the administration port prevents the masses from accessing your console while giving you access to the same. It’s the best of both worlds. With the administration port enabled:

  • The console is only accessible over a non-standard port (which should not be available from outside your firewall)
  • You have to use SSL
  • You get a dedicated administration listen thread
  • Administrative requests over any port other than the admin port are rejected

So, by using the admin port you protect your console and get several other nice side-effects. The admin port will not be on port 80 or 443 and will thus not be available outside your firewall. Technically, you could open the admin port on the firewall but then you’re back in the same boat. Also, anybody who tries to do an administrative request over any other port will find their request rejected.

Another feature is that your interaction with the console has to be over SSL which protects your data as it transits the wire. And really, who doesn’t love SSL? (Aside: When is the last time you heard of data compromise via an SSL attack? Pretty rare, indeed.)

Finally, using the admin port gets you a dedicated listen thread. What’s the big deal? Let’s say that you have 40 listen threads and the admin port is not enabled. A bug or poor resource utilization causes all 40 threads to be blocked or otherwise unavailable. If you want to get into the console and see what’s going on or fix the problem you’d be out of luck because there’s no thread available to do your work. That’s not good.

The outlook is sunnier when you’ve enabled the admin port, though. Now you have 40 normal listen threads and a dedicated admin thread. If all 40 normal threads are hung you still have a responsive thread for doing your investigation. Of course, you can also look at the separate thread benefit from the opposite perspective: An admin poking around on the console won’t consume a thread intended for satisfying user requests.

Now you’re clamoring for the admin port, right? πŸ˜‰ Let’s set it up.

A prerequisite is that you need to set up SSL normally which is well-documented by BEA. After that, access the console and do the following:

  1. Click on the first node under Domain Structure (it’s your domain name)
  2. Click Lock & Edit
  3. Select the Enable Administration port checkbox
  4. Specify the administration port
  5. Click Save
  6. Click Activate Changes

No restart is required and you’re automatically switched to using the admin port. By the way, the same page allows you to disable the console or change its context path.

Now that you’re using the admin port, if you attempt to access the console over the standard listen ports you’ll be greeted with

Console/Management requests can only be made through an administration channel

Unfortunately, this is also a fingerprint of WebLogic but at least your console is hidden behind your firewall. You can mitigate this fingerprinting to a degree by changing the context path for the console. For example, I changed mine to SecurityThroughObscurity and I would thus access the console via

https://localhost:7777/SecurityThroughObscurity

assuming 7777 is my admin port. Now, going to http://localhost/console will provide the inquisitive user with a nice 404–Not Found page.

The choice of “SecurityThroughObscurity” was obviously tongue-in-cheek but it does highlight the fact that changing the context path is not securing anything but it is making it harder to find. Every little bit helps, I guess.

There are some things of which you need to be aware if you’re running a cluster. See Administration Port and Administrative Channel for more information.

P.S. Don’t forget to change BOTH your username and password. People are on to weblogic/weblogic, I’m afraid… πŸ˜‰

DBMS Security Providers

BEA’s Peter Laird recently wrote an excellent article entitled "WebLogic Security: Configuring the Database Authentication Providers (SQL, Custom, DBMS)." His post describes the following DBMS authentication providers that come with WLS 9 and later:

  • SQL Authentication provider
  • Read-Only SQL Authentication provider
  • Custom DBMS Authentication provider

Peter lays out the technical details of the providers as well as their differences. He then finishes with a SQL authenticator configuration walk-through.

I am surprised to see that he says that when choosing an authentication repository "…you are safest performance-wise with a database backed authentication store." I do agree that databases are typically well-understood by developers but I’d think that an LDAP server would kick the tail of a database in the speed department.

Anyway, that’s a tiny nitpick on an outstanding article. I encourage you to have a look.

I think I’m done gushing about Peter’s article but wait, there’s more! Turns out that Peter is the Managing Architect for the WebLogic Portal team. In the prequel to the above article he wrote "Discussion on WebLogic Security: Authentication Providers, Internal LDAP, JAAS, WebLogic Portal, Profile." This post is a set of fact-filled soundbites concerning Portal and security. If you do portal work you’ll want to have a look at this post, too.

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.

RoleManager Audit Events in WebLogic

Want to fill up your audit logs quickly? Set the auditor’s severity to INFORMATION and you’re well on your way. In this post we’ll take a closer look and see if the information gained is worthy of the disk space and processing time.

More is Better, Right?

It’s natural to expect that audit logs won’t be as "chatty" as application logging. After all, you’d typically only expect one or a handful of authorization events for each accessed resource. Application logging, on the other hand, might spew dozens of lines per request depending upon the logging level.

With this in mind, your security officer or well-meaning admin might see that the WebLogic DefaultAuditor is initially set to a severity of ERROR leaving not one but TWO severity levels untapped. More security data has to be good, right?

Not necessarily. Besides INFORMATION, the other severity level below ERROR is WARNING. I’ve never seen a WARNING event from the out-of-the-box providers. That’s not to say they don’t exist — just that I’ve never seen one. The INFORMATION severity is the lowest level which only seems to include a certain class of Role Manager events.

Role Manager audit events can be sourced from a Role Mapping provider or an Authorization provider. Useful Role Manager events can happen at the SUCCESS and FAILURE levels, but the INFORMATION-level events are highly repetitive and provide little bang for buck. Here are a couple of examples:

#### Audit Record Begin <Jun 26, 2007 9:20:01 PM> <Severity =INFORMATION> <<<Event Type = RoleManager Audit Event ><Subject: 2
Principal = class weblogic.security.principal.WLSUserImpl("weblogic")
Principal = class weblogic.security.principal.WLSGroupImpl("Administrators")
><<adm>><type=<adm>, category=Configuration><>>> Audit Record End ####

#### Audit Record Begin <Jun 26, 2007 9:20:01 PM> <Severity =INFORMATION> <<<Event Type = RoleManager Audit Event ><Subject: 2
Principal = class weblogic.security.principal.WLSUserImpl("weblogic")
Principal = class weblogic.security.principal.WLSGroupImpl("Administrators")
><<adm>><type=<adm>, category=Configuration><||Anonymous||Admin>>> Audit Record End ####

As you can see, there’s very little actionable information here. Yes, user "weblogic" did something but we’re not quite sure what.

Crunch the Numbers

To give you an idea of the volume of Role Manager events at the INFORMATION severity, I started up a WebLogic 8.1 domain which includes five custom applications. I then logged into console but went no further than the initial page. Here’s the breakdown of audit events (note that I’ve enabled configuration auditing):

Authentication: 2
Authorization: 6
AuthorizationPolicy Deploy: 25
Invoke Configuration: 1
RoleManager: 772
RoleManager Deploy: 3
Set Attribute: 10

As you can see, the RoleManager events account for 94%(!) of all events for my scenario. Hitting Refresh on the console caused approximately the same number of Role Manager events. I haven’t timed it, but writing all of those events to disk is probably quite measurable.

Console makes heavy use of JMX so I suspect a lot of the Role Manager events are caused by that. I tested a "normal" web app with just a protected page. Here are the results:

Authentication: 1
Authorization: 1
RoleManager: 14

Thus, for one request, the Role Manager events comprise 88% of the total number of events. The information is slightly different (and maybe even a little useful) as long as you don’t mind seeing it a bunch of times. Here are a couple events:

#### Audit Record Begin <Jun 26, 2007 10:44:08 PM> <Severity =INFORMATION> <<<Event Type = RoleManager Audit Event ><Subject: 2
Principal = class weblogic.security.principal.WLSUserImpl("weblogic")
Principal = class weblogic.security.principal.WLSGroupImpl("Administrators")
><<url>><type=<url>, application=ImplicitGroupsApp, contextPath=/implicitgroupsapp, uri=/users/users.jsp, httpMethod=GET><>>> Audit Record End ####

#### Audit Record Begin <Jun 26, 2007 10:44:08 PM> <Severity =INFORMATION> <<<Event Type = RoleManager Audit Event ><Subject: 2
Principal = class weblogic.security.principal.WLSUserImpl("weblogic")
Principal = class weblogic.security.principal.WLSGroupImpl("Administrators")
><<url>><type=<url>, application=ImplicitGroupsApp, contextPath=/implicitgroupsapp, uri=/users/users.jsp, httpMethod=GET><||user||Anonymous||everyone||Admin>>> Audit Record End ####

I suspect these are sourced by the authorization provider given that it’s showing the requested resource information. The list of roles is barely useful — which one is required?

Quantum Logging

If you decide to not use the INFORMATION severity you can still get the equivalent information from the audit log if you had to. The first thing to consider is the Authorization event. Here’s the event that accompanied the RoleManager event above:

#### Audit Record Begin <Jun 26, 2007 10:44:08 PM> <Severity =SUCCESS> <<<Event Type = Authorization Audit Event ><Subject: 2
Principal = class weblogic.security.principal.WLSUserImpl("weblogic")
Principal = class weblogic.security.principal.WLSGroupImpl("Administrators")
><ONCE><<url>><type=<url>, application=ImplicitGroupsApp, contextPath=/implicitgroupsapp, uri=/users/users.jsp, httpMethod=GET>>> Audit Record End ####

Notice that the resource information is identical to the equivalent RoleManager event.

How can you know which role was required for "/users/users.jsp?" One way is to check that application’s web.xml. However, that data could be newer than what was in place when the event was logged (e.g., web.xml was updated and the app was redeployed after the event).

A better way to do it is to find the most recent corresponding Authorization Policy Deploy event prior to the authorization event in question. For example,

#### Audit Record Begin <Jun 26, 2007 9:12:12 PM> <Severity =SUCCESS> <<<Event Type = Authorization Policy Deploy Audit Event ><Subject: 1
Principal = class weblogic.security.principal.WLSKernelIdentity("<WLS Kernel>")
><<url>><type=<url>, application=ImplicitGroupsApp, contextPath=/implicitgroupsapp, uri=/users/*, httpMethod=GET><user>>> Audit Record End ####

shows one of the policies for the ImplicitGroupsApp. Note that the policy applies to "/users/*" and requires the "user" role for URIs with that pattern.

This concludes our little romp through an audit log. If you choose to not select the INFORMATION severity you can save yourself considerable disk space while still retaining the ability to get the data you need.

Recording WLST Scripts in WebLogic 10

As I mentioned in my WebLogic 10 Released post, WebLogic 10 has the ability to record your sessions in the console as WLST scripts. Unfortunately, doing so takes all the excitement and mystery out of sleuthing around for MBean information! πŸ˜‰

Even though it was deprecated in Weblogic 9, weblogic.Admin is still around which means you can still use the techniques described in Find WebLogic MBeans with Ease and Using Audit Logs to Make Scripting Easier. Furthermore, the approaches given in those posts give you the real object names of the MBeans in case you need to do some JMX work. Otherwise, WLST is the way to go for normal server configuration. The rest of this post will be a quick walk-through of the new script recording feature.

The first thing you’ll notice when you load the WebLogic 10 console is that it looks very similar to the WebLogic 9 console. You’ll also quickly notice the disabled “Record” link and the “Record WLST Scripts” link under “How Do I…” The simple steps below illustrate how to record a configuration script:

  1. Click the “Lock & Edit” button
  2. Click the Record link which is now enabled. A message like the following is displayed:

    The recording session has started. Recording to C:\BEA10\user_projects\domains\Test\AddAuditorScript.py.

  3. Configure whatever you want in the console. I happened to add an auditor. When you’re done, go to the next step.
  4. Click the “Activate Changes” button
  5. Navigate to Preferences->WLST Script Recording and click the Stop Recording button. You can also see the contents of the script file on this page. For adding an auditor and setting the severity, my script file looks like this:

    cmo.createAuditor(‘TestAuditor’, ‘weblogic.security.providers.audit.DefaultAuditor’)

    cd(‘/SecurityConfiguration/Test/Realms/myrealm/Auditors/TestAuditor’)
    cmo.setSeverity(‘INFORMATION’)

    activate()

Doesn’t get much easier than that, does it?

At this point you can edit the script (outside of console, of course) or do whatever you need to do. Then, you can subsequently run the script as you would any WLST script.

If you are interested in recording scripts, you should read the “How Do I” link since there are some things the recorder won’t do. For example, it won’t record the addition or deletion of users, roles, or policies. You can also learn about how the recorder handles encrypted values.

Finally, if you’re running Weblogic 9 and wish you could record scripts, look no further than the WLST Script Generator. At the other end of this link you will find Satya Ghattu‘s script generator and accompanying console extension for WebLogic 9. Thanks to Andre Glauser for passing along the link.

check-auth-on-forward

What happens when a servlet (or JSP) forwards the user to a protected resource for which the user does not have authorization? According to the servlet specification, the user will see the protected resource. Surprise!

I checked the servlet specifications on this subject. Servlet 2.2 has no explicit mention of what happens during forwards or includes from a security perspective. Starting with Servlet 2.3, however, section SRV.12.2 explicitly states that declarative security does not apply to forwards and includes.

I’d prefer it to default the other way such that the container checks security for forwards and includes. Too bad for me, I guess. Fortunately, WebLogic meets the specification’s requirement by default but provides a way to check security if you want to enable it. To use it, add the following stanza to weblogic.xml:

<container-descriptor>
   <check-auth-on-forward/>
</container-descriptor>

Now, authorization will be checked for the target forward or include.

WebLogic 10 Released

BEA announced that WebLogic 10 has been released for general availability. I don’t know about you, but I haven’t even fully kicked the tires on 9.x yet!

With this release, the big push was for Java EE5, EJB, 3.0, and Spring interoperability. Security-wise, the changes seem to be incremental. Here are the highlights of the security changes:

  • Cross-domain security has been improved. Instead of having two or more domains with the same credentials (crazy!), the credential mapper is used. Sounds like a good improvement…
  • The console can now record your interaction with it as WLST scripts. That’s nifty. I haven’t tried it (nor have I tried WebLogic 10 at all yet) but it has the potential to supersede my MBean-finding techniques described in Find WebLogic MBeans with Ease and Using Audit Logs to Make Scripting Easier.
  • The WebLogic Diagnostic Framework (WLDF) can now poke around in an HTTP session. That sounds like fun! πŸ˜‰
  • weblogic.jar has been “refactored.” Read the release notes for more information especially if you use custom Java security policies.
  • Support for additional and updated WS-* specifications include WS-SecureConversations 1.3, WS-Security 1.1, WS-SecurityPolicy 1.2, and WS-Trust 1.3.
  • The Windows NT Authentication provider was deprecated.

That’s all of the documented changes in the security arena. I plan on going a little more in-depth on some of these in the near future.

« Previous Entries  

Bookmark this page on del.icio.us