NetWork Monitoring using SCOM

Are there any good write ups on monitoring Network devices using SCOM.? Looking to monitor Dell switches and Fortigate Firewalls using SCOM SNMP feature.Tried using “Extensible NetWork Monitoring MP Generator Tool” without much luck.

 

Thanks

Hi,

 

first thing you need to check is if the devices and models are supported to be monitored:
https://www.microsoft.com/en-us/download/details.aspx?id=51219

Afterwards I just can refer to the following official docs:
https://docs.microsoft.com/en-us/system-center/scom/manage-monitor-networkdevice-overview?view=sc-om-2019

There is a blog about Fortigate that you might want to check out:
http://www.opsman.co.za/scom-monitoring-a-fortigate-firewall/

 

Getting network monitoring working properly in SCOM is hard work and doesn’t return the invest you made. From my perspective I would choose a dedicated tool network monitoring.
SolarWinds does a pretty nice job and with the Management Packs (official or community) you can also get the information into SCOM & Squared Up.

1 Like

Hi,

Network monitoring in SCOM out of the box can be a bit lackluster but there are numerous things you can do to make it better. I am planning on creating a blog about this for ages but have not found the time to do so.

There are alternative ways to monitor your network devices by not leveraging the standard SNMP modules in SCOM, because these can be challenging to get to work properly.

What I usually do to make things easier for me is:

  • Look if the device has an API and get my information from there. Most modern network devices have this.
  • Use the powershell module instead of the native SNMP modules in SCOM. You can find it here https://www.powershellgallery.com/packages/Proxx.SNMP/1.1.1.4. That way you can either author a MP yourself with Visual Studio / MP Author or you can use the Powershell community management pack of Squared Up. Keep in mind that you will have to install this on each management server and gateway server that does the actual SNMP monitoring.
My usual approach is this:
  1. Create an MP in Visual Studio
  2. Find the MIB file with the OID values. I usually use IReasoning MIB Browser.
  3. Create an an initial SNMP discovery (this is relatively ‘easy’). I can give you some sample code if you want.
  4. Create other powershell discoveries targetting the devices based on my initial discovery. You can use SNMP walk for that in the powershell module.
  5. Create monitors / rules also using either the API or SNMP, both using powershell.
Another advice I can give you is to rename the network interfaces with this management pack: https://gallery.technet.microsoft.com/scriptcenter/Network-Change-Network-f20551ca

Here’s some sample code (still work in progress) I made last week. This does not leverage the SNMP Powershell Module however. Here I read data from an API to monitor certain metrics.

<?xml version="1.0" encoding="utf-8"?>
<ManagementPack SchemaVersion="2.0" ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Manifest>
    <Identity>
      <ID>Switch.ManagementPack</ID>
      <Version>1.0.0.22</Version>
    </Identity>
    <Name>Switch Management Pack</Name>
    <References>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>7.5.8501.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Health">
        <ID>System.Health.Library</ID>
        <Version>7.0.8437.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>7.5.8501.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="SNL">
        <ID>System.NetworkManagement.Library</ID>
        <Version>7.2.11719.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        <ClassType ID="Switch.NetworkDevice" Base="SNL!System.NetworkManagement.Node" Accessibility="Public" Abstract="false" Hosted="false" Singleton="false"></ClassType>
      </ClassTypes>
    </EntityTypes>
    <SecureReferences>
      <SecureReference ID="Switch.ManagementPack.RunasProfile" Accessibility="Public" />
    </SecureReferences>
    <ModuleTypes>
      <DataSourceModuleType ID="Switch.Device.DataSource" Accessibility="Public" Batching="false">
        <Configuration>
          <xsd:element name="OIDPattern" type="xsd:string" minOccurs="1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="DeviceDisplayName" type="xsd:string" minOccurs="1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="ClassId" type="xsd:string" minOccurs="1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="IntervalInHours" type="xsd:integer" minOccurs="1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="SyncTime" type="xsd:string" minOccurs="0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalInHours" Selector="$Config/IntervalInHours$" ParameterType="int" />
          <OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <DataSource ID="Scheduler" TypeID="System!System.Discovery.Scheduler">
                <Scheduler>
                  <SimpleReccuringSchedule>
                    <Interval Unit="Hours">$Config/IntervalInHours$</Interval>
                    <SyncTime>$Config/SyncTime$</SyncTime>
                  </SimpleReccuringSchedule>
                  <ExcludeDates />
                </Scheduler>
              </DataSource>
              <ConditionDetection ID="MapToDiscovery" TypeID="System!System.Discovery.FilteredClassSnapshotDataMapper">
                <Expression>
                  <RegExExpression>
                    <ValueExpression>
                      <Value>$Target/Property[Type="SNL!System.NetworkManagement.Node"]/SystemObjectID$</Value>
                    </ValueExpression>
                    <Operator>MatchesRegularExpression</Operator>
                    <Pattern>$Config/OIDPattern$</Pattern>
                  </RegExExpression>
                </Expression>
                <ClassId>$Config/ClassId$</ClassId>
                <InstanceSettings>
                  <Settings>
                    <Setting>
                      <Name>$MPElement[Name="System!System.Entity"]/DisplayName$</Name>
                      <Value>$Config/DeviceDisplayName$</Value>
                    </Setting>
                    <Setting>
                      <Name>$MPElement[Name="SNL!System.NetworkManagement.Node"]/DeviceKey$</Name>
                      <Value>$Target/Property[Type="SNL!System.NetworkManagement.Node"]/DeviceKey$</Value>
                    </Setting>
                    <Setting>
                      <Name>$MPElement[Name="SNL!System.NetworkManagement.Node"]/Vendor$</Name>
                      <Value>Switch </Value>
                    </Setting>
                  </Settings>
                </InstanceSettings>
              </ConditionDetection>
            </MemberModules>
            <Composition>
              <Node ID="MapToDiscovery">
                <Node ID="Scheduler" />
              </Node>
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.Discovery.Data</OutputType>
      </DataSourceModuleType>
      <DataSourceModuleType ID="Switch.ManagementPack.DataSource" Accessibility="Public" Batching="false">
        <Configuration>
          <xsd:element minOccurs="1" name="IntervalSeconds" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="0" name="SyncTime" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="IPAddress" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="Verbose" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="UserName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="Password" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="Interval" Selector="$Config/IntervalSeconds$" ParameterType="int" />
          <OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string" />
          <OverrideableParameter ID="Verbose" Selector="$Config/Verbose$" ParameterType="string" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <DataSource ID="Schedule" TypeID="System!System.SimpleScheduler">
                <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
                <SyncTime>$Config/SyncTime$</SyncTime>
              </DataSource>
              <ProbeAction ID="Probe" TypeID="Switch.ManagementPack.DataSource.PSScript"></ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="Probe">
                <Node ID="Schedule" />
              </Node>
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
      </DataSourceModuleType>
      <ProbeActionModuleType ID="Switch.ManagementPack.DataSource.PSScript" Accessibility="Public" Batching="false" PassThrough="false">
        <Configuration>
          <xsd:element minOccurs="0" name="IPAddress" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="0" name="Verbose" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="0" name="UserName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="0" name="Password" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <ProbeAction ID="PSScript" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagTriggerOnlyProbe">
                <ScriptName>Get-ScenarioResponseTime</ScriptName>
                <ScriptBody><![CDATA[#=================================================================================
#  This script will check the status of the switch devices by reading different values -
#  the API
#  
#
#  Author: Jasper Van Damme 
#  v1.0
#=================================================================================

param([string]$IPAddress, [string]$Verbose, [string]$UserName, [string]$Password)

#================[Constants/Variables]====================================================

$ScriptName = "Get-SwitchStatus.ps1"
$EventID = "10015"
$StartTime = Get-Date
#================[ Main Execution ]====================================================


Try { 
    $API = New-Object -ComObject "MOM.ScriptAPI"
    $bag = $api.createpropertybag()
    #Creating an array for the values that will be retrieved from the API.
    
    $Metrics = @("sms.get_sentitems_length"),
    ("sms.get_inbox_length"),
    ("sms.get_queue_length")

    $ModemMetrics = @("signal.get_gsmsignal")

    $StateMonitors = @("sms.get_modem_state")
#Region get all values from API
    Foreach ($Metric in $Metrics) {

        $Body = @"
{"method":"$Metric", "params":{"login":"$UserName","pass":"$Password"}}
"@
	$URL = "http://" + $IPAddress + "/jsonrpc/sms"
        $Value = Invoke-WebRequest -UseBasicParsing -Uri $URL -Method Post -Body $Body 
        [double]$Result = $value.split('"')[3]
        $Bag.AddValue($Metric, $Result)
    }

    Foreach ($ModemMetric in $ModemMetrics) {
        $Body = @"
{"method":"$ModemMetric", "params":{"login":"$UserName","pass":"$Password","modem_no":"1"}}
"@
        $Value = Invoke-WebRequest -UseBasicParsing -Uri "http://$IPAddress/jsonrpc/sms" -Method Post -Body $Body   
        [Double]$Result = $value.split('"')[3]
        $Bag.AddValue($ModemMetric, $Result)
    }

    Foreach ($StateMonitor in $StateMonitors) {
        $Body = @"
{"method":"$StateMonitor", "params":{"login":"$UserName","pass":"$Password","modem_no":"1"}}
"@
        $Value = Invoke-WebRequest -UseBasicParsing -Uri "http://$IPAddress/jsonrpc/sms" -Method Post -Body $Body  
        [string]$Result = $value.split('"')[3]
        $Bag.AddValue($StateMonitor, $Result)
    }
#Endregion get all values from API
    $Bag
}

Catch { $api.LogScriptEvent($ScriptName, $EventID, 0, "Failed to monitor Switch  $IPAddress The error given was:`r`n" + $Error) }

$EndTime = Get-Date
$ScriptTime = ($EndTime - $StartTime).TotalSeconds

$api.LogScriptEvent($ScriptName, $EventID, 0, "`n Script Completed. `n Script Runtime : ($ScriptTime) seconds. ")
]]></ScriptBody>
                <Parameters>
                  <Parameter>
                    <Name>ScenarioName</Name>
                    <Value>$Config/IPAddress$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>Verbose</Name>
                    <Value>$Config/Verbose$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>UserName</Name>
                    <Value>$Config/UserName$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>Password</Name>
                    <Value>$Config/Password$</Value>
                  </Parameter>
                </Parameters>
                <TimeoutSeconds>60</TimeoutSeconds>
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="PSScript" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
        <TriggerOnly>true</TriggerOnly>
      </ProbeActionModuleType>
    </ModuleTypes>
    <MonitorTypes>
      <UnitMonitorType ID="Switch.ManagementPack.ModemState.MonitorType" Comment="Monitor type that tests the state of the modem" Accessibility="Public">
        <MonitorTypeStates>
          <MonitorTypeState ID="Healthy" NoDetection="false" />
          <MonitorTypeState ID="Critical" NoDetection="false" />
        </MonitorTypeStates>
        <Configuration>
          <xsd:element minOccurs="1" name="IntervalSeconds" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="SyncTime" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="IPAddress" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="Verbose" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="UserName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="Password" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
          <OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string" />
        </OverrideableParameters>
        <MonitorImplementation>
          <MemberModules>
            <DataSource ID="DataSource" TypeID="Switch.ManagementPack.DataSource">
              <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
              <SyncTime>$Config/SyncTime$</SyncTime>
              <IPAddress>$Config/IPAddress$</IPAddress>
              <Verbose>$Config/Verbose$</Verbose>
              <UserName>$Config/UserName$</UserName>
              <Password>$Config/Password$</Password>
            </DataSource>
            <ConditionDetection ID="FilterCritical" TypeID="System!System.ExpressionFilter">
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="String">Property[@Name='"sms.get_modem_state"']</XPathQuery>
                  </ValueExpression>
                  <Operator>NotEqual</Operator>
                  <ValueExpression>
                    <Value Type="String">enabled</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </ConditionDetection>
            <ConditionDetection ID="FilterHealthy" TypeID="System!System.ExpressionFilter">
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="String">Property[@Name='"sms.get_modem_state"']</XPathQuery>
                  </ValueExpression>
                  <Operator>Equal</Operator>
                  <ValueExpression>
                    <Value Type="String">enabled</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </ConditionDetection>
          </MemberModules>
          <RegularDetections>
            <RegularDetection MonitorTypeStateID="Critical">
              <Node ID="FilterCritical">
                <Node ID="DataSource" />
              </Node>
            </RegularDetection>
            <RegularDetection MonitorTypeStateID="Healthy">
              <Node ID="FilterHealthy">
                <Node ID="DataSource" />
              </Node>
            </RegularDetection>
          </RegularDetections>
        </MonitorImplementation>
      </UnitMonitorType>
    </MonitorTypes>
  </TypeDefinitions>
  <Monitoring>
    <Discoveries>
      <Discovery ID="Switch.ManagementPack.Device.Discovery" Target="SNL!System.NetworkManagement.Node" Enabled="true" ConfirmDelivery="false" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryClass TypeID="Switch.NetworkDevice" />
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="Switch.Device.DataSource">
        <!-- Based on the OID of the Device 
        -->
          <OIDPattern>.1.3.6.1.4.1.8072.3.2.10</OIDPattern>
          <DeviceDisplayName>$Target/Property[Type="System!System.Entity"]/DisplayName$</DeviceDisplayName>
          <ClassId>$MPElement[Name="Switch.NetworkDevice"]$</ClassId>
          <IntervalInHours>4</IntervalInHours>
          <SyncTime></SyncTime>
        </DataSource>
      </Discovery>
    </Discoveries>
    <Monitors>
      <UnitMonitor ID="Switch.ManagementPack.Modem.State" Accessibility="Public" Enabled="true" Target="Switch.NetworkDevice" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" TypeID="Switch.ManagementPack.ModemState.MonitorType" ConfirmDelivery="false">
        <Category>AvailabilityHealth</Category>
        <AlertSettings AlertMessage="Switch.ManagementPack.Modem.State.AlertMessage">
          <AlertOnState>Warning</AlertOnState>
          <AutoResolve>true</AutoResolve>
          <AlertPriority>Normal</AlertPriority>
          <AlertSeverity>MatchMonitorHealth</AlertSeverity>
          <AlertParameters>
            <AlertParameter1>$Data/Context/Property[@Name='"sms.get_modem_state"']$</AlertParameter1>
          </AlertParameters>
        </AlertSettings>
        <OperationalStates>
          <OperationalState ID="Healthy" MonitorTypeStateID="Healthy" HealthState="Error" />
          <OperationalState ID="Critical" MonitorTypeStateID="Critical" HealthState="Success" />
        </OperationalStates>
        <Configuration>
          <IntervalSeconds>300</IntervalSeconds>
          <SyncTime>00:05</SyncTime>
          <IPAddress>$MPElement[Name="System!System.Entity"]/DisplayName$</IPAddress>
          <Verbose>0</Verbose>
          <UserName>$RunAs[Name="Switch.ManagementPack.Switch.RunasProfile"]/UserName$</UserName>
          <Password>$RunAs[Name="Switch.ManagementPack.Switch.RunasProfile"]/Password$</Password>
        </Configuration>
      </UnitMonitor>
    </Monitors>
  </Monitoring>
  <Presentation>
    <StringResources>
      <StringResource ID="Switch.ManagementPack.Modem.State.AlertMessage" />
    </StringResources>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Switch.ManagementPack.Device.Discovery">
          <Name>Switch  Device Discovery</Name>
          <Description>This discovery will find the network devices which correspond to Switch  gateways</Description>
        </DisplayString>
        <DisplayString ElementID="Switch.ManagementPack.Modem.State.AlertMessage">
          <Name>Switch  Modem State Unhealthy</Name>
          <Description>The Switch  Device is reporting that the modem is in the following state: {0}</Description>
        </DisplayString>
        <DisplayString ElementID="Switch.ManagementPack.Modem.State">
          <Name>Switch  Modem State</Name>
        </DisplayString>
        <DisplayString ElementID="Switch.ManagementPack">
          <Name>Switch Management Pack</Name>
          <Description>Monitors the Switch  devices and the status of the SMS being sent by the SCOM command channel</Description>
        </DisplayString>
        <DisplayString ElementID="Switch.NetworkDevice">
          <Name>Switch  Network Device</Name>
          <Description></Description>
        </DisplayString>
        <DisplayString ElementID="Switch.ManagementPack.Switch.RunasProfile">
          <Name>Switch  Runas Profile</Name>
          <Description>Used to monitor the Switch  devices (API)</Description>
        </DisplayString>
      </DisplayStrings>
      <KnowledgeArticles></KnowledgeArticles>
    </LanguagePack>
  </LanguagePacks>
</ManagementPack>

Br,

Jasper

1 Like

Thanks Jasper for sharing the links. Would love to read more details on this in your blogs.

I’m planning on just using data already in Solarwinds following this method - https://squaredup.com/blog/how-to-add-solarwind-nodes-to-your-enterprise-applications/

I don’t need to monitor devices as such but I definitely want to include the visibility of network device health so this is the perfect solution for me anyway :slight_smile:

Silect MP Studio makes writing custom MPs for monitoring network devices pretty easy. Hardest part is finding all the MIB files once you have those the rest is pretty easy. When I did my POC it took me most of the day to find and import the MIB files then about an hour to write the MP and build a basic dashboard.

Thx Reuben. !! Let me chk out the blog on Fortigate.