DSCResources/xCIMSecurity/xCIMSecurity.psm1
#region helper #region GetAccessMask Function GetAccessMask { param ( [Parameter(Mandatory = $true)] [ValidateSet( "Enable", "MethodExecute", "FullWrite", "PartialWrite", "ProviderWrite", "RemoteAccess", "Subscribe", "Publish", "ReadSecurity", "WriteSecurity" )] [string[]]$Rigth ) [int32]$Mask = 0 foreach ($item in $Rigth) { switch ($item) { "Enable" { $Mask += 1 } "MethodExecute" { $Mask += 2 } "FullWrite" { $Mask += 4 } "PartialWrite" { $Mask += 8 } "ProviderWrite" { $Mask += 16 } "RemoteAccess" { $Mask += 32 } "Subscribe" { $Mask += 60 } "Publish" { $Mask += 128 } "ReadSecurity" { $Mask += 131072 } "WriteSecurity" { $Mask += 262144 } } } $Mask } #endregion #region GetCimSecurity Function GetCimSecurity { param ( $NameSpace ) $Security = Get-CimInstance -Namespace $NameSpace -ClassName "__SystemSecurity" $Descriptor = (Invoke-CimMethod -InputObject $Security -MethodName GetSecurityDescriptor).Descriptor $DACL = $Descriptor.DACL $has = @{} $has.Add("Security", $Security) $has.Add("Descriptor", $Descriptor) $has.Add("DACL", $DACL) $re = New-Object psobject -Property $has $re } #endregion #region GetCustomAllDACL Function GetCustomAllDACL { param ( [ciminstance[]]$Input_CimDACL ) $ALL_DACL = @() foreach ($item in $DACL) { $HAS = @{} $HAS.Add("SID", $item.trustee.sidstring) $HAS.Add("Mask", $item.AccessMask) $HAS.Add("Allow", $item.AceType) $HAS.Add("CIMDACL", $item) $HAS.Add("AceFlags",$item.AceFlags) $re = New-Object psobject -Property $HAS $ALL_DACL += $re } $ALL_DACL } #endregion #GetAccessMask -Rigth Enable, RemoteAccess #region Enum [System.Flags()] Enum RightMask { Enable = 1 MethodExecute = 2 FullWrite = 4 PartialWrite = 8 ProviderWrite = 16 RemoteAccess = 32 Subscribe = 60 Publish = 128 ReadSecurity = 131072 WriteSecurity = 262144 } [System.Flags()] Enum AceFlags { NameSpaceOnly = 0 ChildOnly = 10 WithChild = 2 } #[RightMask][System.Enum]::Parse([type][AccessRight],13) #endregion #region NewACE Function NewACE { param ( [string]$UserSID, [bool]$Allow, [AceFlags]$AceFlags, [RightMask]$Right ) $trustee = New-CimInstance -Namespace root/cimv2 -ClassName Win32_Trustee -ClientOnly -Property ` @{ SidString = $UserSID } $aceparam = @{} $aceparam.Add("Trustee", $trustee) $aceparam.Add("AccessMask", [uint32]([int]$Right)) $aceparam.Add("AceFlags", [uint32]$AceFlags) if ($Allow) { $aceparam.Add("AceType", [uint32]0) } else { $aceparam.Add("AceType", [uint32]1) } $ace = New-CimInstance -Namespace root/cimv2 -ClassName Win32_Ace -ClientOnly -Property $aceparam $ace } #endregion #endregion #region get function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [parameter(Mandatory = $true)] [System.String] $NameSpace, [parameter(Mandatory = $true)] [System.String] $AccountName, [parameter(Mandatory = $true)] [ciminstance[]]$ACL ) #Write-Verbose "Use this cmdlet to deliver information about command processing." #Write-Debug "Use this cmdlet to write debug information while troubleshooting." <# $returnValue = @{ NameSpace = [System.String] AccountName = [System.String] Enusre = [System.String] } $returnValue #> } #endregion #region Set function Set-TargetResource { [CmdletBinding()] param ( [parameter(Mandatory = $true)] [System.String] $NameSpace, [parameter(Mandatory = $true)] [System.String] $AccountName, [parameter(Mandatory = $true)] [ciminstance[]]$ACL ) #Write-Verbose "Use this cmdlet to deliver information about command processing." #Write-Debug "Use this cmdlet to write debug information while troubleshooting." #Include this line if the resource requires a system reboot. #$global:DSCMachineStatus = 1 $ALL_DACL = @() $NTAccount = New-Object "System.Security.Principal.NTAccount" $AccountName $UserSID = $NTAccount.Translate([System.Security.Principal.SecurityIdentifier]).Value $CimSecurity = (GetCimSecurity -NameSpace $NameSpace) $DACL = $CimSecurity.DACL $Security = $CimSecurity.Security $Descriptor = $CimSecurity.Descriptor $ALL_DACL = GetCustomAllDACL -Input_CimDACL $DACL ## all in system $Fileter_Result = @() $ALL_DACL.foreach( { if (!($_.Sid -eq $UserSID)) { $Fileter_Result += $_.CIMDACL } } ) foreach ($item in $ACL) { $Fileter_Result += NewACE -UserSID $UserSID -Allow $item.Allow -AceFlags $item.AceFlags -Right $item.Right Write-Verbose ("add" + $($UserSID) + $( $item.Right) ) } $Descriptor.DACL = $Fileter_Result Write-Verbose ($Fileter_Result.count) Invoke-CimMethod -InputObject $Security -MethodName SetSecurityDescriptor -Arguments @{ Descriptor = $Descriptor} } #endregion #region test function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [parameter(Mandatory = $true)] [System.String] $NameSpace, [parameter(Mandatory = $true)] [System.String] $AccountName, [parameter(Mandatory = $true)] [ciminstance[]]$ACL ) $re = $true $ALL_DACL = @() $NTAccount = New-Object "System.Security.Principal.NTAccount" $AccountName $UserSID = $NTAccount.Translate([System.Security.Principal.SecurityIdentifier]).Value $DACL = (GetCimSecurity -NameSpace $NameSpace).DACL $ALL_DACL = GetCustomAllDACL -Input_CimDACL $DACL ## all in system $Fileter_Result = @() foreach ($item in $ACL) { $allowFilter = 0 if (!$item.Allow) { $allowFilter = 1 } $ALL_DACL.foreach( { if (($_.Sid -eq $UserSID) -and ( $_.Allow -eq $allowFilter) -and ($_.AceFlags -eq [int32][AceFlags]$item.AceFlags)) { $Fileter_Result += $_ Write-Verbose ("Find ACL in System $($_.sid) Allow $($item.Allow)") } } ) if ($Fileter_Result.count -ne 0) { $Sys_summask = ($Fileter_Result| Measure-Object -Property Mask -Sum).sum $Input_summask = [int32]([RightMask]$item.Right) Write-Verbose ("Sys Mask $($Sys_summask) Input Mask $($Input_summask)") if ($Sys_summask -ne $Input_summask) { $re = $false } $Fileter_Result.Clear() } else { $re = $false } } Write-Verbose ("Test Result $($re)") $re } #endregion Export-ModuleMember -Function *-TargetResource |