11 Auditing Events From Custom Security Providers
As described in Auditing Providers auditing is the process whereby information about operating requests and the outcome of those requests are collected, stored, and distributed for the purposes of non-repudiation. Auditing providers provide this electronic trail of computer activity.
Each type of security provider can call the configured Auditing providers with a request to write out information about security-related events, before or after these events take place. For example, if a user attempts to access a withdraw
method in a bank account application (to which they should not have access), the authorization provider can request that this operation be recorded. Security-related events are only recorded when they meet or exceed the severity level specified in the configuration of the Auditing providers.
This chapter includes the following sections:
Security Services and the Auditor Service
The SecurityServices
interface, located in the weblogic.security.spi
package, is a repository for security services (currently just the Auditor Service). As such, the SecurityServices
interface is responsible for supplying callers with a reference to the Auditor Service via the following method:
-
getAuditorService
public AuditorService getAuditorService
The
getAuditorService
method returns theAuditService
if an Auditing provider is configured.
The AuditorService
interface, also located in the weblogic.security.spi
package, provides other types of security providers (for example, authentication providers) with limited (write-only) auditing capabilities. In other words, the Auditor Service fans out invocations of each configured Auditing provider's writeEvent
method, which simply writes an audit record based on the information specified in the AuditEvent
object that is passed in.
See Implement the AuditChannel SSPIand Create an Audit Event. The AuditorService
interface includes the following method:
-
providerAuditWriteEvent
public void providerAuditWriteEvent (AuditEvent event)
The
providerAuditWriteEvent
method gives security providers write access to the object in the WebLogic Security Framework that calls the configured Auditing providers. Theevent
parameter is anAuditEvent
object that contains the audit criteria, including the type of event to audit and the audit severity level. See Create an Audit Event and Audit Severity respectively.
The Auditor Service can be called to write audit events before or after those events have taken place, but does not maintain context in between pre and post operations. Security providers designed with auditing capabilities will need to obtain the Auditor Service as described in Obtain and Use the Auditor Service to Write Audit Events.
Note:
Implementations for both the SecurityServices
and AuditorService
interfaces are created by the WebLogic Security Framework at boot time if an Auditing provider is configured. (See Configure the Custom Auditing Provider.) Therefore, you do not need to provide your own implementations of these interfaces.
Additionally, SecurityServices
objects are specific to the security realm in which your security providers are configured. Your custom security provider's runtime class automatically obtains a reference to the realm-specific SecurityServices
object as part of its initialize method. (See Understand the Purpose of the Provider SSPIs.)
See Java API Reference for Oracle WebLogic Serverfor the SecurityServices and AuditorServiceinterfaces.
How to Audit From a Custom Security Provider
Add auditing capability to your custom security provider by following these steps:
Examples for each of these steps are provided in Example: Implementation of the AuditRoleEvent Interface and Example: Obtaining and Using the Auditor Service to Write Role Audit Events, respectively.
Note:
If your custom security provider is to record audit events, be sure to include any classes created as a result of these steps into the MBean JAR File (MJF) for the custom security provider (that is, in addition to the other files that are required).
Create an Audit Event
Security providers must provide information about the events they want audited, such as the type of event (for example, an authentication event) and the audit severity (for example, error). Audit Events contain this information, and can also contain any other contextual data that is understandable to a configured Auditing provider. To create an Audit Event, either:
Implement the AuditEvent SSPI
To implement the AuditEvent
SSPI, provide implementations for the following methods:
-
getEventType
public java.lang.String getEventType()
The
getEventType
method returns a string representation of the event type that is to be audited, which is used by the Audit Channel (that is, the runtime class that implements theAuditChannel
SSPI). For example, the event type for the Oracle-provided implementation isAuthentication Audit Event
. See Audit Channels and Implement the AuditChannel SSPI. -
getFailureException
public java.lang.Exception getFailureException()
The
getFailureException
method returns anException
object, which is used by the Audit Channel to obtain audit information, in addition to the information provided by thetostring
method. -
getSeverity
public AuditSeverity getSeverity()
The
getSeverity
method returns the severity level value associated with the event type that is to be audited, which is used by the Audit Channel. This allows the Audit Channel to make the decision about whether or not to audit. See Audit Severity. -
toString
public java.lang.String toString()
The
toString
method returns preformatted audit information to the Audit Channel.Note:
The
toString
method can produce any character and no escaping is used. If your Audit provider is writing thetoString
value into a format that uses characters for syntax, escape thetoString
value before writing it.
See Java API Reference for Oracle WebLogic Server for the AuditEvent SSPI.
Implement an Audit Event Convenience Interface
There are several subinterfaces of the AuditEvent
SSPI that are provided for your convenience, and that can assist you in structuring and creating Audit Events.
Each of these Audit Event convenience interfaces can be used by an Audit Channel (that is, a runtime class that implements the AuditChannel
SSPI) to more effectively determine the instance types of extended event type objects, for a certain type of security provider. For example, the AuditAtnEventV2
convenience interface can be used by an Audit Channel that wants to determine the instance types of extended authentication event type objects. (See Audit Channels and Implement the AuditChannel SSPI.)
The Audit Event convenience interfaces are:
-
The AuditRoleEvent and AuditRoleDeploymentEvent Interfaces
Note:
It is recommended, but not required, that you implement one of the Audit Event convenience interfaces.
The AuditAtnEventV2 Interface
The AuditAtnEventV2
convenience interface helps Audit Channels to determine instance types of extended authentication event type objects.
Note:
The AuditAtnEvent
interface is deprecated in this release of WebLogic Server.
To implement the AuditAtnEventV2
interface, provide implementations for the methods described in Implement the AuditEvent SSPI and the following methods:
-
getUsername
public String getUsername()
The
getUsername
method returns the username associated with the authentication event. -
getAtnEventType
public AuditAtnEventV2.AtnEventTypeV2 getAtnEventType()
The
getAtnEventType
method returns an event type that more specifically represents the authentication event. The specific authentication event types are:AUTHENTICATE
: simple authentication using a username and password occurred.ASSERTIDENTITY
: perimeter authentication based on tokens occurred.CREATEDERIVEDKEY
: represents the creation of the Derived key.CREATEPASSWORDDIGEST
: represents the creation of the Password Digest.IMPERSONATEIDENTITY
: client identity has been established using the supplied client username (requires kernel identity).USERLOCKED
: a user account has been locked because of invalid login attempts.USERUNLOCKED
: a lock on a user account has been cleared.USERLOCKOUTEXPIRED
: a lock on a user account has expired.VALIDATEIDENTITY
: authenticity (trust) of the principals within the supplied subject has been validated. -
toString
public String toString()
The
toString
method returns the specific authentication information to audit, represented as a string.Note:
The
toString
method can produce any character and no escaping is used. If your Audit provider is writing thetoString
value into a format that uses characters for syntax, escape thetoString
value before writing it.The
AuditAtnEventV2
convenience interface extends both theAuditEvent
andAuditContext
interfaces. For more information about the AuditContext interface, see Audit Context.
See Java API Reference for Oracle WebLogic Server for the AuditAtnEventV2 interface.
The AuditAtzEvent and AuditPolicyEvent Interfaces
The AuditAtzEvent
and AuditPolicyEvent
convenience interfaces help Audit Channels to determine instance types of extended authorization event type objects.
Note:
The difference between the AuditAtzEvent
convenience interface and the AuditPolicyEvent
convenience interface is that the latter only extends the AuditEvent
interface. (It does not also extend the AuditContext
interface.) See Audit Context.
To implement the AuditAtzEvent
or AuditPolicyEvent
interface, provide implementations for the methods described in Implement the AuditEvent SSPI and the following methods:
-
getSubject
public Subject getSubject()
The
getSubject
method returns the subject associated with the authorization event (that is, the subject attempting to access the WebLogic resource). -
getResource
public Resource getResource()
The
getResource
method returns the WebLogic resource associated with the authorization event that the subject is attempting to access.
See Java API Reference for Oracle WebLogic Server for the AuditAtzEvent and AuditPolicyEvent interfaces.
The AuditMgmtEvent Interface
The AuditMgmtEvent
convenience interface helps Audit Channels to determine instance types of extended security management event type objects, such as a security provider's MBean. It contains no methods that you must implement, but maintains the best practice structure for an Audit Event implementation.
See Java API Reference for Oracle WebLogic Server for the AuditMgmtEvent interface.
The AuditRoleEvent and AuditRoleDeploymentEvent Interfaces
The AuditRoleDeploymentEvent
and AuditRoleEvent
convenience interfaces help Audit Channels to determine instance types of extended role mapping event type objects. They contain no methods that you must implement, but maintain the best practice structure for an Audit Event implementation.
Note:
The difference between the AuditRoleEvent
convenience interface and the AuditRoleDeploymentEvent
convenience interface is that the latter only extends the AuditEvent
interface. (It does not also extend the AuditContext
interface.) See Audit Context.
See Java API Reference for Oracle WebLogic Server for the AuditRoleEvent and AuditRoleDeploymentEventinterfaces.
Audit Severity
The audit severity is the level at which a security provider wants audit events to be recorded. When the configured Auditing providers receive a request to audit, each will examine the severity level of events taking place. If the severity level of an event is greater than or equal to the level an Auditing provider was configured with, that Auditing provider will record the audit data.
Note:
Auditing providers are configured using the WebLogic Remote Console. See Configure the Custom Auditing Provider.
The AuditSeverity
class, which is part of the weblogic.security.spi
package, provides audit severity levels as both numeric and text values to the Audit Channel (that is, the AuditChannel
SSPI implementation) through the AuditEvent
object. The numeric severity value is to be used in logic, and the text severity value is to be used in the composition of the audit record output. See Implement the AuditChannel SSPI and Create an Audit Eventrespectively.
Audit Context
Some of the Audit Event convenience interfaces extend the AuditContext
interface to indicate that an implementation will also contain contextual information. This contextual information can then be used by Audit Channels. See Audit Channels and Implement the AuditChannel SSPI.
The AuditContext
interface includes the following method:
-
getContext
public ContextHandler getContext()
The
getContext
method returns aContextHandler
object, which is used by the runtime class (that is, theAuditChannel
SSPI implementation) to obtain additional audit information. See ContextHandlers and WebLogic Resources.
Example: Implementation of the AuditRoleEvent Interface
Example 11-1 shows the MyAuditRoleEventImpl.java
class, which is a sample implementation of an Audit Event convenience interface (in this case, the AuditRoleEvent
convenience interface). This class includes implementations for:
-
The four methods inherited from the
AuditEvent
SSPI:getEventType
,getFailureException
,getSeverity
andtoString
(as described in Implement the AuditEvent SSPI). -
One additional method:
getContext
, which returns additional contextual information via the ContextHandler. (See ContextHandlers and WebLogic Resources.)Note:
The bold face code in Example 11-1 highlights the class declaration and the method signatures.
Example 11-1 MyAuditRoleEventImpl.java
package mypackage; import javax.security.auth.Subject; import weblogic.security.SubjectUtils; import weblogic.security.service.ContextHandler; import weblogic.security.spi.AuditRoleEvent; import weblogic.security.spi.AuditSeverity; import weblogic.security.spi.Resource; /*package*/ class MyAuditRoleEventImpl implements AuditRoleEvent { private Subject subject; private Resource resource; private ContextHandler context; private String details; private Exception failureException; /*package*/ MyAuditRoleEventImpl(Subject subject, Resource resource, ContextHandler context, String details, Exception failureException) { this.subject = subject; this.resource = resource; this.context = context; this.details = details; this.failureException = failureException; } public Exception getFailureException() { return failureException; } public AuditSeverity getSeverity() { return (failureException == null) ? AuditSeverity.SUCCESS : AuditSeverity.FAILURE; } public String getEventType() { return "MyAuditRoleEventType"; } public ContextHandler getContext() { return context; } public String toString() { StringBuffer buf = new StringBuffer(); buf.append("EventType:" + getEventType() + "\n"); buf.append("\tSeverity: " + getSeverity().getSeverityString()); buf.append("\tSubject: " + SubjectUtils.displaySubject(getSubject()); buf.append("\tResource: " + resource.toString()); buf.append("\tDetails: " + details); if (getFailureException() != null) { buf.append("\n\tFailureException:" + getFailureException()); } return buf.toString(); } }
Obtain and Use the Auditor Service to Write Audit Events
To obtain and use the Auditor Service to write audit events from a custom security provider, follow these steps:
-
Use the
getAuditorService
method to return the Audit Service.Note:
Recall that a
SecurityServices
object is passed into a security provider's implementation of a Provider SSPI as part of the initialize method. (For more information, see Understand the Purpose of the Provider SSPIs.) AnAuditorService
object will only be returned if an Auditing provider has been configured. -
Instantiate the Audit Event you created in Implement the AuditEvent SSPI and send it to the Auditor Service through the
AuditService.providerAuditWriteEvent
method.
Example: Obtaining and Using the Auditor Service to Write Role Audit Events
Example 11-2 illustrates how a custom role mapping provider's runtime class (called MyRoleMapperProviderImpl.java
) would obtain the Auditor Service and use it to write out audit events.
Note:
The MyRoleMapperProviderImpl.java
class relies on the MyAuditRoleEventImpl.java
class from Example 11-1.
Example 11-2 MyRoleMapperProviderImpl.java
package mypackage; import javax.security.auth.Subject; import weblogic.management.security.ProviderMBean; import weblogic.security.SubjectUtils; import weblogic.security.service.ContextHandler; import weblogic.security.spi.AuditorService; import weblogic.security.spi.RoleMapper; import weblogic.security.spi.RoleProvider; import weblogic.security.spi.Resource; import weblogic.security.spi.SecurityServices; public final class MyRoleMapperProviderImpl implements RoleProvider, RoleMapper { private AuditorService auditor; public void initialize(ProviderMBean mbean, SecurityServices services) { auditor = services.getAuditorService(); ... } public Map getRoles(Subject subject, Resource resource, ContextHandler handler) { ... if (auditor != null) { auditor.providerAuditWriteEvent( new MyRoleEventImpl(subject, resource, context, "why logging this event", null); // no exception occurred } ... } }
Auditing Management Operations from a Provider's MBean
A SecurityServices
object is passed into a security provider's implementation of a "Provider" SSPI as part of the initialize
method. (See Understand the Purpose of the Provider SSPIs.) The provider can use this object's auditor to audit provider-specific security events, such as when a user is successfully logged in.
A security provider's MBean implementation is not passed a SecurityServices object. However, the provider may need to audit its MBean operations, such as a user being created.
To work around this, the provider's runtime implementation can cache the SecurityServices object and use a provider-specific mechanism to pass it to the provider's MBean implementation. This allows the provider to audit its MBean operations.
The Manageable Sample Authentication Provider shows one way to accomplish this task. The sample provider contains three major implementation classes:
-
ManageableSampleAuthenticationProviderImpl contains its security runtime implementation.
-
ManageableSampleAuthenticatorImpl contains its MBean implementation.
-
UserGroupDatabase is a helper class used by ManageableSampleAuthenticationProviderImpl and ManageableSampleAuthenticatorImpl.
The code flow to cache and obtain the SecurityServices object is as follows:
-
The ManageableSampleAuthenticationProviderImpl's
initialize
method is passed a SecurityServices object. -
The
initialize
method creates a UserGroupDataBase object and passes it the SecurityServices object. -
The UserGroupDataBaseObject caches the SecurityServices object. The
initialize
method also puts the UserGroupDatabase object into a hash table using the realm's name as the lookup key. -
The ManageableSampleAuhenticatorImpl's
init
method finds its realm name from its MBean. -
The
init
method uses the realm name to find the corresponding UserGroupDataBase object from the hash table. -
The
init
method then retrieves the SecurityServices object from the UserGroupDatabase object, and uses its auditor to audit management operations such as "createUser."Note:
A provider's runtime implementation is initialized only if the provider is part of the default realm when the server is booted. Therefore, if the provider is not in the default realm when the server is booted, its runtime implementation is never initialized, and the provider's MBean implementation cannot gain access to the
SecurityServices
object. That is, if the provider is not in the default realm when the server is booted, the provider cannot audit its MBean operations.
Example: Auditing Management Operations from a Provider's MBean
Example 11-3 illustrates how the ManageableSampleAuhenticatorImpl's init
method finds its realm name from its MBean, how it uses the realm name to find the corresponding UserGroupDataBase
object from the hash table (via the UserGroupDatabase
helper class), and how it then retrieves the SecurityServices
object from the UserGroupDatabase
object.
Example 11-3 also shows how ManageableSampleAuhenticatorImpl
uses its auditor to audit management operations such as "createUser."
Example 11-3 ManageableSampleAuthenticatorImpl.java
package examples.security.providers.authentication.manageable;
import java.util.Enumeration;
import javax.management.MBeanException;
import javax.management.modelmbean.ModelMBean;
import weblogic.management.security.authentication.AuthenticatorImpl;
import weblogic.management.utils.AlreadyExistsException;
import weblogic.management.utils.InvalidCursorException;
import weblogic.management.utils.NotFoundException;
import weblogic.security.spi.AuditorService;
import weblogic.security.spi.SecurityServices;
public class ManageableSampleAuthenticatorImpl extends AuthenticatorImpl
{
// Manages the user and group definitions for this provider:
private UserGroupDatabase database;
// Manages active queries (see listUsers, listGroups, listMemberGroups):
private ListManager listManager = new ListManager();
// The name of the realm containing this provider:
private String realm;
// The name of this provider:
private String provider;
// The auditor for auditing user/group management operations.
// This is only available if this provider was configured in
// the default realm when the server was booted.
private AuditorService auditor;
public ManageableSampleAuthenticatorImpl(ModelMBean base) throws MBeanException
{
super(base);
}
private synchronized void init() throws MBeanException
{
if (database == null) {
try {
ManageableSampleAuthenticatorMBean myMBean = (ManageableSampleAuthenticatorMBean)getProxy();
database = UserGroupDatabase.getDatabase(myMBean);
realm = myMBean.getRealm().getName();
provider = myMBean.getName();
SecurityServices services = database.getSecurityServices();
auditor = (services != null) ? services.getAuditorService() : null;
}
catch(Exception e) {
throw new MBeanException(e, "SampleAuthenticatorImpl.init failed");
}
}
}
...
public void createUser(String user, String password, String description)
throws MBeanException, AlreadyExistsException
{
init();
String details = (auditor != null) ?
"createUser(user = " + user + ", password = " + password + ",
description = " + description + ")" : null;
try {
// we don't support descriptions so just ignore it
database.checkDoesntExist(user);
database.getUser(user).create(password);
database.updatePersistentState();
auditOperationSucceeded(details);
}
catch (AlreadyExistsException e) { auditOperationFailed(details, e); throw e; }
catch (IllegalArgumentException e) { auditOperationFailed(details, e); throw e; }
}
...
private void auditOperationSucceeded(String details)
{
if (auditor != null) {
auditor.providerAuditWriteEvent(
new ManageableSampleAuthenticatorManagementEvent(realm, provider, details, null)
);
}
}
...
private void auditOperationFailed(String details, Exception failureException)
{
if (auditor != null) {
auditor.providerAuditWriteEvent(
new ManageableSampleAuthenticatorManagementEvent(realm, provider, details, failureException)
);
}
}
}
Best Practice: Posting Audit Events from a Provider's MBean
Provider's management operations that do writes (for example, create user, delete user, remove data) should post audit events, regardless of whether or not the operation succeeds.
If your provider audits MBean operations, you should keep the following Best Practice guidelines in mind.
-
If the write operation succeeds, post an INFORMATION audit event.
-
If the write operation fails because of a bad parameter (for example, because the user already exists, or due to a bad import format name, a non-existent file name, or the wrong file format), do not post an audit event.
-
If the write operation fails because of an error (for example, LDAPException, RuntimeException), post a FAILURE audit event.
-
Import operations can partially succeed. For example, some of the users are imported, but others are skipped because there are already users with that name in the provider.
-
If you can easily detect that the data you are skipping is identical to the data already in the provider (for example, the username, description, and password are the same) then consider posting a WARNING event.
-
If you are skipping data because there is a partial collision (for example, the username is the same but the password is different), you should post a FAILURE event.
-
If it is too difficult to distinguish the import data from the data already stored in the provider, post a FAILURE event.