Covering J2EE Security and WebLogic Topics

WebLogic Auditing

According to the explanatory text in the WebLogic Console:

"An Auditing provider collects, stores, and distributes information about operating requests and the outcome of those requests for the purposes of non-repudiation. You can configure multiple Auditing providers in a security realm, but none are required."

This article will discuss how to configure WebLogic to audit security events and configuration changes.

Auditing Security Events

By default, WebLogic does not have auditing turned on. To enable auditing, configure an audit provider in WebLogic Console by navigating to the Auditing Providers section of the active security realm. In the WebLogic 8.1 Console applet, drill down to mydomain->Security->Realms->myrealm->Providers->Auditing.

Add a new DefaultAuditor and click Create. You can set the auditing severity and log rotation time in the Details tab. The DefaultAuditor writes to a file called DefaultAuditRecorder.log in your server directory alongside access.log and myserver.log.

The DefaultAuditor doesn’t have any settings other than severity and rotation time. To have auditing take effect you’ll have to restart WebLogic. Now, whenever auditable security actions such as authentication or authorization occur, a line describing the event and the outcome is recorded in the audit log. Be aware that the audit log can be very verbose so keep an eye on disk space and performance.

Here’s an example authorization event from DefaultAuditRecorder.log:

#### Audit Record Begin <Mar 9, 2006 6:38:48 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=console, contextPath=/console, uri=/actions/mbean/editmbeanaction, httpMethod=GET>>> Audit Record End ####

Auditing Configuration Changes

The auditing process typically only involves security events as they relate to the security providers. For example, events such as authentication, identity assertion, authorization, role mapping, etc., get audited. But what if you’d like to be able to audit any of the following actions:

  • Addition/deletion of configuration items
  • Modification of a setting
  • Addition/deletion of a user, group, etc.
  • Password resets
  • And so on

    These are things that a WebLogic administrator can do in WebLogic Console or via other forms of configuration MBean access such as scripting or weblogic.Admin. Logging these events is as simple as making one configuration change.

    In WebLogic Console, navigate to the domain screen. In WebLogic 8.1, simply click on the domain node in the applet. On the right hand side, set Configuration Auditing from None to one of the following

    • log
    • audit
    • logaudit

      and click Apply.

      Choosing "log" causes the configuration events to go to the server log (e.g., myserver.log). That’s right, you don’t have to have an audit provider configured to capture the data. Choosing "audit," on the other hand, causes the configuration events to be sent to the audit providers. Finally, "logaudit" causes the data to be sent to both places.

      This setting takes effect immediately, so after you clicked Apply configuration changes are logged.

      Here’s an example from the DefaultAuditRecorder.log of the "weblogic" user changing the SSL listen port from 443 to 444:

      #### Audit Record Begin <Mar 9, 2006 10:19:34 PM> <Severity =SUCCESS> <<<Event Type = SetAttribute Configuration Audit Event><Subject = Subject: 2
      Principal = class weblogic.security.principal.WLSUserImpl("weblogic")
      Principal = class weblogic.security.principal.WLSGroupImpl("Administrators")
      ><Object = AppSec:Name=myserver,Server=myserver,Type=SSL><Attribute = ListenPort><From = 443><To = 444>>> Audit Record End ####

      The corresponding entry from the server log file is a little more readable:

      ####<Mar 9, 2006 10:19:34 PM EST> <Info> <Configuration Audit> <Laptop> <myserver> <ExecuteThread: ‘1’ for queue: ‘weblogic.admin.HTTP’> <weblogic> <> <BEA-159904> <USER weblogic MODIFIED AppSec:Name=myserver,Server=myserver,Type=SSL ATTRIBUTE ListenPort FROM 443 TO 444>

      Advanced Auditing

      Clearly, all of these event types can find their way to the audit providers. The significance of this is that you can write your own auditor to process the events in any way you’d like. Have a look at a set of sample security providers (with source) from BEA for a quick start at building your own.

      Let me know when you’ve written an audit provider for emailing the boss when some bozo changes the SSL port to 444! 😉

      Reversed DN in WebLogic 8.1.4

      If you do mutual authentication via two-way SSL, you sometimes need to pull the certificate from the request. For web applications, it’s a simple matter of grabbing the "javax.servlet.request.X509Certificate" attribute. Here’s an extract from the sample SnoopServlet.jsp that comes with WebLogic:

        try {
          // request is HttpServletRequest
          java.security.cert.X509Certificate certs [] = 
             (java.security.cert.X509Certificate [])
      	request.getAttribute(
                 "javax.servlet.request.X509Certificate");
      
          if ((certs != null) && (certs.length > 0)) {
            out.println("DN: "+
              certs[0].getSubjectDN().getName()+"<br/>");
          }
          else // certs==null
          {
            out.println("Not using SSL or client "+
              "certificate not required.");
          }
        } catch (ClassCastException cce) {
          cce.printStackTrace();
        }

      The full JSP can be found at <WL_HOME>\samples\server\examples\src\examples\jsp. I cleaned it up a bit for simpler presentation here.

      Notice that the code pulls the certificate and then prints the Distinguished Name (DN) from the certificate. The DN might look like "cn=Mike Fleming, ou=Engineering,o=XYZ Corp.,c=US" and it identifies the user associated with the certificate. The user certificate is always the first (i.e., zero) element in the certificates array while the issuer certificates in the certificate chain occupy subsequent slot(s). The issuers, by the way, are the Certificate Authorities that signed the certificates in the chain.

      Everything I’ve said thus far is the set up for the big punchline: The order in which the DN is presented is flipped in WebLogic 8.1.4+.

      As a result, running SnoopServlet in 8.1.4 would print "c=US,o=XYZ Corp.,ou=Engineering,cn=Mike Fleming" using my example above.

      Now, this order reversal is not "wrong" since either order is perfectly valid. What’s upsetting is that the first example is what WebLogic has been returning since at least 7.x and now it’s suddenly a different representation.

      This situation might not be a big deal depending upon what you are doing with the DN. However, if you are parsing it or passing it along for further processing, you’ll likely have to take action.

      If you control the source code, the fix is easy. Instead of using

      certs[0].getSubjectDN().getName()

      as SnoopServlet does, use

      certs[0].getSubjectX500Principal().getName()

      instead. In fact, the second approach is now the preferred way of retrieving the DN as I’ll discuss momentarily.

      I’ve presented the problem and provided a solution. But what bugs me is why did it change? Information on this is very hard to come by. Here’s what I uncovered along with some speculation:

      Obviously, the change occurred in WebLogic 8.1.4. Versions prior to that presented the DN in the "normal" order. What happened in 8.1.4 is that the Certicom classes changed.

      Certicom is the provider of much of the crypto functionality in WebLogic. In this case, the class in question is com.certicom.security.cert.internal.X509.X509V3CertImpl. This class implements the java.security.cert.X509Certificate interface and is the object you actually deal with in the example code above.

      Interestingly, JDK 1.5.0 deprecates the getSubjectDN() method but WebLogic 8.1.4 uses JDK 1.4.2_05. My guess is that Certicom knew about the impending deprecation and decided to flip the order just to tick me off. 😉 Deprecation is one thing but why would they totally change the output like they did?

      If you have any information on this, please leave a comment. It’s not a burning issue, of course, but I’m quite curious…

       

      Bookmark this page on del.icio.us