Public/Get-ADCSTemplateDacl.ps1

<#
.SYNOPSIS
Retrieves the discretionary access control list (DACL) for an ADCS certificate template.
 
.DESCRIPTION
This function retrieves the DACL for a specified Active Directory Certificate Services (ADCS) certificate template.
Depending on the `-Detailed` switch parameter, it either summarizes the permissions per principal or provides detailed
information about each access control entry (ACE) in the DACL.
 
.PARAMETER Name
Specifies the name of the ADCS certificate template.
 
.PARAMETER Server
Specifies the Active Directory server to connect to.
 
.PARAMETER Detailed
Switch parameter. If specified, provides detailed information about each ACE in the DACL.
 
.OUTPUTS
System.Object
Returns custom objects representing DACL information. For `-Detailed` mode, includes Type, Principal, Rights, and Property.
For standard mode, includes Principal, AllowPermissions, and DenyPermissions.
 
.EXAMPLE
PS C:\> Get-ADCSTemplateDacl -Name "User" -Detailed
 
Retrieves detailed DACL information for the ADCS certificate template with the name "User".
 
.EXAMPLE
Get-ADCSTemplateDacl -Name "User"
 
Retrieves DACL information for the ADCS certificate template with the name "User".
#>

Function Get-ADCSTemplateDacl {
    [CmdletBinding()]
    [OutputType([System.Object])]
    param(
        [Parameter(
            Mandatory = $true,
            Position = 0,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true
        )]
        [ValidateNotNullOrEmpty()]
        [SupportsWildcards()]
        [System.String]$Name,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [System.String]$Server,

        [Parameter(Mandatory = $false)]
        [switch]$Detailed
    )

    begin {
        $ErrorActionPreference = 'Stop'

        $common = @{}
        if ($PSBoundParameters.ContainsKey('Server')) {
            $common.Server = $server
        }

        New-PSDrive @common -Name CUSTOMAD -PSProvider ActiveDirectory -Root "" -WhatIf:$false | Out-Null
    }
    process {
        $template = Get-ADCSTemplate @common -Name $Name -Properties Name, DistinguishedName

        $templatePath = "CUSTOMAD:\$($template.DistinguishedName)"
        $acl = Get-ACL -Path $templatePath

        if (-not $Detailed) {
            $identityGroups = $acl.Access | Group-Object -Property IdentityReference
            foreach ($group in $identityGroups) {

                $allowPermissions = [System.Collections.ArrayList]@()
                $denyPermissions = [System.Collections.ArrayList]@()
                foreach ($ace in $group.Group) {
                    $rights = $ace.ActiveDirectoryRights
                    $objectType = $ace.ObjectType
                    $permissions = [System.Collections.ArrayList]@()

                    # Enroll rights
                    if ($rights.HasFlag([System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight)) {
                        switch ($objectType) {
                            'a05b8cc2-17bc-4802-a710-e7c15ab866a2' {
                                $permissions.Add('AutoEnroll') | Out-Null
                            }
                            '0e10c968-78fb-11d2-90d4-00c04f79dc55' {
                                $permissions.Add('Enroll') | Out-Null
                            }
                            "00000000-0000-0000-0000-000000000000" {
                                $permissions.Add('AutoEnroll') | Out-Null
                                $permissions.Add('Enroll') | Out-Null
                            }
                        }
                    }

                    # Full Control rights
                    if ($objectType -eq "00000000-0000-0000-0000-000000000000" -and
                        $rights.HasFlag([System.DirectoryServices.ActiveDirectoryRights]::GenericAll)) {
                        $permissions.Add('FullControl') | Out-Null
                    }

                    # Read rights
                    if ($objectType -eq "00000000-0000-0000-0000-000000000000" -and
                        $rights.HasFlag([System.DirectoryServices.ActiveDirectoryRights]::GenericRead)) {
                        $permissions.Add('Read') | Out-Null
                    }

                    # Write rights
                    if ($objectType -eq "00000000-0000-0000-0000-000000000000" -and
                        (
                            $rights.HasFlag([System.DirectoryServices.ActiveDirectoryRights]::WriteDacl) -or
                            $rights.HasFlag([System.DirectoryServices.ActiveDirectoryRights]::WriteProperty) -or
                            $rights.HasFlag([System.DirectoryServices.ActiveDirectoryRights]::WriteOwner)
                        )
                    ) {
                        $permissions.Add('Write') | Out-Null
                    }

                    if ($ace.AccessControlType.HasFlag([System.Security.AccessControl.AccessControlType]::Allow)) {
                        $allowPermissions.AddRange($permissions)
                    }
                    else {
                        $denyPermissions.AddRange($permissions)
                    }
                }

                $templateDacl = [PSCustomObject]@{
                    Principal        = $group.Name
                    AllowPermissions = ($allowPermissions | Select-Object -Unique)
                    DenyPermissions  = ($denyPermissions | Select-Object -Unique)
                }

                Write-Output -InputObject $templateDacl
            }
        }
        else {
            # Detailed
            $acl.Access | ForEach-Object {
                $ace = $_
                $objectType = $ace.ObjectType

                # Default value
                $property = "Unknown ($objectType)"
                # "00000000-0000-0000-0000-000000000000" is a special guid
                if ($objectType -eq "00000000-0000-0000-0000-000000000000") {
                    $property = "All Properties"
                }
                else {
                    $rightsObj = Resolve-SchemaRightsName @common -ObjectGuid $objectType

                    if($rightsObj) {
                        $property = "$($rightsObj.Name) ($($rightsObj.DisplayName))"
                    }
                }

                $templateDacl = [PSCustomObject]@{
                    Type      = $ace.AccessControlType
                    Principal = $ace.IdentityReference
                    Rights    = $ace.ActiveDirectoryRights
                    Property  = $property
                }

                Write-Output -InputObject $templateDacl
            }
        }
    }
    end {
        Remove-PSDrive -Name CUSTOMAD -WhatIf:$false
    }
}