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>: 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 += '
' + ' Set Default' + '
'; } // Add test links cellHtml += '
' + ' Test Conection' + '
'; cellHtml += '
' + ' Delete ' + '
'; $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 = '
' + ' Test' + '
'; $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) }); }); });