Solving the problem of automated distribution of credentials (literal expression)
This is a continuation of a previous post. The only difference is this accepts a literal expression, rather than a group system name.
As with the other script example, there is no reverse action. If you specify a group that contains hundreds of windows computer objects and it was a mistake, you'll have to manually delete hundreds of health service instances from your secure distribution in the Run As Account.
The script accepts the below parameters – all are required. First set of variables (with a “$”) can be uncommented if executing without parameters, and the second set (with a “-“) is an example of parameter format you would specify if running with parameter names.
# $RootManagementServer = "srvrms01"
# $DatabaseServer = "srvsql01"
# $DatabaseName = "OperationsManager"
# $Expression = "FQDN like '%hyper%'"
# $Account = "Test Run As Account"
# $BinariesFolder = "C:\Program Files\System Center Operations Manager 2007\SDK Binaries"
# -RootManagementServer srvrms01
# -DatabaseServer srvsql01
# -DatabaseName OperationsManager
# -Expression "FQDN like '%hyper%'"
# -Account "Test Run As Account"
# -BinariesFolder "f:\Program Files\System Center Operations Manager 2007\SDK Binaries"
# -Debug true
param($RootManagementServer, $DatabaseServer, $DatabaseName, $Expression, $Account, $BinariesFolder, $DebugFlag) #Local
#-------------------------------------------------------------------------------------Start Main
# This function controls program flow.
function Main
{
$CollectionHSIDs = CreateCollectionHSIDs
ValidateSnapIn
$MG = ConnectToManagementGroup
$CollectionHSOs = CreateCollectionHSOs
$NumInstances = $CollectionHSOs.Count
LoadHelperClass
AddHealthServiceToAccountDistributionList
Remove-ManagementGroupConnection $RootManagementServer
QuitScript $QuitSuccess "Workflow completed successfully."
}#------------------------------------------------------------------------------------End Main
#-------------------------------------------------------------------------------------Start AddHealthServiceToAccountDistributionList
# This function adds health service instances to the Run As Account distribution list.
function AddHealthServiceToAccountDistributionList
{
# Add health service objects to Run As Account distribution list.
$data = $MG.ManagementGroup.GetMonitoringSecureData() | Where-Object {$_.Name -eq $Account}
[Helper]::ApproveCredentialForDistribution($MG.ManagementGroup, $data, $CollectionHSOs)
if ($DebugFlag) {DebugEvent "Sequence 6 - Completed function AddHealthServiceToAccountDistributionList"}
}#------------------------------------------------------------------------------------End AddHealthServiceToAccountDistributionList
#-------------------------------------------------------------------------------------Start CreateCollectionHSIDs
# This function queries the operational database for members of the specified windows
# computer group and resolves the health service id of those instances. Then adds
# those health service id's to a collection.
# The use of system.data.sqlclient.sqlconnection requires Windows Server 2003 SP2+,
# Windows Server 2008 or Windows Server 2008 R2 (except core editions).
function CreateCollectionHSIDs
{
# Setup the SQL connection
$connection = new-object system.data.sqlclient.sqlconnection("Data Source=$DatabaseServer;Initial Catalog=$DatabaseName;Integrated Security=SSPI;");
# Define TSQL
[string]$query =
"
/*
Get Health Service IDs
Based on literal expression
*/
SELECT distinct ME.Id AS 'HSID'
from ManagedEntityGenericView AS ME INNER JOIN
ManagedTypeView AS MT ON ME.MonitoringClassId = MT.Id INNER JOIN
RelationshipGenericView AS REL ON ME.DisplayName = REL.TargetMonitoringObjectDisplayName
where MT.Name = 'Microsoft.SystemCenter.HealthService' AND
ME.IsDeleted <> 1 AND
($Expression)
"
# Create the dataset
$execute = new-object system.data.sqlclient.sqldataadapter ($query, $connection)
$dataset = new-object system.data.dataset
$execute.Fill($dataset) | Out-Null #speeds processing
# Create an empty collection
[System.Collections.ArrayList]$CollectionHSIDs = @()
# Add each row in dataset to the collection
foreach ($row in $dataset.Tables[0])
{
$CollectionHSIDs.Add($row) | Out-Null #speeds processing
}
if ($DebugFlag) {DebugEvent "Sequence 1 - Completed function CreateCollectionHSIDs"}
# Pass collection to main script.
return $CollectionHSIDs
}#------------------------------------------------------------------------------------End CreateCollectionHSIDs
#-------------------------------------------------------------------------------------Start CreateCollectionHSOs
# This function adds health service objects to a collection.
function CreateCollectionHSOs
{
# Create an empty collection.
[System.Collections.ArrayList]$CollectionHSOs = @()
# Add each Health Service instance to the collection.
foreach ($HSID in $CollectionHSIDs)
{
$CollectionHSOs.Add((Get-MonitoringObject -Id $HSID.HSID.ToString())) | Out-Null #speeds processing
}
if ($DebugFlag) {DebugEvent "Sequence 4 - Completed function CreateCollectionHSOs"}
# Pass collection to main script.
return $CollectionHSOs
}#------------------------------------------------------------------------------------End CreateCollectionHSOs
#-------------------------------------------------------------------------------------Start LoadHelperClass
# This function is used to test and load the helper class that enables distribution.
function LoadHelperClass
{
# Create variable to test whether type is already added.
$b=$false
$b = Get-Type ([helper])
trap [exception] {continue} #always throws exception if class isn't added.
# Add Type Definition for helper class if not already added
if (!$b)
{
Add-Type –typedefinition $src -ReferencedAssemblies ($BinariesFolder + "\Microsoft.EnterpriseManagement.OperationsManager.dll"), 'System.Xml'
# Create variable to test whether type is already added.
$b = Get-Type ([helper])
trap [exception] {continue} #always throws exception if class isn't added.
if (!$b)
{
QuitScript $QuitFailure "Error in function LoadHelperClass: Unable to load helper class."
}
}
if ($DebugFlag) {DebugEvent "Sequence 5 - Completed function LoadHelperClass"}
# Recycle variable
Remove-Variable b
}#------------------------------------------------------------------------------------End LoadHelperClass
#-------------------------------------------------------------------------------------Start AddAccountToProfile
# This function associates Run As Account to Run As Profile.
function AddAccountToProfile
{
# This function not being used at this time.
}#------------------------------------------------------------------------------------End AddAccountToProfile
#-------------------------------------------------------------------------------------Start ValidateSnapIn
# This function is used to test and load the OM snapin.
function ValidateSnapIn
{
# Create a variable to hold OM snapin
$b=$false
$b = Get-PSSnapin | Where-Object {$_.Name -like "*Microsoft.EnterpriseManagement.OperationsManager.Client*"}
# Test variable. If empty, add OM snapin.
if (!$b)
{
Add-PSSnapin -Name "Microsoft.EnterpriseManagement.OperationsManager.Client"
# Refresh variable after snapin load attempt.
$b = Get-PSSnapin | Where-Object {$_.Name -like "*Microsoft.EnterpriseManagement.OperationsManager.Client*"}
# If snapin failed to load, quit script - cannot move forward.
if (!$b)
{
QuitScript $QuitFailure "Error in function ValidateSnapIn: Unable to load OM snapin."
}
}
if ($DebugFlag) {DebugEvent "Sequence 2 - Completed function ValidateSnapin"}
# Recycle variable
Remove-Variable -Name b
}#------------------------------------------------------------------------------------End ValidateSnapIn
#-------------------------------------------------------------------------------------Start ConnectToManagementGroup
# This function is used to connect to the root management server and set location.
function ConnectToManagementGroup
{
# Create variable to hold connection.
$b = (Get-ManagementGroupConnection).ManagementServerName
# Test variable. If empty, attempt to create the connection.
if ($b -ne $RootManagementServer)
{
$NewConnection = New-ManagementGroupConnection -ConnectionString:$RootManagementServer
# Refresh variable after connection attempt.
$b = (Get-ManagementGroupConnection).ManagementServerName
# If still unable to connect, quit script - cannot move forward.
if ($b -ne $RootManagementServer)
{
QuitScript $QuitFailure "Error in function ConnectToManagementGroup: Unable to establish connection to $RootManagementServer."
}
# Now that we have a connection, set location to OM monitoring drive.
Set-Location "OperationsManagerMonitoring::"
}
else
{
# Perhaps connection already existed, so we'll just move on.
$NewConnection = Get-ManagementGroupConnection
Set-Location "OperationsManagerMonitoring::"
}
if ($DebugFlag) {DebugEvent "Sequence 3 - Completed function ConnectToManagementGroup"}
# Recycle variable
Remove-Variable -Name b
return $NewConnection
}#------------------------------------------------------------------------------------End ConnectToManagementGroup
#-------------------------------------------------------------------------------------Start QuitScript
# This function is used to set error levels and return details.
function QuitScript ($Level, $Detail)
{
if ($Level -eq 1)
{
$Message = "$Detail Account distribution failed for $Account."
Write-EventLog -LogName Application -Source OM-SecureDist -EventID 100 -EntryType Error -Message $Message
exit
}
else
{
$Message = "$Detail Distribution occurred for $Account for $NumInstances health service instance(s)."
Write-EventLog -LogName Application -Source OM-SecureDist -EventID 100 -EntryType Information -Message $Message
exit
}
}#------------------------------------------------------------------------------------End QuitScript
#-------------------------------------------------------------------------------------Start DebugEvent
# This function is used to write debug events.
function DebugEvent ($Detail)
{
$Message = "$Account : $Detail"
Write-EventLog -LogName Application -Source OM-SecureDist -EventID 101 -EntryType Information -Message $Message
}#------------------------------------------------------------------------------------End DebugEvent
#-------------------------------------------------------------------------------------Start Get-Type
# This function is used to test whether the helper class has been added.
# Successfully detects when type is added, but throws exception when it's not.
# https://solutionizing.net/2009/01/01/powershell-get-type-simplified-generics/
function global:Get-Type ($type = $(Throw "Please specify a type"))
{
trap [System.Management.Automation.RuntimeException] { Throw ($_.Exception.Message) }
if ($Args -and $Args.Count -gt 0)
{
$types = $Args[0] -as [type[]]
if (-not $types)
{
$types = [type[]] $Args
}
if ($genericType = [type] ($type + '`' + $types.Count))
{
$genericType.MakeGenericType($types)
}
}
else
{
[type] $type
}
}#------------------------------------------------------------------------------------End Get-Type
#-------------------------------------------------------------------------------------Start variables
# Set variables
$QuitFailure = 1
$QuitSuccess = 0
# Source for helper class
$src = @"
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Monitoring;
using System.Collections.Generic;
public class Helper {
public static void ApproveCredentialForDistribution(ManagementGroup mg, ISecuredData credential, MonitoringObject[] targets) {
mg.ApproveCredentialForDistribution<MonitoringObject>(credential, new List<MonitoringObject>(targets));
}
}
"@
# Set Debug Flag
if ($DebugFlag -and $DebugFlag -ne "true")
{
Remove-Variable DebugFlag
}
# Fix Expression Filter
$Expression = $Expression.Replace("FQDN", "ME.DisplayName")
#-------------------------------------------------------------------------------------End variables
#-------------------------------------------------------------------------------------Start EventLogSourceCheck
# Check if the OM-SecureDist source has been added to the Operations Manager log.
$b=$false
$b=[system.diagnostics.eventlog]::SourceExists("OM-SecureDist")
trap [Exception] {continue}
if (!$b)
{
# Create the source if it doesn't exist.
# Requires elevated privileges.
New-EventLog -Source OM-SecureDist -LogName Application
}
# Recycle variable
Remove-Variable b
#-------------------------------------------------------------------------------------End EventLogSourceCheck
#-------------------------------------------------------------------------------------Start variables for local runtime
# $RootManagementServer = "srvrms01"
# $DatabaseServer = "srvsql01"
# $DatabaseName = "OperationsManager"
# $Expression = "FQDN like '%hyper%'"
# $Expression = $Expression.Replace("FQDN", "ME.DisplayName")
# $Account = "Test Run As Account"
# $BinariesFolder = "C:\Program Files\System Center Operations Manager 2007\SDK Binaries"
# -RootManagementServer srvrms01
# -DatabaseServer srvsql01
# -DatabaseName OperationsManager
# -Group Microsoft.SystemCenter.AllComputersGroup
# -Account "Test Run As Account"
# -BinariesFolder "f:\Program Files\System Center Operations Manager 2007\SDK Binaries"
# -Debug true
#-------------------------------------------------------------------------------------End variables for local runtime
#-------------------------------------------------------------------------------------Start main program
Main
Always test scripts you find on the internet before implementing in production.
Also see the other one if you want to use group criteria.
Comments
- Anonymous
October 05, 2011
The comment has been removed