Splunk Enterprise

JS script loaded before searches in a dashboard?

Razziat
Explorer

Hello,
I am creating a dashboard in which I have a search that returns a multiple value field table.
I'm also using a JS script and a CSS script to make this table look better.
Each time I open/refresh the dashboard, I have the impression that the JS script loads before the searches finish loading. So I have to press the edit button to see the JS script applied to the table search.
Do you have a solution to fix this problem?

Thanks in advance !

Labels (2)
0 Karma

kamlesh_vaghela
SplunkTrust
SplunkTrust

@Razziat 

Can you please share your Sample Dashboard code? 

 

KV

Razziat
Explorer

The pretty_print.js and the pretty_colors.css are used for the research named "MITRE matrix".

<form script="pretty_print.js" stylesheet="pretty_colors.css" version="1.1">
  <label>Mitre Compliance</label>
  <search id="basesearch2">
    <query>
| inputlookup technique_mitre.csv
| lookup tactique_mitre.csv idTactique OUTPUT nomTactique idTactiqueMitre
| lookup security_mitre.csv idTechnique output item type
| lookup attack_group_mitre.csv idTechnique output nomGrpAtck
| fillnull value="toto" type nomGrpAtck
    </query>
    <earliest>-24h@h</earliest>
    <latest>now</latest>
    <sampleRatio>1</sampleRatio>
  </search>
  <fieldset submitButton="false" autoRun="false"></fieldset>
  <row>
    <panel>
      <title>Filtre la mitre matrix</title>
      <input type="radio" token="filter_outil_alerte" searchWhenChanged="true">
        <label>Filtre Outil/Alerte</label>
        <choice value="*">Tous</choice>
        <choice value="outil">Outil</choice>
        <choice value="alerte">Alerte</choice>
        <choice value="ngp et/ou edr">NGP et/ou EDR</choice>
        <default>*</default>
        <prefix>"</prefix>
        <suffix>"</suffix>
        <initialValue>*</initialValue>
      </input>
      <input type="multiselect" token="idGrpAtck">
        <label>Liste des schémas d'attaques</label>
        <choice value="*">All</choice>
        <default>*</default>
        <valuePrefix>"</valuePrefix>
        <valueSuffix>"</valueSuffix>
        <fieldForLabel>nomGrpAtck</fieldForLabel>
        <fieldForValue>nomGrpAtck</fieldForValue>
        <search>
          <query>| inputlookup attack_group_mitre.csv
| fields nomGrpAtck
| dedup nomGrpAtck</query>
          <earliest>-24h@h</earliest>
          <latest>now</latest>
        </search>
        <delimiter> </delimiter>
      </input>
    </panel>
  </row>
  <row>
    <panel>
      <title>MITRE matrix</title>
      <table id="mitrematrix">
        <search base="basesearch2">
          <query>| search type IN($filter_outil_alerte$)
| search nomGrpAtck IN($idGrpAtck$)
| stats values(item) as item dc(item) as dis_count values(nomTechnique) as nomTechnique by idTactique idTechnique
| eval item=mvjoin(item, "=")
| strcat idTechnique "|" nomTechnique "|" item "|" dis_count nomTechnique
| streamstats count by idTactique
| xyseries count idTactique nomTechnique
| sort count
| table reconnaissance, resource-development, initial-access, execution, persistence, privilege-escalation, defense-evasion, credential-access, discovery, lateral-movement, collection, command-and-control, exfiltration, impact
| rename reconnaissance as "Reconnaissance", resource-development as "Resource Development", initial-access as "Initial Access", execution as "Execution", persistence as "Persistence", privilege-escalation as "Privilege Escalation", defense-evasion as "Defense Evasion", credential-access as "Credential Access", discovery as "Discovery", lateral-movement as "Lateral Movement", collection as "Collection", command-and-control as "Command and Control", exfiltration as "Exfiltration", impact as "Impact"
| fillnull value="NULL|NULL|NULL"</query>
        </search>
        <option name="count">50</option>
        <option name="drilldown">cell</option>
        <option name="percentagesRow">true</option>
        <option name="refresh.display">progressbar</option>
        <option name="totalsRow">false</option>
      </table>
    </panel>
  </row>
</form>

 

0 Karma

kamlesh_vaghela
SplunkTrust
SplunkTrust

@Razziat 

JS will always load first. When the dashboard is getting loaded, Splunk JS Extension will be loaded just before the dashboard is ready for use.

Splunk JS Extension has 2 token models.

  • default token model  
  • submitted token model

https://dev.splunk.com/enterprise/docs/developapps/visualizedata/convertsimplexml/tokenmodels/

You need to write your javascript code according to the requirements and these two models.

Eg, if you are customizing the TableView then you should declare the customization code in JS, which execute before the dashboard gets finished to load. And the same declared code will be executed on the basis of the lifecycle of that component (in this example, TableView). TableView is dependent on the SearchManager.  When searching is done then TableView is getting populated and will be displayed, at this point, our defined Custom JS logic will be executed and will change the Table Row/Cell.

Your XML code looks good to me. 

If you want your JS to be executed after dashboard loading then use below JS code and put your code in the SECTION.

require([
    'splunkjs/mvc',
    'underscore',
    'splunkjs/mvc/simplexml/ready!'
], function(
    mvc,
    _
) {
    console.log("HIe");
    $(document).ready(function () {
        /*Add Your code here.*/
    });
    
});

 

For further help, you can share your sample JS here OR you can message it to me.

 

Thanks
KV
If any of my replies help you to solve the problem Or gain knowledge, an upvote would be appreciated.

Razziat
Explorer

The solution that you prposed didn't work for me.
Here is my JS script that I am using : (I post it here too for people who may have the same problem)

require.config({
    paths: {
      theme_utils: '../app/test-mitre/theme_utils',
      jquery_local: '../app/test-mitre/lib/js/jquery-3.6.0.min'
    }
  });
  
  require([
      'underscore',
      'jquery_local',
      'splunkjs/mvc',
      'splunkjs/mvc/tableview',
      'theme_utils',
      'splunkjs/mvc/simplexml/ready!'
  ], function(_, jquery, mvc, TableView, themeUtils) {
    
      jQuery.noConflict(); // remove jquery conflicts for splunk js sdk
      var $ = jQuery; // take dollar sign as a local variable
  
       // Row Coloring Example with custom, client-side range interpretation
  
      var isDarkTheme = themeUtils.getCurrentTheme && themeUtils.getCurrentTheme() === 'dark';
  
      var CustomRangeRenderer = TableView.BaseCellRenderer.extend({
          canRender: function(cell) {
          return _(["Reconnaissance", "Resource Development", "Initial Access", "Execution", "Persistence", "Privilege Escalation", "Defense Evasion", "Credential Access", "Discovery", "Lateral Movement", "Collection", "Command and Control", "Exfiltration", "Impact"]).contains(cell.field);
             },
          render: function($td, cell) {
              // Add a class to the cell based on the returned value
              var value_arr = cell.value.split("|");
              //var value_arr2 = cell.value.split("|");
              var technique_id = value_arr[0];
              var technique_name = value_arr[1];
              var alert_list = value_arr[2];
              var total_count = value_arr[3];
              var urgency_str = "None"

              var good_list = alert_list.replaceAll('=', '\n');
              var ttl = "Total: " + total_count + "\nAlert_list : " + good_list
                if(technique_id.includes('.')) {
                  $td.addClass('subtechnique');
              }
              else {
                if(technique_name=="NULL"){
                  $td.addClass('empty');
                  }
                else {
                  $td.addClass('technique');
                  }
              }
              $td.tooltip();
              $td.prop('title', ttl);
              if (total_count != "NULL") {
                  total =  parseFloat(total_count);
                  if(total >= 10){
                      $td.addClass('range-cell').addClass('range-compliance_high');
                  }
                    if(total >= 4){
                      $td.addClass('range-cell').addClass('range-compliance_mid');
                  }
                  if(total >= 1){
                      $td.addClass('range-cell').addClass('range-compliance_low');
                  }
                  if(total >= 0){
                      $td.addClass('range-cell').addClass('range-compliance_zero');
                  }
  
              }
              else if(total_count == "NULL"){
                  $td.addClass('range-cell').addClass('range-none');
              }
  
  
              if (isDarkTheme) {
                $td.addClass('dark');
              }
  
              // Update the cell content
             //$td.text(value.toFixed(2)).addClass('numeric');
  
              if (technique_name=="NULL"){
                  $td.text(" ");
              }
              else {
                  $td.text(technique_id + ": " + technique_name);
                  $td.addClass('add-border').addClass('text-align-center');
  
              }
          }
      });
  
      mvc.Components.get('mitrematrix').getVisualization(function(tableView) {
          // Add custom cell renderer, the table will re-render automatically.
          tableView.addCellRenderer(new CustomRangeRenderer());
      });
  
  });
Get Updates on the Splunk Community!

Extending Observability Content to Splunk Cloud

Watch Now!   In this Extending Observability Content to Splunk Cloud Tech Talk, you'll see how to leverage ...

More Control Over Your Monitoring Costs with Archived Metrics!

What if there was a way you could keep all the metrics data you need while saving on storage costs?This is now ...

New in Observability Cloud - Explicit Bucket Histograms

Splunk introduces native support for histograms as a metric data type within Observability Cloud with Explicit ...