Novell Home

Action Development Guide

PLUG-IN METHODS

The Action execution structure is not actually defined in the *.js file in the development directory. Instead it is defined in a template which calls out to the methods that you will define in that file. The two are combined during the build process that creates the actual plug-in.

Action Control Flow

The overall flow of Action execution looks like this:

Action-flow

The steps in light green are the methods that you will create; the rest of the template will handle the control flow necessary to make the Action work correctly.

Developing Action Methods

When you write your Action code, keep in mind the following:

  • The Action code is written in JavaScript, which runs in the Rhino engine. This means that most modern JavaScript classes and methods are supported, including things like E4X. This also means that you can define custom Java extensions to the JavaScript if you need to.
  • The full Sentinel JavaScript API is available, although not all methods will make sense in the Action context.
  • The actual overall flow is determined by the template's main.js file, which executes the methods that you define in release.js.
  • The template copy of release.js which is copied into your new Action directory includes some sample code, most of which doesn't do anything and will need to be replaced, but which provides some hints as to where to begin.
  • Unlike a Collector, the Action is designed to run once, then exit.
  • Most Collectors perform a very specific, fairly constrained task whereas Actions are less predictable. As a result, the template is less constrained and there are fewer design patterns that are universally recommended.

Action States

The Action processing is broken out into several distinct phases; such division is somewhat arbitrary, but supports code modularity and enforces good practices. As with the Collector, each method is called by the template and is implemented as a prototype on some global object. In this case, the first and last methods are implemented on the Action class and represent the Action initializing itself and then cleaning itself up, and the intervening methods are on the Input class and represent the input data being fetched, parsed, and processed.

The template defines the following methods:

initialize()
After setting up the Action environment, the template calls the initialize() method. The developer should create any new objects or call any methods necessary to initialize the environment that will be used for the Action.
get()
The get() method is now called; this method should implement any code necessary to fetch input that will be used by the Action. Use the Input methods defined in the API to get events, correlated events, and instances.
normalize()
The normalize() method should be implemented to normalize any input that has been received. You can use any standard JS or template utility object/string manipulation functions, including KeyMap and other translation and lookup methods.
doAction()
If the preceding states completed successfully, at some point the global instance.DO_ACTION should be set. If so, then this method is called to actually perform the desired action. Implement any code needed to do the desired remediation, delivery, or other type of action, using the normalized input from the previous steps.
instance.cleanup()
This is called at the end of the Action code to ensure that any necessary shutdown activities are performed.

You may add code to all or only a few of these methods, depending on your needs.

Examples

Initializing the Action

The initialize() method sets up the Action environment. This might involve loading external code, loading parameters, establishing communications with external systems or integrators, or any other initialization activity.

The following code demonstrates loading an Integrator plus loading a parameter into a JS variable:

Action.prototype.initialize = function() {    
    this.integrator = new IntegratorInstance();  
    if (this.integrator.api == null) { return false; }  
    this.CONFIG.params.attribute = scriptEnv.getParameter("Attribute Name");   
    return true;  
};
  • The IntegratorInstance() constructor will by default use the Integrator selected by an Action parameter — see Action parameters.
  • scriptEnv.getParameter() is part of the Sentinel Event Source Management API, and loading parameters are placed in the instance.CONFIG.params map by convention.
  • This method must return true or the Action will exit
Getting Event/Incident Data

The get() method should be constructed to fetch all the required raw events, trigger events, or incident data from the input. If any particular class of input type is required for the Action to function correctly, that should be specified at the time the Action is created (via the Input Objects dropdown).

The following code demonstrates fetching the correlated events from the triggered rule:

Input.prototype.get = function(){   
    // returns an array of the associated events  
   this.events = this.getEvents();  
};

The data in the input.events[] array can now be used to drive output.

Normalizing the Data

The normalize() method is used to perform any data normalization before the actual action is performed.

The following code demonstrates conversion of the event into JSON notation and loading of Identity information (the LDAP DN).

Input.prototype.normalize = function() {  
    // Convert to JSON   
    this.outputString = JSON.stringify(this.events[0]);   
    // Go fetch the identity associated with the account  
    if (typeof this.events[0].iuident != 'undefined') {    
    this.IUID = Identity.find({ IdentityGuid: this.events[0].iuident });    
    if (typeof this.IUID[0].ExtAttrs["LDAPDN"] != 'undefined') {       
        this.LDAPDN = this.IUID[0].ExtAttrs["LDAPDN"];    
        instance.DO_ACTION = true;  
    }     
};
  • This method should set the instance.DO_ACTION flag to true if everything goes according to plan.
Executing the Action

In this method the desired action is actually performed. In general this should be about constructing the appropriate output signal or message based on the pre-normalized component parts created in previous methods.

The following example demonstrates using the LDAP integrator to set an LDAP attribute on a user object:

Input.prototype.doAction = function(){  
    var result = instance.integrator.api.setAttribute(this.LDAPDN,"loginDisabled","true");  
};
  • This method will not be called if the instance.DO_ACTION flag is not set to true
Post Cleanup

This method is used for cleanup of things established in the course of performing the Action. This might involve shutting down external connections or similar. In most cases, however, simply exiting the Action will cause data and connections to be cleaned up automatically, so this method is rarely used.

The following example closes a JMS connection that was created using an internal Java class:

Action.prototype.cleanup = function() {   
    try {     
        this.JMSClient.exit();  
    } catch(err) {    
        log(err);  
    }   
    return true;  
};

Action Development Guide

© 2014 Novell