SiD2
ServiceNow Employee
ServiceNow Employee

Hi Folks,

This blog is to identify and list Terminal Commands [Linux & WIn], WMI Queries, Regsitry Query, SNMP Query and finally cloud API's a particular pattern executes during discovery which gives you a good visibility per infrastructure that helps administrator teams to meet and fulfill necessary configuration/access related tasks.

Though this is available in SNOW docs, but is not very specific or in a granular level per pattern.

This would be another additional way to check quickly running a script on the instance and you can see what all different commands/queries that will be run in a particular pattern execution.

Target Audience
Anyone using Discovery product using Patterns on their SNOW instance.

Overview
This script covers the terminal commands that are part of standard "Parse Command Output" operation, WMI and Registry Queries, SNMP Queries for Network Devices and finally API Calls for Cloud Discovery. It doesn't have capability to fetch commands run from EVAL Scripts or any other code blocks.


You can get the above list of operations for one particular pattern by giving the pattern sys id in the variable "args" in below script. You can get the sys id of the pattern quickly by right clicking on the pattern record and click "Copy sys_id".

Script Output also prints the Scope of the respective pattern which tells you whether it is part of family release or Store Release.

If Scope is Global it is a family release and if it is "Discovery and Service Mapping Patterns" it is indeed the Patterns store app name. If you have patterns from other store apps respective name gets displayed.

To run this script in your instance open "System Definition->Scripts-Background" in filter navigator and copy this script and click Run script.

Note: If the main pattern sys id is provided, it fetches the shared libraries and extension sections that are part of the pattern and lists above items from all of them.


Ex: Below is the sample output for windows server pattern.

*** Script: *********************************************************************************************************
*** Script: -----------------------------------------------------------------------------------------------------
*** Script: Pattern: Windows OS - Servers   Scope: Global
*** Script: -----------------------------------------------------------------------------------------------------
*** Script: -----------------------------------------------------------------------------------------------------
*** Script: Pattern[Shared Library]: DNS   Scope: Global
*** Script: -----------------------------------------------------------------------------------------------------
*** Script: Step: Get DNS name - format 1
*** Script: Command: nslookup $computer_system.managementIP

*** Script: Step: Get DNS name - format 2
*** Script: Command: nslookup $computer_system.managementIP

*** Script: -----------------------------------------------------------------------------------------------------

*** Script: -----------------------------------------------------------------------------------------------------
*** Script: Pattern[Shared Library]: Windows - General Pattern Variables   Scope: Global
*** Script: -----------------------------------------------------------------------------------------------------
*** Script: Step: Get cluster info from MSCluster_Cluster
*** Script: WMI Query:
*** Script: Namespace: Root\\MSCluster
*** Script: Query: SELECT Name,Status,Description,Caption FROM MSCluster_Cluster

*** Script: Step: Get cluster resources info from MSCluster_Resource
*** Script: WMI Query:
*** Script: Namespace: root/MSCluster
*** Script: Query: SELECT Caption,Description,Name,State,Status,Type,PrivateProperties FROM MSCluster_Resource

*** Script: Step: Get cluster to resource mapping from MSCluster_ClusterToResource
*** Script: WMI Query:
*** Script: Namespace: Root\\MSCluster
*** Script: Query: SELECT GroupComponent,PartComponent FROM MSCluster_ClusterToResource

*** Script: Step: Get OS data from Win32_OperatingSystem
*** Script: WMI Query:
*** Script: Namespace: root\\CIMV2
*** Script: Query: SELECT Caption,Version,CSDVersion,Description FROM Win32_OperatingSystem

*** Script: Step: Get hostname and domain from registry
*** Script: Registry Query:
*** Script: Registry Path: HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters
*** Script: Keys: Hostname,Domain

 

Script

gs.log('*********************************************************************************************************');
var args = '';
PatternAnalyzer(args);
ParsePatternExtensions(args);
gs.log('*********************************************************************************************************');


function ParsePatternExtensions(parPattern) {
    var gPatternExtRec = new GlideRecord('sa_pattern_extension');
    gPatternExtRec.addQuery('pattern', parPattern);
    gPatternExtRec.query();

    var totalExts = gPatternExtRec.getRowCount();
    if (totalExts != 0) {
        gs.log('Available Pattern Extensions are ' + totalExts);
        while (gPatternExtRec.next()) {
            var extSysID = gPatternExtRec.getValue('extension');
            PatternAnalyzer(extSysID, true);
        }
    }
}


function PatternAnalyzer(patternSysId) {
    var gPatternRec = new GlideRecord('sa_pattern');
    gPatternRec.addQuery('sys_id', patternSysId);
    gPatternRec.addEncodedQuery('ndlLIKEruncmd_to_var^ORndlLIKErun_wmi_query_to_var^ORndlLIKEfind_registry_val_to_var^ORndlLIKErun_snmp_to_var^ORndlLIKEcustom_operation^ORndlLIKErefid');
    gPatternRec.query();

    if (gPatternRec.getRowCount() != 0) {
        if (gPatternRec.next()) {
            gs.log('-----------------------------------------------------------------------------------------------------');
            var pattern_name = gPatternRec.getValue('name');
            var pattern_text = gPatternRec.getValue('ndl');
            var pattern_type = gPatternRec.getValue('cpattern_type');
            var sysscope_Ref = gPatternRec.sys_scope.getRefRecord();
            var sys_scope = sysscope_Ref.getValue('name');

            if (pattern_type != '2')
                gs.log('Pattern: ' + pattern_name + '   Scope: ' + sys_scope);
            else
                gs.log('Pattern[Shared Library]: ' + pattern_name + '   Scope: ' + sys_scope);
            gs.log('-----------------------------------------------------------------------------------------------------');

            var pattern_steps = pattern_text.split('step'); // Fetches all steps of pattern
            for (var index in pattern_steps) {
                var command = '';
                var stepName = '';
                var namespace = '';
                var query = '';
                var regPath = '';
                var keys = '';
                var oid = '';
                var cols = '';
                if (pattern_steps[index].contains('runcmd_to_var')) { // Steps that run a command
                    var tmp = pattern_steps[index].match(/name = "(.*)"/);
                    if (tmp)
                        stepName = tmp[1];
                    var index1 = pattern_steps[index].indexOf('cmd = ') + 6;
                    if (pattern_steps[index].contains('execution_mode'))
                        var index2 = pattern_steps[index].lastIndexOf('execution_mode') - 1;
                    else if (pattern_steps[index].contains('credentials ='))
                        var index2 = pattern_steps[index].lastIndexOf('credentials =') - 1;
                    else
                        var index2 = pattern_steps[index].lastIndexOf('var_names') - 1;
                    command = pattern_steps[index].substring(index1, index2);

                    if (command.length > 0) {
                        var formattedCmd = FormatCommand(command); // Formats and gets the command
                        gs.log('Step: ' + stepName);
                        gs.log('Command: ' + formattedCmd + '\n');
                    }
                }
                if (pattern_steps[index].contains('run_wmi_query_to_var')) { // Steps that perform WMI Query
                    stepName = pattern_steps[index].match(/name = "(.*)"/)[1];
                    var tmpnamespace = pattern_steps[index].match(/namespace = "(.*)"/);
                    if (tmpnamespace)
                        namespace = tmpnamespace[1];
                    tmpnamespace = pattern_steps[index].match(/namespace = get_attr {"(.*)"}/);
                    if (tmpnamespace)
                        namespace = '$' + tmpnamespace[1];
                    var tmpquery = pattern_steps[index].match(/query = "(.*)"/);
                    if (tmpquery)
                        query = tmpquery[1];
                    else
                        query = FormatWMIQuery(pattern_steps[index]);
                    gs.log('Step: ' + stepName);
                    gs.log('WMI Query:');
                    gs.log('Namespace: ' + namespace);
                    gs.log('Query: ' + query + '\n');
                }
                if (pattern_steps[index].contains('find_registry_val_to_var')) { // Steps that perform Registry Query
                    stepName = pattern_steps[index].match(/name = "(.*)"/)[1];
                    var tmpregPath = pattern_steps[index].match(/key_base_dir = "(.*)"/);
                    if (tmpregPath)
                        regPath = tmpregPath[1];
                    tmpregPath = pattern_steps[index].match(/key_base_dir = get_attr {"(.*)"}/);
                    if (tmpregPath)
                        regPath = '$' + tmpregPath[1];
                    keys = pattern_steps[index].match(/keys = "(.*)"/)[1];
                    if (keys.contains(','))
                        keys = keys.replaceAll('"', '');
                    gs.log('Step: ' + stepName);
                    gs.log('Registry Query:');
                    gs.log('Registry Path: ' + regPath);
                    gs.log('Keys: ' + keys + '\n');
                }
                if (pattern_steps[index].contains('run_snmp_to_var')) { // Steps that perform SNMP Query
                    stepName = pattern_steps[index].match(/name = "(.*)"/)[1];
                    var tmpoid = pattern_steps[index].match(/snmp_object_ids = "(.*)"/);
                    if (tmpoid)
                        oid = tmpoid[1];
                    else {
                        var start = pattern_steps[index].indexOf('snmp_object_ids = ') + 18;
                        var end = pattern_steps[index].indexOf('var_names');
                        var tabsnmp = pattern_steps[index].substring(start, end);

                        oid = tabsnmp.match(/name = "(.*)"/)[1];
                        cols = tabsnmp.match(/col_names = "(.*)"/)[1];
                        cols = cols.replaceAll('"', '');
                    }
                    gs.log('Step: ' + stepName);
                    gs.log('SNMP Query:');
                    
                    if (cols.length > 0) {
                        gs.log('OID: ' + oid);
                        gs.log('Columns: ' + cols + '\n');
                    }
                    else
                    gs.log('OID: ' + oid + '\n');
                }
                if (pattern_steps[index].contains('custom_operation') && !pattern_steps[index].contains('source_column')) { // Steps that run custom operation but exclude Parse JSON Op
                    var tmp = pattern_steps[index].match(/name = "(.*)"/);
                    if (tmp)
                        stepName = tmp[1];
                    var attribs = pattern_steps[index].split('attribute');
                    var url = '';
                    var body = '';
                    for (var i in attribs) {
                        if (attribs[i].contains('url'))
                            url = attribs[i].split('value');

                        if (attribs[i].contains('body'))
                            body = attribs[i].split('value');

                        if (body) {
                            gs.log('Step: ' + stepName);
                            var uri = FormatCommand(url[1]);
                            gs.log('URL: ' + uri);
                            var frmtdBody = FormatCommand(body[1]);
                            gs.log('Body: ' + frmtdBody + '\n');
                            break;
                        }
                    }
                }
                if (pattern_steps[index].contains('refid = ')) { // Steps that refer a shared lib
                    var code_lines = pattern_steps[index].split('\n');
                    for (var idx in code_lines) { // Making a recursive call to parse the shared library that came across in sequence.
                        if (code_lines[idx].contains('refid')) {
                            var index1 = code_lines[idx].indexOf('"') + 1;
                            var index2 = code_lines[idx].lastIndexOf('"');
                            libSysID = code_lines[idx].substring(index1, index2);
                            PatternAnalyzer(libSysID);
                        }
                    }
                }
            }
            gs.log('-----------------------------------------------------------------------------------------------------\n');
        }
    }
}

function FormatCommand(command) {
    var frmtCmd = '';
    var tempVar = false;

    var cmdList = command.split('\n');
    for (var cmd in cmdList) {
        var temp = cmdList[cmd].trim();
        
        if (temp.contains('concat') || temp == '}')
            continue;
        else if (temp.contains('get_attr')) {
            temp = temp.match(/get_attr {"(.*)"}/);
            frmtCmd += '$' + temp[1];
            tempVar = true;
        }
        else {
            if (temp.contains('\\\\'))
                temp = temp.replaceAll('\\\\', '\\');

            if (temp.contains('\\"'))
                temp = temp.replaceAll('\\"', '"');
            
            temp = temp.substring(1, temp.length - 1);

            if (tempVar && temp.substr(0, 1).match(/[A-Za-z]/) != null)
                frmtCmd += ' ' + temp;
            else
                frmtCmd = frmtCmd + temp;
            
            tempVar = false;
        }
    }
    return frmtCmd;
}

function FormatWMIQuery(wmiquery) {
    var frmtQuery = '';

    var i = wmiquery.indexOf('query = ') + 8;
    var j = wmiquery.lastIndexOf('var_names');

    var subquery = wmiquery.substring(i, j);
    var list = subquery.split('\n');

    for (var line in list) {
        var str = list[line].trim();
        if (str.contains('concat') || str == '}')
            continue;
        else if (str.contains('get_attr')) {
            str = str.match(/get_attr {"(.*)"}/);
            frmtQuery += '$' + str[1];
        }
        else {
            str = str.substring(1, str.length - 1);
            frmtQuery += str;
        }
    }
    return frmtQuery;
}
1 Comment