SCOM 2012: SCOM Groups based on AD Groups (PowerShell)

Standard

Based on an article of Boris Yanushpolsky I was inspired to build a PowerShell equivalent. Boris described how you could populate an SCOM group with members of an Active Directory group. His example was using VBScript. Since I’m trying to avoid VBScript I have created a PowerShell one.

This discovery has some pre-requisites. On each server which could possibly execute this discovery the Active Directory cmdlets need to be installed. First we start with defining the group. This is done with the following piece of XML code.

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TypeDefinitions>
<EntityTypes>
<ClassTypes>
<ClassType ID="ACS.Security.Alerting.LogonEvent.Group.AD" Accessibility="Public" Abstract="false" Base="System!System.Group" Hosted="false" Singleton="true" />
</ClassTypes>
</EntityTypes>
</TypeDefinitions>
<LanguagePacks>
<LanguagePack ID="ENU" IsDefault="false">
<DisplayStrings>
<DisplayString ElementID="ACS.Security.Alerting.LogonEvent.Group.AD">
<Name>ACS Security Alerting LogonEvent Group (Based on AD Group)</Name>
</DisplayString>
</DisplayStrings>
</LanguagePack>
</LanguagePacks>
</ManagementPackFragment>

Now we have defined the group we need to define the relationship type. Group membership in SCOM is defined through relations between the group and his members. To populate the members of this group we first need to define the relationshiptype. This is done through the following piece of XML code:

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TypeDefinitions>
<EntityTypes>
<RelationshipTypes>
<RelationshipType ID="ACS.Security.Alerting.LogonEvent.Group.AD.Contains.Windows.Computer" Accessibility="Internal" Abstract="false" Base="System!System.Containment">
<Source ID="ACS.Security.Alerting.LogonEvent.Group.AD.Rel.Source" Type="ACS.Security.Alerting.LogonEvent.Group.AD" />
<Target ID="ACS.Security.Alerting.LogonEvent.Group.AD.Rel.Target" Type="Windows!Microsoft.Windows.Computer" />
</RelationshipType>
</RelationshipTypes>
</EntityTypes>
</TypeDefinitions>
<LanguagePacks>
<LanguagePack ID="ENU" IsDefault="false">
<DisplayStrings>
<DisplayString ElementID="ACS.Security.Alerting.LogonEvent.Group.AD.Contains.Windows.Computer">
<Name>ACS Security Alerting LogonEvent Group Contains Windows Computer</Name>
</DisplayString>
</DisplayStrings>
</LanguagePack>
</LanguagePacks>
</ManagementPackFragment>

Based on these relationshiptype we can use this in a PowerShell Discovery. The following PowerShell script will query the Active Directory get the members of the group and create a relationshiptype for each member.

# AD_GroupDiscovery_check.ps1
# Written by Arjan Vroege. All rights reserved.

param($SourceID, $ManagedEntityID)

$scomapi  = new-object -comObject "MOM.ScriptAPI"
$DiscData = $scomapi.CreateDiscoveryData(0, $SourceID, $ManagedEntityID)

#$scomapi.LogScriptEvent("AD_GroupDiscovery_check.ps1",101,2, "Discovery was executed")
$groupInstance = $DiscData.CreateClassInstance("$MPElement[Name='ACS.Security.Alerting.LogonEvent.Group.AD']$")
$groupmembers  = Get-ADGroupMember -Identity "<< AD GROUP >>"

foreach($member in $groupmembers) {
$DNSHostName    = Get-ADComputer -Filter 'Name -eq $member.Name' | Select -Expand DNSHostName
#$scomapi.LogScriptEvent("AD_GroupDiscovery_check.ps1",101,2, "Instance $DNSHostName")

$serverInstance = $DiscData.CreateClassInstance("$MPElement[Name='Windows!Microsoft.Windows.Computer']$")
$serverInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $DNSHostName)

$RelationshipInstance = $DiscData.CreateRelationshipInstance("$MPElement[Name='ACS.Security.Alerting.LogonEvent.Group.AD.Contains.Windows.Computer']$")
$RelationshipInstance.Source = $groupInstance
$RelationshipInstance.Target = $serverInstance

$DiscData.AddInstance($RelationshipInstance)
}

$discData

The following script need to be used in a TimedPowerShellDiscovery inside SCOM. Before we can create the discovery we need to define a target for the discovery. I decided to use my All Management Servers Resource pool as a target. This means that my discovery is high available through the resource pools technology. The following XML code will define this discovery

<Discovery ID="ACS.Security.Alerting.LogonEvent.Group.AD.DiscoveryRule" Enabled="true" Target="SC!Microsoft.SystemCenter.RootManagementServer" ConfirmDelivery="false" Remotable="true" Priority="Normal">
<Category>Discovery</Category>
<DiscoveryTypes>
<DiscoveryClass TypeID="ACS.Security.Alerting.LogonEvent.Group.AD" />
</DiscoveryTypes>
<DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider">
<IntervalSeconds>900</IntervalSeconds>
<SyncTime />
<ScriptName>AD_GroupDiscovery_check.ps1</ScriptName>
<ScriptBody>
<![CDATA[
# AD_GroupDiscovery_check.ps1
# Written by Arjan Vroege. All rights reserved.
param($SourceID, $ManagedEntityID)
$scomapi  = new-object -comObject "MOM.ScriptAPI"
$DiscData = $scomapi.CreateDiscoveryData(0, $SourceID, $ManagedEntityID)
$scomapi.LogScriptEvent("AD_GroupDiscovery_check.ps1",101,2, "Discovery was executed")
$groupInstance = $DiscData.CreateClassInstance("$MPElement[Name='ACS.Security.Alerting.LogonEvent.Group.AD']$")
$groupmembers  = Get-ADGroupMember -Identity "Res-ApplicationServers"
foreach($member in $groupmembers) {
$DNSHostName    = Get-ADComputer -Filter 'Name -eq $member.Name' | Select -Expand DNSHostName
$scomapi.LogScriptEvent("AD_GroupDiscovery_check.ps1",101,2, "Instance $DNSHostName")
$serverInstance = $DiscData.CreateClassInstance("$MPElement[Name='Windows!Microsoft.Windows.Computer']$")
$serverInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $DNSHostName)
$RelationshipInstance = $DiscData.CreateRelationshipInstance("$MPElement[Name='ACS.Security.Alerting.LogonEvent.Group.AD.Contains.Windows.Computer']$")
$RelationshipInstance.Source = $groupInstance
$RelationshipInstance.Target = $serverInstance
$DiscData.AddInstance($RelationshipInstance)
}
$discData
]]>
</ScriptBody>
<Parameters>
<Parameter>
<Name>sourceId</Name>
<Value>$MPElement$</Value>
</Parameter>
<Parameter>
<Name>managedEntityId</Name>
<Value>$Target/Id$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>300</TimeoutSeconds>
<StrictErrorHandling>true</StrictErrorHandling>
</DataSource>
</Discovery>

 

Now we have defined all the information we need to create a management pack with a SCOM group based on an Active Directory group.

This Management Pack is published on the Technet Gallery

15 thoughts on “SCOM 2012: SCOM Groups based on AD Groups (PowerShell)

  1. Arjan, Your post was very timely, as I’ve been struggling to accomplish exactly this by adapting several different scripts I’ve found. Most of the available info is for SCOM 2007, and we’re on 2012. Could you please send me a full copy of the code?

    • Arjan Vroege

      Have send you an full copy of the Management Pack. If you need any assistance please let me know.

      Regards, Arjan

  2. Martin

    Hello Arjan,

    Trying to schedule maintenance mode for wsus updates, and since all patching is done based on ad groups, this could be what i am looking for. Could you please send me a mp i can test?

  3. Paul Hart

    Arjan,

    I too have been looking for a way to create groups based on AD Groups. I would appreciate it if you would send me a copy of the MS as well.

    Thanks
    Paul H

    • Arjan Vroege

      Hi Paul,
      I’ve send you the MP and instructions. Please let me know if you need anything.
      Regards, Arjan

  4. Joshua

    Thank Arjan, could you send me a full copy of the MP guessing I have some ordering messedup when I tried applying this.

  5. Tarkan

    Hi Arjan,
    can you send me the MP for validation purposes. Thanks

    I have adjusted the script with the following entries:
    $objtarget=””
    $Filter = “(&(objectCategory=group)(Name=$objtarget))”
    $Searcher = [adsiSearcher]($Filter)
    $colResults=$Searcher.Findone()

    foreach ($i in $colResults.properties.member)
    {
    $filter = “(&(objectCategory=computer)(distinguishedname=$i))”
    $Searcher = [adsiSearcher]($Filter)
    $objcomputer=$Searcher.Findall()

    $DNSHostName=$objcomputer.Properties.dnshostname

    #$scomapi.LogScriptEvent(“AD_GroupDiscovery_check.ps1”,101,2, “Instance $DNSHostName”)

    $serverInstance = $DiscData.CreateClassInstance(“$MPElement[Name=’Windows!Microsoft.Windows.Computer’]$”)
    $serverInstance.AddProperty(“$MPElement[Name=’Windows!Microsoft.Windows.Computer’]/PrincipalName$”, $DNSHostName)

    $RelationshipInstance = $DiscData.CreateRelationshipInstance(“$MPElement[Name=’ACS.Security.Alerting.LogonEvent.Group.AD.Contains.Windows.Computer’]$”)
    $RelationshipInstance.Source = $groupInstance
    $RelationshipInstance.Target = $serverInstance

    $DiscData.AddInstance($RelationshipInstance)
    }

  6. Michael Winkenbach

    Hello Arjan,

    did you post your Management Pack on Technet? I did not found it.
    It would be nice if you could send me the link or your Management Pack.

    Thank you. Regards,

    Michael

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.