Public/New-AclSddl.ps1
function New-AclSddl { <# .SYNOPSIS Generates an SDDL (Security Descriptor Definition Language) string based on specified access control entries. .DESCRIPTION This function creates a security descriptor using .NET's FileSecurity class. Default permissions for `SYSTEM` and `Administrators` are always included. Additional custom access control entries can be specified as input. .PARAMETER IdentityPermissions An array of hashtable entries containing: - Identity: The user or group for which the permission applies. - Permission: The permission to grant or deny (e.g., Read, Write, FullControl). - AccessType: The type of access (Allow or Deny). .EXAMPLE $identityPermissions = @( @{ Identity = 'EguibarIT.local\SL_PAWs'; Permission = 'Read'; AccessType = 'Allow' }, @{ Identity = 'EguibarIT.local\Domain Controllers'; Permission = 'Write'; AccessType = 'Deny' } ) $sddl = New-AclSddl -IdentityPermissions $identityPermissions -Verbose Write-Output $sddl .INPUTS Array of hashtable with Identity, Permission, and AccessType. .OUTPUTS System.String Returns the SDDL string representation of the ACL. .NOTES Used Functions: Name ║ Module/Namespace ═══════════════════════════════════════╬══════════════════════════════ AddAccessRule ║ System.Security.AccessControl.FileSecurity GetSecurityDescriptorSddlForm ║ System.Security.AccessControl.FileSecurity Get-FunctionDisplay ║ EguibarIT Write-Verbose ║ Microsoft.PowerShell.Utility Write-Debug ║ Microsoft.PowerShell.Utility .NOTES Version: 1.1 DateModified: 22/May/2025 LastModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar IT http://www.eguibarit.com .LINK https://github.com/vreguibar/EguibarIT/blob/main/Public/New-AclSddl.ps1 .COMPONENT Security .ROLE Security Administration .FUNCTIONALITY Access Control #> [CmdletBinding(SupportsShouldProcess = $false, ConfirmImpact = 'Low')] [OutputType([string])] param ( # Array of identity-permission-accessType tuples [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $False, HelpMessage = 'Array of Identity and permissions used to build the corresponding SDDL.', Position = 0)] [ValidateNotNullOrEmpty()] [array] $IdentityPermissions ) begin { Set-StrictMode -Version Latest $error.clear() $txt = ($Variables.Header -f (Get-Date).ToString('dd/MMM/yyyy'), $MyInvocation.Mycommand, (Get-FunctionDisplay -HashTable $PsBoundParameters -Verbose:$False) ) Write-Verbose -Message $txt ############################## # Module imports ############################## # Variables Definition # Create a FileSecurity object to manage the ACL $fileSecurity = [System.Security.AccessControl.FileSecurity]::new() # Define default rules for SYSTEM and Administrators $defaultRules = @( [System.Security.AccessControl.FileSystemAccessRule]::new( 'NT AUTHORITY\SYSTEM', [System.Security.AccessControl.FileSystemRights]::FullControl, [System.Security.AccessControl.AccessControlType]::Allow ), [System.Security.AccessControl.FileSystemAccessRule]::new( 'BUILTIN\Administrators', [System.Security.AccessControl.FileSystemRights]::FullControl, [System.Security.AccessControl.AccessControlType]::Allow ) ) # Add default rules to the FileSecurity object foreach ($rule in $defaultRules) { $fileSecurity.AddAccessRule($rule) } #end Foreach Write-Verbose -Message 'Default rules for SYSTEM and Administrators added.' } #end begin process { foreach ($entry in $IdentityPermissions) { try { # Extract entry details $identity = $entry.Identity $permission = $entry.Permission $accessType = $entry.AccessType # Map permission to FileSystemRights using .NET Enum $fileSystemRights = [System.Security.AccessControl.FileSystemRights]::$permission # Map access type to AccessControlType using .NET Enum $accessControlType = [System.Security.AccessControl.AccessControlType]::$accessType # Create a FileSystemAccessRule object $accessRule = [System.Security.AccessControl.FileSystemAccessRule]::new( $identity, # Identity as string $fileSystemRights, # Permissions $accessControlType # Allow or Deny ) # Add the access rule to the FileSecurity object $fileSecurity.AddAccessRule($accessRule) Write-Verbose -Message ( 'Added rule for identity: {0}, permissions: {1}, access type: {2}' -f $identity, $permission, $accessType ) } catch { Write-Error -Message ('Failed to process entry for identity: {0}. Error: {1}' -f $identity, $_) } #end Try-Catch } #end Foreach } #end process end { # Convert ACL to SDDL string $sddl = $fileSecurity.GetSecurityDescriptorSddlForm('Access') Write-Verbose -Message ('Generated SDDL: {0}' -f $sddl) $txt = ($Variables.Footer -f $MyInvocation.InvocationName, 'adding members to the group.' ) Write-Verbose -Message $txt return $sddl } #end end } #end function Generate-AclSddl |