The PowerShell Access Control module provides a way to manage Windows access control for most securable objects using Windows PowerShell. For files, folders, registry keys, and Active Directory objects, it can either fully replace the Get-Acl and Set-Acl cmdlets, or it can be used as a supplement to them (see below for details). It has the following features:
The following securable objects have built-in support:
dir c:\ | Get-AccessControlEntry Get-AccessControlEntry c:\*
dir c:\ | Get-AccessControlEntry Get-AccessControlEntry c:\*
Get-Item HKLM:\SOFTWARE | Get-AccessControlEntry Get-AccessControlEntry HKLM:\SOFTWARE, HKLM:\SOFTWARE\Microsoft # Get remote registry permissions: Get-SecurityDescriptor \\RemoteComputerName\Machine\SOFTWARE -ObjectType RegistryKey | Get-AccessControlEntry Get-SecurityDescriptor \\RemoteComputerName\Machine\SOFTWARE -ObjectType RegistryWow6432Key | Get-AccessControlEntry
Get-Item HKLM:\SOFTWARE | Get-AccessControlEntry Get-AccessControlEntry HKLM:\SOFTWARE, HKLM:\SOFTWARE\Microsoft # Get remote registry permissions: Get-SecurityDescriptor \\RemoteComputerName\Machine\SOFTWARE -ObjectType RegistryKey | Get-AccessControlEntry Get-SecurityDescriptor \\RemoteComputerName\Machine\SOFTWARE -ObjectType RegistryWow6432Key | Get-AccessControlEntry
Get-Printer | Get-AccessControlEntry Get-CimInstance Win32_Printer | Get-AccessControlEntry
Get-Printer | Get-AccessControlEntry Get-CimInstance Win32_Printer | Get-AccessControlEntry
Get-Service | select -first 5 | Get-AccessControlEntry
Get-Service | select -first 5 | Get-AccessControlEntry
Get-SmbShare | Get-AccessControlEntry Get-WmiObject Win32_Share | Get-AccessControlEntry Get-SecurityDescriptor \\ServerName\ShareName -ObjectType LMShare | Get-AccessControlEntry
Get-SmbShare | Get-AccessControlEntry Get-WmiObject Win32_Share | Get-AccessControlEntry Get-SecurityDescriptor \\ServerName\ShareName -ObjectType LMShare | Get-AccessControlEntry
Get-CimInstance __SystemSecurity | Get-AccessControlEntry Get-WmiObject __SystemSecurity | Get-AccessControlEntry
Get-CimInstance __SystemSecurity | Get-AccessControlEntry Get-WmiObject __SystemSecurity | Get-AccessControlEntry
Get-Process | where { $_.Handle } | Get-AccessControlEntry
Get-Process | where { $_.Handle } | Get-AccessControlEntry
Get-AdUser $env:username | Get-AccessControlEntry dir AD:\ | Get-AccessControlEntry
Get-AdUser $env:username | Get-AccessControlEntry dir AD:\ | Get-AccessControlEntry
Each of the previous examples used the Get-AccessControlEntry function, but the input objects can be used with any of the following functions:
If an object doesn't have built-in support, that doesn't mean the module can't be used. If you have access to the SDDL or binary forms of a security descriptor, you can still use the New-AdaptedSecurityDescriptor function to create a security descriptor object that you can work with, then you can convert the SD back into the SDDL or binary forms (there is an example of this below).
The module was developed for PowerShell version 3, but it should work with version 2. If you find any problems with it, please let me know via the 'Questions and Answers' section.
If you're looking for version 2.1 of the module, there is a link to download it in the history section at the bottom of this page.
To install the module, follow these steps:
Import-Module PowerShellAccessControl
Import-Module PowerShellAccessControl
Get-Command -Module PowerShellAccessControl
Get-Command -Module PowerShellAccessControl
Below are a few examples. Please see the help included with the module for more information, including many more examples.
The native Get-Acl and Set-Acl cmdlets are very useful for files, folders, registry keys, and Active Directory objects (they support more than that, but that's what I use them for). If you're not comfortable using a non-Microsoft approved tool to modify security descriptors (proper access control is VERY important after all), then youc can use this module to work with the security descriptors, but you can still depend on the native PowerShell cmdlets to actually get and set the security descriptors. Take a look at the following example, which shows the native PowerShell way to add an ACE to a folder, and a few different ways to use the PowerShell Access Control module to ease the process:
#--------------------------------- # Native PS way to add an ACE that grants 'Modify' rights to 'Everyone': #--------------------------------- $Acl = Get-Acl C:\temp $Ace = New-Object System.Security.AccessControl.FileSystemAccessRule ( "Everyone", "Modify", "ContainerInherit, ObjectInherit", "None", "Allow" ) $Acl.AddAccessRule($Ace) $Acl | Set-Acl # Under certain scenarios, Set-Acl will not work when it should. If # you're just working with discretionary access (no auditing), then # this would also work: [System.IO.File]::SetAccessControl($Acl.Path, $Acl) #--------------------------------- # PAC Module Example 1 - New-AccessControlEntry #--------------------------------- $Acl = Get-Acl C:\temp # Notice that the following line replaces the .NET constructor used above: $Ace = New-AccessControlEntry -Principal Everyone -FolderRights Modify $Acl.AddAccessRule($Ace) $Acl | Set-Acl #--------------------------------- # PAC Module Example 2 - New-AccessControl and Add-AccessControl #--------------------------------- $Acl = Get-Acl C:\temp $Ace = New-AccessControlEntry -Principal Everyone -FolderRights Modify # Notice that the following line replaces the AddAccessRule() method above $Acl | Add-AccessControlEntry -AceObject $Ace $Acl | Set-Acl #--------------------------------- # PAC Module Example 3 - Add-AccessControl only #--------------------------------- $Acl = Get-Acl C:\temp # Notice that the following line replaces the New-AccessControlEntry function $Acl | Add-AccessControlEntry -Principal Everyone -FolderRights Modify $Acl | Set-Acl #--------------------------------- # PAC Module Example 4 - Fully replace Get-Acl and Set-Acl (use -Force to suppress prompt) #--------------------------------- # This one line does everything that the previous examples do: Get-Item C:\temp | Add-AccessControlEntry -Principal Everyone -FolderRights Modify
#--------------------------------- # Native PS way to add an ACE that grants 'Modify' rights to 'Everyone': #--------------------------------- $Acl = Get-Acl C:\temp $Ace = New-Object System.Security.AccessControl.FileSystemAccessRule ( "Everyone", "Modify", "ContainerInherit, ObjectInherit", "None", "Allow" ) $Acl.AddAccessRule($Ace) $Acl | Set-Acl # Under certain scenarios, Set-Acl will not work when it should. If # you're just working with discretionary access (no auditing), then # this would also work: [System.IO.File]::SetAccessControl($Acl.Path, $Acl) #--------------------------------- # PAC Module Example 1 - New-AccessControlEntry #--------------------------------- $Acl = Get-Acl C:\temp # Notice that the following line replaces the .NET constructor used above: $Ace = New-AccessControlEntry -Principal Everyone -FolderRights Modify $Acl.AddAccessRule($Ace) $Acl | Set-Acl #--------------------------------- # PAC Module Example 2 - New-AccessControl and Add-AccessControl #--------------------------------- $Acl = Get-Acl C:\temp $Ace = New-AccessControlEntry -Principal Everyone -FolderRights Modify # Notice that the following line replaces the AddAccessRule() method above $Acl | Add-AccessControlEntry -AceObject $Ace $Acl | Set-Acl #--------------------------------- # PAC Module Example 3 - Add-AccessControl only #--------------------------------- $Acl = Get-Acl C:\temp # Notice that the following line replaces the New-AccessControlEntry function $Acl | Add-AccessControlEntry -Principal Everyone -FolderRights Modify $Acl | Set-Acl #--------------------------------- # PAC Module Example 4 - Fully replace Get-Acl and Set-Acl (use -Force to suppress prompt) #--------------------------------- # This one line does everything that the previous examples do: Get-Item C:\temp | Add-AccessControlEntry -Principal Everyone -FolderRights Modify
View ACEs for 'C:\Program Files' (not recursive):
# Method 1: Pass path directly to Get-AccessControlEntry Get-AccessControlEntry -Path 'C:\Program Files' # Method 2: Pipe items from Get-SecurityDescriptor function (found in this module) dir 'C:\Program Files' | Get-SecurityDescriptor -Audit | Get-AccessControlEntry
# Method 1: Pass path directly to Get-AccessControlEntry Get-AccessControlEntry -Path 'C:\Program Files' # Method 2: Pipe items from Get-SecurityDescriptor function (found in this module) dir 'C:\Program Files' | Get-SecurityDescriptor -Audit | Get-AccessControlEntry
# Show the BITs service: Get-Service bits | Get-AccessControlEntry # Alternate way: $SD = Get-Service bits | Get-SecurityDescriptor $SD.Access $SD.Audit $SD $SD | fl # Filter the ACEs Get-Service b* | Get-AccessControlEntry -Principal Administrators Get-Service b* | Get-AccessControlEntry -Principal Administrators -AceType SystemAudit Get-Service b* | Get-AccessControlEntry -Principal Administrators -AceType AccessAllowed -ServiceAccessRights FullControl
# Show the BITs service: Get-Service bits | Get-AccessControlEntry # Alternate way: $SD = Get-Service bits | Get-SecurityDescriptor $SD.Access $SD.Audit $SD $SD | fl # Filter the ACEs Get-Service b* | Get-AccessControlEntry -Principal Administrators Get-Service b* | Get-AccessControlEntry -Principal Administrators -AceType SystemAudit Get-Service b* | Get-AccessControlEntry -Principal Administrators -AceType AccessAllowed -ServiceAccessRights FullControl
# List all share permissions: Get-SmbShare | Get-AccessControlEntry -ErrorAction SilentlyContinue # List NTFS permissions for all shares: Get-SmbShare | select path | Get-AccessControlEntry -ErrorAction SilentlyContinue
# List all share permissions: Get-SmbShare | Get-AccessControlEntry -ErrorAction SilentlyContinue # List NTFS permissions for all shares: Get-SmbShare | select path | Get-AccessControlEntry -ErrorAction SilentlyContinue
# Logical shares: Get-WmiObject Win32_LogicalShareSecuritySetting | Get-AccessControlEntry # Printers: Get-WmiObject Win32_Printer | Get-AccessControlEntry # root/cimv2 Namespace Get-CimInstance __SystemSecurity -Namespace root/cimv2 | Get-AccessControlEntry
# Logical shares: Get-WmiObject Win32_LogicalShareSecuritySetting | Get-AccessControlEntry # Printers: Get-WmiObject Win32_Printer | Get-AccessControlEntry # root/cimv2 Namespace Get-CimInstance __SystemSecurity -Namespace root/cimv2 | Get-AccessControlEntry
WsMan security:
dir wsman:\ -Recurse | ? { $_.Name -eq "Sddl" } | Get-AccessControlEntry
dir wsman:\ -Recurse | ? { $_.Name -eq "Sddl" } | Get-AccessControlEntry
PowerShell doesn't provide a cmdlet for creating ACEs, so the only way to natively create one is using .NET constructors. Creating an access ACE for a folder is slightly different than creating an access ACE for a file, which is different than creating an access ACE for a registry key, which is significantly different than creating an access ACE for an Active Directory object (and all of those are different than creating audit ACEs). Want to create an ACE for a service or printer? Those are different, too.
The New-AccessControlEntry tries to fix that problem. Creating ACEs for each of the previously mentioned objects is very similar. The only difference is the access rights parameter (-FolderRights, -FileRights, -RegistryRights, -ActiveDirectoryRights, -ServiceRights, -PrinterRights).
The ACEs that are output by the -FolderRights, -FileRights, -RegistryRights, and -ActiveDirectoryRights can be used by SD objects from Get-Acl (unless you use the -Generic switch; don't do that) or Get-SecurityDescriptor.
Here are some examples:
# Create a deny ACE for a file: New-AccessControlEntry -FileRights Delete -Principal Everyone -AceType AccessDenied # Create an audit ACE for a folder that only applies to child files (Audit failures): New-AccessControlEntry -AceType SystemAudit -Principal Everyone -FolderRights FullControl -AppliesTo ChildObjects -AuditFailure # Create an ACE for a service that allows Users to start and stop New-AccessControlEntry -Principal Users -ServiceAccessRights Start, Stop # Create an ACE for AD object that gives the 'TestUser' the ability to read the 'Public-Information' property set: # (See the section on Active Directory below for more information) New-AccessControlEntry -Principal TestUser -ActiveDirectoryRights ReadProperty -ObjectAceType Public-Information
# Create a deny ACE for a file: New-AccessControlEntry -FileRights Delete -Principal Everyone -AceType AccessDenied # Create an audit ACE for a folder that only applies to child files (Audit failures): New-AccessControlEntry -AceType SystemAudit -Principal Everyone -FolderRights FullControl -AppliesTo ChildObjects -AuditFailure # Create an ACE for a service that allows Users to start and stop New-AccessControlEntry -Principal Users -ServiceAccessRights Start, Stop # Create an ACE for AD object that gives the 'TestUser' the ability to read the 'Public-Information' property set: # (See the section on Active Directory below for more information) New-AccessControlEntry -Principal TestUser -ActiveDirectoryRights ReadProperty -ObjectAceType Public-Information
The following function deal with modifying security descriptors:
Here's an example of modifying the DACL for the current user's temp folder:
# Get-Acl could be used here, too $SD = Get-SecurityDescriptor $env:temp # Give Users 'Modify' rights; apply only to sub folders and files (not the current folder), and allow inheritance $SD | Add-AccessControlEntry -FolderRights Modify -Principal Users -AppliesTo ChildContainers, ChildObjects # Give 'Authenticated Users' the 'CreateFiles' right, and only apply it to direct sub folders and files (not sub folders of sub folders). # Notice that param is -AceObject, and the object being passed was created with New-AccessControlEntry. This is an alternate way to # provide the ACE (the line above is another way): $SD | Add-AccessControlEntry -AceObject (New-AccessControlEntry -FolderRights CreateFiles -Principal "Authenticated Users" -OnlyApplyToThisContainer) # This would save it (if -WhatIf wasn't supplied) $SD | Set-SecurityDescriptor -WhatIf # Alternate way to do the previous example in a single line: Get-Item $env:temp | Add-AccessControlEntry -FolderRights Modify -Principal Users -AppliesTo ChildContainers, ChildObjects -PassThru | Add-AccessControlEntry -FolderRights CreateFiles -Principal "Authenticated Users" -OnlyApplyToThisContainer -Apply -WhatIf
# Get-Acl could be used here, too $SD = Get-SecurityDescriptor $env:temp # Give Users 'Modify' rights; apply only to sub folders and files (not the current folder), and allow inheritance $SD | Add-AccessControlEntry -FolderRights Modify -Principal Users -AppliesTo ChildContainers, ChildObjects # Give 'Authenticated Users' the 'CreateFiles' right, and only apply it to direct sub folders and files (not sub folders of sub folders). # Notice that param is -AceObject, and the object being passed was created with New-AccessControlEntry. This is an alternate way to # provide the ACE (the line above is another way): $SD | Add-AccessControlEntry -AceObject (New-AccessControlEntry -FolderRights CreateFiles -Principal "Authenticated Users" -OnlyApplyToThisContainer) # This would save it (if -WhatIf wasn't supplied) $SD | Set-SecurityDescriptor -WhatIf # Alternate way to do the previous example in a single line: Get-Item $env:temp | Add-AccessControlEntry -FolderRights Modify -Principal Users -AppliesTo ChildContainers, ChildObjects -PassThru | Add-AccessControlEntry -FolderRights CreateFiles -Principal "Authenticated Users" -OnlyApplyToThisContainer -Apply -WhatIf
Here's an example of modifying the DACL and SACL for a service:
Get-Service bits | Get-SecurityDescriptor -Audit | Add-AccessControlEntry -ServiceAccessRights Start, Stop -Principal Users -PassThru | Add-AccessControlEntry -AceType SystemAudit -ServiceAccessRights Start, Stop -Principal Users -AuditSuccess -AuditFailure -Apply -WhatIf # Confirm settings (new settings won't show here if -WhatIf was passed in previous command) Get-Service bits | Get-AccessControlEntry -Audit # Here's how to modify more than one service at a time: Get-Service | select -first 5 | Add-AccessControlEntry -Principal TestUser -ServiceAccessRights Start,Stop -WhatIf
Get-Service bits | Get-SecurityDescriptor -Audit | Add-AccessControlEntry -ServiceAccessRights Start, Stop -Principal Users -PassThru | Add-AccessControlEntry -AceType SystemAudit -ServiceAccessRights Start, Stop -Principal Users -AuditSuccess -AuditFailure -Apply -WhatIf # Confirm settings (new settings won't show here if -WhatIf was passed in previous command) Get-Service bits | Get-AccessControlEntry -Audit # Here's how to modify more than one service at a time: Get-Service | select -first 5 | Add-AccessControlEntry -Principal TestUser -ServiceAccessRights Start,Stop -WhatIf
dir C:\Folder -Recurse | Remove-AccessControlEntry -RemoveAllAccessEntries -PassThru | Enable-AclInheritance -Apply -WhatIf
dir C:\Folder -Recurse | Remove-AccessControlEntry -RemoveAllAccessEntries -PassThru | Enable-AclInheritance -Apply -WhatIf
# Copy ACEs from one security descriptor to another: Get-AccessControlEntry C:\temp -Principal Users | Add-AccessControlEntry -Path C:\folder -WhatIf # Remove certain access (this would remove Write access from any user that contains 'PartialUserName' in their name) Get-AccessControlEntry C:\temp -Principal *PartialUserName* -FolderRights Write -NotInherited | Remove-AccessControlEntry -WhatIf
# Copy ACEs from one security descriptor to another: Get-AccessControlEntry C:\temp -Principal Users | Add-AccessControlEntry -Path C:\folder -WhatIf # Remove certain access (this would remove Write access from any user that contains 'PartialUserName' in their name) Get-AccessControlEntry C:\temp -Principal *PartialUserName* -FolderRights Write -NotInherited | Remove-AccessControlEntry -WhatIf
Here are a few examples of giving a specific user or group the ability to join workstations to a domain. The permissions apply to an OU. See this forum topic for more details:
$Principal = "UserOrGroupName" $DistinguishedName = "OU=ComputerOU,DC=Domain,DC=Local" # Confirm that the SD doesn't contain the access already: Get-AccessControlEntry $DistinguishedName -Principal $Principal #--------------------------------- # Method 1 uses 3 lines and the native PS cmdlets Get-Acl and Set-Acl: #--------------------------------- $SD = Get-Acl "AD:\$DistinguishedName" $SD | Add-AccessControlEntry -Principal $Principal -ActiveDirectoryRights CreateChild -ObjectAceType computer -PassThru | Add-AccessControlEntry -Principal $Principal -ObjectAceType Reset-Password -InheritedObjectAceType computer -PassThru | Add-AccessControlEntry -Principal $Principal -ActiveDirectoryRights WriteProperty -ObjectAceType Account-Restrictions -InheritedObjectAceType computer -PassThru | Add-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-service-principal-name -InheritedObjectAceType computer -PassThru | Add-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-DNS-host-name -InheritedObjectAceType computer $SD | Set-Acl # Confirm that the SD has been chagned: Get-AccessControlEntry $DistinguishedName -Principal $Principal #--------------------------------- # Method 2 is the same as method 1 except that the ACEs are contained in an array (it # makes the Add-AccessControlEntry command shorter) #--------------------------------- $Aces = @( New-AccessControlEntry -Principal $Principal -ActiveDirectoryRights CreateChild -ObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Reset-Password -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ActiveDirectoryRights WriteProperty -ObjectAceType Account-Restrictions -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-service-principal-name -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-DNS-host-name -InheritedObjectAceType computer ) $SD = Get-Acl "AD:\$DistinguishedName" $SD | Add-AccessControlEntry -AceObject $Aces $SD | Set-Acl #--------------------------------- # Method 3 removes the Get-Acl and Set-Acl calls. Get-SecurityDescriptor and # Set-SecurityDescriptor could be used in their place, but most of the SD modification # functions will call them automatically when necessary. The simplified method looks # like this: #--------------------------------- $Aces = @( New-AccessControlEntry -Principal $Principal -ActiveDirectoryRights CreateChild -ObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Reset-Password -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ActiveDirectoryRights WriteProperty -ObjectAceType Account-Restrictions -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-service-principal-name -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-DNS-host-name -InheritedObjectAceType computer ) $DistinguishedName | Add-AccessControlEntry -AceObject $Aces
$Principal = "UserOrGroupName" $DistinguishedName = "OU=ComputerOU,DC=Domain,DC=Local" # Confirm that the SD doesn't contain the access already: Get-AccessControlEntry $DistinguishedName -Principal $Principal #--------------------------------- # Method 1 uses 3 lines and the native PS cmdlets Get-Acl and Set-Acl: #--------------------------------- $SD = Get-Acl "AD:\$DistinguishedName" $SD | Add-AccessControlEntry -Principal $Principal -ActiveDirectoryRights CreateChild -ObjectAceType computer -PassThru | Add-AccessControlEntry -Principal $Principal -ObjectAceType Reset-Password -InheritedObjectAceType computer -PassThru | Add-AccessControlEntry -Principal $Principal -ActiveDirectoryRights WriteProperty -ObjectAceType Account-Restrictions -InheritedObjectAceType computer -PassThru | Add-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-service-principal-name -InheritedObjectAceType computer -PassThru | Add-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-DNS-host-name -InheritedObjectAceType computer $SD | Set-Acl # Confirm that the SD has been chagned: Get-AccessControlEntry $DistinguishedName -Principal $Principal #--------------------------------- # Method 2 is the same as method 1 except that the ACEs are contained in an array (it # makes the Add-AccessControlEntry command shorter) #--------------------------------- $Aces = @( New-AccessControlEntry -Principal $Principal -ActiveDirectoryRights CreateChild -ObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Reset-Password -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ActiveDirectoryRights WriteProperty -ObjectAceType Account-Restrictions -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-service-principal-name -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-DNS-host-name -InheritedObjectAceType computer ) $SD = Get-Acl "AD:\$DistinguishedName" $SD | Add-AccessControlEntry -AceObject $Aces $SD | Set-Acl #--------------------------------- # Method 3 removes the Get-Acl and Set-Acl calls. Get-SecurityDescriptor and # Set-SecurityDescriptor could be used in their place, but most of the SD modification # functions will call them automatically when necessary. The simplified method looks # like this: #--------------------------------- $Aces = @( New-AccessControlEntry -Principal $Principal -ActiveDirectoryRights CreateChild -ObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Reset-Password -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ActiveDirectoryRights WriteProperty -ObjectAceType Account-Restrictions -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-service-principal-name -InheritedObjectAceType computer New-AccessControlEntry -Principal $Principal -ObjectAceType Validated-write-to-DNS-host-name -InheritedObjectAceType computer ) $DistinguishedName | Add-AccessControlEntry -AceObject $Aces
The Get-MandatoryIntegrityLabel has the ability to view a mandatory integrity label if one has been set. If one isn't set, the function will return null. Here's a screenshot showing what the results look like:
The Get-EffectiveAccess function can get the simple effective access access mask, and a more detailed view of which rights are allowed and which ones aren't. Here's a screenshot:
If you work with WMI security descriptors a lot, the module can help with that, too. The module has a function that will get a Win32_SecurityDescriptor from any WMI/CIM object that supports those. There are also functions to convert those into SDDL and/or binary representations, and from those back into Win32_SecurityDescriptor objects. You can also pipe a Win32_SecurityDescriptor object into Get-AccessControlEntry, too.
The module contains three DSC resources that are in beta:
See about_PowerShellAccessControl_DscResources for more information. There's also an 'examples' folder in the module that provides a few examples of each DSC resource in use.
If you come across an unsupported securable object, you can still probably work with it using the module. Here's an example of converting a binary security descriptor into a form that can be worked with:
$SD = New-AdaptedSecurityDescriptor -BinarySD (gp HKLM:\SOFTWARE\Microsoft\Ole | select -exp MachineAccessRestriction) # Modification goes here # Sddl representation: $SD.Sddl # Binary representation: $SD.GetSecurityDescriptorBinaryForm()
$SD = New-AdaptedSecurityDescriptor -BinarySD (gp HKLM:\SOFTWARE\Microsoft\Ole | select -exp MachineAccessRestriction) # Modification goes here # Sddl representation: $SD.Sddl # Binary representation: $SD.GetSecurityDescriptorBinaryForm()
PowerShell v3 users will have a much better experience with the module. When using any of the access mask enumerations, Intellisense (in the ISE) and tab completion (in the console) work. PSv2 users need to know what strings are contained in the enumerations. Here's an example of viewing the valid strings in an enumeration (see example above on how to list the enumerations):
[enum]::GetValues([PowerShellAccessControl.ServiceAccessRights])
[enum]::GetValues([PowerShellAccessControl.ServiceAccessRights])
1.0 (7/2013):
1.1 (12/2103):
1.2 (1/4/2014):
2.0 (1/31/2014):
2.1 (2/17/2014):
2.1 Quick Fix (3/1/2014):
3.0