Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

##### This project is community maintained and has no sponsorship from Microsoft, its employees or any of its affiliates.

## [0.9.12] - 2026-02-27

### :toolbox: Added

- Add Authentication Policies and Authentication Policy Silos support (`Get-AbrADAuthenticationPolicy`)

### :arrows_clockwise: Changed

- Update module version to `0.9.12`

## [0.9.11] - 2026-02-21

### :toolbox: Added
Expand Down
248 changes: 248 additions & 0 deletions Src/Private/Get-AbrADAuthenticationPolicy.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
function Get-AbrADAuthenticationPolicy {
<#
.SYNOPSIS
Used by As Built Report to retrieve Microsoft AD Authentication Policy and Authentication Policy Silo information.
.DESCRIPTION

.NOTES
Version: 0.9.12
Author: Jonathan Colon
Twitter: @jcolonfzenpr
Github: rebelinux
.EXAMPLE

.LINK

#>
[CmdletBinding()]
param (
$Domain,
[string]$ValidDcFromDomain
)

begin {
Write-PScriboMessage -Message "Collecting AD Authentication Policy and Silo information from $($Domain.DNSRoot.toUpper())."
Show-AbrDebugExecutionTime -Start -TitleMessage 'AD Authentication Policy Silos'
}

process {
try {
$SiloProperties = @('Name', 'Enforce', 'Description', 'UserAuthenticationPolicy', 'ServiceAuthenticationPolicy', 'ComputerAuthenticationPolicy', 'Members')
$PolicyProperties = @('Name', 'Enforce', 'Description', 'UserTGTLifetimeMins', 'ServiceTGTLifetimeMins', 'ComputerTGTLifetimeMins')
$AuthPolicySilos = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADAuthenticationPolicySilo -Filter * -Properties $using:SiloProperties -Server $using:ValidDcFromDomain -ErrorAction SilentlyContinue }
$AuthPolicies = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock { Get-ADAuthenticationPolicy -Filter * -Properties $using:PolicyProperties -Server $using:ValidDcFromDomain -ErrorAction SilentlyContinue }
if ($AuthPolicySilos -or $AuthPolicies) {
Section -Style Heading3 'Authentication Policies and Silos' {
Paragraph 'The following section provides an overview of Authentication Policy Silos and Authentication Policies configured in the domain. Authentication Policy Silos restrict where accounts can sign in and apply authentication policies to control the Kerberos ticket-granting ticket (TGT) lifetime for privileged accounts.'
BlankLine
if ($AuthPolicySilos) {
try {
Section -Style Heading4 'Authentication Policy Silos' {
Paragraph "The following table provides a summary of Authentication Policy Silos configured in domain $($Domain.DNSRoot.ToString().ToUpper())."
BlankLine
$SiloInfo = [System.Collections.ArrayList]::new()
foreach ($Silo in $AuthPolicySilos) {
try {
$inObj = [ordered] @{
'Name' = $Silo.Name
'Enforce' = $Silo.Enforce
'Description' = & {
if ([string]::IsNullOrEmpty($Silo.Description)) { '--' } else { $Silo.Description }
}
'User Authentication Policy' = & {
if ([string]::IsNullOrEmpty($Silo.UserAuthenticationPolicy)) { '--' } else { $Silo.UserAuthenticationPolicy }
}
'Service Authentication Policy' = & {
if ([string]::IsNullOrEmpty($Silo.ServiceAuthenticationPolicy)) { '--' } else { $Silo.ServiceAuthenticationPolicy }
}
'Computer Authentication Policy' = & {
if ([string]::IsNullOrEmpty($Silo.ComputerAuthenticationPolicy)) { '--' } else { $Silo.ComputerAuthenticationPolicy }
}
}
$SiloInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) | Out-Null
} catch {
Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silo Item)"
}
}

if ($HealthCheck.Domain.Security) {
$SiloInfo | Where-Object { $_.'Enforce' -eq 'No' } | Set-Style -Style Warning -Property 'Enforce'
}

if ($InfoLevel.Domain -ge 2) {
foreach ($Silo in $SiloInfo) {
Section -Style NOTOCHeading5 -ExcludeFromTOC "$($Silo.Name)" {
$TableParams = @{
Name = "Authentication Policy Silo - $($Silo.Name)"
List = $true
ColumnWidths = 40, 60
}
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$Silo | Table @TableParams
}
}
} else {
$TableParams = @{
Name = "Authentication Policy Silos - $($Domain.DNSRoot.ToString().ToUpper())"
List = $false
Columns = 'Name', 'Enforce', 'User Authentication Policy', 'Service Authentication Policy', 'Computer Authentication Policy'
ColumnWidths = 20, 12, 23, 23, 22
}
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$SiloInfo | Table @TableParams
}

if ($HealthCheck.Domain.Security -and ($SiloInfo | Where-Object { $_.'Enforce' -eq 'No' })) {
Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
Text 'Best Practice:' -Bold
Text 'Authentication Policy Silos should be set to Enforce mode to actively restrict where privileged accounts can authenticate. Silos in audit mode only log events without enforcing restrictions.'
}
BlankLine
}

try {
$SiloMemberInfo = [System.Collections.ArrayList]::new()
foreach ($Silo in $AuthPolicySilos) {
foreach ($Member in $Silo.Members) {
try {
$MemberObj = Invoke-CommandWithTimeout -Session $TempPssSession -ScriptBlock {
Get-ADObject -Identity $using:Member -Properties DistinguishedName, ObjectClass, SamAccountName -Server $using:ValidDcFromDomain -ErrorAction SilentlyContinue
}
if ($MemberObj) {
$inObj = [ordered] @{
'Silo Name' = $Silo.Name
'Member Name' = & {
if ($MemberObj.SamAccountName) { $MemberObj.SamAccountName } else { $MemberObj.Name }
}
'Object Class' = $TextInfo.ToTitleCase($MemberObj.ObjectClass)
'Distinguished Name' = $MemberObj.DistinguishedName
}
$SiloMemberInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) | Out-Null
}
} catch {
Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silo Member Item)"
}
}
}
if ($SiloMemberInfo) {
Section -Style NOTOCHeading5 -ExcludeFromTOC 'Silo Members' {
Paragraph "The following table lists the accounts assigned to Authentication Policy Silos in domain $($Domain.DNSRoot.ToString().ToUpper())."
BlankLine
$TableParams = @{
Name = "Authentication Policy Silo Members - $($Domain.DNSRoot.ToString().ToUpper())"
List = $false
ColumnWidths = 20, 20, 15, 45
}
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$SiloMemberInfo | Table @TableParams
}
}
} catch {
Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silo Members Table)"
}
}
} catch {
Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silos Section)"
}
} else {
Write-PScriboMessage -Message "No Authentication Policy Silo information found in $($Domain.DNSRoot), Disabling this section."
}
if ($AuthPolicies) {
try {
Section -Style Heading4 'Authentication Policies' {
Paragraph "The following table provides a summary of Authentication Policies configured in domain $($Domain.DNSRoot.ToString().ToUpper())."
BlankLine
$PolicyInfo = [System.Collections.ArrayList]::new()
foreach ($Policy in $AuthPolicies) {
try {
$inObj = [ordered] @{
'Name' = $Policy.Name
'Enforce' = $Policy.Enforce
'Description' = & {
if ([string]::IsNullOrEmpty($Policy.Description)) { '--' } else { $Policy.Description }
}
'User TGT Lifetime (mins)' = & {
if ($null -eq $Policy.UserTGTLifetimeMins -or $Policy.UserTGTLifetimeMins -eq 0) { '--' } else { $Policy.UserTGTLifetimeMins }
}
'Service TGT Lifetime (mins)' = & {
if ($null -eq $Policy.ServiceTGTLifetimeMins -or $Policy.ServiceTGTLifetimeMins -eq 0) { '--' } else { $Policy.ServiceTGTLifetimeMins }
}
'Computer TGT Lifetime (mins)' = & {
if ($null -eq $Policy.ComputerTGTLifetimeMins -or $Policy.ComputerTGTLifetimeMins -eq 0) { '--' } else { $Policy.ComputerTGTLifetimeMins }
}
}
$PolicyInfo.Add([pscustomobject](ConvertTo-HashToYN $inObj)) | Out-Null
} catch {
Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Item)"
}
}

if ($HealthCheck.Domain.Security) {
$PolicyInfo | Where-Object { $_.'Enforce' -eq 'No' } | Set-Style -Style Warning -Property 'Enforce'
}

if ($InfoLevel.Domain -ge 2) {
foreach ($Policy in $PolicyInfo) {
Section -Style NOTOCHeading5 -ExcludeFromTOC "$($Policy.Name)" {
$TableParams = @{
Name = "Authentication Policy - $($Policy.Name)"
List = $true
ColumnWidths = 40, 60
}
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$Policy | Table @TableParams
}
}
} else {
$TableParams = @{
Name = "Authentication Policies - $($Domain.DNSRoot.ToString().ToUpper())"
List = $false
Columns = 'Name', 'Enforce', 'User TGT Lifetime (mins)', 'Service TGT Lifetime (mins)', 'Computer TGT Lifetime (mins)'
ColumnWidths = 20, 12, 23, 23, 22
}
if ($Report.ShowTableCaptions) {
$TableParams['Caption'] = "- $($TableParams.Name)"
}
$PolicyInfo | Table @TableParams
}

if ($HealthCheck.Domain.Security -and ($PolicyInfo | Where-Object { $_.'Enforce' -eq 'No' })) {
Paragraph 'Health Check:' -Bold -Underline
BlankLine
Paragraph {
Text 'Best Practice:' -Bold
Text 'Authentication Policies should be set to Enforce mode to actively restrict Kerberos TGT lifetimes and account sign-in. Policies in audit mode only log events without enforcing restrictions.'
}
BlankLine
}
}
} catch {
Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policies Section)"
}
} else {
Write-PScriboMessage -Message "No Authentication Policy information found in $($Domain.DNSRoot), Disabling this section."
}
}
} else {
Write-PScriboMessage -Message "No Authentication Policy or Silo information found in $($Domain.DNSRoot), Disabling this section."
}
} catch {
Write-PScriboMessage -IsWarning -Message "$($_.Exception.Message) (Authentication Policy Silos Section)"
}
}

end {
Show-AbrDebugExecutionTime -End -TitleMessage 'AD Authentication Policy Silos'
}

}
1 change: 1 addition & 0 deletions Src/Private/Get-AbrDomainSection.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function Get-AbrDomainSection {
Get-AbrADDomain -Domain $DomainInfo -ValidDcFromDomain $ValidDC
Get-AbrADFSMO -Domain $DomainInfo -ValidDcFromDomain $ValidDC
Get-AbrADTrust -Domain $DomainInfo -ValidDcFromDomain $ValidDC
Get-AbrADAuthenticationPolicy -Domain $DomainInfo -ValidDcFromDomain $ValidDC
Get-AbrADHardening -Domain $DomainInfo -ValidDcFromDomain $ValidDC
Get-AbrADDomainObject -Domain $DomainInfo -ValidDcFromDomain $ValidDC
if ($HealthCheck.Domain.Backup -or $HealthCheck.Domain.DFS -or $HealthCheck.Domain.SPN -or $HealthCheck.Domain.Security -or $HealthCheck.Domain.DuplicateObject) {
Expand Down