@kamlesh_vaghela please find the code. 1) XML code <form script="table_row_expansion.js" theme="dark">
<label>Scan reports v3</label>
<fieldset submitButton="false" autoRun="true"></fieldset>
<row>
<panel>
<title>Vulnerability report</title>
<input type="checkbox" token="srStatus">
<label>Status</label>
<choice value="1">solved</choice>
<choice value="0">unsolved</choice>
<default>1,0</default>
<prefix>(</prefix>
<suffix>)</suffix>
<initialValue>1,0</initialValue>
<valuePrefix>is_solved=</valuePrefix>
<delimiter> OR </delimiter>
</input>
<input type="checkbox" token="rsSeverity">
<label>Severity</label>
<choice value="critical">critical</choice>
<choice value="high">high</choice>
<choice value="medium">medium</choice>
<choice value="low">low</choice>
<choice value="informational">informational</choice>
<default>critical,high,medium,low,informational</default>
<prefix>(</prefix>
<suffix>)</suffix>
<initialValue>critical,high,medium,low,informational</initialValue>
<valuePrefix>severity=</valuePrefix>
<delimiter> OR </delimiter>
</input>
<input type="dropdown" token="srAsset">
<label>Asset Group</label>
<choice value="*">All</choice>
<default>*</default>
<fieldForLabel>Asset_Gruppe</fieldForLabel>
<fieldForValue>Asset_Gruppe</fieldForValue>
<search>
<query>| inputlookup lkp-asset-list-master | stats count by Asset_Gruppe</query>
</search>
</input>
<input type="dropdown" token="srCcode">
<label>Company Code</label>
<choice value="*">All</choice>
<default>*</default>
<fieldForLabel>Company Code</fieldForLabel>
<fieldForValue>Company Code</fieldForValue>
<search>
<query>| inputlookup lkp-GlobalIPRange | dedup "Company Code"</query>
<earliest>-24h@h</earliest>
<latest>now</latest>
</search>
</input>
<input type="dropdown" token="srCompany">
<label>Homag / Dürr</label>
<choice value="*">All</choice>
<fieldForLabel>Scan-Company</fieldForLabel>
<fieldForValue>Scan-Company</fieldForValue>
<search>
<query>| inputlookup lkp-asset-list-master | eval Scan-Company=substr('Scan-Company',0,1).lower(substr('Scan-Company',2)) | stats count by Scan-Company</query>
</search>
<default>*</default>
</input>
<input type="dropdown" token="srLocation">
<label>Location</label>
<choice value="*">All</choice>
<default>*</default>
<fieldForLabel>Location</fieldForLabel>
<fieldForValue>Location</fieldForValue>
<search>
<query>| inputlookup lkp-asset-list-master | stats count by Location</query>
</search>
</input>
<input type="dropdown" token="srScanner">
<label>Scanner</label>
<choice value="*">All</choice>
<default>*</default>
<fieldForLabel>Scanner</fieldForLabel>
<fieldForValue>Scanner</fieldForValue>
<search>
<query>| inputlookup lkp-asset-list-master | stats count by Scanner</query>
</search>
</input>
<input type="text" token="srHostname">
<label>Hostname</label>
<default>*</default>
</input>
<input type="text" token="srIp">
<label>IP</label>
<default>*</default>
</input>
<input type="text" token="srPluginname">
<label>Plugin name</label>
<default>*</default>
</input>
<input type="text" token="srScanDate">
<label>Scan Date</label>
<default>*</default>
</input>
<table id="reports_table">
<search>
<query>| inputlookup lkp-all-findings
| lookup lkp-findings-blacklist.csv blfinding as finding OUTPUTNEW blfinding
| lookup lkp-asset-list-master "IP Adresse" as ip OUTPUTNEW Asset_Gruppe Scan-Company Scanner Scan-Location Location "DNS Name" as dns_name
| lookup lkp-GlobalIpRange 3-Letter-Code as Location OUTPUTNEW "Company Code"
| eval key=_key,is_solved=if(lastchecked>lastfound OR lastchecked == 1,1,0),solved=finding."-".is_solved."-".key,blacklisted=if(isnull(blfinding),0,1),scandate=strftime(lastfound,"%Y-%m-%d %H:%M:%S"),lastchecked=strftime(lastchecked,"%Y-%m-%d %H:%M:%S")
| fillnull value="N.A." Asset_Gruppe Scan-Company Scanner Scan-Location Location hostname
| search $srStatus$ $rsSeverity$ blacklisted=0 Asset_Gruppe="$srAsset$" Scan-Company="$srCompany$" Location="$srLocation$" Scanner="$srScanner$" dns="$srHostname$" pluginname="$srPluginname$" ip="$srIp$" scandate="*$srScanDate$*" "Company Code"="$srCcode$"
| strcat finding "#" NessusHost sid hostid pluginid finding
| fields dns ip lastchecked severity pluginid pluginname scandate Asset_Gruppe Location Scan-Company "Company Code" Scan-Location Scanner solved finding
| rename dns as Hostname,ip as IP</query>
<earliest>0</earliest>
<latest></latest>
<sampleRatio>1</sampleRatio>
</search>
<option name="count">100</option>
<option name="dataOverlayMode">none</option>
<option name="drilldown">none</option>
<option name="percentagesRow">false</option>
<option name="refresh.display">progressbar</option>
<option name="rowNumbers">false</option>
<option name="totalsRow">false</option>
<option name="wrap">true</option>
<format type="color" field="severity">
<colorPalette type="map">{"critical":#ff0000,"high":#ff631e,"medium":#ffb750,"low":#fffcab,"informational":#8ba6ff}</colorPalette>
<scale type="category"></scale>
</format>
</table>
</panel>
</row>
</form> 2) JS code require([
'splunkjs/mvc/tableview',
'splunkjs/mvc/chartview',
'splunkjs/mvc/dataview',
'splunkjs/mvc/searchmanager',
'splunkjs/mvc/postprocessmanager',
'splunkjs/mvc',
'underscore',
'splunkjs/mvc/simplexml/ready!'],function(
TableView,
ChartView,
DataView,
SearchManager,
PostProcessManager,
mvc,
_
){
var EventSearchBasedRowExpansionRenderer = TableView.BaseRowExpansionRenderer.extend({
initialize: function(args) {
// initialize will run once, so we will set up a search and a chart to be reused.
this._searchManager = new SearchManager({
id: 'details-search-manager',
preview: false
});
this._baseSearchManager = new SearchManager({
id: 'base-search-manager',
search: '| loadjob savedsearch="debie2scmi:duerr_it_vuln_management:saved-plugin_outputv2"',
preview: false
});
this._postproc_pluginOutput = new PostProcessManager({
id: 'postproc-plugin-output',
managerid: 'base-search-manager',
});
this._tableView = new TableView({
managerid: 'details-search-manager',
'charting.legend.placement': 'none'
});
this._plugintableView = new TableView({
managerid: 'postproc-plugin-output',
'charting.legend.placement': 'none'
});
//this._dataView = new DataView({
// managerid: 'details-search-manager',
// template: "<b>Solution:</b> <p><%= results[0].solution %></p>"
//});
},
canRender: function(rowData) {
// Since more than one row expansion renderer can be registered we let each decide if they can handle that
// data
// Here we will always handle it.
return true;
},
render: function($container, rowData) {
// rowData contains information about the row that is expanded. We can see the cells, fields, and values
// We will find the sourcetype cell to use its value
var findingCell = _(rowData.cells).find(function (cell) {
return cell.field === 'finding';
});
// get plugin and ip
var result = findingCell.value.split("#");
//update the searches
this._searchManager.set({ search: '| inputlookup nessus_plugin_solution.csv | search id=' + result[1] + ' | fields solution | append [| makeresults | eval solution="No data available." | fields - _time ] | head 1'});
// the rex is a workaround for splunk not implementing linebreaks in the details tables correctly, only mv fields seem to work
this._postproc_pluginOutput.set({search: '| search pokey="' + result[3] + '" | fields plugin_output | rex mode=sed field=plugin_output "s/(\\n)/\\1 #BREAK#/g" | makemv delim="#BREAK#" plugin_output | append [| makeresults | eval plugin_output="No data available." | fields - _time ] | head 1' });
// $container is the jquery object where we can put out content.
// In this case we will render our chart and add it to the $container
$container.append(this._tableView.render().el);
$container.append(this._plugintableView.render().el);
// $container.append("IP: " + result[0] + " Plugin: " + result[1] );
}
});
var CustomLinkRenderer = TableView.BaseCellRenderer.extend({
canRender: function(cell) {
return cell.field === 'solved';
},
render: function($td, cell) {
var solved = cell.value;
var solved_result = solved.split("-");
//var a = $('<a>').attr("href", "www.test.de").text("testlink");
//var a = $('<input>').attr('type','checkbox');
//var a = $('<div>').attr({"id":"chk-sourcetype"+cell.value,"value":cell.value}).attr('class','icon-minus-circle');
var a = $('<div>').attr({"id":"chk-sourcetype"+cell.value,"value":cell.value});
// check if marked as solved
if(solved_result[1] == 1)
{
a.attr('class','icon-check-circle');
}
else
{
a.attr('class','icon-minus-circle');
}
$td.empty().append(a);
a.click(function(e) {
e.preventDefault();
//window.location = $(e.currentTarget).attr('href');
// or for popup:
// window.open($(e.currentTarget).attr('href'));
if($(e.currentTarget).attr('class') == 'icon-minus-circle')
{
$(e.currentTarget).attr('class','icon-gear');
var updatestring = '| inputlookup lkp-all-findings | eval key=_key | where key="' + solved_result[2] +'" | eval lastchecked=1 | outputlookup append=t lkp-all-findings';
var kvupdate = new SearchManager({
preview: false
});
kvupdate.set({search: updatestring});
kvupdate.on('search:done', function(properties) {
//console.log("DONE!\nSearch job properties:", properties.content);
// Set new value when search is done
$(e.currentTarget).attr('class','icon-check-circle');
});
}
else
{
$(e.currentTarget).attr('class','icon-gear');
var updatestring = '| inputlookup lkp-all-findings | eval key=_key | where key="' + solved_result[2] +'" | eval lastchecked=0 | outputlookup append=t lkp-all-findings';
var kvupdate = new SearchManager({
preview: false
});
kvupdate.set({search: updatestring});
kvupdate.on('search:done', function(properties) {
//console.log("DONE!\nSearch job properties:", properties.content);
// Set new value when search is done
$(e.currentTarget).attr('class','icon-minus-circle');
});
}
});
}
});
var tableElement = mvc.Components.getInstance("reports_table");
tableElement.getVisualization(function(tableView) {
// Add custom cell renderer, the table will re-render automatically.
tableView.addRowExpansionRenderer(new EventSearchBasedRowExpansionRenderer());
tableView.table.addCellRenderer(new CustomLinkRenderer());
// Force the table to re-render
tableView.table.render();
});
});
... View more