Public/Get-ADCSTemplateAcl.ps1
<#
.SYNOPSIS Retrieves Access Control Lists (ACLs) for Active Directory Certificate Services (ADCS) certificate templates. .DESCRIPTION Retrieves ACLs for ADCS certificate templates based on name, display name, or input object. Converts principal names and resolves schema rights for each ACL entry. .PARAMETER Name Specifies the name of the ADCS certificate template to retrieve ACLs for. .PARAMETER DisplayName Specifies the display name of the ADCS certificate template to retrieve ACLs for. .PARAMETER InputObject Specifies an ADCSTemplate object from which to retrieve ACLs. .PARAMETER IncludePrincipalDomain Switch parameter to include the domain part in principal names. .PARAMETER ExcludeInheritedAce Exclude inherited Dacl and Sacl aces in the output. .PARAMETER Server Specifies the server to connect to for retrieving ADCS information. .OUTPUTS PSCustomObject with type 'ADCSTemplateAcl'. .EXAMPLE PS C:\> Get-ADCSTemplateAcl -Name "WebServer" Retrieves ACLs for the ADCS certificate template named "WebServer". .EXAMPLE PS C:\> Get-ADCSTemplateAcl -DisplayName "Web Server Authentication" Retrieves ACLs for the ADCS certificate template with the display name "Web Server Authentication". .EXAMPLE PS C:\> Get-ADCSTemplate -Name "UserTemplate" | Get-ADCSTemplateAcl -IncludePrincipalDomain Retrieves ACLs for the ADCS certificate template named "WebServer" and includes the domain part of the principal names in the output. #> function Get-ADCSTemplateAcl { [CmdletBinding(DefaultParameterSetName = 'Name')] [OutputType('ADCSTemplateAcl')] param ( [Parameter( Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Name' )] [ValidateNotNullOrEmpty()] [SupportsWildcards()] [System.String]$Name, [Parameter( Mandatory = $true, Position = 0, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'DisplayName' )] [ValidateNotNullOrEmpty()] [SupportsWildcards()] [System.String]$DisplayName, [Parameter( Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'InputObject' )] [ValidateNotNullOrEmpty()] [PSTypeName('ADCSTemplate')]$InputObject, [Parameter(Mandatory = $false)] [switch]$IncludePrincipalDomain = $false, [Parameter()] [switch]$ExcludeInheritedAce = $false, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.String]$Server ) begin { $ErrorActionPreference = 'Stop' $common = @{} if ($PSBoundParameters.ContainsKey('Server')) { $common.Server = $Server } New-PSDrive @common -Name CUSTOMAD -PSProvider ActiveDirectory -Root "" -WhatIf:$false | Out-Null } process { if ($PSBoundParameters.ContainsKey('Name')) { $templates = Get-ADCSTemplate @common -Name $Name -Properties Name, DistinguishedName } elseif ($PSBoundParameters.ContainsKey('DisplayName')) { $templates = Get-ADCSTemplate @common -DisplayName $DisplayName -Properties Name, DistinguishedName } elseif ($PSBoundParameters.ContainsKey('InputObject')) { $templates = $InputObject } foreach ($template in $templates) { $templatePath = "CUSTOMAD:\$($template.DistinguishedName)" $acl = Get-ACL -Path $templatePath -Audit if ($null -eq $acl) { # Get-ACL silently fails when retrieving audit sacls lowpriv user on DC's due to missing SeSecurityPrivilege Write-Warning -Message "Failed to retrieve audit sacls. Please elevate to administrator." $acl = Get-ACL -Path $templatePath $acl | Add-Member -Type NoteProperty -Name Audit -Value @() } # Function to convert (transform) a principal name function Convert-PrincipalName { param ( [System.String]$Principal, [switch]$IncludePrincipalDomain = $false ) if (-not $IncludePrincipalDomain) { return ($Principal -replace '^[^\\]+\\', '') } else { return $Principal } } # Convert (transform) principals based on the RemoveDomainPart switch $group = Convert-PrincipalName -Principal $acl.Group -IncludePrincipalDomain:$IncludePrincipalDomain $owner = Convert-PrincipalName -Principal $acl.Owner -IncludePrincipalDomain:$IncludePrincipalDomain $dacls = [System.Collections.ArrayList]@() foreach ($ace in $acl.Access) { if (($ExcludeInheritedAce -eq $true) -and ($ace.IsInherited -eq $true)) { continue } $objectType = (Resolve-SchemaRightsName @common -ObjectGuid $ace.ObjectType) | Select-Object -ExpandProperty Name if (-not $objectType) { # default to guid $objectType = $ace.ObjectType } $inheritedObjectType = (Resolve-SchemaRightsName @common -ObjectGuid $ace.InheritedObjectType) | Select-Object -ExpandProperty Name if (-not $inheritedObjectType) { $inheritedObjectType = $ace.InheritedObjectType } $aceObject = [PSCustomObject]@{ PSTypeName = "ADCSTemplateDacl" IdentityReference = Convert-PrincipalName -Principal $ace.IdentityReference.ToString() -IncludePrincipalDomain:$IncludePrincipalDomain ActiveDirectoryRights = $ace.ActiveDirectoryRights.ToString() AccessControlType = $ace.AccessControlType.ToString() ObjectType = $objectType InheritanceType = $ace.InheritanceType.ToString() InheritedObjectType = $inheritedObjectType IsInherited = $ace.IsInherited } $dacls.Add($aceObject) | Out-Null } $sacls = [System.Collections.ArrayList]@() foreach ($ace in $acl.Audit) { if (($ExcludeInheritedAce -eq $true) -and ($ace.IsInherited -eq $true)) { continue } $objectType = (Resolve-SchemaRightsName @common -ObjectGuid $ace.ObjectType) | Select-Object -ExpandProperty Name if (-not $objectType) { # default to guid $objectType = $ace.ObjectType } $inheritedObjectType = (Resolve-SchemaRightsName @common -ObjectGuid $ace.InheritedObjectType) | Select-Object -ExpandProperty Name if (-not $inheritedObjectType) { $inheritedObjectType = $ace.InheritedObjectType } $aceObject = [PSCustomObject]@{ PSTypeName = "ADCSTemplateSacl" IdentityReference = Convert-PrincipalName -Principal $ace.IdentityReference.ToString() -IncludePrincipalDomain:$IncludePrincipalDomain ActiveDirectoryRights = $ace.ActiveDirectoryRights.ToString() AuditFlags = $ace.AuditFlags.ToString() ObjectType = $objectType InheritanceType = $ace.InheritanceType.ToString() InheritedObjectType = $inheritedObjectType IsInherited = $ace.IsInherited } $sacls.Add($aceObject) | Out-Null } # Create a custom object to hold the information $templateAcl = [PSCustomObject]@{ PSTypeName = "ADCSTemplateAcl" TemplateName = $template.Name Group = $group Owner = $owner DACLs = $dacls SACLs = $sacls AreAccessRulesProtected = $acl.AreAccessRulesProtected AreAuditRulesProtected = $acl.AreAuditRulesProtected } Write-Output -InputObject $templateAcl } } end { Remove-PSDrive -Name CUSTOMAD -WhatIf:$false } } |