8th May 2019
Configure rights on WMI for monitoring
If you have PRTG and want to monitor thru wmi i´ve put together a guide based on two scripts (not created by me) what you need to do….
- You need an service-account in your domain, not with domain-admin-rights, only a domain user.
- You need two scripts (se later in blogpost) to add service-account to two local groups on the windows server and to add the service-account to have read-rights in wmi.
- When you run the scripts you need to be a admin-user on the server/servers you want to add the service-account.
You need both scripts från Niklas Åkerlund to automate the “adding” of service-account to local group and wmi-namespace.
The way to use the scripts…
You can use it with a script (se below) or you can use it by one-liner, your choice…
One-liners…
Add user to wmi root
1 |
Set-WMINamespaceSecurity -namespace root -operation add -account "domain\serviceaccount" -permissions enable,remoteaccess -allowInherit $true -computer Servername |
Remove user from wmi root
1 |
Set-WMINamespaceSecurity -namespace root -operation remove "domain\serviceaccount" -computer server -allowInherit $true |
Add user to local groups
1 |
Set-UserLocalGroup -Computer servername -Group "Distributed COM Users","Performance Monitor Users" -Domain domain -User serviceaccount -add |
Remove user from local groups
1 |
Set-UserLocalGroup -Computer servername -Group "Distributed COM Users","Performance Monitor Users" -Domain domain -User serviceaccount -remove |
Script
This script require a txt-fil with the servers you what to add the serviceaccount to local groups and wmi root.
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 |
<# .Synopsis Script to add serviceaccount to localgroups and set security on wmi. .DESCRIPTION When you need to add security for a serviceaccount on server/servers for monitoring thru ex. PRTG. .EXAMPLE You need to this script and three other files in the same folder. - servers.txt - a list of servers on which you need to modify the security - Set-UserLocalGroup.ps1 - the script for adding account to local groups - Set-WmiNamespaceSecurity - the script for modifying the security in wmi .EXAMPLE Another example of how to use this workflow .NOTES You need to verify the names on the local groups you want to modify. The script is based on OS with english names. If you need to add to local groups on ex. swedish OS the script will fail because the names of the groups doesn´t match. ************************************************************** Created: 2019-05-08 Version: 1.0 Disclaimer: This script is provided "AS IS" with no warranties Author - Christian Damberg Twitter: @DambergC Blog : https://www.damberg.org ************************************************************** #> #parameters in the script to be used $servers = Get-Content .\servers.txt $DomainName = 'our domainname' $Serviceaccount = 'your serviceaccount' $LocalGroups = "Distributed COM Users","Performance Monitor Users" # add functions to call .\Set-UserLocalGroup.ps1 .\Set-WmiNamespaceSecurity.ps1 foreach ($servername in $Servers) { Set-WMINamespaceSecurity -namespace root -operation add "$DomainName\$ServiceAccount" -permissions Enable,RemoteAccess -computer $serverName -allowInherit $true foreach ($groups in $localgroups) { Set-UserLocalGroup -Computer $servername -Group $groups -Domain $DomainName -User $Serviceaccount -add } } |
The first script did i found at Niklas Åkerlunds site https://vniklas.djungeln.se.
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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# Copyright (c) Microsoft Corporation. All rights reserved. # For personal use only. Provided AS IS and WITH ALL FAULTS. # Set-WmiNamespaceSecurity.ps1 # Example to add various security permissions to root of namespace and inherit to all subnamespaces # Set-WmiNamespaceSecurity root add steve MethodExecute,Enable,RemoteAccess,ReadSecurity -allowInherit $true # # MethodExecute = Execute Methods # FullWrite = Full Write # PartialWrite = Partial Write # ProviderWrite = Provider Write # Enable = Enable Account # RemoteAccess = Remote Enable # ReadSecurity = Read Security # WriteSecurity = Edit Security # # -allowInherit $true|$false = allow inheritance of the settings to subnamespaces # Function Set-WmiNamespaceSecurity { Param ( [parameter(Mandatory=$true,Position=0)][string] $namespace, [parameter(Mandatory=$true,Position=1)][string] $operation, [parameter(Mandatory=$true,Position=2)][string] $account, [parameter(Position=3)][string[]] $permissions = $null, [bool] $allowInherit = $false, [bool] $deny = $false, [string] $computerName = ".", [System.Management.Automation.PSCredential] $credential = $null) Process { $ErrorActionPreference = "Stop" Function Get-AccessMaskFromPermission($permissions) { $WBEM_ENABLE = 1 $WBEM_METHOD_EXECUTE = 2 $WBEM_FULL_WRITE_REP = 4 $WBEM_PARTIAL_WRITE_REP = 8 $WBEM_WRITE_PROVIDER = 0x10 $WBEM_REMOTE_ACCESS = 0x20 $WBEM_RIGHT_SUBSCRIBE = 0x40 $WBEM_RIGHT_PUBLISH = 0x80 $READ_CONTROL = 0x20000 $WRITE_DAC = 0x40000 $WBEM_RIGHTS_FLAGS = $WBEM_ENABLE,$WBEM_METHOD_EXECUTE,$WBEM_FULL_WRITE_REP,` $WBEM_PARTIAL_WRITE_REP,$WBEM_WRITE_PROVIDER,$WBEM_REMOTE_ACCESS,` $READ_CONTROL,$WRITE_DAC $WBEM_RIGHTS_STRINGS = "Enable","MethodExecute","FullWrite","PartialWrite",` "ProviderWrite","RemoteAccess","ReadSecurity","WriteSecurity" $permissionTable = @{} for ($i = 0; $i -lt $WBEM_RIGHTS_FLAGS.Length; $i++) { $permissionTable.Add($WBEM_RIGHTS_STRINGS[$i].ToLower(), $WBEM_RIGHTS_FLAGS[$i]) } $accessMask = 0 foreach ($permission in $permissions) { if (-not $permissionTable.ContainsKey($permission.ToLower())) { throw "Unknown permission: $permission`nValid permissions: $($permissionTable.Keys)" } $accessMask += $permissionTable[$permission.ToLower()] } $accessMask } if ($PSBoundParameters.ContainsKey("Credential")) { $remoteparams = @{ComputerName=$computer;Credential=$credential} } else { $remoteparams = @{ComputerName=$computerName} } $invokeparams = @{Namespace=$namespace;Path="__systemsecurity=@"} + $remoteParams $output = Invoke-WmiMethod @invokeparams -Name GetSecurityDescriptor if ($output.ReturnValue -ne 0) { throw "GetSecurityDescriptor failed: $($output.ReturnValue)" } $acl = $output.Descriptor $OBJECT_INHERIT_ACE_FLAG = 0x1 $CONTAINER_INHERIT_ACE_FLAG = 0x2 $computerName = (Get-WmiObject @remoteparams Win32_ComputerSystem).Name if ($account.Contains('\')) { $domainaccount = $account.Split('\') $domain = $domainaccount[0] if (($domain -eq ".") -or ($domain -eq "BUILTIN")) { $domain = $computerName } $accountname = $domainaccount[1] } elseif ($account.Contains('@')) { $domainaccount = $account.Split('@') $domain = $domainaccount[1].Split('.')[0] $accountname = $domainaccount[0] } else { $domain = $computerName $accountname = $account } $getparams = @{Class="Win32_Account";Filter="Domain='$domain' and Name='$accountname'"} $win32account = Get-WmiObject @getparams if ($win32account -eq $null) { throw "Account was not found: $account" } switch ($operation) { "add" { if ($permissions -eq $null) { throw "-Permissions must be specified for an add operation" } $accessMask = Get-AccessMaskFromPermission($permissions) $ace = (New-Object System.Management.ManagementClass("win32_Ace")).CreateInstance() $ace.AccessMask = $accessMask if ($allowInherit) { # #https://www.reddit.com/r/PowerShell/comments/4cwaow/help_with_wmi_namespace_security_inheritance/ #$ace.AceFlags = $OBJECT_INHERIT_ACE_FLAG + $CONTAINER_INHERIT_ACE_FLAG $ace.AceFlags = $CONTAINER_INHERIT_ACE_FLAG # } else { $ace.AceFlags = 0 } $trustee = (New-Object System.Management.ManagementClass("win32_Trustee")).CreateInstance() $trustee.SidString = $win32account.Sid $ace.Trustee = $trustee $ACCESS_ALLOWED_ACE_TYPE = 0x0 $ACCESS_DENIED_ACE_TYPE = 0x1 if ($deny) { $ace.AceType = $ACCESS_DENIED_ACE_TYPE } else { $ace.AceType = $ACCESS_ALLOWED_ACE_TYPE } $acl.DACL += $ace.psobject.immediateBaseObject } "delete" { if ($permissions -ne $null) { throw "Permissions cannot be specified for a delete operation" } [System.Management.ManagementBaseObject[]]$newDACL = @() foreach ($ace in $acl.DACL) { if ($ace.Trustee.SidString -ne $win32account.Sid) { $newDACL += $ace.psobject.immediateBaseObject } } $acl.DACL = $newDACL.psobject.immediateBaseObject } default { throw "Unknown operation: $operation`nAllowed operations: add delete" } } $setparams = @{Name="SetSecurityDescriptor";ArgumentList=$acl.psobject.immediateBaseObject} + $invokeParams $output = Invoke-WmiMethod @setparams if ($output.ReturnValue -ne 0) { throw "SetSecurityDescriptor failed: $($output.ReturnValue)" } } } |
The second script did i found at Niklas Åkerlunds site https://vniklas.djungeln.se.
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 |
# Add/Remove user from local group # # Niklas Akerlund/Most code from Scriptingguy Blog http://blogs.technet.com/b/heyscriptingguy/archive/2010/08/19/use-powershell-to-add-domain-users-to-a-local-group.aspx Function Set-UserLocalGroup { [cmdletBinding()] Param( [Parameter(Mandatory=$True)] [string]$Computer, [Parameter(Mandatory=$True)] [string]$Group, [Parameter(Mandatory=$True)] [string]$Domain, [Parameter(Mandatory=$True)] [string]$User, [switch]$add, [switch]$remove ) $de = [ADSI]"WinNT://$Computer/$Group,group" if($add){ $de.psbase.Invoke("Add",([ADSI]"WinNT://$Domain/$User").path) } elseif ($remove){ $de.psbase.Invoke("Remove",([ADSI]"WinNT://$Domain/$User").path) } } |