This chapter describes how to develop your own plug-ins for Oracle Privileged Account Manager.
Note:
For basic information about managing Oracle Privileged Account Manager plug-ins, including how to configure and deploy plug-ins, refer to Section 11, "Working with Plug-Ins."
This chapter includes the following sections:
You can use Oracle Privileged Account Manager's Java-based plug-in framework to create plug-ins that extend Oracle Privileged Account Manager's functionality to accommodate your specific business and technical requirements. Plug-ins enable you to provide custom logic within a transaction or to connect to a custom data source.
The topics in this section include:
The Oracle Privileged Account Manager plug-in framework contains the plug-in interfaces and classes you need to develop a plug-in implementation. This framework is shipped in the following jar file:
ORACLE_HOME/opam/jlib/opam-plugin-framework.jar
You can use this jar
file to develop, implement, and compile plug-ins.
Note:
Refer to Section 11.2, "Developing Plug-Ins for Oracle Privileged Account Manager" for additional information about developing plug-ins for Oracle Privileged Account Manager.
Following are some special considerations and dependencies that you must consider when developing plug-ins:
Although an Oracle Privileged Account Manager server runtime is not required when developing plug-ins, the server runtime is required for deployment and testing purposes.
To set-up an Oracle Privileged Account Manager Java plug-in,
Create a standalone Java
program using the predefined interface and implement the required methods.
You can execute the plug-in using pre or post timing for an operation. You must implement the corresponding pre plug-in or post plug-in interface.
Note:
Refer to Section 11.2.7.1, "Pre-Operation Plug-Ins" and Section 11.2.7.2, "Post-Operation Plug-Ins"
for a description of these timings.
Before compiling, place the following jar
in your classpath:
ORACLE_HOME/opam/jlib/opam-plugin-framework.jar
Compile the plug-in Java files and create the class
or jar
file. Ensure the compilation completes without errors.
Put the class
or jar
file in a file system location that is accessible to the Oracle Privileged Account Manager server. For high-availability cluster configurations, you may want to place the class
or jar
file in each individual node or in a shared location that is accessible to all nodes.
Register the plug-in by adding the plug-in configuration entry.
Note:
For information about managing plug-in configurations from the Console, refer to Section 11.3, "Creating a Plug-In Configuration."
For information about managing plug-in configurations from the command line, refer to Section A.7, "Working with Plug-Ins."
You can choose any name and package for the class
and jar
files. However, you must be sure to use the same name and package when configuring the Plug-in Class Name
and the Plug-in Class Path
attributes when registering the plug-in.
For example, if you create a plug-in using a fully qualified name, such as my.sample.OpamPlugin, that is compiled to the /u01/myplugin.jar
file and that has a dependency on some classes in /u01/myutils.jar
, then your plug-in configuration must use the following:
Plug-in Class Name | Plug-in Classpath |
---|---|
my.sample.OpamPlugin |
|
After the plug-in configuration is registered and enabled, the server invokes the plug-in whenever the invocation criteria are met.
This section presents a high-level overview of the plug-in API and explains the role of the main classes and interfaces.
Note:
Do not use System.exit()
in a plug-in implementation because it might cause failures in the server runtime.
The topics in this section include:
Oracle Privileged Account Manager plug-ins use the PrePlugin or PostPlugin interface to communicate with the Oracle Privileged Account Manager server. When invoking a plug-in, the server constructs the PluginContext
object and passes details about the operation (such as target, account, and so forth) to the plug-in invoked by that operation. The server also passes the operation request body and the plug-in configuration that invokes the plug-in to the plug-in.
The plug-in constructs a PluginResult
object. After completing its task, the plug-in passes the PluginResult
object back to the server. The PluginResult
object can contain a success or failure code, custom error messages, and log messages. In some cases, the plug-in can change or add details to the request body and pass those details back to the server.
The following figure illustrates how Oracle Privileged Account Manager plug-ins communicate with the server.
The general structure for a Java plug-in is as follows:
public class OPAM_PLUGIN_CLASSNAME implements PrePlugin { public void runPrePlugin(PluginContext ctx, String reqBodyJSON, String pluginCfgJSON) { // Plugin Code } }
public class OPAM_PLUGIN_CLASSNAME implements PostPlugin { public void runPostPlugin(PluginContext ctx, String reqBodyJSON, String pluginCfgJSON) { // Plugin Code } }
Note:
Refer to the Oracle Privileged Account Manager Plug-In Framework Java API Reference for more information.
This section describes the plug-in interfaces and classes to use for Oracle Privileged Account Manager.
The topics in this section include:
The Oracle Privileged Account Manager server creates the PluginContext
object during plug-in invocation and sends it to the plug-in. This object contains the following information:
Account information in JSON format. Obtained by using the getAccountJSON()
method.
Account information is present in operations involving accounts, such as checkin
and checkout
.
Account information is not present in operations that do not involve accounts, such as adding or deleting a target. Also, account information is not present when you add a new account because the account is not yet created, and the details sent by the client can be obtained in the request body JSON.
Note:
Refer to Section B.6, "Account Resource" in Appendix B, "Working with Oracle Privileged Account Manager's RESTful Interface"
for more information about the Account Resource and its JSON format.
Target information in JSON format. Obtained by using the getTargetJSON()
method.
Similar to Account information in JSON format, target information is only present in operations involving targets.
Note:
Refer to Section B.5, "Target Resource" in Appendix B, "Working with Oracle Privileged Account Manager's RESTful Interface"
for more information about the Target Resource and its JSON format.
Operation information in JSON format. Obtained by using the getOperationJSON()
method.
This method contains information about on which resource this operation is being performed (such as target, account, etc.) and which operation is being performed (such as add
, delete
, etc.) For example:
{ "resourceType":"account", "operationName":"add" }
Authentication information in JSON format. Obtained using the getAuthContextJSON()
method.
This method contains information about which user is performing the operation and in which groups that user is a member. For example
{ "requestor":"johndoe", "requestorGroups":["ITADMINS", "MANAGERS"] }
This information is not present for operations of resource type server
because the Oracle Privileged Account Manager server performs the operation rather than an end user.
PluginResult Object. Must be created by the plug-in to pass information back to the server. Set this object by using the setPluginResult()
method and obtain the value that was set by using getPluginResult()
method.
Note:
Refer to Section 16.3.3.2, "PluginResult" for additional information about the
PluginResult
object.
HTTP Response Status (for post plug-ins only). Obtained using the getHTTPResponseStatus()
method.
For post plug-ins, when the Oracle Privileged Account Manager server REST API-based operation has completed, the operation response code (such as 200 OK, 401 Unauthorized, etc.) is sent to the plug-in.
HTTP Response Entity (for post plug-ins only). Obtained using the getHTTPResponseEntity()
method.
For post plug-ins, when the Oracle Privileged Account Manager Server REST API-based operation has completed, the operation results are sent to the plug-in. For example, operation results might include a list of accounts in JSON format from a search operation, an account token in JSON format from a checkout
operation, and so forth.
HTTP Response Location > Created GUID (for post plug-ins only). Obtained using the gettHTTPResponseLocation() -> getGuid()
method.
For post plug-ins and add
operations, when the Oracle Privileged Account Manager Server REST API-based add
operation has completed, the newly created entity's GUID is sent to the plug-in. This GUID is only present for creation operations. The GUID is not present for operations such as delete target, modify target, and so forth.
The plug-in creates PluginResult
and uses it to send information back to the Oracle Privileged Account Manager server.
To create this object, the plug-in uses the PluginResult(java.lang.String resultJSON,int plgErrorCode,java.lang.String plgErrorMsg)
method. After creation, PluginResult
is passed back to the server by storing it in the PluginContext
sent by the server. For example
PluginResult result = new PluginResult(resultJSON, plgErrorCode, plgErrorMsg); ctx.setPluginResult(result);
The PluginResult
object contains the following information:
Plugin modified request body JSON. Result information in JSON format.
In pre plug-in operations, the plug-in uses this information to change or add details to the request body JSON that is passed to it and then returns the updated content as result JSON. The server uses the result JSON to replace the request body JSON before performing the operation.
If multiple pre plug-ins are executed for the same operation, then each plug-in gets the updated request body based on their order of execution. After the last pre plug-in is executed, the final request body is used to execute the operation in the server.
If the plug-in does not want to modify the request body JSON, it can be passed as is into the plug-in result JSON. The plug-in can set this value when creating the PluginResult
object and can access it by using the getResultJSON()
and setResultJSON()
methods.
In post plug-in operations, the plug-in can read this value but modifying the value has no impact because the operation has already been completed.
Error code. Specifies success (PluginResult.CODE_SUCCESS
) or failure (PluginResult.CODE_FAILURE
).
The plug-in can set this value during the PluginResult
object creation and can access it by using the getErrorCode()
and setErrorCode()
methods.
Error message. Describes the error in case of failures.
The plug-in can set any string message and pass it back to the client. The plug-in can set the message during the PluginResult
object creation and can access it by using the getPlgErrorMsg()
and setPlgErrorMsg()
methods.
For example, assume you configured a pre plug-in for checkout
operations to validate checkout dates and prevent account usage on blacklisted dates, such as regional holidays, weekends, etc. The plug-in can set an error message on checkout such as, "Checkout is not allowed on holidays.
" In this case, the checkout
operation will fail and it will include the error message, "Plug-in execution failed with error message: Checkout is not allowed on holidays.
"
Debug logging. Provides information about the plug-in execution.
The plug-in can pass log messages back to the server that will be logged in the server log file. You can use these logs for debugging the plug-in execution. access the log message by using the getLog()
, appendLog(String)
, and clearLog()
methods.
You must implement the PrePlugin interface to create a pre plug-in for Oracle Privileged Account Manager operations. Use following method to implement the PrePlugin interface:
void runPrePlugin(PluginContext ctx, java.lang.String reqBodyJSON, java.lang.String pluginCfgJSON)
The following information is passed from the server to the pre plug-in through runPrePlugin
method:
PluginContext object. Contains details about the operation.
Refer to Section 16.3.3.1, "PlugInContext" for more information.
Request Body JSON. Provides the request sent by the client to Oracle Privileged Account Manager for the REST API operation.
The plug-in can modify this information for pre plug-ins and it can send the newly updated JSON back to the server in the PluginResult
object. Refer to Section 16.3.3.2, "PluginResult" for more information.
Plug-in configuration. Invokes this operation in JSON format.
You can use the same Java plug-in implementation for many operations. For example, you can use the same plug-in that performs email notification for both checkout
and checkin
operations.
When the plug-in configuration is passed to the plug-in, it provides details to the plug-in on which the configuration is causing this invocation, which is also useful for passing custom attributes that are present in the configuration to the plug-in. For example, in the email notification case, you can store mail server details as custom attributes in the plug-in configuration and they will be passed to the plug-in.
You must implement the PostPlugin interface to create a post plug-in for Oracle Privileged Account Manager operations. Use following method to implement the PostPlugin interface:
void runPostPlugin(PluginContext ctx, java.lang.String reqBodyJSON, java.lang.String pluginCfgJSON)
The information that is passed from the server to the post plug-in through the runPostPlugin
method is the same as the information described in the previous section. Review the list in Section 16.3.3.3, "PrePlugin."
A plug-in can maintain its own log file and can log to that file in real time. In addition, a plug-in can log debug messages in the Oracle Privileged Account Manager server log file during execution by using PluginResult
object debug logging methods, as described in Section 16.3.3.2, "PluginResult."
Messages logged using the PluginResult
method will be present in the Oracle Privileged Account Manager Server log file. To view these messages, you must set the logging level to TRACE:32
(very detailed trace or debug information).
The following example shows the sample code used to implement a plug-in's logging functionality.
Example 16-1 Sample Code Used to Implement Plug-In Logging
public void runPostPlugin(PluginContext ctx, String reqBodyJSON, String pluginCfgJSON) { // the parameters are the same for runPrePlugin() … PluginResult result = ctx.getPluginResult(); // get the PluginResult object from PluginContext object result.appendLog("Here is the log"); // append log … // System.out.println(result.getLog()); // getLog() will return current log // result.clearLog(); // clearLog() will remove the log that has been recorded … }
The examples in this section include
Example 16-3 (located at the end of this section) illustrates a pre plug-in that blocks an operation, based on the specified dates, before the operation is executed.
Your organization may have some blacklist dates, such as regional holidays and yearly closures, when access to privileged accounts should not be allowed. This pre plug-in performs the validation and extends Oracle Privileged Account Manager's Usage Policy functionality.
This plug-in uses the following custom attributes to specify the blacklist dates.
Attribute Name | Attribute Value |
---|---|
date |
Month/Day, for example 10/01. Note:
|
To configure the plug-in, use the attributes described in the following table:
Attribute Name | Attribute Value |
---|---|
pluginName |
BlackListDates |
pluginStatus |
active |
pluginResource |
account |
pluginOperation |
checkout |
pluginTiming |
pre |
pluginOrder |
1 |
pluginClassName |
BlackListDates |
pluginClassPath |
|
pluginCustomAttrs |
Use the
|
pluginTimeout |
60 |
To compile the plug-in
If necessary, download the following files:
Download From | Files to Download |
---|---|
ORACLE_HOME |
|
Use the following sample compile command:
javac -cp .:ORACLE_HOME/opam/jlib/opam-plugin-framework.jar: ORACLE_HOME/opam/jlib/third-party/jettison-1.3.jar: ORACLE_HOME/opam/jlib/third-party/jersey-bundle-1.4.jar: ORACLE_HOME/opam/jlib/third-party/jsr311-api.jar BlackListDates.java
Create a jar file:
jar -cf BlackListDates.jar BlackListDates.class
After you configure this plug-in for Oracle Privileged Account Manager, the plug-in will block the user from executing the Oracle Privileged Account Manager operation based on the date
attributes. For example, if today is 10/01, and one of the date attributes is 10/01, then the user will not be able to perform this operation.
Note:
In the following example, only the month and day are necessary. The year does not matter.
Example 16-2 Blacklist Dates Pre Plug-In
import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONStringer; import org.codehaus.jettison.json.JSONArray; import com.oracle.idm.opam.plugin.interfaces.PrePlugin; import com.oracle.idm.opam.plugin.context.PluginContext; import com.oracle.idm.opam.plugin.context.PluginResult; import java.util.Date; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; public class BlackListDates implements PrePlugin { public void runPrePlugin(PluginContext ctx, String reqBodyJSON, String pluginCfgJSON){ System.out.println("===== In BlackListDates.runPrePlugin ====="); try { JSONArray blackDates = null; JSONObject plugin = new JSONObject(pluginCfgJSON); JSONObject config = plugin.getJSONObject("plugin"); JSONArray customAttrsArr = new JSONArray(); if(config.has("pluginCustomAttrs")) customAttrsArr = config.getJSONArray("pluginCustomAttrs"); for(int i=0; i<customAttrsArr.length(); i++) { JSONObject singleJSON = customAttrsArr.getJSONObject(i); JSONObject singleAttr = singleJSON.getJSONObject("pluginCustomAttr"); String attrName = singleAttr.getString("attrname"); if(attrName.equalsIgnoreCase("date")) blackDates = singleAttr.getJSONArray("attrvalue"); } for(int i=0; i<blackDates.length(); i++) { String date = blackDates.getString(i); String[] count = date.split("/"); if(count.length != 2) // wrong format, ignore continue; else { if(isToday(date)) { setResult(ctx, reqBodyJSON, PluginResult.CODE_FAILURE, "You are not allowed to do the operation on this date : " + date); return; } } } } catch (Exception e) { System.out.println("Exception happened: "); e.printStackTrace(); PluginResult ret = new PluginResult(reqBodyJSON, PluginResult.CODE_FAILURE, e.getMessage()); ctx.setPluginResult(ret); } System.out.println("===== Finished BlackListDates.runPrePlugin ====="); } private static boolean isToday(String blackDate) { DateFormat dateFormat = new SimpleDateFormat("MM/dd"); Date date = new Date(); if( blackDate.equalsIgnoreCase( dateFormat.format(date).toString() ) ) return true; else return false; } private static void setResult(PluginContext ctx, String reqBodyJSON, int resultCode, String msg) { PluginResult ret = new PluginResult(reqBodyJSON, resultCode, msg); ctx.setPluginResult(ret); return; } }
Example 16-3 (located at the end of this section) illustrates a post plug-in that sends an email about the operation after the operation has completed.
To configure the plug-in, use the attributes described in the following table:
Attribute Name | Attribute Value |
---|---|
pluginName |
EmailNotification |
pluginDescription |
This is an Email Notification Plug-in. |
pluginResource |
account |
pluginOperation |
checkout |
pluginTiming |
post |
pluginOrder |
1 |
pluginClassName |
EmailNotificationPlugin Note: Class Name should be consistent with the class name in your plug-in jar file |
pluginClassPath |
Note: The pluginClassPath: ["/myhome/plugins/EmailNotificationPlugin.jar"]
|
pluginCustomAttrs |
Use the following custom attributes to send information, such as the SMTP server to use for sending the email, the address where the email is sent, and so forth:
|
You must also configure the following custom attributes to send information, such as the SMTP server to use for sending the email, the address where the email is sent, and so forth.
Attribute Name | Attribute Value |
---|---|
smtp_server |
SMTP host name |
smtp_port |
25 |
to_addr |
<EMAIL ADDRESS> Note: You can set up multiple values. Enter as many |
from_addr |
<EMAIL ADDRESS> |
user |
Optional. SMTP login user name |
password |
Optional. SMTP login user password |
This plug-in uses the JAVA Mail API for sending email. For more information about the JAVA Mail library and to download the library, refer to the following location:
http://www.oracle.com/technetwork/java/javamail/index.html
To compile the plug-in
If necessary, download the following files:
Download From | Files to Download |
---|---|
ORACLE_HOME |
|
JAVA Mail API |
|
Use the following sample compile command:
javac -cp .:ORACLE_HOME/opam/jlib/opam-plugin-framework.jar: ORACLE_HOME/opam/jlib/third-party/jettison-1.3.jar: ORACLE_HOME/opam/jlib/third-party/jersey-bundle-1.4.jar: ORACLE_HOME/opam/jlib/third-party/jsr311-api.jar:. /javax.mail.jar EmailNotificationPlugin.java
Create a jar file:
jar -cf EmailNotificationPlugin.jar EmailNotificationPlugin.class
After you configure this plug-in for Oracle Privileged Account Manager, the plug-in will send an email to the address that you set-up in custom attributes whenever the configured operation is performed. For example, if you configure this plug-in for the account resource type and checkout operation, then the plug-in will send an email notification whenever a checkout is completed.
Example 16-3 Email Notification Post Plug-In
import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.codehaus.jettison.json.JSONStringer; import org.codehaus.jettison.json.JSONArray; import com.oracle.idm.opam.plugin.interfaces.PostPlugin; import com.oracle.idm.opam.plugin.context.PluginContext; import com.oracle.idm.opam.plugin.context.PluginResult; import java.lang.Thread; import java.io.*; import java.util.*; import javax.mail.*; import javax.mail.internet.*; import javax.activation.*; /* Sample post plugin that sends email notification */ public class EmailNotificationPlugin implements PostPlugin { public void runPostPlugin(PluginContext ctx, String reqBodyJSON, String pluginCfgJSON) { PluginResult result = new PluginResult(reqBodyJSON, PluginResult.CODE_SUCCESS, null); try { result.appendLog("Starting EmailNotificationPlugin"); /* Get the resource type and operation name from the context */ JSONObject opJSON = new JSONObject(ctx.getOperationJSON()); String resourceType = opJSON.getString("resourceType"); String operationName = opJSON.getString("operationName"); /* Get the target name */ JSONObject json = null; String targetName = null; if (ctx.getTargetJSON() != null) { JSONObject targetJSON = new JSONObject(ctx.getTargetJSON()); json = targetJSON.getJSONObject("target"); targetName = json.getString("targetName"); } /* Get the account name */ String accountName = null; if (ctx.getAccountJSON() != null) { JSONObject accountJSON = new JSONObject(ctx.getAccountJSON()); json = accountJSON.getJSONObject("account"); accountName = json.getString("accountName"); } /* Get which user performed the operation */ JSONObject pluginAuthJSON = new JSONObject(ctx.getAuthContextJSON()); String requestor = pluginAuthJSON.getString("requestor"); /* Get custom attributes defined in plugin configuration such as email server, to address etc */ JSONObject plugin = new JSONObject(pluginCfgJSON); JSONObject config = plugin.getJSONObject("plugin"); JSONArray customAttrsArr = new JSONArray(); if (config.has("pluginCustomAttrs")) customAttrsArr = config.getJSONArray("pluginCustomAttrs"); String smtpServer = null; String smtpPort = null; String fromAddr = null; String user = null; String password = null; JSONArray emailList = null; for (int i = 0; i < customAttrsArr.length(); i++) { JSONObject singleJSON = customAttrsArr.getJSONObject(i); JSONObject singleAttr = singleJSON.getJSONObject("pluginCustomAttr"); String attrName = singleAttr.getString("attrname"); if (attrName.equalsIgnoreCase("smtp_server")) smtpServer = singleAttr.getJSONArray("attrvalue").getString(0); if (attrName.equalsIgnoreCase("smtp_port")) smtpPort = singleAttr.getJSONArray("attrvalue").getString(0); if (attrName.equalsIgnoreCase("from_addr")) fromAddr = singleAttr.getJSONArray("attrvalue").getString(0); if (attrName.equalsIgnoreCase("to_addr")) emailList = singleAttr.getJSONArray("attrvalue"); if (attrName.equalsIgnoreCase("user")) user = singleAttr.getJSONArray("attrvalue").getString(0); if (attrName.equalsIgnoreCase("password")) password = singleAttr.getJSONArray("attrvalue").getString(0); } for (int i = 0; i < emailList.length(); i++) { Properties properties = System.getProperties(); properties.setProperty("mail.smtps.host", smtpServer); properties.setProperty("mail.smtp.port", smtpPort); if (user != null && password != null) { properties.setProperty("mail.user", user); properties.setProperty("mail.password", password); } Session session = Session.getDefaultInstance(properties); MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(fromAddr)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(emailList.getString(i))); /* Set the email subject and body */ String subject = "OPAM Notification : " + resourceType + " " + operationName; String emailBody = "Target : " + targetName + "\nAccount : " + accountName + "\nOperation : " + operationName + "\nRequestor : " + requestor; message.setSubject(subject); message.setText(emailBody); /* Send the email */ Transport.send(message); result.appendLog("Completed EmailNotificationPlugin successfully"); ctx.setPluginResult(result); } } catch (Exception e) { result.appendLog("Exception happened: " + e); result.setErrorCode(PluginResult.CODE_FAILURE); result.setErrorMsg(e.getMessage()); ctx.setPluginResult(result); } } }
For information about managing plug-ins,
Refer to Chapter 11, "Working with Plug-Ins" for information about managing plug-ins from the Console.
Refer to Section A.7, "Working with Plug-Ins" for information about managing plug-ins from the command line.