• Products
  • Get started
  • Documentation
  • Resources

Jira Automation docs have moved

All content related to Jira Cloud Automation, previously under the Automate your Jira processes and workflows section, have moved to the new Cloud Automation docs.

Go to Cloud Automation documentation | Why did we do this?

Create a custom pattern

Create a custom pattern

For creating a custom pattern navigate to the Discovery/pattern folder. Here you can create a new file (UTF-8) with the ending .pat or you copy and modifying an existing pattern of the Pattern-Type you want. The best practice to develop and test a new pattern is to extract a separate Discover-Tool Instance and setting up a connection to the Host or Device that returning the result data you want to handle with.

Then remove all Pattern excluding a "main" HostInfo Pattern (Linux_Hostinfo_Hostname.pat, Windows_Hostinfo_Hostname_Model.pat, SNMP_Deviceinfo_Default.pat) it is mandatory to have a "main" HostInfo Object with the including Hostname. With this Setup it is possible to fast testing a new pattern without waiting of the response of all other Pattern.

Be sure that your new Pattern are containing all required XML-Nodes, the <Processing>-Node containing the C# class to process the result data from the command to a Discovery-Object. The functionality is that the Discovery-Tool reading the C# Source Code that is including the <Processing>-Node and invoking the PerformAction-Method of the PatternExec-Class.

The PerformAction Method is mandatory and the Discovery-Tool invoking it with an object array that are including the following 3 objects:

Parameter

Object Type

Description

parameters[0]

Command Result

Containing the result of the initial pattern command

parameters[1]

IProvider

Containing the executing Provider-Class that is connected to the discovering system.

This provider will be used in the pattern to execute other commands if required.

parameters[2]

object

Containing the HostInfo-/Device-Object that is initial created on the start of the scan.

1 2 3 4 5 public void PerformAction(object[] parameters) { HostInfo hostInfo = (HostInfo)parameters[2]; try {

Provider classes

For connecting to Host or Devices there are 4 Types of Providers used by the Discovery-Tool, the following described Providers handling the connection and execution of commands to collecting data.

Inside of a Pattern you have the availability to use the actual connected Provider to execute additional commands if more informations from the System are needed.

SSH-Provider

The SSH-Provider-Class is connected to a Linux System and can be used insight of a Pattern:

1 2 3 4 5 6 7 8 using Insight.Discovery.ProviderClasses; // Include the ProviderClasses Namespace at the Head of the PatternCode using Insight.Discovery.InfoClasses; // Include the InfoClasses Namespace at the Head of the PatternCode // Casting the connected Provider out of the parameters from the PerformAction-Method SSHProvider ssh = (SSHProvider)parameters[1]; // using the SSH-Provider to execute a command and receiving the result. var result = (SSHExecuteResult)ssh.ExecuteCommand("hostname"); // returning the hostname of a Linux System

For example a cast SSHProvider is used in the "Linux_Hostinfo_Hostname.pat" Pattern.

WMI-Provider

The WMI-Provider-Class is connected to a Windows System and can be used insight of a Pattern:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 using Insight.Discovery.ProviderClasses; // Include the ProviderClasses Namespace at the Head of the PatternCode using Insight.Discovery.InfoClasses; // Include the InfoClasses Namespace at the Head of the PatternCode // Casting the connected Provider out of the parameters from the PerformAction-Method WMIProvider wmiProvider = (WMIProvider)parameters[1]; // using the WMI-Provider to read a Registry Value. var result = (WMIRegValueResult)wmiProvider.GetRegistryValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\<Key>", "DisplayName"); // using the WMI-Provider to get a List of all Registry-Sub-Keys. var result = (WMIRegValueListResult)wmiProvider.GetSubKeysFromRegistry("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"); //using the WMI-Provider to execute a WMI query receiving the result. var result = (WMIQueryResult)wmiProvider.ExecuteWMIQuery("netstat -an"); //using the WMI-Provider to execute a command and receiving the result. var result = (WMIExecuteResult)wmiProvider.ExecuteWMICommand("netstat -an");

SNMP-Provider

The SNMP-Provider-Class is connected to a SNMP Device and can be used insight of a Pattern:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 using Insight.Discovery.ProviderClasses; // Include the ProviderClasses Namespace at the Head of the PatternCode using Insight.Discovery.InfoClasses; // Include the InfoClasses Namespace at the Head of the PatternCode // Casting the connected Provider out of the parameters from the PerformAction-Method SNMPProvider snmp = (SNMPProvider)parameters[1]; // using the SNMP-Provider to execute a SNMPGet command and receiving the results var result = (SNMPExecuteResult)snmp.ExecuteCommand("1.3.6.1.2.1.1.6.0", ScanProcessType.SNMP_GET, true); // using the SNMP-Provider to execute a SNMPWalk command and receiving the results var result = (SNMPExecuteResult)snmp.ExecuteCommand("1.3.6.1.2.1.2.2.1.2", ScanProcessType.SNMP_WALK, true); // using the SNMP-Provider to execute a SNMPWalk command with contextName and receiving the results var result = (SNMPExecuteResult)snmp.ExecuteCommand("1.3.6.1.2.1.2.2.1.2", ScanProcessType.SNMP_WALK, "myContext",true);

VIM-Provider

The SNMP-Provider-Class is connected to a VMWare ESXi System and can be used insight of a Pattern:

1 2 3 4 5 6 7 8 using Insight.Discovery.ProviderClasses; // Include the ProviderClasses Namespace at the Head of the PatternCode using Insight.Discovery.InfoClasses; // Include the InfoClasses Namespace at the Head of the PatternCode // Casting the connected Provider out of the parameters from the PerformAction-Method VIMProvider snmp = (SNMPProvider)parameters[1]; // using the VIM-Provider to execute a command and receiving the results var result = (VIMCommandResult)snmp.ExecuteCommand("HostSystem");

Additional functions

Some additional functions are also available:

ImportService

If you want to set a Date Attribute for a Discovery-Object like the InstallDate for an Application it must be in a specific Format ("MM/dd/yyyy"). You can use the delivered ImportService.ImportDate Method that will do the transformation for you:

1 2 3 4 5 6 7 using Insight.Discovery.Tools; // Include the Discovery Tools Namespace at the Head of the PatternCode    // using the ImportDate Method to transform the Date string of a result Object discoveryObject.InstallDate = ImportService.Instance.ImportDate("resultDateString");    // The following input formats will be transformed: // "MM/dd/yy", "M/dd/yy", "MM/dd/yyyy", "M/dd/yyyy", "MM/dd/yy", "M/d/yy", "MM/d/yyyy", "M/d/yyyy", "yyyyMMdd", "yyMMdd", "dd.MM.yy", "dd.MM.yyyy", "MMM-dd-yy", "MMM-dd-yyyy", "yyyy-MM-dd"

LogService

If you want to write entries into the Discovery log file, you can use the delivered LogService Class.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 using Insight.Discovery.Tools; // Include the Discovery Tools Namespace at the Head of the PatternCode    // creating a "normal" log entry LogService.Instance.LogNormal("My normal log entry");    // creating a "debug" log entry with additional Exception object try {     LogService.Instance.LogDebug("a debug log entry");     // Code that could raise an exception } catch (Exception ex) {     LogService.Instance.LogError("Log of an exception", ex); }

Custom pattern examples

Here are some example of custom patterns that you could create to return unique information using Insight Discovery:

Example: SNMP Extended Values

It is possible to extend the Information of a SNMP Device. You must know which OID-Number returning the Value that should be discovered. In the processing script the return value of the OID will be mapped to a ExtendedInformation.

The following example is sending 3 OID's to discover different RAM Information.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 <?xml version="1.0" encoding="utf-8"?> <ScanPattern xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Version>3.0.1</Version> <PatternID>RIADA-Cust-SNMP-1</PatternID> <OrderNr>0</OrderNr> <ProcessType>SNMP_GET</ProcessType> <PatternType>SNMPExtendedValues</PatternType> <Command>     <![CDATA[     1.3.6.1.4.1.2021.4.5.0;1.3.6.1.4.1.2021.4.6.0;1.3.6.1.4.1.2021.4.11.0     ]]> </Command> <Processing>     <![CDATA[     using System;     using System.Collections.Generic;     using Insight.Discovery.InfoClasses.CommandResult.ResultTypes;     using Insight.Discovery.Tools;     using Insight.Discovery.InfoClasses;     using Insight.Discovery.InfoClasses.CommandResult;           namespace Insight.Discovery {       public class PatternExec {         public void PerformAction(object[] parameters)         {             DeviceInfo deviceInfo = (DeviceInfo)parameters[2];                           if (deviceInfo.ExtendedInformations.IsNullOrEmpty())                     deviceInfo.ExtendedInformations = new List<ExtendedInformation>();               try             {                 var commandResult = (SNMPExecuteResult)parameters[0];                 commandResult.LogResult();                   foreach (KeyValuePair<string, object> item in commandResult)                 {                     switch (item.Key)                     {                         case "1.3.6.1.4.1.2021.4.5.0": // OID to get available RAM                             if (item.Value != null)                             {                                 try                                 {                                     long t = 0;                                     long.TryParse(item.Value.ToString().Replace("\n", "").Trim(), out t);                                       if (t > 0)                                     {                                         deviceInfo.ExtendedInformations.Add(new ExtendedInformation() { Name = "RAM Total", Value = (t / 1024).ToString() });                                     }                                 }                                 catch                                 {                                     //                                 }                             }                               break;                         case "1.3.6.1.4.1.2021.4.6.0": // OID to get used RAM                             if (item.Value != null)                             {                                 try                                 {                                     long t = 0;                                     long.TryParse(item.Value.ToString().Replace("\n", "").Trim(), out t);                                       if (t > 0)                                     {                                         deviceInfo.ExtendedInformations.Add(new ExtendedInformation()                                         { Name = "RAM Used", Value = (t / 1024).ToString() });                                     }                                 }                                 catch                                 {                                     //                                 }                             }                             break;                         case "1.3.6.1.4.1.2021.4.11.0": // OID to get free RAM                             if (item.Value != null)                             {                                 try                                 {                                     long t = 0;                                     long.TryParse(item.Value.ToString().Replace("\n", "").Trim(), out t);                                       if (t > 0)                                     {                                         deviceInfo.ExtendedInformations.Add(new ExtendedInformation() { Name = "RAM Free", Value = (t / 1024).ToString() });                                     }                                 }                                 catch                                 {                                     //                                 }                             }                             break;                     }                 }             }             catch (Exception ex)             { LogService.Instance.LogDebug("Error getting Extended SNMP RAM Information.", ex); }         }           }     }      ]]>   </Processing> </ScanPattern>

 

Example: Application Product Key

It is possible to add a discovered Licence-Information to an Application. For example if you know that a Licence File exists you can add a Pattern that read this file.

In the following example the pattern is reading a file "lic" that contains the Licence-Key for the Linux-Application "apt".

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 <?xml version="1.0" encoding="utf-8"?> <!-- © Mindville --> <ScanPattern xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Version>1.0.1</Version> <PatternID>Mindville-Cust-Linux-AppPK-1</PatternID> <OrderNr>0</OrderNr> <ProcessType>SSHExecute</ProcessType> <PatternType>ApplicationProductKey</PatternType> <ApplicationName>apt</ApplicationName> <Command>     <![CDATA[     cat /etc/apt/lic     ]]> </Command> <Processing>     <![CDATA[     using System;     using Insight.Discovery.InfoClasses;     using Insight.Discovery.Tools;     using Insight.Discovery.InfoClasses.CommandResult.ResultTypes;     using System.Collections.Generic;           namespace Insight.Discovery {       public class PatternExec {                  public void PerformAction(object[] parameters)         {             HostInfo hostInfo = (HostInfo) parameters[2];               try             {                 SSHExecuteResult sshExecuteResult = (SSHExecuteResult)parameters[0];                 sshExecuteResult.LogResult();                   string input = sshExecuteResult;                   if (input != string.Empty)                 {                     if(hostInfo.OS.License == null)hostInfo.OS.License = new LicenseInfo();                       hostInfo.OS.License.LicenseKey = input.Trim();                 }             }             catch (Exception ex)             { LogService.Instance.LogDebug("Error getting apt product key Information", ex); }                       }       }     }     ]]>   </Processing> </ScanPattern>

Example: Application Extended Information

It is possible to extend the Information of any object type. In the following example, we extend the host info with some additional information:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 <?xml version="1.0" encoding="utf-8"?> <ScanPattern xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Version>1.0.1</Version> <PatternID>Mindville-Cust-Linux-OpenPorts-1</PatternID> <OrderNr>700</OrderNr> <ProcessType>SSHExecute</ProcessType> <PatternType>Host</PatternType> <Command>     <![CDATA[     netstat -an     ]]> </Command> <Processing>     <![CDATA[     using System;     using System.Collections.Generic;     using Insight.Discovery.Tools;     using Insight.Discovery.InfoClasses;     using Insight.Discovery.InfoClasses.CommandResult.ResultTypes;     using Insight.Discovery.Tools.Networking;           namespace Insight.Discovery {       public class PatternExec {         public void PerformAction(object[] parameters)         {             HostInfo hostInfo = (HostInfo)parameters[2];             try             {                 SSHExecuteResult sshExecuteResult = (SSHExecuteResult)parameters[0];                 sshExecuteResult.LogResult();                   string input = sshExecuteResult;                   if (input != string.Empty)                 {                     if (hostInfo != null)                     {                         string[] lines = input.Split('\n');                         ExtendedInformation tcpPortInfo = new ExtendedInformation() { Name = "TCP Ports", Value = string.Empty };                         ExtendedInformation udpPortInfo = new ExtendedInformation() { Name = "UDP Ports", Value = string.Empty };                           for (int i = 0; i < lines.Length; i++)                         {                             if (!string.IsNullOrEmpty(lines[i]) && lines[i].Contains(":")                                 && (lines[i].ToLower().StartsWith("tcp") || lines[i].ToLower().StartsWith("udp")))                             {                                 string[] parts = lines[i].TrimReduce().Split(' ');                                   try                                 {                                     for (int x = 0; x < parts.Length; x++)                                     {                                         if (parts[x].Contains("]"))                                         {                                             parts[x] = parts[1].Substring(parts[x].IndexOf("]"));                                         }                                           if (parts[0].ToLower().StartsWith("tcp") && !string.IsNullOrEmpty(parts[x]) &&                                             parts[x].Contains(":"))                                         {                                             if (!tcpPortInfo.Value.Contains(parts[x].Split(':')[1]))                                             {                                                 tcpPortInfo.Value += parts[x].Split(':')[1] + ",";                                                 break;                                             }                                         }                                           if (parts[0].ToLower().StartsWith("udp") && !string.IsNullOrEmpty(parts[x]) &&                                             parts[x].Contains(":"))                                         {                                             if (!udpPortInfo.Value.Contains(parts[x].Split(':')[1]))                                             {                                                 udpPortInfo.Value += parts[x].Split(':')[1] + ",";                                                 break;                                             }                                         }                                     }                                 }                                 catch                                 {                                     //                                 }                             }                         }                           if (hostInfo.ExtendedInformations.IsNullOrEmpty())                             hostInfo.ExtendedInformations = new List<ExtendedInformation>();                           if (!string.IsNullOrEmpty(tcpPortInfo.Value) && tcpPortInfo.Value.EndsWith(","))                         {                             tcpPortInfo.Value = tcpPortInfo.Value.Substring(0, tcpPortInfo.Value.Length - 1);                             hostInfo.ExtendedInformations.Add(tcpPortInfo);                         }                         if (!string.IsNullOrEmpty(udpPortInfo.Value) && udpPortInfo.Value.EndsWith(","))                         {                             udpPortInfo.Value = udpPortInfo.Value.Substring(0, udpPortInfo.Value.Length - 1);                             hostInfo.ExtendedInformations.Add(udpPortInfo);                         }                     }                 }             }             catch (Exception ex)             { LogService.Instance.LogDebug("Error getting ReferencedHosts Information", ex); }             }         }     }     ]]>   </Processing> </ScanPattern>

Modifying patterns

It is possible but not recommend to modify the delivered Patterns.

If there are any missing Information the best practice is to add a new pattern, the missing Information will be merged to the Discovery-Object. If you are modified a delivered Pattern, you should save that Pattern external to pretend the lose of your change by updating the Discovery-Tool.

When you updating the Discovery-Tool with the updater, the updater will ask you before overwriting the modified Pattern.

 

Removing patterns

  • You can disable a pattern file in general by navigating to the Pattern Tab and unchecking the unwanted pattern.

  • You can disable a pattern file for a specific scan range by navigating to the Scan Setting and select the pattern files that you don't want to use.

 

Additional Help