# Set WMI Namespace Sec-Win2003-2008-Remotely Many servers

**URL:** <https://forums.powershell.org/t/set-wmi-namespace-sec-win2003-2008-remotely-many-servers/2059>\
**Category:** PowerShell Help\
**Created:** [November 12, 2013, 4:34pm UTC](https://forums.powershell.org/t/set-wmi-namespace-sec-win2003-2008-remotely-many-servers/2059 "2013-11-12T16:34:30Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jake-sully](https://avatars.discourse-cdn.com/v4/letter/j/848f3c/32.png) [@jake-sully](https://forums.powershell.org/u/jake-sully)\
**Post date:** [November 12, 2013, 4:34pm UTC](https://forums.powershell.org/t/set-wmi-namespace-sec-win2003-2008-remotely-many-servers/2059/1 "2013-11-12T16:34:30Z")

</div>

Howdy - I posted a question here last week and found out that what I was trying to use for a script that I found MS posted was not valid for Windows 2003 because the Security Descriptor is not available. Instead of wasting anyone’s time I thought a new request for help would be better.

I wanted to ask anyone if they could help me with a new script that would do what I need to set WMI Namespace permissions for a service account on root\cimv2 and if possible do this on 2003, 2008, 2008r2, and even 2012 if that’s possible?

I have tried doing things found in several articles and haven’t had any luck at all. The best thing I found was the script below which states it works on 2003 but I haven’t tested it because I want to remove the items it sets for DCOM permissions but I’m not sure what they are? Then if I remove them I’m sure I’ll break the WMI portion which I need. Can someone help me possibly set this so it only sets the permissions required on root\cimv2 for servers, I have the systems in a list, obviously I can use csv or txt, but I was thinking it would be great to run this against the domain and do a search for 2003, 2008, 2008r2, and then based on the results run the proper commands to set the permissions using the right commands. The service account is for a monitoring application and it states that the WMI access required is:  
Enable Account  
Remote Enable

For the groups it has to be a member of dist com users, perf log users, and per mon users, but I’m using a gpo for that part. For standalone servers I wanted to have this script either determine the domain or even a separate script that would create a regular “user” account on the system, set the pwd, set it to never expire, set it to “user cant change pwd”, and then add it to the groups. What’s the best way to handle these systems?

`function get-sid
{
Param (
$DSIdentity
)
$ID = new-object System.Security.Principal.NTAccount($DSIdentity)
return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString()
}
$sid = get-sid “local\maxsmart”
$SDDL = “A;;CCWP;;;$sid”
$DCOMSDDL = “A;;CCDCRP;;;$sid”
$computers = Get-Content “computers.txt”
foreach ($strcomputer in $computers)
{
$Reg = [WMIClass]“\$strcomputer\root\default:StdRegProv”
$DCOM = $Reg.GetBinaryValue(2147483650,“software\microsoft\ole”,“MachineLaunchRestriction”).uValue
$security = Get-WmiObject -ComputerName $strcomputer -Namespace root/cimv2 -Class __SystemSecurity
$converter = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper
$binarySD = @($null)
$result = $security.PsBase.InvokeMethod(“GetSD”,$binarySD)
$outsddl = $converter.BinarySDToSDDL($binarySD[0])
$outDCOMSDDL = $converter.BinarySDToSDDL($DCOM)
$newSDDL = $outsddl.SDDL += “(” + $SDDL + “)”
$newDCOMSDDL = $outDCOMSDDL.SDDL += “(” + $DCOMSDDL + “)”
$WMIbinarySD = $converter.SDDLToBinarySD($newSDDL)
$WMIconvertedPermissions = ,$WMIbinarySD.BinarySD
$DCOMbinarySD = $converter.SDDLToBinarySD($newDCOMSDDL)
$DCOMconvertedPermissions = ,$DCOMbinarySD.BinarySD
$result = $security.PsBase.InvokeMethod(“SetSD”,$WMIconvertedPermissions)
$result = $Reg.SetBinaryValue(2147483650,“software\microsoft\ole”,“MachineLaunchRestriction”, $DCOMbinarySD.binarySD)
}`

---

<div class="post-metadata">

**Author:** ![donj](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/donj/32/137_2.png) [@donj](https://forums.powershell.org/u/donj)\
**Post date:** [November 13, 2013, 4:32am UTC](https://forums.powershell.org/t/set-wmi-namespace-sec-win2003-2008-remotely-many-servers/2059/2 "2013-11-13T04:32:42Z")

</div>

So… I’m sorry, I don’t think I’m following what the question is.

How do I \_\_\_\_\_\_\_\_?

Fill in the blank?

---

<div class="post-metadata">

**Author:** ![jake-sully](https://avatars.discourse-cdn.com/v4/letter/j/848f3c/32.png) [@jake-sully](https://forums.powershell.org/u/jake-sully)\
**Post date:** [November 13, 2013, 5:39pm UTC](https://forums.powershell.org/t/set-wmi-namespace-sec-win2003-2008-remotely-many-servers/2059/3 "2013-11-13T17:39:29Z")

</div>

Don -  
Your response is much appreciated

"How do I modify the script above to remove the parts that set the “DCOM” permissions?

“How do I set the WMI namespace permissions on root\cimv2 for the required 2 permissions, Remote Enable, Enable Account”?

How can I search the AD domain for the OS version and run this on 2003 servers and then what will work to set the same permissions on 2008/2008r/, and 2012? What I would like to do is have 1 script that could be run against either a list of servers or modified to search AD for server OS types, detect the version and then set the permissions. As I mentioned, I don’t want to modify the DCOM access when I’m adding the account to the DCOM users group as that’s redundant, and a gpo is a better method to centralize the permissions.

I did find a script I posed in the 1st post which works on 2008/2008r2 but not on 2003, and I could not find anyway to get it to work on 2003, not combine that with this script which should work on 2003. I have no idea what in this script is setting DCOM access, I’ve read through it and understand quite a bit, but I can’t narrow down the WMI vs DCOM settings being applied in terms of what is needed to set WMI access.

By the way, I just joined CBT and your new videos are great!! I’ve gotten many scripts written, although basic, they work and when I share them they are apparently done right and commented well, so I’m learning!

---

<div class="post-metadata">

**Author:** ![donj](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/donj/32/137_2.png) [@donj](https://forums.powershell.org/u/donj)\
**Post date:** [November 14, 2013, 2:05am UTC](https://forums.powershell.org/t/set-wmi-namespace-sec-win2003-2008-remotely-many-servers/2059/4 "2013-11-14T02:05:05Z")

</div>

So, the one thing I can probably help with is getting the OS version. AD obviously keeps that in an attribute, and if you’re using Get-ADComputer, you can specify a -Filter or -LdapFilter that limits the results to just those computers of a particular OS. Or, you can use -Property to make sure that attribute comes down in the results, and then filter it in a Where clause, or build a Switch construct to take a different action for each OS.

The other two, dunno - but I’ve asked our resident WMI expert to have a look at this topic.

And thanks for joining CBT ;). They’re great to work with from my end, and a big chunk of your fee really helps us trainers pay the mortgage, so it’s very much appreciated.

---

<div class="post-metadata">

**Author:** ![richard-siddaway](https://avatars.discourse-cdn.com/v4/letter/r/d78d45/32.png) [@richard-siddaway](https://forums.powershell.org/u/richard-siddaway)\
**Post date:** [November 14, 2013, 7:06am UTC](https://forums.powershell.org/t/set-wmi-namespace-sec-win2003-2008-remotely-many-servers/2059/5 "2013-11-14T07:06:20Z")

</div>

I think the best way to approach this is to try and step through the code determining what each line, or group of lines, does.

`
function get-sid { 
Param ( $DSIdentity ) 
$ID = new-object System.Security.Principal.NTAccount($DSIdentity) 
return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString() 
} 
$sid = get-sid "local\maxsmart"
` This defines a function to get the SID of an account which looks something like this S-1-5-21-2408039147-2416000835-5500772448-1009

$SDDL = “A;;CCWP;;;$sid”  
$DCOMSDDL = “A;;CCDCRP;;;$sid”

Are Security Dexcriptor Definition Language ACE definitions where  
A = allow  
CC = create child  
WP = write property  
DC = delete child  
RP = read property

More info can be found here [http://msdn.microsoft.com/en-us/library/aa374928(v=vs.85).aspx](http://msdn.microsoft.com/en-us/library/aa374928(v=vs.85).aspx)

$computers = Get-Content “computers.txt”  
foreach ($strcomputer in $computers) {

reads a list of computers and loops through them

$Reg = [WMIClass]“\$strcomputer\root\default:StdRegProv”  
$DCOM = $Reg.GetBinaryValue(2147483650,“software\microsoft\ole”,“MachineLaunchRestriction”).uValue

“creates” an instance of the StdRegprov class to read the registry and reads the given key  
this part appears to be for DCOM

$security = Get-WmiObject -ComputerName $strcomputer -Namespace root/cimv2 -Class \_\_SystemSecurity

gets the \_\_SystemSecurity class which is used for setting permissions on a namespace see:  
[http://msdn.microsoft.com/en-us/library/aa394677(v=vs.85).aspx](http://msdn.microsoft.com/en-us/library/aa394677(v=vs.85).aspx)

$converter = new-object system.management.ManagementClass Win32\_SecurityDescriptorHelper

creates an instance of the Win32\_SecurityDescriptorHelper helper class - could probably have used [wmiclass] here as well

$binarySD = @($null)  
creates an empty array - using $null doesn’t add anything - could just use @()

$result = $security.PsBase.InvokeMethod(“GetSD”,$binarySD)  
Use the GetSD method of \_\_SystemSecurity class to populate the array with the security descriptor data. A much neater way to do this is:  
Invoke-WmiMethod -Class \_\_SystemSecurity -Name GetSD | select -ExpandProperty SD

$outsddl = $converter.BinarySDToSDDL($binarySD[0])  
$outDCOMSDDL = $converter.BinarySDToSDDL($DCOM)  
$newSDDL = $outsddl.SDDL += “(” + $SDDL + “)”  
$newDCOMSDDL = $outDCOMSDDL.SDDL += “(” + $DCOMSDDL + “)”

convert the SD to SSDL and add the extra permissions

$WMIbinarySD = $converter.SDDLToBinarySD($newSDDL)  
$WMIconvertedPermissions = ,$WMIbinarySD.BinarySD  
$DCOMbinarySD = $converter.SDDLToBinarySD($newDCOMSDDL)  
$DCOMconvertedPermissions = ,$DCOMbinarySD.BinarySD

convert the permissions back

$result = $security.PsBase.InvokeMethod(“SetSD”,$WMIconvertedPermissions)  
$result = $Reg.SetBinaryValue(2147483650,“software\microsoft\ole”,“MachineLaunchRestriction”, $DCOMbinarySD.binarySD)

set the permissions

If you read through the code you will see that there are two strands to the processing - one modifies the registry for the DCOM setting and the other works on the name space

If I’ve understood your need correctly you want to just modify the setting on the namespace. I’ve commented out the lines in your code that for the DCOM modification.

**PLEASE TEST THIS VERY, VERY, VERY CAREFULLY**  
`
function get-sid {
Param ( $DSIdentity )
$ID = new-object System.Security.Principal.NTAccount($DSIdentity)
return $ID.Translate( [System.Security.Principal.SecurityIdentifier] ).toString()
}
$sid = get-sid “local\maxsmart”
$SDDL = “A;;CCWP;;;$sid”
#$DCOMSDDL = “A;;CCDCRP;;;$sid”`

`
`

`$computers = Get-Content “computers.txt”
foreach ($strcomputer in $computers) {
#$Reg = [WMIClass]“\$strcomputer\root\default:StdRegProv”
#$DCOM = $Reg.GetBinaryValue(2147483650,“software\microsoft\ole”,“MachineLaunchRestriction”).uValue
$security = Get-WmiObject -ComputerName $strcomputer -Namespace root/cimv2 -Class __SystemSecurity
$converter = new-object system.management.ManagementClass Win32_SecurityDescriptorHelper
$binarySD = @($null)
$result = $security.PsBase.InvokeMethod(“GetSD”,$binarySD)
$outsddl = $converter.BinarySDToSDDL($binarySD[0])
#$outDCOMSDDL = $converter.BinarySDToSDDL($DCOM)
$newSDDL = $outsddl.SDDL += “(” + $SDDL + “)”
#$newDCOMSDDL = $outDCOMSDDL.SDDL += “(” + $DCOMSDDL + “)”
$WMIbinarySD = $converter.SDDLToBinarySD($newSDDL)
$WMIconvertedPermissions = ,$WMIbinarySD.BinarySD
#$DCOMbinarySD = $converter.SDDLToBinarySD($newDCOMSDDL)
#$DCOMconvertedPermissions = ,$DCOMbinarySD.BinarySD
$result = $security.PsBase.InvokeMethod(“SetSD”,$WMIconvertedPermissions)
#$result = $Reg.SetBinaryValue(2147483650,“software\microsoft\ole”,“MachineLaunchRestriction”, $DCOMbinarySD.binarySD)
}
`

**PLEASE TEST THIS VERY, VERY, VERY CAREFULLY**  
DISCLAIMER  
This isn’t something that I normally modify so I’m making a number of assumptions. Modifying permissions on WMI namespaces can have an adverse effect on your machine. The code is supplied as is with no warranty

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [May 16, 2024, 8:56pm UTC](https://forums.powershell.org/t/set-wmi-namespace-sec-win2003-2008-remotely-many-servers/2059/6 "2024-05-16T20:56:51Z")

</div>


