You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

751 lines
29 KiB

require.config({
paths: {
'app': '../app'
}
});
require([
"underscore",
"jquery",
"splunkjs/mvc/utils",
"splunkjs/mvc",
"splunkjs/mvc/tokenutils",
"splunkjs/mvc/simplexml",
"splunkjs/mvc/layoutview",
"splunkjs/mvc/simplexml/dashboardview",
"splunkjs/mvc/simplexml/dashboard/panelref",
"splunkjs/mvc/simplexml/element/chart",
"splunkjs/mvc/simplexml/element/event",
"splunkjs/mvc/simplexml/element/html",
"splunkjs/mvc/simplexml/element/list",
"splunkjs/mvc/simplexml/element/map",
"splunkjs/mvc/simplexml/element/single",
"splunkjs/mvc/simplexml/element/table",
"splunkjs/mvc/simplexml/element/visualization",
"splunkjs/mvc/simpleform/formutils",
"splunkjs/mvc/simplexml/eventhandler",
"splunkjs/mvc/simplexml/searcheventhandler",
"splunkjs/mvc/simpleform/input/dropdown",
"splunkjs/mvc/simpleform/input/radiogroup",
"splunkjs/mvc/simpleform/input/linklist",
"splunkjs/mvc/simpleform/input/multiselect",
"splunkjs/mvc/simpleform/input/checkboxgroup",
"splunkjs/mvc/simpleform/input/text",
"splunkjs/mvc/simpleform/input/timerange",
"splunkjs/mvc/simpleform/input/submit",
"splunkjs/mvc/searchmanager",
"splunkjs/mvc/savedsearchmanager",
"splunkjs/mvc/postprocessmanager",
"splunkjs/mvc/simplexml/urltokenmodel",
"splunkjs/mvc/tableview",
"splunkjs/mvc/simplexml/ready!"
], function(
_,
$,
utils,
mvc,
TokenUtils,
DashboardController,
LayoutView,
Dashboard,
PanelRef,
ChartElement,
EventElement,
HtmlElement,
ListElement,
MapElement,
SingleElement,
TableElement,
VisualizationElement,
FormUtils,
EventHandler,
SearchEventHandler,
DropdownInput,
RadioGroupInput,
LinkListInput,
MultiSelectInput,
CheckboxGroupInput,
TextInput,
TimeRangeInput,
SubmitButton,
SearchManager,
SavedSearchManager,
PostProcessManager,
UrlTokenModel,
TableView
) {
require(["splunkjs/mvc/simplexml/ready!"], function () {
let isAdmin = false;
let organization = '';
let search1 = null;
let keySearchManager = null;
let no_data_keys = true;
let roleSearchManager = new SearchManager({
"id": "roleSearch",
"status_buckets": 300,
"search": '| rest splunk_server=local /services/authentication/current-context | table roles | mvexpand roles'
});
var roleResults = roleSearchManager.data("results", {count:0});
roleResults.on("data", function() {
console.log("Got Search Results");
var d = roleResults.data();
if (d && d.rows) {
for (var i = 0; i < d.rows.length; i++) {
if ( (d.rows[i][0] === 'admin') || (d.rows[i][0] === 'incident_intelligence_admin') || (d.rows[i][0] === 'sc_admin') ){
$("#voCriteriaPanel").show();
isAdmin = true;
break;
}
}
}
getOrgIdsAndSFXTokens();
$("#iiTablePanel").show();
});
roleSearchManager.startSearch();
let ActionCellRenderer = TableView.BaseCellRenderer.extend({
canRender: function (cell) {
return (cell.field === 'Actions');
},
render: function ($td, cell) {
// Actions comes in from search as savedSearchName
if (cell.field === 'Actions') {
// Cell contains <_key>:<is_default>
let rawCell = cell.value;
let tokens = rawCell.split(':');
let theKey = tokens[0];
let isDefault = tokens[1];
let realm = tokens[2];
let orgId = tokens[3];
if (isAdmin) {
let cellHtml = '';
if ((isDefault !== 'true')) {
// Not the default key, add 'make default' link.
cellHtml += '<div class="data-bar-wrapper" style="display:inline-block;"> ' +
' <a id="make_default_key" href="#" objKey="' + theKey + '" class="action-col-button">Set Default</a>' +
'</div> ';
}
// Add test links
cellHtml += '<div class="data-bar-wrapper" style="display:inline-block;"> ' +
' <a id="test_sfxtoken" href="#" objKey="' + theKey + '" realm="' + realm + '" orgId="' + orgId + '" class="action-col-button" style="color:#0264D7;font-weight:bold;">Test Conection</a>' +
'</div> ';
cellHtml += '<div class="data-bar-wrapper" style="display:inline-block;margin-left:10px;"> ' +
' <a id="delete_sfxtoken" href="#" objKey="' + theKey + '" class="action-col-button" style="color:red">Delete</a> ' +
'</div>';
$td.addClass('action-cell').html(cellHtml);
$td.css('width', '250px');
// Default key action
$td.find('#make_default_key').on("click", function (e) {
let objKey = $(this).attr("objKey");
makeDefaultkey(objKey);
});
$td.find('#delete_sfxtoken').on("click", function (e) {
let objKey = $(this).attr("objKey");
require(["bootstrap.modal"],function() {
$(".modal-body").html("Delete Key, are you sure?");
$("#confirmDialogButton").html("Delete");
$("#confirmDialogButton").show();
$("#cancelDialogButton").html("Cancel");
$("#cancelDialogButton").show();
$('#configurationModal').css('z-index', '9999');
$('#configurationModal').modal('show');
$('#configurationModal').data("state", {key: objKey, orgId: orgId});
});
});
// Test key action
$td.find('#test_sfxtoken').on("click", function (e) {
let realm = $(this).attr("realm");
let orgId = $(this).attr("orgId");
let objKey = $(this).attr("objKey");
testKey(objKey, realm, orgId);
});
}
else {
// Add test link
let cellHtml = '<div class="data-bar-wrapper" style="display:inline-block;"> ' +
' <a id="test_sfxtoken" href="#" objKey="' + theKey + '" realm="' + realm + '" orgId="' + orgId + '" class="action-col-button">Test</a>' +
'</div> ';
$td.addClass('action-cell').html(cellHtml);
$td.css('width', '250px');
// Test key action
$td.find('#test_sfxtoken').on("click", function (e) {
let realm = $(this).attr("realm");
let orgId = $(this).attr("orgId");
let objKey = $(this).attr("objKey");
testKey(objKey, realm, orgId);
});
}
}
}
});
$("#confirmDialogButton").click(function(e) {
e.preventDefault();
console.log("configurationModal.data(\"state\").org_id: " + $('#configurationModal').data("state").orgId)
let objKey = $('#configurationModal').data("state").key;
let orgId = $('#configurationModal').data("state").orgId;
// let org_id = $('#configurationModal').data("state").org_id;
deleteKey(objKey);
// delete services for the org_id
deleteIRServices(orgId);
});
function getOrgIdsAndSFXTokens() {
search1 = new SearchManager({
"id": "search1",
"status_buckets": 300,
"search": '| inputlookup incident_intelligence_kvstore_lookup | eval "Realm" = realm | eval "Org Id" = org_id | eval Actions=(_key + ":" + is_default + ":" + realm + ":" + org_id) | eval "Is Default"=is_default | table "Realm", "Org Id", "Is Default", "Actions" | sort -"Is Default"',
"sample_ratio": null,
"latest_time": "now",
"cancelOnUnload": true,
"earliest_time": "-24h@h",
"app": utils.getCurrentApp(),
"auto_cancel": 90,
"preview": true
});
search1.on("search:done", function(properties) {
if (properties.content.resultCount == 0) {
console.log("No Org IDs, Org level ids configured.");
}
else {
console.log("Got Org IDs, Org level ids");
if (no_data_keys) {
$("#display_next").show();
}
}
});
let table = new TableView({
id: "orgIdSFXTokensTable",
managerid: "search1",
pagesize: 25,
drilldown: "none",
drilldownredirect: false,
el: $("#org_id_sfx_tokens_table")
});
let customCellRenderer = new ActionCellRenderer();
table.addCellRenderer(customCellRenderer);
}
// Create a service object using the Splunk SDK for JavaScript
// to send REST requests
let service = mvc.createService({ owner: "nobody" , app: "splunk_incident_intelligence_app"});
let param = {
output_mode: "JSON"
};
function makeDefaultkey(keyVal) {
// First, find key that's currently default, so it can be made not default.
const defaultKeyQuery = '| inputlookup incident_intelligence_kvstore_lookup ' +
'| eval "Routing Key" = routing_key ' +
'| search is_default=true ' +
'| eval "Key"=_key ' +
'| eval "Realm" = realm ' +
'| eval "Org ID" = org_id | eval "Is Default"=is_default ' +
'| table "Realm", "Org ID", "Is Default", "Key"';
console.log('Looking for current default entry...');
const search = service.oneshotSearch(
defaultKeyQuery,
null,
function (err, results) {
if (err) {
console.error('make default key, default key search error - ', err);
}
if (results && results.rows && results.rows.length > 0) {
const realm = results.rows[0][0];
const orgId = results.rows[0][1];
const isDefault = results.rows[0][2];
const key = results.rows[0][3];
// Clear the is_default flag on the old default record.
const record = {
"realm": realm,
"org_id": orgId,
"is_default": "false",
"_key": key
};
service.request(
"storage/collections/data/incident_intelligence_collection/" + encodeURIComponent(key),
"POST",
null,
null,
JSON.stringify(record),
{"Content-Type": "application/json"},
null).done(function () {
console.log('Done disabling current default entry.');
});
}
const updateKeyQuery = '| inputlookup incident_intelligence_kvstore_lookup ' +
'| search _key=' + keyVal +
'| eval "Key"=_key ' +
'| eval "Realm" = realm ' +
'| eval "Org ID" = org_id | eval "Is Default"=is_default ' +
'| table "Realm", "Org ID", "Is Default", "Key"';
const search = service.oneshotSearch(
updateKeyQuery,
null,
function (err, results) {
if (err) {
console.err('Make default key, key to update search error - ', err);
}
if (results && results.rows && results.rows.length > 0) {
const realm = results.rows[0][0];
const orgId = results.rows[0][1];
const isDefault = results.rows[0][2];
const key = results.rows[0][3];
// Set the is_default flag on the new default record.
const record = {
"realm": realm,
"org_id": orgId,
"is_default": "true",
"_key": keyVal
};
console.log('Making entry default');
service.request(
"storage/collections/data/incident_intelligence_collection/" + encodeURIComponent(keyVal),
"POST",
null,
null,
JSON.stringify(record),
{"Content-Type": "application/json"},
null).done(function () {
console.log('Done enabling new default.');
search1.startSearch();
});
}
});
});
}
function deleteKey(keyVal) {
service.del("storage/passwords/" + encodeURIComponent(keyVal)).catch(function(err) {
console.log("delete from storage: statusCode="+err.status)
$('#configurationModal').css('z-index', '-9999');
$('#configurationModal').modal('hide');
if (err.status == 404) {
service.del("storage/collections/data/incident_intelligence_collection/" + encodeURIComponent(keyVal)).catch(function(err) {
console.log("Failure removing Org ID, Org Level id from collection.");
$('#configurationModal').css('z-index', '-9999');
$('#configurationModal').modal('hide');
$('#errorModalBody').html("Failure deleting Org ID, Org Level Access token.");
$('#errorModal').css('z-index', '9999');
$('#errorModal').modal('show');
})
.done(function(err) {
// Reload table, to remaining keys.
console.log('Successfully removed Org ID, Org Level id from collection.');
search1.startSearch();
$('#configurationModal').css('z-index', '-9999');
$('#configurationModal').modal('hide');
})
}
else if (err.status == 403) {
if (err.responseText) {
var error = JSON.parse(err.responseText);
if (error.messages && (error.messages.length > 0)) {
var msg = error.messages[0].type + ": " + error.messages[0].text;
console.log(msg);
$('#errorModalBody').html(msg);
}
}
}
else {
$('#errorModalBody').html("Failure deleting Org ID, Org Level Access token.");
}
$('#errorModal').css('z-index', '9999');
$('#errorModal').modal('show');
}).done(function(err) {
service.del("storage/collections/data/incident_intelligence_collection/" + encodeURIComponent(keyVal)).catch(function(err) {
console.log("delete from collection: statusCode="+err.status)
$('#configurationModal').css('z-index', '-9999');
$('#configurationModal').modal('hide');
$('#errorModalBody').html("Failure deleting Org ID, Org Level id token.");
$('#errorModal').css('z-index', '9999');
$('#errorModal').modal('show');
})
.done(function(err) {
console.log('Successfully removed collection Org ID, Org Level id entry.');
// If there are other keys, then make sure one of them is default
checkDefaultKey();
//search1.startSearch();
$('#configurationModal').css('z-index', '-9999');
$('#configurationModal').modal('hide');
})
});
}
function deleteIRServices(orgId) {
let query = '| inputlookup incident_intelligence_ir_services_lookup\n' +
'| where org_id!="' + encodeURIComponent(orgId) + '"\n' +
'| outputlookup incident_intelligence_ir_services_lookup'
// console.log('query: ' + query);
const search = service.oneshotSearch(
query,
null,
function(err, results) {
if (err) {
console.error('lookupKey error - ', err);
}
console.log('Successfully deleted the IR policies.');
});
}
function checkDefaultKey() {
// Check if there are keys and make sure one of them is a default key
if (keySearchManager == null) {
keySearchManager = new SearchManager({
"id": "keySearch",
"status_buckets": 300,
"search": '| inputlookup incident_intelligence_kvstore_lookup | table _key realm org_id is_default',
"sample_ratio": null,
"latest_time": "now",
"cancelOnUnload": true,
"earliest_time": "-24h@h",
"app": utils.getCurrentApp(),
"auto_cancel": 90,
"preview": true
});
var keyResults = keySearchManager.data("results", {count:0});
keyResults.on("data", function() {
console.log("Got search results.");
var d = keyResults.data();
if (d && d.rows) {
var hasDefault = false;
for (var i = 0; i < d.rows.length; i++) {
if (d.rows[i][7] == "true") {
hasDefault = true;
}
}
}
if (hasDefault == false) {
// No default keys, make the first one the default
const record = {
"realm": d.rows[0][1],
"org_id": d.rows[0][2],
"is_default": "true",
"_key": d.rows[0][0]
};
console.log('Making entry: ' + d.rows[0][2] + ' default');
service.request(
"storage/collections/data/incident_intelligence_collection/" + encodeURIComponent(d.rows[0][0]),
"POST",
null,
null,
JSON.stringify(record),
{"Content-Type": "application/json"},
null).done(function () {
console.log('Done enabling new default.');
});
}
});
keySearchManager.on("search:done", function(properties) {
search1.startSearch();
});
}
keySearchManager.startSearch();
}
function lookupKey(org_id, cb) {
console.log('Looking for KV Store record: ' + org_id);
const query = '| inputlookup incident_intelligence_kvstore_lookup | regex org_id =^' + encodeURIComponent(org_id) + '$ ' +
'| table realm, org_id, is_default, _key';
//console.log('query: ' + query);
const search = service.oneshotSearch(
query,
null,
function(err,results) {
if (err) {
console.error('lookupKey error - ', err);
}
if (!results || !results.rows || results.rows.length === 0) {
cb(undefined);
return;
}
// Add the new API to the kvstore
const realm = results.rows[0][0];
const org_id = results.rows[0][1];
const is_default = results.rows[0][2];
const _key = results.rows[0][3];
// Set the is_default flag on the new default record.
const record = { realm, org_id, is_default, _key };
console.log('Found KV Store record.');
cb(record);
});
}
function createKey(realm, orgId, sfxToken) {
let query = '| inputlookup incident_intelligence_kvstore_lookup';
let search = service.oneshotSearch( query, null, function(err,results) {
let isDefault = false; // The first key created should always be default.
if (err) {
console.error('Create key search error - ', err);
}
if (results && results.rows && results.rows.length === 0) {
isDefault = true;
}
console.log('Attempting to create new Org ID=' + orgId + ' , isDefault=' + isDefault);
// Search to see if the Org Id already exists
const existingKey = lookupKey(orgId, function cb(existingKey) {
if (existingKey) {
var msg = 'OrgID entry with a Org Level Access token already exists.';
$("#errorMessage").html(msg);
return;
}
console.log('Record NOT found, creating it in the KV store.');
// Add the new API to the kvstore
const record = {
"realm": realm,
"org_id": orgId,
"is_default": isDefault.toString(),
"_key": ""
};
service.request(
"storage/collections/data/incident_intelligence_collection/",
"POST",
null,
null,
JSON.stringify(record),
{"Content-Type": "application/json"},
null)
.done(function () {
console.log('Looking up record created to retrieve id.');
const existingKey = lookupKey(orgId, function cb(newRecord) {
if (newRecord) {
console.log('Found new record, creating storage entry.');
} else {
console.log('Failed to look up newly created record in KV store.');
alert('Unexpected - Failed to find record for Org ID: ' + orgId + ' in the KV store.');
return;
}
// Create storage/password entry with user set to the Record's KV Store _key and password
// as the unmasked Org Level Access Token.
let body = 'name='+ encodeURIComponent(newRecord._key )+ '&password='+ encodeURIComponent(sfxToken);
//console.log("body="+body)
service.request(
"/servicesNS/nobody/splunk_incident_intelligence_app/storage/passwords",
"POST",
null,
null,
body,
{"Content-Type": "application/x-www-form-urlencoded"},
null)
.catch(function (err) {
console.log("create storage: statusCode="+err.status)
$('#configurationModal').css('z-index', '-9999');
$('#configurationModal').modal('hide');
if (err.status == 403) {
if (err.responseText) {
var error = JSON.parse(err.responseText);
if (error.messages && (error.messages.length > 0)) {
var msg = error.messages[0].type + ": " + error.messages[0].text;
console.log(msg);
$('#errorModalBody').html(msg);
}
}
}
else {
$('#errorModalBody').html("Failure creating Org Level Access token entry in storage password.");
}
$('#errorModal').css('z-index', '9999');
$('#errorModal').modal('show');
// Remove the record from Mongo
service.del("storage/collections/data/incident_intelligence_collection/" + encodeURIComponent(newRecord._key)).catch(function(err) {
console.log("Failure removing record from the KV store.");
})
.done(function(err) {
console.log("Err");
})
})
.done(function () {
$("#realm1").val('');
$("#orgId1").val('');
$("#sfxToken1").val('');
search1.startSearch();
});
});
});
});
});
}
function testKey(keyVal, realm, orgId) {
const query = '| rest /servicesNS/admin/splunk_incident_intelligence_app/configs/conf-alert_actions/incident_intelligence'
const search = service.oneshotSearch(
query,
null,
function(err,results) {
var hostname = window.location.hostname;
if (results) {
var hostnameIndex = -1;
// Is there a field for hostname?
for (var i = 0; i < results.fields.length; i++) {
if (results.fields[i] == 'hostname') {
hostnameIndex = i;
break;
}
}
if (hostnameIndex != -1) {
if (results.rows[0][hostnameIndex] != "") {
hostname = results.rows[0][hostnameIndex];
}
}
}
sendAlert(keyVal, realm, orgId, hostname)
})
}
function sendAlert(keyVal, realm, orgId, hostname) {
// Use the sendalert command to generate a test alert. This will invoke incident_intelligence.py in the app'
// bin directory. The command will lookup the Org Id, Org Level Access Token to test from kvstore & storage password using the
// value passed the org_id parameter.
const query = '| sendalert incident_intelligence param.severity="" param.title="Test Alert" param.description="Test Alert from ' + hostname + '" param.service_id="Test Service" param.realm="' + encodeURIComponent(realm) + '" param.org_id="' + encodeURIComponent(orgId) + '"';
console.log('Sending test alert, search command');
const search = service.oneshotSearch(
query,
null,
function(err, results) {
console.log('sendalert result: ' + JSON.stringify(results) + ', err: ' + err);
let isSuccess = true;
if (results && results.messages) {
for (let i = 0; i < results.messages.length; i++) {
const obj = results.messages[i];
if (obj.type === 'FATAL' || obj.type === 'ERROR') {
isSuccess = false;
// NOTE: Errors should already be logged in the console.
}
}
const status = isSuccess ? "Connection successful." : "Connection refused.";
require(["bootstrap.modal"],function() {
$(".modal-body").html(status);
$("#cancelDialogButton").html("Dismiss");
$("#cancelDialogButton").show();
$("#confirmDialogButton").hide();
$('#configurationModal').css('z-index', '9999');
$('#configurationModal').modal('show');
});
setTestResult(orgId,isSuccess);
}
});
return false;
}
function setTestResult(orgId,isSuccess) {
var status = (isSuccess == true)?'SUCCESS':'FAIL';
const query = '| setTestResult org_id=' + orgId + ' test_result=' + status;
console.log("setTestResult query="+query)
const search = service.oneshotSearch(
query,
null,
function(err,results) {
// don't care
if (results && results.rows && results.rows.length > 0) {
if (results.rows[0] == "SUCCESS") {
console.log("Successfully updated test result.");
}
else {
console.log("Failure updating test result.");
}
}
});
}
function getIRServices(realm, orgId, sfxToken) {
const query = '| getirservices realm=' + realm + ' org_id=' + orgId + ' sfx_token=' + sfxToken;
//console.log("query=" + query)
const search = service.oneshotSearch(
query,
null,
function(err,results) {
// don't care
if (results && results.rows && results.rows.length > 0) {
if (results.rows[0] == "SUCCESS") {
console.log("Successfully got IR policies.");
}
else {
console.log("Failure to get IR policies.");
}
}
});
}
// Create key
$("#submit1").on("click", function (e) {
const realm = $('#realm1').val()
const orgId = $("#orgId1").val();
const sfxToken = $("#sfxToken1").val();
if ( (!realm || !realm.length) || (!orgId|| !orgId.length) || (!sfxToken|| !sfxToken.length)) {
var msg = 'Realm, Org ID, and Org Level Access Token are required fields.';
$("#errorMessage").html(msg);
return;
}
createKey(realm, orgId, sfxToken);
// get IR policies
getIRServices(realm, orgId, sfxToken)
});
});
});