Commit ca8e54ef authored by Ad Schellevis's avatar Ad Schellevis

(ids) work in progress IDS/suricata

parent 1e8b70bb
...@@ -29,7 +29,9 @@ ...@@ -29,7 +29,9 @@
namespace OPNsense\IDS\Api; namespace OPNsense\IDS\Api;
use \OPNsense\Base\ApiControllerBase; use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Core\Backend;
use \OPNsense\IDS\IDS; use \OPNsense\IDS\IDS;
use \OPNsense\Core\Config;
/** /**
* Class SettingsController Handles settings related API actions for the IDS module * Class SettingsController Handles settings related API actions for the IDS module
...@@ -37,5 +39,146 @@ use \OPNsense\IDS\IDS; ...@@ -37,5 +39,146 @@ use \OPNsense\IDS\IDS;
*/ */
class SettingsController extends ApiControllerBase class SettingsController extends ApiControllerBase
{ {
private $idsModel = null;
/**
* get ids model
* @return null|IDS
*/
public function getModel()
{
if ($this->idsModel == null) {
$this->idsModel = new IDS();
}
return $this->idsModel;
}
/**
* search installed ids rules
* @return array
*/
public function searchInstalledRulesAction()
{
if ($this->request->isPost()) {
$this->sessionClose();
// fetch query parameters
$itemsPerPage = $this->request->getPost('rowCount', 'int', 9999);
$currentPage = $this->request->getPost('current', 'int', 1);
if ($this->request->hasPost('sort') && is_array($this->request->getPost("sort"))) {
$sortStr = '';
$sortBy = array_keys($this->request->getPost("sort"));
if ($this->request->getPost("sort")[$sortBy[0]] == "desc") {
$sortOrd = 'desc';
} else {
$sortOrd = 'asc';
}
foreach ($sortBy as $sortKey) {
if ($sortStr != '') {
$sortStr .= ',';
}
$sortStr .= $sortKey . ' '. $sortOrd . ' ';
}
} else {
$sortStr = 'sid';
}
if ($this->request->getPost('searchPhrase', 'string', '') != "") {
$searchPhrase = 'msg,classtype,source,sid/"'.$this->request->getPost('searchPhrase', 'string', '').'%"';
} else {
$searchPhrase = '';
}
// add filter for classtype
if ($this->request->getPost("classtype", "string", '') != "") {
$searchPhrase .= "classtype/".$this->request->getPost("classtype", "string", '').' ';
}
// request list of installed rules
$backend = new Backend();
$response = $backend->configdpRun("ids list installedrules", array($itemsPerPage,
($currentPage-1)*$itemsPerPage,
$searchPhrase, $sortStr));
$data = json_decode($response, true);
if ($data != null && array_key_exists("rows", $data)) {
$result = array();
$result['rows'] = $data['rows'];
// update rule status with own administration
foreach ($result['rows'] as &$row) {
$row['enabled'] = $this->getModel()->getRuleStatus($row['sid'], $row['enabled']);
}
$result['rowCount'] = count($result['rows']);
$result['total'] = $data['total_rows'];
$result['current'] = (int)$currentPage;
return $result;
} else {
return array();
}
} else {
return array();
}
}
/**
* get rule information
* @param $sid rule identifier
* @return array|mixed
*/
public function getRuleInfoAction($sid)
{
// request list of installed rules
$backend = new Backend();
$response = $backend->configdpRun("ids list installedrules", array(1, 0,'sid/'.$sid));
$data = json_decode($response, true);
if ($data != null && array_key_exists("rows", $data) && count($data['rows'])>0) {
$row = $data['rows'][0];
$row['enabled'] = $this->getModel()->getRuleStatus($row['sid'], $row['enabled']);
return $row;
} else {
return array();
}
}
/**
* list available classtypes
* @return array
* @throws \Exception
*/
public function listRuleClasstypesAction()
{
$backend = new Backend();
$response = $backend->configdRun("ids list classtypes");
$data = json_decode($response, true);
if ($data != null && array_key_exists("items", $data)) {
return $data;
} else {
return array();
}
}
/**
* @param $sid
* @return array
*/
public function toggleRuleAction($sid)
{
$ruleinfo = $this->getRuleInfoAction($sid);
if (count($ruleinfo) > 0) {
if ($ruleinfo['enabled'] == 1) {
$this->getModel()->disableRule($sid) ;
} else {
$this->getModel()->enableRule($sid) ;
}
$this->getModel()->serializeToConfig();
Config::getInstance()->save();
}
return array();
}
} }
...@@ -32,4 +32,84 @@ use OPNsense\Base\BaseModel; ...@@ -32,4 +32,84 @@ use OPNsense\Base\BaseModel;
class IDS extends BaseModel class IDS extends BaseModel
{ {
private $sid_list = array();
private function updateSIDlist()
{
if (count($this->sid_list) == 0) {
foreach ($this->rules->rule->__items as $NodeKey => $NodeValue) {
$this->sid_list[$NodeValue->sid->__toString()] = $NodeValue;
}
}
}
/**
* get new or existing rule
* @param $sid
* @return mixed
*/
private function getRule($sid)
{
$this->updateSIDlist();
if (!array_key_exists($sid, $this->sid_list)) {
$rule = $this->rules->rule->Add();
$rule->sid = $sid;
$this->sid_list[$sid] = $rule;
}
return $this->sid_list[$sid];
}
/**
* enable rule
* @param $sid
*/
public function enableRule($sid)
{
$rule = $this->getRule($sid);
$rule->enabled = "1";
}
/**
* disable rule
* @param $sid
*/
public function disableRule($sid)
{
$rule = $this->getRule($sid);
$rule->enabled = "0";
}
/**
* remove rule by sid
* @param $sid
*/
public function removeRule($sid)
{
// search and drop rule
foreach ($this->rules->rule->__items as $NodeKey => $NodeValue) {
if ((string)$NodeValue->sid == $sid) {
$this->rules->rule->Del($NodeKey);
unset ($this->sid_list[$sid]);
break;
}
}
}
/**
* retrieve current altered rule status
* @param $sid
* @param $default default value
* @return default, 0, 1 ( default, true, false)
*/
public function getRuleStatus($sid, $default)
{
$this->updateSIDlist();
if (array_key_exists($sid, $this->sid_list)) {
return (string)$this->sid_list[$sid]->enabled;
} else {
return $default;
}
}
} }
...@@ -4,5 +4,17 @@ ...@@ -4,5 +4,17 @@
OPNsense IDS OPNsense IDS
</description> </description>
<items> <items>
<rules>
<rule type="ArrayField">
<sid type="IntegerField">
<ValidationMessage>sid should be a number</ValidationMessage>
<Required>Y</Required>
</sid>
<enabled type="BooleanField">
<default>1</default>
<Required>Y</Required>
</enabled>
</rule>
</rules>
</items> </items>
</model> </model>
...@@ -30,6 +30,45 @@ POSSIBILITY OF SUCH DAMAGE. ...@@ -30,6 +30,45 @@ POSSIBILITY OF SUCH DAMAGE.
$( document ).ready(function() { $( document ).ready(function() {
function addFilters(request) {
var selected =$('#ruleclass').find("option:selected").val();
if ( selected != "") {
request['classtype'] = selected;
}
return request;
}
$("#grid-installedrules").UIBootgrid(
{ 'search':'/api/ids/settings/searchinstalledrules',
'options':{
'requestHandler':addFilters,
'formatters':{
"rowtoggle": function (column, row) {
if (parseInt(row[column.id], 2) == 1) {
return "<span class=\"fa fa-check-square-o command-toggle\" data-value=\"1\" data-row-id=\"" + row.sid + "\"></span>";
} else {
return "<span class=\"fa fa-square-o command-toggle\" data-value=\"0\" data-row-id=\"" + row.sid + "\"></span>";
}
}
}
},
'toggle':'/api/ids/settings/toggleRule/'
}
);
// list all known classtypes and add to selection box
ajaxGet(url="/api/ids/settings/listRuleClasstypes",sendData={}, callback=function(data, status) {
if (status == "success") {
$.each(data['items'], function(key, value) {
$('#ruleclass').append($("<option></option>").attr("value",value).text(value));
});
$('.selectpicker').selectpicker('refresh');
// link on change event
$('#ruleclass').on('change', function(){
$('#grid-installedrules').bootgrid('reload');
});
}
});
}); });
...@@ -44,7 +83,38 @@ POSSIBILITY OF SUCH DAMAGE. ...@@ -44,7 +83,38 @@ POSSIBILITY OF SUCH DAMAGE.
</ul> </ul>
<div class="tab-content content-box tab-content"> <div class="tab-content content-box tab-content">
<div id="item1" class="tab-pane fade in active"> <div id="item1" class="tab-pane fade in active">
<div class="bootgrid-header container-fluid">
<div class="row">
<div class="col-sm-12 actionBar">
<b>Classtype &nbsp;</b>
<select id="ruleclass" class="selectpicker" data-width="200px"><option value="">ALL</option></select>
</div>
</div>
</div>
<!-- tab page "installed rules" -->
<table id="grid-installedrules" class="table table-condensed table-hover table-striped table-responsive">
<thead>
<tr>
<th data-column-id="sid" data-type="number" data-visible="true" data-identifier="true" >sid</th>
<th data-column-id="source" data-type="string">Source</th>
<th data-column-id="classtype" data-type="string">ClassType</th>
<th data-column-id="msg" data-type="string">Message</th>
<th data-column-id="enabled" data-formatter="rowtoggle" data-sortable="false">enabled</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button>
</td>
</tr>
</tfoot>
</table>
</div> </div>
<div id="item2" class="tab-pane fade in"> <div id="item2" class="tab-pane fade in">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment