Public/New-Tier0AuthPolicyAndSilo.ps1
function New-Tier0AuthPolicyAndSilo { <# .SYNOPSIS Creates and configures Tier 0 Authentication Policies and Silos in Active Directory. .DESCRIPTION This function implements Authentication Policies and Silos specifically for Tier 0 assets in a tiered security model. It creates both audit and enforcement policies for users, computers, and service accounts, then creates corresponding policy silos. The function enables Kerberos claims support, which is a requirement for Authentication Policies and Silos, and then configures the necessary policies with appropriate Security Descriptor Definition Language (SDDL) strings. The Tier 0 Authentication Policies and Silos are designed to limit authentication paths for the most sensitive administrative accounts and resources in the environment, preventing lateral movement and credential theft attacks. .PARAMETER ConfigXMLFile [System.IO.FileInfo] Full path to the XML configuration file. Contains all naming conventions, OU structure, and security settings. Must be a valid XML file with required schema elements. Default: C:\PsScripts\Config.xml .PARAMETER DMScripts Path to all the scripts and files needed by this function. Must contain a SecTmpl subfolder with necessary template files. Default: C:\PsScripts\ .EXAMPLE New-Tier0AuthPolicyAndSilo -ConfigXMLFile "C:\PsScripts\Config.xml" Creates Tier 0 Authentication Policies and Silos using the specified XML configuration file. .EXAMPLE New-Tier0AuthPolicyAndSilo -ConfigXMLFile "C:\PsScripts\Config.xml" -DMScripts "C:\CustomScripts\" Creates Tier 0 Authentication Policies and Silos using the specified XML configuration file and a custom script directory. .EXAMPLE New-Tier0AuthPolicyAndSilo -ConfigXMLFile "C:\PsScripts\Config.xml" -Verbose Creates Tier 0 Authentication Policies and Silos with verbose output logging. .INPUTS [System.IO.FileInfo] - Path to the configuration XML file [System.String] - Path to the directory containing support scripts .OUTPUTS [System.String] - Status message indicating completion .NOTES Used Functions: Name ║ Module/Namespace ═══════════════════════════════════════════╬══════════════════════════════ Import-MyModule ║ EguibarIT Enable-KerberosClaimSupport ║ EguibarIT Get-ADAuthenticationPolicy ║ ActiveDirectory New-ADAuthenticationPolicy ║ ActiveDirectory New-ADAuthenticationPolicySilo ║ ActiveDirectory Grant-ADAuthenticationPolicySiloAccess ║ ActiveDirectory Set-ADUser ║ ActiveDirectory Set-ADComputer ║ ActiveDirectory Get-ADComputer ║ ActiveDirectory Write-Verbose ║ Microsoft.PowerShell.Utility Write-Error ║ Microsoft.PowerShell.Utility Write-Progress ║ Microsoft.PowerShell.Utility Get-FunctionDisplay ║ EguibarIT .NOTES Version: 1.1 DateModified: 9/May/2025 LastModifiedBy: Vicente Rodriguez Eguibar vicente@eguibar.com Eguibar IT http://www.eguibarit.com .LINK https://github.com/vreguibar/EguibarIT .COMPONENT Active Directory Security .ROLE Security Administrator .FUNCTIONALITY Authentication Policy, Authentication Policy Silo, Tier 0, Security #> [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High' )] [OutputType([void])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True, ValueFromRemainingArguments = $false, HelpMessage = 'Full path to the configuration.xml file', Position = 0)] [ValidateScript({ if (-Not ($_ | Test-Path -PathType Leaf) ) { throw ('File not found: {0}' -f $_) } if ($_.Extension -ne '.xml') { throw ('File must be XML: {0}' -f $_) } try { [xml]$xml = Get-Content -Path $_ -ErrorAction Stop if ($null -eq $xml.n.Admin -or $null -eq $xml.n.Admin.LG -or $null -eq $xml.n.Admin.Users -or $null -eq $xml.n.Admin.GPOs -or $null -eq $xml.n.NC) { throw 'XML file is missing required elements (Admin, LG, Users, GPOs or NC section)' } return $true } catch { throw ('Invalid XML file: {0}' -f $_.Exception.Message) } })] [PSDefaultValue(Help = 'Default Value is "C:\PsScripts\Config.xml"', Value = 'C:\PsScripts\Config.xml' )] [Alias('Config', 'XML', 'ConfigXml')] [System.IO.FileInfo] $ConfigXMLFile, [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ValueFromRemainingArguments = $false, HelpMessage = 'Path to all the scripts and files needed by this function', Position = 1)] [PSDefaultValue( Help = 'Default Value is "C:\PsScripts\"', Value = 'C:\PsScripts\' )] [Alias('ScriptPath')] [string] $DMScripts = 'C:\PsScripts\', [Parameter(Mandatory = $false, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $false, ValueFromRemainingArguments = $false, HelpMessage = 'Start transcript logging to DMScripts path with function name', Position = 2)] [Alias('Transcript', 'Log')] [switch] $EnableTranscript ) Begin { Set-StrictMode -Version Latest # Check if running with administrative privileges $CurrentIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent() $WindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($CurrentIdentity) $IsAdmin = $WindowsPrincipal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $IsAdmin) { $ErrorMessage = 'This function requires administrative privileges to create ' + 'and manage Authentication Policies in Active Directory.' Write-Error -Message $ErrorMessage throw $ErrorMessage } # Check if running as Domain Admin or equivalent (needed for AD Authentication Policies) try { $CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name $IsDomainAdmin = $false # Check Domain Admins membership $DomainAdmins = Get-ADGroup -Identity 'Domain Admins' -ErrorAction SilentlyContinue if ($DomainAdmins) { $IsDomainAdmin = Get-ADGroupMember -Identity $DomainAdmins -Recursive -ErrorAction SilentlyContinue | Where-Object { $_.SamAccountName -eq $CurrentUser.Split('\')[1] } } if (-not $IsDomainAdmin) { Write-Warning -Message 'Current user is not a member of Domain Admins. ' + 'Authentication Policy operations may fail due to insufficient permissions.' } } catch { Write-Warning -Message "Failed to verify domain privileges: $($_.Exception.Message)" } If (-not $PSBoundParameters.ContainsKey('ConfigXMLFile')) { $PSBoundParameters['ConfigXMLFile'] = 'C:\PsScripts\Config.xml' } #end If If (-not $PSBoundParameters.ContainsKey('DMScripts')) { $PSBoundParameters['DMScripts'] = 'C:\PsScripts\' } #end If # If EnableTranscript is specified, start a transcript if ($EnableTranscript) { # Ensure DMScripts directory exists if (-not (Test-Path -Path $DMScripts -PathType Container)) { try { New-Item -Path $DMScripts -ItemType Directory -Force | Out-Null Write-Verbose -Message ('Created transcript directory: {0}' -f $DMScripts) } catch { Write-Warning -Message ('Failed to create transcript directory: {0}' -f $_.Exception.Message) } #end try-catch } #end if # Create transcript filename using function name and current date/time $TranscriptFile = Join-Path -Path $DMScripts -ChildPath ('{0}_{1}.LOG' -f $MyInvocation.MyCommand.Name, (Get-Date -Format 'yyyyMMdd_HHmmss')) try { Start-Transcript -Path $TranscriptFile -Force -ErrorAction Stop Write-Verbose -Message ('Transcript started: {0}' -f $TranscriptFile) } catch { Write-Warning -Message ('Failed to start transcript: {0}' -f $_.Exception.Message) } #end try-catch } #end if # Initialize logging if ($null -ne $Variables -and $null -ne $Variables.Header) { $txt = ($Variables.Header -f (Get-Date).ToString('dd/MMM/yyyy'), $MyInvocation.Mycommand, (Get-FunctionDisplay -HashTable $PsBoundParameters -Verbose:$False) ) Write-Verbose -Message $txt } #end If ############################## # Module imports Import-MyModule -Name 'ActiveDirectory' -Verbose:$false Import-MyModule -Name 'EguibarIT' -Verbose:$false Import-MyModule -Name 'EguibarIT.DelegationPS' -Verbose:$false ############################## # Variables Definition # Parameters variable for splatting CMDlets [hashtable]$Splat = [hashtable]::New([StringComparer]::OrdinalIgnoreCase) # Progress reporting variables [int]$ProgressID = 1 [int]$ProgressSteps = 5 [int]$CurrentStep = 0 [hashtable]$ProgressSplat = @{} # Authentication Policy variables [string]$AuditComputerPolicyName = 'T0_AuditOnly_Computers' [string]$AuditUserPolicyName = 'T0_AuditOnly_Users' [string]$AuditServicePolicyName = 'T0_AuditOnly_ServiceAccounts' [string]$EnforceComputerPolicyName = 'T0_Enforce_Computers' [string]$EnforceUserPolicyName = 'T0_Enforce_Users' [string]$EnforceServicePolicyName = 'T0_Enforce_ServiceAccounts' # Authentication Silo variables [string]$AuditingSiloName = 'T0_AuditingSilo' [string]$EnforceSiloName = 'T0_EnforcedSilo' # TGT Lifetime in minutes [int]$UserTGTLifetime = 240 [int]$ComputerTGTLifetime = 120 [int]$ServiceTGTLifetime = 120 # Load the XML configuration file try { $confXML = [xml](Get-Content $PSBoundParameters['ConfigXMLFile']) Write-Debug -Message ('Successfully loaded configuration XML from: {0}' -f $PSBoundParameters['ConfigXMLFile']) } catch { Write-Error -Message ('Error reading XML file: {0}' -f $_.Exception.Message) throw } #end Try-Catch # Load naming conventions from XML [hashtable]$NC = @{ 'sl' = $confXML.n.NC.LocalDomainGroupPreffix 'sg' = $confXML.n.NC.GlobalGroupPreffix 'su' = $confXML.n.NC.UniversalGroupPreffix 'Delim' = $confXML.n.NC.Delimiter 'T0' = $confXML.n.NC.AdminAccSufix0 'T1' = $confXML.n.NC.AdminAccSufix1 'T2' = $confXML.n.NC.AdminAccSufix2 } #region Users Variables $AdminName = Get-SafeVariable -Name 'AdminName' -CreateIfNotExist { try { Get-ADUser -Filter * | Where-Object { $_.SID -like 'S-1-5-21-*-500' } } catch { Write-Debug -Message ('Failed to retrieve Administrator account: {0}' -f $_.Exception.Message) $null } } $newAdminName = Get-SafeVariable -Name 'newAdminName' -CreateIfNotExist { try { $name = $confXML.n.Admin.users.NEWAdmin.Name if ([string]::IsNullOrEmpty($name)) { return $null } Get-AdObjectType -Identity $name } catch { Write-Debug -Message ('Failed to retrieve new admin account: {0}' -f $_.Exception.Message) $null } } #endregion Users Variables #region Local groups Variables $SL_PAWs = Get-SafeVariable -Name 'SL_PAWs' -CreateIfNotExist { $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.PAWs.Name) Get-AdObjectType -Identity $groupName } $SL_InfrastructureServers = Get-SafeVariable -Name 'SL_InfrastructureServers' -CreateIfNotExist { $groupName = ('{0}{1}{2}' -f $NC['sl'], $NC['Delim'], $confXML.n.Admin.LG.InfraServers.Name) Get-AdObjectType -Identity $groupName } #endregion Local groups Variables } #end Begin Process { try { # Configure Kerberos Claims and Authentication Policies/Silos if ($PSCmdlet.ShouldProcess('Active Directory Security', 'Create Authentication Policies and Silos')) { # Update progress: Enabling Kerberos Claims $CurrentStep++ $ProgressSplat = @{ Id = $ProgressID Activity = 'Creating Tier 0 Authentication Policies and Silos' Status = 'Step {0}/{1}: Enabling Kerberos Claims support' -f $CurrentStep, $ProgressSteps PercentComplete = ($CurrentStep / $ProgressSteps) * 100 } Write-Progress @ProgressSplat # Enable Kerberos Claims support first - required for Authentication Policies $Splat = @{ DomainDNSName = $env:USERDNSDOMAIN GeneralGPO = 'C-Baseline' DomainControllerGPO = 'C-{0}-Baseline' -f $confXML.n.Admin.GPOs.DCBaseline.Name Confirm = $false } Write-Verbose -Message 'Enabling Kerberos Claims support via Enable-KerberosClaimSupport' Enable-KerberosClaimSupport @Splat # Reference: https://learn.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/authentication-policies-and-authentication-policy-silos # Build SDDL string with proper format # SDDL reference: https://learn.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format # Using direct string instead of StringBuilder to avoid formatting issues [string]$AllowToAuthenticateFromSDDL = 'O:SYG:SY' # Build the condition part using Domain Controllers SID and our custom groups [string]$DCCondition = '(Member_of {SID(DD)})' [string]$PawsCondition = '(Member_of_any {SID(' + $SL_PAWs.SID.Value + ')})' [string]$InfraCondition = '(Member_of_any {SID(' + $SL_InfrastructureServers.SID.Value + ')})' # Combine conditions with OR operators [string]$FullCondition = '(((' + $DCCondition + ' || ' + $PawsCondition + ' || ' + $InfraCondition + ')))' # Add DACL with ACE - XA=ACCESS_ALLOWED_CALLBACK_ACE, OICI=inheritance flags, CR=control rights, WD=Everyone $AllowToAuthenticateFromSDDL += 'D:(XA;OICI;CR;;;WD;' + $FullCondition + ')' Write-Debug -Message ('SDDL string: {0}' -f $AllowToAuthenticateFromSDDL) #region Create AuditOnly Policies # Update progress: Creating audit policies $CurrentStep++ $ProgressSplat = @{ Id = $ProgressID Activity = 'Creating Tier 0 Authentication Policies and Silos' Status = 'Step {0}/{1}: Creating AuditOnly authentication policies' -f $CurrentStep, $ProgressSteps PercentComplete = ($CurrentStep / $ProgressSteps) * 100 } Write-Progress @ProgressSplat Write-Verbose -Message 'Creating AuditOnly authentication policies' # Computer AUDIT [bool]$PolicyExists = $false try { $PolicyExists = $null -ne (Get-ADAuthenticationPolicy -Filter "Name -eq '$AuditComputerPolicyName'" -ErrorAction Stop) } catch { Write-Debug -Message ('Error checking policy existence: {0}' -f $_.Exception.Message) $PolicyExists = $false } #end Try-Catch If (-Not $PolicyExists) { $Splat = @{ Name = $AuditComputerPolicyName Description = 'This Kerberos Authentication policy used to AUDIT computer logon ' + 'from untrusted computers' ComputerAllowedToAuthenticateTo = $AllowToAuthenticateFromSDDL.ToString() ComputerTGTLifetimeMins = $ComputerTGTLifetime ProtectedFromAccidentalDeletion = $true } Write-Verbose -Message 'Creating T0_AuditOnly_Computers authentication policy' New-ADAuthenticationPolicy @Splat } else { Write-Verbose -Message 'T0_AuditOnly_Computers authentication policy already exists' } #end If-else # User AUDIT $PolicyExists = $false try { $PolicyExists = $null -ne (Get-ADAuthenticationPolicy -Filter "Name -eq '$AuditUserPolicyName'" -ErrorAction Stop) } catch { Write-Debug -Message ('Error checking policy existence: {0}' -f $_.Exception.Message) $PolicyExists = $false } #end Try-Catch If (-Not $PolicyExists) { $Splat = @{ Name = $AuditUserPolicyName Description = 'This Kerberos Authentication policy used to AUDIT interactive logon ' + 'from untrusted users' UserAllowedToAuthenticateFrom = $AllowToAuthenticateFromSDDL.ToString() UserAllowedToAuthenticateTo = $AllowToAuthenticateFromSDDL.ToString() UserTGTLifetimeMins = $UserTGTLifetime ProtectedFromAccidentalDeletion = $true } Write-Verbose -Message 'Creating T0_AuditOnly_Users authentication policy' New-ADAuthenticationPolicy @Splat } else { Write-Verbose -Message 'T0_AuditOnly_Users authentication policy already exists' } #end If-else # ServiceAccounts AUDIT $PolicyExists = $false try { $PolicyExists = $null -ne (Get-ADAuthenticationPolicy -Filter "Name -eq '$AuditServicePolicyName'" -ErrorAction Stop) } catch { Write-Debug -Message ('Error checking policy existence: {0}' -f $_.Exception.Message) $PolicyExists = $false } #end Try-Catch If (-Not $PolicyExists) { $Splat = @{ Name = $AuditServicePolicyName Description = 'This Kerberos Authentication policy used to AUDIT ServiceAccount ' + 'logon from untrusted Service Accounts' ServiceAllowedToAuthenticateFrom = $AllowToAuthenticateFromSDDL.ToString() ServiceAllowedToAuthenticateTo = $AllowToAuthenticateFromSDDL.ToString() ServiceTGTLifetimeMins = $ServiceTGTLifetime ProtectedFromAccidentalDeletion = $true } Write-Verbose -Message 'Creating T0_AuditOnly_ServiceAccounts authentication policy' New-ADAuthenticationPolicy @Splat } else { Write-Verbose -Message 'T0_AuditOnly_ServiceAccounts authentication policy already exists' } #end If-else #endregion Create AuditOnly Policies #region Create ENFORCE policies # Update progress: Creating enforce policies $CurrentStep++ $ProgressSplat = @{ Id = $ProgressID Activity = 'Creating Tier 0 Authentication Policies and Silos' Status = 'Step {0}/{1}: Creating Enforce authentication policies' -f $CurrentStep, $ProgressSteps PercentComplete = ($CurrentStep / $ProgressSteps) * 100 } Write-Progress @ProgressSplat Write-Verbose -Message 'Creating Enforcement authentication policies' # Computer ENFORCE $PolicyExists = $false try { $PolicyExists = $null -ne (Get-ADAuthenticationPolicy -Filter "Name -eq '$EnforceComputerPolicyName'" -ErrorAction Stop) } catch { Write-Debug -Message ('Error checking policy existence: {0}' -f $_.Exception.Message) $PolicyExists = $false } #end Try-Catch If (-Not $PolicyExists) { $Splat = @{ Name = $EnforceComputerPolicyName Description = 'This Kerberos Authentication policy used to ENFORCE ' + 'interactive logon from untrusted computers' ComputerAllowedToAuthenticateTo = $AllowToAuthenticateFromSDDL.ToString() ComputerTGTLifetimeMins = $ComputerTGTLifetime Enforce = $true ProtectedFromAccidentalDeletion = $true } Write-Verbose -Message 'Creating T0_Enforce_Computers authentication policy' New-ADAuthenticationPolicy @Splat } else { Write-Verbose -Message 'T0_Enforce_Computers authentication policy already exists' } #end If-else # User Enforce $PolicyExists = $false try { $PolicyExists = $null -ne (Get-ADAuthenticationPolicy -Filter "Name -eq '$EnforceUserPolicyName'" -ErrorAction Stop) } catch { Write-Debug -Message ('Error checking policy existence: {0}' -f $_.Exception.Message) $PolicyExists = $false } #end Try-Catch If (-Not $PolicyExists) { $Splat = @{ Name = $EnforceUserPolicyName Description = 'This Kerberos Authentication policy used to ENFORCE ' + 'interactive logon from untrusted users' UserAllowedToAuthenticateFrom = $AllowToAuthenticateFromSDDL.ToString() UserAllowedToAuthenticateTo = $AllowToAuthenticateFromSDDL.ToString() UserTGTLifetimeMins = $UserTGTLifetime Enforce = $true ProtectedFromAccidentalDeletion = $true } Write-Verbose -Message 'Creating T0_Enforce_Users authentication policy' New-ADAuthenticationPolicy @Splat } else { Write-Verbose -Message 'T0_Enforce_Users authentication policy already exists' } #end If-else # ServiceAccounts ENFORCE $PolicyExists = $false try { $PolicyExists = $null -ne (Get-ADAuthenticationPolicy -Filter "Name -eq '$EnforceServicePolicyName'" -ErrorAction Stop) } catch { Write-Debug -Message ('Error checking policy existence: {0}' -f $_.Exception.Message) $PolicyExists = $false } #end Try-Catch If (-Not $PolicyExists) { $Splat = @{ Name = $EnforceServicePolicyName Description = 'This Kerberos Authentication policy used to ENFORCE ' + 'interactive logon from untrusted ServiceAccounts' ServiceAllowedToAuthenticateFrom = $AllowToAuthenticateFromSDDL.ToString() ServiceAllowedToAuthenticateTo = $AllowToAuthenticateFromSDDL.ToString() ServiceTGTLifetimeMins = $ServiceTGTLifetime Enforce = $true ProtectedFromAccidentalDeletion = $true } Write-Verbose -Message 'Creating T0_Enforce_ServiceAccounts authentication policy' New-ADAuthenticationPolicy @Splat } else { Write-Verbose -Message 'T0_Enforce_ServiceAccounts authentication policy already exists' } #end If-else #endregion Create ENFORCE policies #region Create Audit-only authentication policy silo and assigning policies # Update progress: Creating policy silos $CurrentStep++ $ProgressSplat = @{ Id = $ProgressID Activity = 'Creating Tier 0 Authentication Policies and Silos' Status = 'Step {0}/{1}: Creating authentication policy silos' -f $CurrentStep, $ProgressSteps PercentComplete = ($CurrentStep / $ProgressSteps) * 100 } Write-Progress @ProgressSplat Write-Verbose -Message 'Creating authentication policy silos' # Check if the audit silo already exists using filter-based query [bool]$SiloExists = $false try { $SiloExists = $null -ne (Get-ADAuthenticationPolicySilo -Filter "Name -eq '$AuditingSiloName'" -ErrorAction Stop) } catch { Write-Debug -Message ('Error checking silo existence: {0}' -f $_.Exception.Message) $SiloExists = $false } #end Try-Catch if (-Not $SiloExists) { try { $Splat = @{ ComputerAuthenticationPolicy = (Get-ADAuthenticationPolicy -Identity $AuditComputerPolicyName) ServiceAuthenticationPolicy = (Get-ADAuthenticationPolicy -Identity $AuditServicePolicyName) UserAuthenticationPolicy = (Get-ADAuthenticationPolicy -Identity $AuditUserPolicyName) Description = 'User, Computer and Service Account Auditing Silo' Name = $AuditingSiloName ProtectedFromAccidentalDeletion = $true } Write-Verbose -Message 'Creating T0_AuditingSilo authentication policy silo' New-ADAuthenticationPolicySilo @Splat } catch { Write-Error -Message ('Failed to create AuditingSilo: {0}' -f $_.Exception.Message) } #end Try-Catch } else { Write-Verbose -Message 'T0_AuditingSilo authentication policy silo already exists' } #end If-else #endregion #region Create Enforced authentication policy silo and assigning policies # Check if the enforce silo already exists using filter-based query $SiloExists = $false try { $SiloExists = $null -ne (Get-ADAuthenticationPolicySilo -Filter "Name -eq '$EnforceSiloName'" -ErrorAction Stop) } catch { Write-Debug -Message ('Error checking silo existence: {0}' -f $_.Exception.Message) $SiloExists = $false } #end Try-Catch if (-Not $SiloExists) { try { $Splat = @{ ComputerAuthenticationPolicy = (Get-ADAuthenticationPolicy -Identity $EnforceComputerPolicyName) ServiceAuthenticationPolicy = (Get-ADAuthenticationPolicy -Identity $EnforceServicePolicyName) UserAuthenticationPolicy = (Get-ADAuthenticationPolicy -Identity $EnforceUserPolicyName) Description = 'User, Computer and Service Account Enforced Silo' Name = $EnforceSiloName Enforce = $true ProtectedFromAccidentalDeletion = $true } Write-Verbose -Message 'Creating T0_EnforcedSilo authentication policy silo' New-ADAuthenticationPolicySilo @Splat } catch { Write-Error -Message ('Failed to create EnforcedSilo: {0}' -f $_.Exception.Message) } #end Try-Catch } else { Write-Verbose -Message 'T0_EnforcedSilo authentication policy silo already exists' } #end If-else #endregion #region Grant access to silos and assign accounts and computers # Update progress: Assigning accounts and computers $CurrentStep++ $ProgressSplat = @{ Id = $ProgressID Activity = 'Creating Tier 0 Authentication Policies and Silos' Status = 'Step {0}/{1}: Granting access to silos and assigning accounts' -f $CurrentStep, $ProgressSteps PercentComplete = ($CurrentStep / $ProgressSteps) * 100 } Write-Progress @ProgressSplat Write-Verbose -Message 'Granting access to silos and assigning accounts and computers' try { # Verify accounts exist if ($null -eq $NewAdminName) { Write-Warning -Message 'NewAdminName account not defined' } else { Write-Verbose -Message ('Granting {0} access to T0_AuditingSilo' -f $NewAdminName.SamAccountName) Grant-ADAuthenticationPolicySiloAccess -Identity 'T0_AuditingSilo' -Account $NewAdminName.SamAccountName } #end If-else if ($null -eq $AdminName) { Write-Warning -Message 'AdminName account not defined' } else { Write-Verbose -Message ('Granting {0} access to T0_AuditingSilo' -f $AdminName.SamAccountName) Grant-ADAuthenticationPolicySiloAccess -Identity 'T0_AuditingSilo' -Account $AdminName.SamAccountName } #end If-else # Get current computer account $CurrentComputer = Get-ADComputer $env:COMPUTERNAME -ErrorAction Stop Write-Verbose -Message ('Granting {0} access to T0_AuditingSilo' -f $env:COMPUTERNAME) Grant-ADAuthenticationPolicySiloAccess -Identity 'T0_AuditingSilo' -Account $CurrentComputer # Assign accounts to silo if ($null -ne $AdminName) { Write-Verbose -Message ('Setting {0} to use T0_AuditingSilo' -f $AdminName.SamAccountName) Set-ADUser -Identity $AdminName -AuthenticationPolicySilo 'T0_AuditingSilo' } #end If if ($null -ne $NewAdminName) { Write-Verbose -Message ('Setting {0} to use T0_AuditingSilo' -f $NewAdminName.SamAccountName) Set-ADUser -Identity $NewAdminName -AuthenticationPolicySilo 'T0_AuditingSilo' } # end If # Assign computer to silo Write-Verbose -Message ('Setting {0} to use T0_AuditingSilo' -f $env:COMPUTERNAME) Set-ADComputer -Identity $env:COMPUTERNAME -AuthenticationPolicySilo 'T0_AuditingSilo' } catch { Write-Error -Message ('Failed to assign authentication policy silos: {0}' -f $_.Exception.Message) } #end Try-Catch #endregion # Return success status Write-Verbose -Message 'Successfully created and configured Tier 0 Authentication Policies and Silos' } #end If ShouldProcess } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] { Write-Error -Message ('Identity not found: {0}' -f $_.Exception.Message) throw } catch [Microsoft.ActiveDirectory.Management.ADException] { Write-Error -Message ('Active Directory error: {0}' -f $_.Exception.Message) throw } catch [System.UnauthorizedAccessException] { Write-Error -Message ('Access denied: {0}' -f $_.Exception.Message) throw } catch { Write-Error -Message ('Unexpected error: {0}' -f $_.Exception.Message) throw } #end Try-Catch } #end Process End { if ($null -ne $Variables -and $null -ne $Variables.Footer) { $txt = ($Variables.Footer -f $MyInvocation.InvocationName, 'Creating Authentication Policies and Silos for Tier 0' ) Write-Verbose -Message $txt } #end If # Stop transcript if it was started if ($EnableTranscript) { try { Stop-Transcript -ErrorAction Stop Write-Verbose -Message 'Transcript stopped successfully' } catch { Write-Warning -Message ('Failed to stop transcript: {0}' -f $_.Exception.Message) } #end Try-Catch } #end If } #end End } #end Function New-Tier0AuthPolicyAndSilo |