7.2.4. Plugin Execution
Once we have created the file (Plugin execution file), we must start writing the code to give the Plugin the desired functionality.
Some development tips:
It is highly recommended that the written code is structured in multiple functions (a function must not be longer than 100 lines).
The code should be easy to read and understand.
The functions must have names related to their function.
The more variables you check, the less the code unexpectedly fails.
Check the code of the other Plugins already defined to copy the layout and to have an example of how to create the Plugin’s code.
PHP code layout: https://www.php-fig.org/psr/psr-2/
7.2.4.1. Class definition
The class must have the name of the file. In this case, the file is openPorts.php so the class is openPorts.
<?php
class openPorts extends Common_AbstractPlugin
{}
7.2.4.2. Extends class
7.2.4.2.1. Synchronous
If the class is Sync, you must extend from Common_AbstractPluginSync
extends Common_AbstractPluginSync
7.2.4.2.2. Asynchronous
If the class is Async, you must extend from Common_AbstractPlugin
extends Common_AbstractPlugin
7.2.4.3. LOGS
The logs will be absolutely useful while developing a new Plugin. These logs can be checked in:
Asynchronous -> /var/log/opennac/opennac-job.log
Synchronous -> /var/log/opennac/opennac-api.log
Development logs:
Debug: Add these logs to check a certain part of the code. These logs will only appear if the debug mode is activated in OpenNAC Configuration > Configuration vars > Logs > Verbose mode.
Example:
$this->_log->debug( __METHOD__.': Cmd Nmap ['.$cmd.']' );
Error: These logs must be thrown when there is an error in any part of the Plugin’s code.
$this->_log->err( __METHOD__.' Some required properties are not defined.');
7.2.4.4. Required Methods
CheckProperties
This method will check all the fields defined in the JSON file. A log must be added in the first line to state which parameters are being used by this Plugin and will be checked in this function. If everything is correct, the function will return true. Otherwise, it will return false.
Example In this example, a log is printed with the values of the two fields defined (portList/execTtl). After this, it checks that the fields are not empty. Also, it will check exactly the same as the Validators in the Frontend (for security reasons).
/**
* Check all properties are right defined.
*
* @result boolean Check status
*/
protected function checkProperties(){
$this->_log->debug( __METHOD__.': [portList/execTtl -> '.var_export(@$this->cfg['portList'],true).'/'.var_export(@$this->cfg['execTtl'],true).']' );
if (empty($this->cfg['portList']) || empty($this->cfg['execTtl'])) {
$this->_log->err( __METHOD__.': Some required properties are not defined.');
return false;
}
if ($this->cfg['execTtl'] <= 0) {
$this->_log->err( __METHOD__.': ExecTtl has to be greater than 0.');
return false;
}
$portListArray = explode(',', $this->cfg['portList']);
foreach ($portListArray as $portListPart) {
if(!preg_match(Common_Validate_PortRange::portList_regex, $portListPart)) {
$this->_log->err( __METHOD__.': Port list has incorrect format ['.$portListPart.'].');
return false;
}
}
}
onAuthPlugin
This function is the main and first function that will be called.
In parameters:
$values: fields configured in the Plugins’ Form. It also receives the parameters of the current event that has executed the Plugin.
Values that could be found:
mac: Mac address. Example: ‘00:00:0C:11:22:33’
ip: IP address. Example: ‘192.168.110.2’
switchip: IP address of the device that handled the event. Example: ‘10.10.36.51’
switchport: Port of the device that handled the event. Example: ‘15’
switchid: ID of the device that handled the event. Example: ‘FastEthernet0/15’
uid: User identificator. Example: ‘bob’
uidraw: Complete name with the domain. Example: ‘acmeusre1’
date: Date of the current event. Example: ‘2021-07-16 12:39:30’
vlanid: VLAN assigned to the event (could be NULL). Example: ‘330’
policiesid: Id of the policy that matched the event. Example: ‘16’
policiesname: Name of the policy that matched the event. Example: ‘Corporate Devices’
policiesnum: Policy position in the policy list. Example: ‘1’
status: Id of the policy that matched the event. Example: ‘1’
The event has status error. Value is 99.
The event has status rejected. Value is 3.
The event has status logout. Value is 2.
The event has status active. Value is 1.
source: Where the event comes from. Example: ‘IP’
Types:
IP i. SENSOR, VISIBILITY, IPMAC, IP, IPSESSION, MACDISCOVER, VPN
MAC i. SNMP, MAB, 8021XUSER, 8021XUSERCERT, 8021XHOST, 8021XHOSTCERT, SENSOR, VISIBILITY, IPMAC, IP, AGENT
Information i. LOGIN_USER, LOGIN_GUEST ,
Agent (unused) i. INV_AGENT, INV_FILE1, INV_FILE2
Captive (unused) i. REG_GUEST_REQ , REG_GUEST_ACCEPT, REG_GUEST_DENY, REG_GUEST_VALID
source_params: The parameters of the source. It contains: mac, ip, switchip, switchport, switchid, userid, source.
rule_params: Custom params of the policy that matched. Example: ‘802.1x User>IP’
hook: Initial function that will be called. Example: ‘onAuth’
tags: Tags that the policy is sending. Example: ONC_AUTOLEARNED’
Output parameters:
return $status. The $status is true if everything is correct or false if there is any error.
You can also return poleval params (that OpenNAC will process internally):
If you pass tags, the OpenNAC will add them or remove them.
Format: $paramsPoleval[‘tag<number>’] = “tagContent”; //add tag $paramsPoleval[‘notag<number>’] = “tagName”; //remove tag Example: $paramsPoleval[‘notag01’] = “OCF_TEST”; //remove tag OCF_TEST
Add the Hostname.
Format: $paramsPoleval[‘hostname’] = “hostname”; Example: $paramsPoleval[‘hostname’] = “windows_test”;
Suggested layout:
/**
* Execute plugin onAuthPlugin
*
* @param string $values Values received to execute plugin
* @return boolean Success execution
*/
public function onAuthPlugin($values) {
//Sample values:
//array (
// 'mac' => '00:00:0C:11:22:33',
// 'ip' => '192.168.110.2',
// 'switchip' => '10.10.36.51',
// 'switchport' => '15',
...
//)
$this->_log->debug("-------------- onAuthPlugin " . $this->_pluginName);
$status = true;
//step 1: check valid execution
if ($this->checkValidExecution($values)) {
//step 2: execute your code
}
//step 3: return $status: true if okay, false if there is an error
return $status;
...
7.2.4.5. Suggested methods
checkValidExecution
It is the first function that should be called on AuthPlugin. It mainly checks properties about the connection, the user and the status.
It can call another function of the following:
checkValidExecutionSourceIpAndConnectionEstablished: Check that the connection has been established, that the source IP is valid and that the event has an IP.
checkValidExecutionSourceVpnOrUserAndStatusActive: Only apply plugin to VPN or USER source events and “active” status.
checkValidExecutionSourceIpOrIsStarterOrStatusLogout: Check that the source is IP or any other valid or the status is logout.
You can also create your own checkValidExecution function.
/**
* Check prerequisites to execute plugin, for example, "source" value and "previousExecution" timestamp.
* @param array $params Input values
* @return boolean Plugin needs to be evaluated
*/
public function checkValidExecution ($values) {
return $this->checkValidExecutionSourceIpAndConnectionEstablished($values);
}