SolarWinds

The SolarWinds integration interacts with the SWIS API to allow you to fetch alerts and events. It also provides commands to retrieve lists of alerts and events.

Network Security · SolarWinds

Details

IDSolarWinds
ProviderSolarWinds Corporation
CategoryNetwork Security
From Version5.5.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

The SolarWinds integration interacts with the SWIS API to allow users to fetch alerts and events. It also provides commands to retrieve lists of alerts and events.
This integration was integrated and tested with version 3.0.0 of SolarWinds Information Service (SWIS API).

SolarWinds Help

The SolarWinds integration requires installation of SolarWinds Orion Platform which consolidates the full suite of monitoring capabilities into one platform. The following products used in this integration are managed under Orion

  • Network Performance Manager
  • Netflow Traffic Analyzer
  • Network Configuration Manager
  • IP Address Manager
  • Log Analyzer
  • Server and Application Monitor

How to install SolarWinds Orion Platform

Follow this link to view a comprehensive guide on how to install Orion and the managed products.

Configure SolarWinds in Cortex

Parameter Description Required
Name or IP address of the Orion server Name or IP address of the Orion server you want to connect to. Do not specify the port number. Examples: myorigin.mydomain.local, 12.153.24.2 True
Port Port number with which to connect to the Orion server. Default is 17774. False
Username of the account Admin can create users such as guests from the Orion platform and provide access permission according to need. True
Password   True
Type of incident to be fetched Note: “Type of incident to be fetched” and “Incident type” should be the same to fetch similar types of incidents. False
Maximum number of incidents per fetch The maximum limit is 1000. False
First fetch time interval Date or relative timestamp to start fetching incidents from. For Alert, incidents will be fetched based on triggered date. For Event, the incidents will be fetched based on event time. (Formats accepted: 2 minutes, 2 hours, 2 days, 2 weeks, 2 months, 2 years, yyyy-mm-dd, yyyy-mm-ddTHH:MM:SSZ, etc.). False
Severity levels Fetch list of alerts as per the severity level. If not specified, it fetches all the incidents.
Note: Severity level is only available for alerts.
False
Object Types Filter alerts based on the type of property to monitor. If not specified, it will fetch all types of alerts. To list additional object types, use the query ‘SELECT DISTINCT ObjectType FROM Orion.AlertConfigurations’ in the swis-query command. False
Event Types Filter events based on the type. If not specified, it will fetch all types of events. To list additional event types, use the query ‘SELECT Name FROM Orion.EventTypes’ in the swis-query command. False
Use system proxy settings   False
Trust any certificate (not secure)   False
Incident type   False
Fetch incidents   False

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

swis-event-list


Retrieves a list of events on the filter values provided in the command arguments.

Base Command

swis-event-list

Input

Argument Name Description Required
acknowledged Whether to retrieve events that are acknowledged. If true, then retrieves all acknowledged events.
Possible values: true and false.
Optional
event_id A comma-separated ist of event IDs.
Note: event_id supports integer values (int64).
Optional
event_type A comma-separated list of event types. For example: Warning, Informational, Node Up, etc. Optional
node To retrieve events of specific nodes. Optional
sort_key Key by which the response will be sorted.
For example: EventID, EventTime, Message, TimeStamp, EventTypeName, Node, etc. Default is EventID.
Optional
sort_order Order by which the response will be sorted. Possible values: ascending and descending. Default is ascending. Optional
page The page number from which retrieve events. By default, the per-page limit is 50 events. You can change this value in the limit argument. Default is 0. Optional
limit The maximum number of records to be retrieved.
Note: The maximum value supported by the limit is maxValue int32. Default is 50.
Optional

Context Output

Path Type Description
SolarWinds.Event.EventID Number Event ID of the triggered event.
SolarWinds.Event.EventTime Date Timestamp at which the event is triggered.
SolarWinds.Event.NetworkNode Number Network node ID of a triggered event.
SolarWinds.Event.Node String Network node of a triggered event.
SolarWinds.Event.NetObjectID Number NetObject ID of a triggered event.
SolarWinds.Event.NetObjectValue String NetObject value of a triggered event.
SolarWinds.Event.EngineID Number Engine ID of a triggered event.
SolarWinds.Event.EventType Number Type of a triggered event.
SolarWinds.Event.EventTypeName String Name of the type of a triggered event.
SolarWinds.Event.Message String Message of a triggered event.
SolarWinds.Event.Acknowledged Boolean Whether the event is acknowledged.
SolarWinds.Event.NetObjectType String NetObject type of a triggered event.
SolarWinds.Event.Timestamp String Last modified time of an event. It is a counter that SQL server automatically increments when the event is updated.
SolarWinds.Event.DisplayName String Display name of an event.
SolarWinds.Event.Description String Description of an event.
SolarWinds.Event.InstanceType String Instance type of an event.
SolarWinds.Event.Uri String URI of a triggered event.
SolarWinds.Event.InstanceSiteID Number ID of an instance site of which event is triggered.

Command Example

!swis-event-list sort_key="EventID" sort_order="Ascending" page="1" limit="2"

Context Example

{
    "SolarWinds": {
        "Event": [
            {
                "Acknowledged": false,
                "EngineID": 1,
                "EventID": 3,
                "EventTime": "2021-03-31T12:02:05.6830000",
                "EventType": 315,
                "EventTypeName": "Notification Reset",
                "InstanceSiteId": 0,
                "InstanceType": "Orion.Events",
                "Message": "Resetting unknown traffic notification events.",
                "NetObjectID": 0,
                "NetObjectType": "N",
                "NetworkNode": 1,
                "Node": "WIN-MV956AU5BSN",
                "TimeStamp": [
                    "0",
                    "0",
                    "0",
                    "0",
                    "0",
                    "0",
                    "7",
                    "211"
                ],
                "Uri": "swis://WIN-MV956AU5BSN./Orion/Orion.Events/EventID=3"
            },
            {
                "Acknowledged": false,
                "EngineID": 1,
                "EventID": 4,
                "EventTime": "2021-03-31T12:02:08.5570000",
                "EventType": 300,
                "EventTypeName": "The NetFlow Receiver Service Started",
                "InstanceSiteId": 0,
                "InstanceType": "Orion.Events",
                "Message": "The NetFlow Receiver Service [WIN-MV956AU5BSN] started - listening on port(s) [2055]",
                "NetObjectID": 0,
                "NetObjectType": "N",
                "NetworkNode": 1,
                "Node": "WIN-MV956AU5BSN",
                "TimeStamp": [
                    "0",
                    "0",
                    "0",
                    "0",
                    "0",
                    "0",
                    "7",
                    "212"
                ],
                "Uri": "swis://WIN-MV956AU5BSN./Orion/Orion.Events/EventID=4"
            }
        ]
    }
}

Human Readable Output

Events

ID Message Type Node Acknowledged Triggered At
3 Resetting unknown traffic notification events. Notification Reset WIN-MV956AU5BSN false 31/03/2021 12:02 PM
4 The NetFlow Receiver Service [WIN-MV956AU5BSN] started - listening on port(s) [2055] The NetFlow Receiver Service Started WIN-MV956AU5BSN false 31/03/2021 12:02 PM

swis-alert-list


Retrieves a list of alerts based on the filter values provided in the command arguments.

Base Command

swis-alert-list

Input

Argument Name Description Required
alert_id A comma-separated list of alert IDs.
Note: alert_id supports integer values (int64).
Optional
type A comma-separated list of the type of property to monitor. For example: Node, IPAM.IPRequests, Orion.DiscoveryLogs, APM: Component, IPAM Networks, Orion.NodesForecastCapacity, APM: Application, Orion.VolumesForecastCapacity, Orion.NodesForecastCapacity, etc. Optional
severity A comma-separated list of severity levels.
Possible values: Information, Warning, Critical, Serious, and Notice.
Optional
sort_key Key by which the response will be sorted.
For example: AlertID, AlertActiveID, AlertObjectID, TriggeredDateTime, TriggeredMessage, AcknowledgedDateTime, EngineID, Name, ObjectType, etc. Default is AlertActiveID.
Optional
sort_order Order by which the response will be sorted. Possible values: ascending and descending. Default is ascending. Optional
page The page number from which to retrieve alerts. By default, the per-page limit is 50 alerts. You can change change this value in the limit argument. Default is 0. Optional
limit The number of records to be retrieved.
Note: The maximum value supported by the limit is maxValue int32. Default is 50.
Optional

Context Output

Path Type Description
SolarWinds.Alert.AlertActiveID Number Active ID of the triggered alert.
SolarWinds.Alert.AlertObjectID Number Object ID of the triggered alert.
SolarWinds.Alert.Acknowledged Boolean Whether the alert is acknowledged.
SolarWinds.Alert.AcknowledgedBy String Name of the person who acknowledged the alert.
SolarWinds.Alert.AcknowledgedDateTime Date Timestamp when the alert was acknowledged.
SolarWinds.Alert.AcknowledgedNote String Acknowledge note of the alert.
SolarWinds.Alert.TriggeredDateTime Date Timestamp when the alert was triggered.
SolarWinds.Alert.TriggeredMessage String Message of the triggered alert.
SolarWinds.Alert.NumberOfNotes Number Number of notes of the alert.
SolarWinds.Alert.LastExecutedEscalationLevel Number Last executed escalation level for the alert.
SolarWinds.Alert.DisplayName String Display name of the alert.
SolarWinds.Alert.AlertDescription String Description of the alert.
SolarWinds.Alert.InstanceType String Type of instance of the alert.
SolarWinds.Alert.Uri String URI of the alert.
SolarWinds.Alert.InstanceSiteId Number Site ID of the instance.
SolarWinds.Alert.AlertID Number ID of the alert.
SolarWinds.Alert.EntityUri String URI for the object that triggered the alert.
SolarWinds.Alert.EntityType String Type of the object that triggered the alert.
SolarWinds.Alert.EntityCaption String The display name for the triggering object.
SolarWinds.Alert.EntityDetailsUrl String Relative URL for the details view for the triggering object.
SolarWinds.Alert.EntityNetObjectId String NetObject ID of the entity.
SolarWinds.Alert.RelatedNodeUri String URI of the related node
SolarWinds.Alert.RelatedNodeId Number ID of the related node.
SolarWinds.Alert.RelatedNodeDetailsUrl String URL which contains node details.
SolarWinds.Alert.RelatedNodeCaption String Caption of the related node.
SolarWinds.Alert.RealEntityUri String URI of the real entity.
SolarWinds.Alert.RealEntityType String Type of the real entity.
SolarWinds.Alert.TriggeredCount Number Number of times the alert was triggered.
SolarWinds.Alert.LastTriggeredDateTime Date Timestamp when the alert was last triggered.
SolarWinds.Alert.Context String Context of the alert.
SolarWinds.Alert.AlertNote String Note of the alert.
SolarWinds.Alert.AlertMessage String Message of the alert.
SolarWinds.Alert.AlertRefID String Unique identifier of the alert.
SolarWinds.Alert.Name String Name of the alert.
SolarWinds.Alert.ConfigurationDescription String Configuration description of the alert.
SolarWinds.Alert.ObjectType String Object type of the alert.
SolarWinds.Alert.Enabled Boolean Whether the alert is enabled.
SolarWinds.Alert.Frequency Number Frequency of the alert.
SolarWinds.Alert.Trigger String Condition due to which the alert was triggered.
SolarWinds.Alert.Reset String Reset condition for the alert. When the condition is met, the alert is removed from active alerts.
SolarWinds.Alert.Severity Number Severity of the alert.
SolarWinds.Alert.NotifyEnabled Boolean Whether it is notified enabled.
SolarWinds.Alert.NotificationSettings String Settings of the notifications for the alerts.
SolarWinds.Alert.LastEdit Date Timestamp when the alert was last edited.
SolarWinds.Alert.CreatedBy String Name of the person who created the alert.
SolarWinds.Alert.Category String Category of the alert.
SolarWinds.Alert.Canned Boolean Whether the alert is canned.
SolarWinds.Alert.ResponsibleTeam String Team that is responsible for the alert.

Command Example

!swis-alert-list sort_key="AlertActiveID" sort_order="ascending" page="1" limit="2"

Context Example

{
    "SolarWinds": {
        "Alert": [
            {
                "AlertActiveID": 4,
                "AlertID": 91,
                "AlertMessage": "${N=SwisEntity;M=FirstName} ${N=SwisEntity;M=LastName} has requested ${N=SwisEntity;M=RequestAddressCount} IP address(es) at ${N=SwisEntity;M=RequestDate}\n      Contact details: ${N=SwisEntity;M=Phone}, ${N=SwisEntity;M=Email}\n      Comments: ${N=SwisEntity;M=Comment}",
                "AlertObjectID": 3,
                "AlertRefID": "227c01da-1e64-44f2-807b-e6c7d2898ae5",
                "Canned": true,
                "ConfigurationDescription": "This alert writes to the event log when Request IP Address is created.",
                "Context": "null",
                "Enabled": true,
                "EntityCaption": "IP Request (test test)",
                "EntityNetObjectId": "IPAMIPREQ:2",
                "EntityType": "IPAM.IPRequests",
                "EntityUri": "swis://WIN-MV956AU5BSN./Orion/IPAM.IPRequests/IPRequestId=2",
                "Frequency": 60,
                "InstanceSiteId": 0,
                "InstanceType": "Orion.AlertActive",
                "LastEdit": "2021-03-31T12:03:59.7466667Z",
                "LastTriggeredDateTime": "2021-04-06T12:53:07.9200000Z",
                "Name": "IP Address Request",
                "NotifyEnabled": true,
                "ObjectType": "IPAM.IPRequests",
                "RealEntityType": "IPAM.IPRequests",
                "RealEntityUri": "swis://WIN-MV956AU5BSN./Orion/IPAM.IPRequests/IPRequestId=2",
                "Reset": "<ArrayOfAlertConditionShelve xmlns=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><AlertConditionShelve><AndThenTimeInterval i:nil=\"true\"/><ChainType>ResetCustom</ChainType><ConditionTypeID>Core.Dynamic</ConditionTypeID><Configuration>&lt;AlertConditionDynamic xmlns=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Alerting.Plugins.Conditions.Dynamic\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"&gt;&lt;ExprTree xmlns:a=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\"&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Field&lt;/a:NodeType&gt;&lt;a:Value&gt;IPAM.IPRequests|State&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Constant&lt;/a:NodeType&gt;&lt;a:Value&gt;3&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Operator&lt;/a:NodeType&gt;&lt;a:Value&gt;=&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Operator&lt;/a:NodeType&gt;&lt;a:Value&gt;AND&lt;/a:Value&gt;&lt;/ExprTree&gt;&lt;Scope i:nil=\"true\" xmlns:a=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\"/&gt;&lt;TimeWindow i:nil=\"true\"/&gt;&lt;/AlertConditionDynamic&gt;</Configuration><ConjunctionOperator>None</ConjunctionOperator><IsInvertedMinCountThreshold>false</IsInvertedMinCountThreshold><NetObjectsMinCountThreshold i:nil=\"true\"/><ObjectType>IPAM IP Requests</ObjectType><SustainTime i:nil=\"true\"/></AlertConditionShelve></ArrayOfAlertConditionShelve>",
                "Severity": 2,
                "Trigger": "<ArrayOfAlertConditionShelve xmlns=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><AlertConditionShelve><AndThenTimeInterval i:nil=\"true\"/><ChainType>Trigger</ChainType><ConditionTypeID>Core.Dynamic</ConditionTypeID><Configuration>&lt;AlertConditionDynamic xmlns=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Alerting.Plugins.Conditions.Dynamic\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"&gt;&lt;ExprTree xmlns:a=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\"&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Field&lt;/a:NodeType&gt;&lt;a:Value&gt;IPAM.IPRequests|State&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Constant&lt;/a:NodeType&gt;&lt;a:Value&gt;2&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Operator&lt;/a:NodeType&gt;&lt;a:Value&gt;=&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Operator&lt;/a:NodeType&gt;&lt;a:Value&gt;AND&lt;/a:Value&gt;&lt;/ExprTree&gt;&lt;Scope i:nil=\"true\" xmlns:a=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\"/&gt;&lt;TimeWindow i:nil=\"true\"/&gt;&lt;/AlertConditionDynamic&gt;</Configuration><ConjunctionOperator>None</ConjunctionOperator><IsInvertedMinCountThreshold>false</IsInvertedMinCountThreshold><NetObjectsMinCountThreshold i:nil=\"true\"/><ObjectType>IPAM IP Requests</ObjectType><SustainTime i:nil=\"true\"/></AlertConditionShelve></ArrayOfAlertConditionShelve>",
                "TriggeredCount": 2,
                "TriggeredDateTime": "2021-04-06T12:53:07.2300000Z",
                "TriggeredMessage": "test test has requested 1 IP address(es) at 4/6/2021 4:54:24 PM\n      Contact details: , dummy@dummy.com\n      Comments: ",
                "Uri": "swis://WIN-MV956AU5BSN./Orion/Orion.AlertActive/AlertActiveID=4,AlertObjectID=3"
            },
            {
                "AlertActiveID": 7,
                "AlertID": 112,
                "AlertMessage": "Network Discovery Failed",
                "AlertObjectID": 5,
                "AlertRefID": "eac27bca-77f7-40a5-a359-4069e96bc88e",
                "Canned": true,
                "ConfigurationDescription": "This alert will send an email if Network Discovery fails.",
                "Context": "{\"PropertiesValues\":{\".DiscoveryLogID\":5,\".FinishedTimeStamp\":\"2021-04-06T14:44:14Z\",\".ProfileID\":2,\".AutoImport\":true,\".Result\":3,\".ResultDescription\":\"Import Failed\",\".BatchID\":\"20881db3-ed49-4f4e-8356-e50f0ac5e4e0\",\".ErrorMessage\":\"Unknown Error\",\".InstanceType\":\"Orion.DiscoveryLogs\",\"Uri\":\"swis://WIN-MV956AU5BSN./Orion/Orion.DiscoveryLogs/DiscoveryLogID=5\",\"DisplayName\":\"Import Failed\"}}",
                "Enabled": true,
                "EntityCaption": "Import Failed",
                "EntityNetObjectId": ":",
                "EntityType": "Orion.DiscoveryLogs",
                "EntityUri": "swis://WIN-MV956AU5BSN./Orion/Orion.DiscoveryLogs/DiscoveryLogID=5",
                "Frequency": 60,
                "InstanceSiteId": 0,
                "InstanceType": "Orion.AlertActive",
                "LastEdit": "2021-03-31T12:04:06.0133333Z",
                "LastTriggeredDateTime": "2021-04-06T15:01:22.3570000Z",
                "Name": "Network Discovery Failed",
                "NotificationSettings": "<AlertNotificationSetting xmlns=\"http://schemas.solarwinds.com/2008/Core\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><Enabled>true</Enabled><NetObjectType>Orion.DiscoveryLogs</NetObjectType><Severity>Informational</Severity><Subject>Network Discovery Failed</Subject><_properties xmlns:a=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\"/></AlertNotificationSetting>",
                "NotifyEnabled": true,
                "ObjectType": "Orion.DiscoveryLogs",
                "RealEntityType": "Orion.DiscoveryLogs",
                "RealEntityUri": "swis://WIN-MV956AU5BSN./Orion/Orion.DiscoveryLogs/DiscoveryLogID=5",
                "Reset": "<ArrayOfAlertConditionShelve xmlns=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><AlertConditionShelve><AndThenTimeInterval i:nil=\"true\"/><ChainType>ResetWhenTriggered</ChainType><ConditionTypeID i:nil=\"true\"/><Configuration i:nil=\"true\"/><ConjunctionOperator>None</ConjunctionOperator><IsInvertedMinCountThreshold>false</IsInvertedMinCountThreshold><NetObjectsMinCountThreshold i:nil=\"true\"/><ObjectType i:nil=\"true\"/><SustainTime i:nil=\"true\"/></AlertConditionShelve></ArrayOfAlertConditionShelve>",
                "Severity": 0,
                "Trigger": "<ArrayOfAlertConditionShelve xmlns=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><AlertConditionShelve><AndThenTimeInterval i:nil=\"true\"/><ChainType>Trigger</ChainType><ConditionTypeID>Core.Dynamic</ConditionTypeID><Configuration>&lt;AlertConditionDynamic xmlns=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Alerting.Plugins.Conditions.Dynamic\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"&gt;&lt;ExprTree xmlns:a=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\"&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child/&gt;&lt;a:NodeType&gt;Constant&lt;/a:NodeType&gt;&lt;a:Value&gt;True&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child/&gt;&lt;a:NodeType&gt;Constant&lt;/a:NodeType&gt;&lt;a:Value&gt;0&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child/&gt;&lt;a:NodeType&gt;Constant&lt;/a:NodeType&gt;&lt;a:Value&gt;0&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Field&lt;/a:NodeType&gt;&lt;a:Value&gt;Orion.DiscoveryLogs|Result&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Constant&lt;/a:NodeType&gt;&lt;a:Value&gt;1&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Operator&lt;/a:NodeType&gt;&lt;a:Value&gt;=&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Field&lt;/a:NodeType&gt;&lt;a:Value&gt;Orion.DiscoveryLogs|Result&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Constant&lt;/a:NodeType&gt;&lt;a:Value&gt;3&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Operator&lt;/a:NodeType&gt;&lt;a:Value&gt;=&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Field&lt;/a:NodeType&gt;&lt;a:Value&gt;Orion.DiscoveryLogs|Result&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;a:Expr&gt;&lt;a:Child i:nil=\"true\"/&gt;&lt;a:NodeType&gt;Constant&lt;/a:NodeType&gt;&lt;a:Value&gt;4&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Operator&lt;/a:NodeType&gt;&lt;a:Value&gt;=&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Operator&lt;/a:NodeType&gt;&lt;a:Value&gt;OR&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Event&lt;/a:NodeType&gt;&lt;a:Value&gt;[createEvent].Orion.DiscoveryLogs|event&lt;/a:Value&gt;&lt;/a:Expr&gt;&lt;/a:Child&gt;&lt;a:NodeType&gt;Operator&lt;/a:NodeType&gt;&lt;a:Value&gt;AND&lt;/a:Value&gt;&lt;/ExprTree&gt;&lt;Scope i:nil=\"true\" xmlns:a=\"http://schemas.datacontract.org/2004/07/SolarWinds.Orion.Core.Models.Alerting\"/&gt;&lt;TimeWindow i:nil=\"true\"/&gt;&lt;/AlertConditionDynamic&gt;</Configuration><ConjunctionOperator>None</ConjunctionOperator><IsInvertedMinCountThreshold>false</IsInvertedMinCountThreshold><NetObjectsMinCountThreshold i:nil=\"true\"/><ObjectType>Orion.DiscoveryLogs</ObjectType><SustainTime i:nil=\"true\"/></AlertConditionShelve></ArrayOfAlertConditionShelve>",
                "TriggeredCount": 1,
                "TriggeredDateTime": "2021-04-06T15:01:22.2170000Z",
                "TriggeredMessage": "Network Discovery Failed",
                "Uri": "swis://WIN-MV956AU5BSN./Orion/Orion.AlertActive/AlertActiveID=7,AlertObjectID=5"
            }
        ]
    }
}

Human Readable Output

Alerts

Active Alert ID Alert Name Triggered Message Entity Caption Triggered At Severity Type Configuration Description
4 IP Address Request test test has requested 1 IP address(es) at 4/6/2021 4:54:24 PM
Contact details: , dummy@dummy.com
Comments:
IP Request (test test) 06/04/2021 12:53 PM CRITICAL IPAM.IPRequests This alert writes to the event log when Request IP Address is created.
7 Network Discovery Failed Network Discovery Failed Import Failed 06/04/2021 03:01 PM INFORMATION Orion.DiscoveryLogs This alert will send an email if Network Discovery fails.

swis-query


Executes a query request.

Click here to navigate to the guidelines to generate a query. SolarWinds Information Service schema can be found here.

Base Command

swis-query

Input

Argument Name Description Required
query The SWQL query to be executed. Required

Context Output

There is no context output for this command.

Command Example

!swis-query query="SELECT AlertActiveID, TriggeredDateTime FROM Orion.AlertActive ORDER BY AlertActiveID DESC WITH ROWS 1 To 3"

Context Example

{
    "SolarWinds": {
        "Query": [
            {
                "AlertActiveID": 18543,
                "TriggeredDateTime": "2021-04-20T06:39:32.4330000Z"
            },
            {
                "AlertActiveID": 18542,
                "TriggeredDateTime": "2021-04-19T18:45:11.7730000Z"
            },
            {
                "AlertActiveID": 18541,
                "TriggeredDateTime": "2021-04-19T18:44:10.5730000Z"
            }
        ]
    }
}

Human Readable Output

Query Result

Alert Active ID Triggered Date Time
18543 2021-04-20T06:39:32.4330000Z
18542 2021-04-19T18:45:11.7730000Z
18541 2021-04-19T18:44:10.5730000Z

Configuration parameters

  • server — Name or IP address of the Orion server (required)
  • port — Port
  • credentials — Username of the account (required)
  • fetch_type — Type of incident to be fetched
  • max_fetch — Maximum number of incidents per fetch
  • first_fetch — First fetch time interval
  • severities — Severity levels
  • object_types — Object Types
  • event_types — Event Types
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)
  • incidentType — Incident type
  • incidentFetchInterval — Incidents Fetch Interval
  • isFetch — Fetch incidents

Commands (3)

  • swis-alert-list

    Retrieves a list of alerts based on the filter values provided in the command arguments.

  • swis-event-list

    Retrieves a list of events according to filter values provided in the command arguments.

  • swis-query

    Executes a query request. Note: The guidelines for composing the query can be found in the 'View Integration Documentation' linked in the integration tips.

import json
import os

import pytest
from unittest import mock
from CommonServerPython import DemistoException
from SolarWinds import BASE_URL

SERVER_DOMAIN = "dummy.server"
PORT_DOMAIN = "1111"


def util_load_json(path):
    with open(path, encoding="utf-8") as f:
        return json.loads(f.read())


@pytest.fixture()
def client():
    """Fixture for client class"""
    from SolarWinds import Client

    return Client(SERVER_DOMAIN, PORT_DOMAIN, False, False, {"identifier": "dummy_username", "password": "dummy_password"})


def test_test_module_success(client, requests_mock):
    """Test for successful execution of test_module function"""
    from SolarWinds import test_module

    requests_mock.get(BASE_URL.format(SERVER_DOMAIN, PORT_DOMAIN) + "/Query", json={"results": []}, status_code=200)
    assert test_module(client, {}) == "ok"


def test_test_module_authentication_failure(client, requests_mock):
    """Test for authentication failure case of test_module function"""
    from SolarWinds import test_module

    requests_mock.get(BASE_URL.format(SERVER_DOMAIN, PORT_DOMAIN) + "/Query", json={"results": []}, status_code=403)
    with pytest.raises(DemistoException):
        test_module(client, {})


@pytest.mark.parametrize(
    "args", [{"page": 1, "limit": 5, "sort_order": "ascending"}, {"page": 1, "limit": 5, "sort_order": "descending"}]
)
def test_validate_common_arguments_success(args):
    """Test cases for success scenarios of validate_common_arguments function"""
    from SolarWinds import validate_common_arguments

    validate_common_arguments(args)


@pytest.mark.parametrize(
    "args,error_msg",
    [
        ({"page": -1}, "PAGE"),
        ({"page": None}, "PAGE"),
        ({"limit": 0}, "LIMIT"),
        ({"limit": None}, "LIMIT"),
        ({"sort_order": "dummy"}, "SORT_ORDER"),
    ],
)
def test_validate_common_arguments_failure_negative_and_zero(args, error_msg):
    """Test cases for failure scenarios of validate_common_arguments function"""
    from SolarWinds import validate_common_arguments, ERR_MSG

    with pytest.raises(ValueError, match=ERR_MSG[error_msg]):
        validate_common_arguments(args)


@pytest.mark.parametrize(
    "args,error_msg",
    [
        ({"page": "dummy"}, "PAGE"),
        ({"limit": "dummy"}, "LIMIT"),
    ],
)
def test_validate_common_arguments_failure_string_arg(args, error_msg):
    """Test cases for failure scenarios of validate_common_arguments function"""
    from SolarWinds import validate_common_arguments

    with pytest.raises(ValueError):
        validate_common_arguments(args)


@pytest.mark.parametrize(
    "args,query",
    [
        ({}, " ORDER BY EventID ASC WITH ROWS 1 TO 50"),
        ({"page": 5, "limit": 4}, " ORDER BY EventID ASC WITH ROWS 21 TO 24"),
        ({"sort_key": "EventTime"}, " ORDER BY EventTime ASC WITH ROWS 1 TO 50"),
        ({"acknowledged": "True"}, " WHERE Acknowledged = True ORDER BY EventID ASC WITH ROWS 1 TO 50"),
        ({"event_type": "warning"}, " WHERE ( EventTypeName = 'warning' ) ORDER BY EventID ASC WITH ROWS 1 TO 50"),
        (
            {"event_type": "warning,node up"},
            " WHERE ( EventTypeName = 'warning' OR EventTypeName = 'node up' ) ORDER BY EventID ASC WITH ROWS 1 TO 50",
        ),
        ({"node": "temporary"}, " WHERE ( Node = 'temporary' ) ORDER BY EventID ASC WITH ROWS 1 TO 50"),
        ({"node": "temporary,dummy"}, " WHERE ( Node = 'temporary' OR Node = 'dummy' ) ORDER BY EventID ASC WITH ROWS 1 TO 50"),
        (
            {"acknowledged": "True", "event_type": "warning"},
            " WHERE Acknowledged = True AND ( EventTypeName = 'warning' ) ORDER BY EventID ASC WITH ROWS 1 TO 50",
        ),
        (
            {"node": "temporary", "event_type": "warning"},
            " WHERE ( EventTypeName = 'warning' ) AND ( Node = 'temporary' ) ORDER BY EventID ASC WITH ROWS 1 TO 50",
        ),
        ({"event_id": "1, 2"}, " WHERE ( EventID = 1 OR EventID = 2 ) ORDER BY EventID ASC WITH ROWS 1 TO 50"),
    ],
)
def test_validate_and_prepare_query_for_event_list_success(args, query):
    """Test cases for success scenarios of validate_and_prepare_query_for_event_list function"""
    from SolarWinds import validate_and_prepare_query_for_event_list, QUERY_PARAM

    expected_query = QUERY_PARAM["GET_EVENTS"] + query
    response_query = validate_and_prepare_query_for_event_list(args)
    assert expected_query == response_query


@pytest.mark.parametrize("args,error_msg", [({"event_id": ", "}, "ID_ERROR"), ({"event_id": "1, "}, "ID_ERROR")])
def test_validate_and_prepare_query_for_event_list_failure(args, error_msg):
    """Test cases for failure scenarios of validate_and_prepare_query_for_event_list function"""
    from SolarWinds import validate_and_prepare_query_for_event_list, ERR_MSG

    with pytest.raises(ValueError, match=ERR_MSG[error_msg].format("event_id")):
        validate_and_prepare_query_for_event_list(args)


def test_convert_events_outputs_to_hr():
    """Test case for convert_events_outputs_to_hr function"""
    from SolarWinds import convert_events_outputs_to_hr

    expected_response = util_load_json("test_data/test_swis_event_list_success.json")
    hr_response = convert_events_outputs_to_hr(expected_response["outputs"])
    assert hr_response == expected_response["readable"]


def test_convert_events_outputs_to_hr_no_events():
    """Test case of convert_events_outputs_to_hr function for no events in response from api"""
    from SolarWinds import convert_events_outputs_to_hr, ERR_MSG

    hr_response = convert_events_outputs_to_hr([])
    assert hr_response == ERR_MSG["NO_RECORDS_FOUND"].format("event(s)")


@mock.patch("SolarWinds.Client.http_request")
def test_swis_event_list_success(http_request, client):
    """Test case for success scenarios of swis-event-list command"""
    from SolarWinds import swis_event_list_command

    expected_response = util_load_json("test_data/test_swis_event_list_success.json")
    http_request.return_value = expected_response["http_mock"]
    response = swis_event_list_command(client, {})
    assert response.outputs == expected_response["outputs"]
    assert response.readable_output == expected_response["readable"]


@mock.patch("SolarWinds.Client.http_request")
def test_swis_event_list_no_data(http_request, client):
    """Test case for no data found in response of swis-event-list command"""
    from SolarWinds import swis_event_list_command, ERR_MSG

    http_request.return_value = {"results": []}
    response = swis_event_list_command(client, {})
    assert response.readable_output == ERR_MSG["NO_RECORDS_FOUND"].format("event(s)")
    assert response.outputs == []


@mock.patch("SolarWinds.Client.http_request")
def test_swis_event_list_failure(client):
    """Test case for failure scenarios of swis-event-list command"""
    from SolarWinds import swis_event_list_command, ERR_MSG

    with pytest.raises(ValueError, match=ERR_MSG["ACKNOWLEDGED"]):
        swis_event_list_command(client, {"acknowledged": "dummy"})


@pytest.mark.parametrize(
    "args,query",
    [
        ({}, " ORDER BY AlertActiveID ASC WITH ROWS 1 TO 50"),
        ({"page": 5, "limit": 4}, " ORDER BY AlertActiveID ASC WITH ROWS 21 TO 24"),
        ({"sort_key": "AlertID"}, " ORDER BY AlertID ASC WITH ROWS 1 TO 50"),
        ({"type": "Node"}, " WHERE ( ObjectType = 'Node' ) ORDER BY AlertActiveID ASC WITH ROWS 1 TO 50"),
        ({"severity": "Notice"}, " WHERE ( Severity = 4 ) ORDER BY AlertActiveID ASC WITH ROWS 1 TO 50"),
        (
            {"alert_id": "1, 2"},
            " WHERE ( AlertActiveID = 1 OR AlertActiveID = 2 ) ORDER BY AlertActiveID ASC WITH ROWS 1 TO 50",
        ),
    ],
)
def test_validate_and_prepare_query_for_alert_list_success(args, query):
    """Test cases for success scenarios of validate_and_prepare_query_for_alert_list function"""
    from SolarWinds import validate_and_prepare_query_for_list_alerts, QUERY_PARAM

    expected_query = QUERY_PARAM["LIST_ALERTS"] + query
    response_query = validate_and_prepare_query_for_list_alerts(args)
    assert expected_query == response_query


@pytest.mark.parametrize(
    "args,error_msg",
    [
        ({"alert_id": ", "}, "ID_ERROR"),
        ({"alert_id": "1, "}, "ID_ERROR"),
    ],
)
def test_validate_and_prepare_query_for_alert_list_failure(args, error_msg):
    """Test cases for failure scenarios of validate_and_prepare_query_for_event_list function"""
    from SolarWinds import validate_and_prepare_query_for_list_alerts, ERR_MSG

    with pytest.raises(ValueError, match=ERR_MSG[error_msg].format("alert_id")):
        validate_and_prepare_query_for_list_alerts(args)


def test_convert_alerts_outputs_to_hr():
    """Test case for convert_alerts_outputs_to_hr function"""
    from SolarWinds import convert_alerts_outputs_to_hr

    with open("test_data/test_swis_alert_list_success_context.json") as data:
        expected_res = json.load(data)

    with open("test_data/test_swis_alert_list_success.md") as data:
        expected_hr = data.read()
    hr_response = convert_alerts_outputs_to_hr(expected_res)
    assert hr_response == expected_hr


def test_convert_alerts_outputs_to_hr_no_alerts():
    """Test case of convert_alerts_outputs_to_hr function for no alerts in response from api"""
    from SolarWinds import convert_alerts_outputs_to_hr, ERR_MSG

    hr_response = convert_alerts_outputs_to_hr([])
    assert hr_response == ERR_MSG["NO_RECORDS_FOUND"].format("alert(s)")


@mock.patch("SolarWinds.Client.http_request")
def test_swis_alert_list_success(http_request, client):
    """Test case for success scenarios of swis-alert-list command"""
    from SolarWinds import swis_alert_list_command

    with open("test_data/swis_alert_list_raw_response.json") as data:
        mock_response = json.load(data)

    with open("test_data/test_swis_alert_list_success_context.json") as data:
        expected_res = json.load(data)

    with open("test_data/test_swis_alert_list_success.md") as data:
        expected_hr = data.read()

    http_request.return_value = mock_response
    response = swis_alert_list_command(client, {})
    assert response.outputs == expected_res
    assert response.readable_output == expected_hr


@mock.patch("SolarWinds.Client.http_request")
def test_swis_alert_list_no_data(http_request, client):
    """Test case for no data found in response of swis-alert-list command"""
    from SolarWinds import swis_alert_list_command, ERR_MSG

    http_request.return_value = {"results": []}
    response = swis_alert_list_command(client, {})
    assert response.readable_output == ERR_MSG["NO_RECORDS_FOUND"].format("alert(s)")
    assert response.outputs == []


@mock.patch("SolarWinds.Client.http_request")
def test_swis_alert_list_failure(client):
    """Test case for failure scenarios of swis-alert-list command"""
    from SolarWinds import swis_alert_list_command, ERR_MSG, SEVERITIES_MAP

    expected_output = ERR_MSG["SEVERITIES_ERROR"].format(SEVERITIES_MAP)
    with pytest.raises(ValueError) as err:
        _ = swis_alert_list_command(client, {"severity": "dummy"})
    assert str(err.value) == expected_output


def test_convert_query_output_to_hr_success():
    from SolarWinds import convert_query_output_to_hr

    expected_response = util_load_json(os.path.join(os.path.dirname(__file__), "test_data", "test_swis_query_success.json"))
    hr_response = convert_query_output_to_hr(expected_response.get("http_mock").get("results"))
    assert hr_response == expected_response.get("readable")


def test_convert_query_output_to_hr_no_data():
    from SolarWinds import convert_query_output_to_hr, ERR_MSG

    hr_response = convert_query_output_to_hr([])
    assert hr_response == ERR_MSG["NO_RECORDS_FOUND"].format("record(s)")


@pytest.mark.parametrize(
    "args",
    [
        (
            {
                "query": "SELECT NodeID, ObjectSubType, IPAddress, IPAddressType, DynamicIP, Caption, NodeDescription, "
                "Description,FROM Orion.Nodes"
            }
        ),
    ],
)
@mock.patch("SolarWinds.Client.http_request")
def test_swis_query_success(http_request, client, args):
    from SolarWinds import swis_query_command

    expected_response = util_load_json(os.path.join(os.path.dirname(__file__), "test_data", "test_swis_query_success.json"))
    http_request.return_value = expected_response["http_mock"]
    response = swis_query_command(client, args)
    assert response.outputs == expected_response.get("http_mock").get("results")


@pytest.mark.parametrize(
    "args",
    [
        ({"query": "SELECT TOP 2 EngineID, AlertID, Name FROM Orion.Alerts"}),
    ],
)
@mock.patch("SolarWinds.Client.http_request")
def test_swis_query_failure_no_data(http_request, client, args):
    from SolarWinds import swis_query_command, ERR_MSG

    http_request.return_value = {"results": []}
    response = swis_query_command(client, args)
    assert response.readable_output == ERR_MSG["NO_RECORDS_FOUND"].format("record(s)")
    assert response.outputs == []


@pytest.mark.parametrize(
    "args",
    [
        ({"query": ""}),
    ],
)
@mock.patch("SolarWinds.Client.http_request")
def test_swis_query_failure_no_query_argument(client, args):
    from SolarWinds import swis_query_command, ERR_MSG

    with pytest.raises(ValueError, match=ERR_MSG["REQUIRED_ARGUMENT"]):
        swis_query_command(client, args)


@mock.patch("SolarWinds.Client.http_request")
def test_fetch_incidents_alerts_success(http_request, client):
    from SolarWinds import fetch_incidents

    expected_response = util_load_json(os.path.join(os.path.dirname(__file__), "test_data", "test_fetch_incidents.json"))[
        "alerts"
    ]
    params = {
        "fetch_type": "Alert",
        "max_fetch": "5",
        "first_fetch": "2 days ago",
        "severities": ["CRITICAL"],
        "object_types": ["Node"],
    }
    raw_response = util_load_json(os.path.join(os.path.dirname(__file__), "test_data", "test_fetch_incidents_raw_response.json"))[
        "alerts"
    ]
    http_request.return_value = raw_response

    _, incidents = fetch_incidents(client, {}, params, is_test=False)

    assert incidents == expected_response["incidents"]


@mock.patch("SolarWinds.Client.http_request")
def test_fetch_incidents_events_success(http_request, client):
    from SolarWinds import fetch_incidents

    expected_response = util_load_json(os.path.join(os.path.dirname(__file__), "test_data", "test_fetch_incidents.json"))[
        "events"
    ]
    params = {"fetch_type": "Event", "max_fetch": "5", "first_fetch": "2 days ago", "event_types": ["Alert Triggered"]}
    raw_response = util_load_json(os.path.join(os.path.dirname(__file__), "test_data", "test_fetch_incidents_raw_response.json"))[
        "events"
    ]
    http_request.return_value = raw_response

    _, incidents = fetch_incidents(client, {}, params, is_test=False)

    assert incidents == expected_response["incidents"]


@pytest.mark.parametrize(
    "args",
    [
        {"max_fetch": "5", "first_fetch": "2 days ago", "severities": ["Critical"]},
        {"max_fetch": "999", "first_fetch": "2021/04/09", "severities": ["Critical", "Notice"]},
    ],
)
def test_validate_fetch_incidents_parameters_success(args):
    """Test cases for success scenarios of validate_fetch_incidents_parameters_success"""
    from SolarWinds import validate_fetch_incidents_parameters

    validate_fetch_incidents_parameters(args)


@pytest.mark.parametrize(
    "args, message",
    [
        ({"max_fetch": "3", "first_fetch": "2 days ago", "severities": ["new"]}, "SEVERITIES_ERROR"),
    ],
)
def test_validate_fetch_incidents_parameters_severity(args, message):
    """Test cases for failure scenarios of validate_fetch_incidents_parameters_success"""
    from SolarWinds import validate_fetch_incidents_parameters, ERR_MSG, SEVERITIES_MAP

    with pytest.raises(ValueError) as e:
        validate_fetch_incidents_parameters(args)
    assert str(e.value) == ERR_MSG[message].format(SEVERITIES_MAP)


@pytest.mark.parametrize(
    "args, message",
    [
        ({"max_fetch": "-1"}, "INVALID_MAX_FETCH"),
        ({"max_fetch": "1500"}, "INVALID_MAX_FETCH"),
    ],
)
def test_validate_fetch_incidents_parameters_maxfetch(args, message):
    """Test cases for failure scenarios of validate_fetch_incidents_parameters_success"""
    from SolarWinds import validate_fetch_incidents_parameters, ERR_MSG

    with pytest.raises(ValueError, match=ERR_MSG[message]):
        validate_fetch_incidents_parameters(args)