# Copyright (c) Microsoft Corporation. All rights reserved. | |
# For personal use only. Provided AS IS and WITH ALL FAULTS. | |
# Set-WmiNamespaceSecurity.ps1 | |
# Example: Set-WmiNamespaceSecurity root/cimv2 add steve Enable,RemoteAccess | |
# https://blogs.msdn.microsoft.com/wmi/2009/07/27/scripting-wmi-namespace-security-part-3-of-3/ | |
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 = @{} | |
} | |
$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 | |
$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'"} + $remoteParams | |
$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 | |
$CONTAINER_INHERIT_ACE_FLAG = 0x2 | |
if ($allowInherit) { | |
$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)" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment