Set-AaddsResourceForestTrust.ps1

<#PSScriptInfo
 
.VERSION 2.0.0
 
.GUID 37c00032-c3ca-4027-9cb8-afa0b4cfef45
 
.AUTHOR aaddsfb@microsoft.com
 
.COMPANYNAME Microsoft Corporation
 
.COPYRIGHT (c) Microsoft Corporation
 
.TAGS Microsoft-Entra-Domain-Services ForestTrust
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
    07/19/2020 - Initial release
    01/09/2024 - Rebrand to Microsoft Entra Domain Services
    06/24/2025 - Adding new trust direction parameter, that allows one to create a inbound, outbound or bidirectional trust.
               - Updating Entra Domain Services resource API to use the latest version.
#>


<#
 
.SYNOPSIS
    Changes some of the settings on an Microsoft Entra Domain Services forest trust.
 
.DESCRIPTION
 
    Changes some of the settings on an Microsoft Entra Domain Services forest trust.
 
.PARAMETER ManagedDomainFqdn [MANADATORY]
    The fqdn of the managed domain (e.g aadds.corp.contoso.com).
 
.PARAMETER TrustFqdn [MANDATORY]
    The FQDN of the trusted forest.
 
.PARAMETER TrustFriendlyName [OPTIONAL]
    The friendly name of the trust relationship.
 
.PARAMETER TrustDirection [MANDATORY]
    The direction of the trust relationship (Inbound, Outbound, Bidirectional).
 
.PARAMETER TrustDnsIps [OPTIONAL]
    A comma delimited list DNS servers for the
    trusted domain listed as IPv4 addresses.
 
.PARAMETER TrustPassword [OPTIONAL]
    The complex password the trust relationship uses.
 
.PARAMETER Credential [OPTIONAL]
    The credentials used to authenticate to Azure.
#>


[CmdletBinding()]
Param (
    
    [Parameter(
        Mandatory=$true,
        Position=0)]
        [string]
        $ManagedDomainFqdn,

    [Parameter(
        Mandatory=$true,
        Position=1)]
        [string]
        $TrustFqdn,

    [Parameter(
        Mandatory=$false,
        Position=2)]
        [string]
        $TrustFriendlyName,   
        
    [Parameter(
        Mandatory = $true,
        Position = 3,
        HelpMessage = "Specify the direction of the trust relationship. Valid options are: Bidirectional, Inbound, Outbound."
    )]
    [ValidateSet("Bidirectional", "Inbound", "Outbound")]
    [string]
    $TrustDirection,

    [Parameter(
        Mandatory=$false,
        Position=4)]
        [string]
        $TrustDnsIps,

    [Parameter(
        Mandatory=$false,
        Position=5)]
        [string]
        $TrustPassword,

    [Parameter(
        Mandatory=$false,
        Position=6)]
        [pscredential]
        $Credentials
)


Process
{

    #
    # Create empty trust settings
    $TrustSettingsValue = [System.Collections.ArrayList]@()
    $azProfile = $null

    Write-Host ([string]::Empty)
    Write-Host ([string]::Empty)
    Write-Host "Authenticating to Azure... " -NoNewline
    #
    # Collect credentials from the user for authentication
    if($null -ne $creds)
    {
        $creds = Get-Credential -ErrorAction SilentlyContinue        
        $azProfile = Connect-AzAccount -Credential $creds -ErrorAction SilentlyContinue
    }
    else
    {
        $azProfile = Connect-AzAccount -ErrorAction SilentlyContinue
    }

    if($null -eq $azProfile)
    {
        # Authentication failed
        Write-Host -ForegroundColor Red "[Failed!]"
        Write-Host -ForegroundColor Red "ERROR: Could not authenticate to Azure. Check your credentials and try again."
        Return
    }
    
    Write-Host "INFO: Authenticated to Azure as $($azProfile.Account.Id)..."

    Write-Host "Getting Microsoft Entra Domain Services instance..." -NoNewline
    $aadds = Get-AzResource -Name $ManagedDomainFqdn -ApiVersion "2022-12-01" -ExpandProperties -ErrorAction Stop

    if($null -eq $aadds)
    {
        Write-Host -ForegroundColor Red "[Failed!]"
        Write-Host -ForegroundColor Red "ERROR: Could not find an Microsoft Entra Domain Services resource with the name $ManagedDomainFqdn."
        Return

    }
    else
    {
        Write-Host -ForegroundColor Green "[Success!]"
    }

    #region PREREQ CHECKS
    Write-Host ([string]::Empty)
    Write-Host "Checking prerequisites..."

    $pass = $true

    Write-Host "Validating resource type..." -NoNewline
    if($aadds.ResourceType -ne "Microsoft.AAD/domainServices")
    {
        $pass = $false
        Write-Host -ForegroundColor Red "[Failed!]"
        Write-Host -ForegroundColor Red "ERROR: The resource is not an Microsoft Entra Domain Services resource (Status:$($aadds.ResourceType))."
    
    }
    else {Write-Host -ForegroundColor Green "[Pass!]"}


    Write-Host "Validating service status..." -NoNewline
    if($null -ne $aadds.Properties.ReplicaSets)
    {
        $replicaSetCount = $aadds.Properties.ReplicaSets.Count
    }
    else { $replicaSetCount = 0 }

    $serviceStatus = $null
    if($replicaSetCount -eq 1)
    {
        $serviceStatus = $aadds.Properties.ReplicaSets[0].serviceStatus
    }
    elseif($replicaSetCount -gt 1)
    {
        $syncOwner = $aadds.Properties.SyncOwner
        $primaryReplicaSet = $aadds.Properties.ReplicaSets | Where-Object { $_.ReplicaSetId -eq $syncOwner }
        $serviceStatus = $primaryReplicaSet.serviceStatus
    }
    else { $serviceStatus = $null }

    if($serviceStatus -ne "Running")
    {
        $pass = $false
        Write-Host -ForegroundColor Red "[Failed!]"
        Write-Host -ForegroundColor Red "ERROR: The managed domain $($aadds.Name) must be running (Status:$($aadds.properties.serviceStatus))."
    }
    else { Write-Host -ForegroundColor Green "[Pass!]" }

    Write-Host "Finding trust name..." -NoNewline
    #
    # Get a list of the current trusts
    $tempTrustSettingsValue = $aadds.Properties.resourceForestSettings.settings
    if(0 -lt $tempTrustSettingsValue.Count)
    {
        $found = $false
    
        foreach($tempTrustValue in $tempTrustSettingsValue)
        {    
            #check for matching #fqdn
            if($TrustFqdn -eq $tempTrustValue.trustedDomainFqdn)
            { 
                $found = $true
                break;             
            }
        }
    
        if($found)
        { 
            Write-Host -ForegroundColor Green "[Pass!]"
        }
        else
        {
            $pass = $false
            Write-Host -ForegroundColor Red "[Failed!]"
            Write-Host -ForegroundColor Red "ERROR: The trust $TrustFqdn does not exist in the managed domain $($aadds.Name)."
        
        }       
    }
    else # There are no existing trusts to edit
    {
        $pass = $false
        Write-Host -ForegroundColor Red "[Failed!]"
        Write-Host -ForegroundColor Red "ERROR: The managed domain $($aadds.Name) does not have any trusts. Use Add-AaddsResourceForestTrust to add a trust."
    }


    if($pass -eq $false)
    {      
        Write-Host -ForegroundColor Red "ERROR: One or more prerequisites checks failed."
        Return
    }
    #endregion


    #
    # Add existing trusts and substitute the matched trust
    foreach($tempTrustValue in $tempTrustSettingsValue)
    {        
        # Check for matching #fqdn
        if($TrustFqdn -eq $tempTrustValue.trustedDomainFqdn)
        { 
            #$found = $ true
            $oldTrust = $tempTrustValue

            if($TrustFriendlyName -eq [string]::Empty)
                {$TrustFriendlyName = $oldTrust.friendlyName}
            if($TrustDnsIps -eq [string]::Empty)
                {$TrustDnsIps = $oldTrust.remoteDNSIps}
            if($TrustPassword -eq [string]::Empty)
                {$TrustPassword = $oldTrust.trustpassword}                   
        
            # Replace the old trust
            # All properties other than the trustedDomainFqdn and trustDirection can change
            if($null -ne $TrustPassword)
            {
                $newTrust = @{
                    "friendlyName" = $TrustFriendlyName;
                    "trustedDomainFqdn" = $TrustFqdn;
                    "remoteDNSIps" = $TrustDnsIps;
                    "trustPassword" = $TrustPassword;
                    "trustDirection" = $TrustDirection
                }
            }
            else
            {
                
                $newTrust = @{                    
                    "friendlyName" = $TrustFriendlyName;                    
                    "trustedDomainFqdn" = $TrustFqdn;                    
                    "remoteDNSIps" = $TrustDnsIps;
                    "trustDirection" = $TrustDirection
                }
            }

            $catchOutput = $TrustSettingsValue.Add($($newTrust))
        }        
        else
        {
            $catchOutput = $TrustSettingsValue.Add($tempTrustValue)
        }
    }

    #
    # Show old and new settings
    Write-Host ([string]::Empty) 
    
        # Create a datatable
    $compareTable = New-Object system.Data.DataTable “”
    $settingsColumn = New-Object system.Data.DataColumn Setting,([string])
    $oldColumn = New-Object system.Data.DataColumn Old,([string])
    $newColumn = New-Object system.Data.DataColumn New,([string])
    $compareTable.columns.Add($settingsColumn)
    $compareTable.columns.Add($oldColumn)
    $compareTable.Columns.Add($newColumn)

    # FriendlyName
    $friendlyNameRow = $compareTable.NewRow()
    $friendlyNameRow.Setting = "FriendlyName"
    $friendlyNameRow.Old = $oldTrust.FriendlyName
    $friendlyNameRow.New = $newTrust.FriendlyName
    $compareTable.Rows.Add($friendlyNameRow)

    # RemoteRemoteIPs
    $remoteIPsRow = $compareTable.NewRow()
    $remoteIPsRow.Setting = "DNS RemoteIPss"
    $remoteIPsRow.Old = $oldTrust.remoteDNSIps
    $remoteIPsRow.New = $newTrust.remoteDNSIps
    $compareTable.Rows.Add($remoteIPsRow)

    if($null -ne $TrustPassword)
    {
        # TrustPassword
        $trustPasswordRow = $compareTable.NewRow()
        $trustPasswordRow.Setting = "Trust Password"
        $trustPasswordRow.Old = "".PadRight(15,'*')
        $trustPasswordRow.New = "".PadRight(15,'*')
        $compareTable.Rows.add($trustPasswordRow)
    }

    Write-Host ([string]::Empty)
    Write-Host ([string]::Empty)

    Write-Host "Trust: " -NoNewline; Write-Host -ForegroundColor White $TrustFqdn

    #Display the table
    $compareTable | format-table
    

    Write-Host ([string]::Empty)
    $answer = Read-host -Prompt "Type 'Yes' to confirm you want to update the trust $TrustFqdn with these settings."

    if("Yes" -cne $answer)
    {
        Write-Host "User canceled."
        Return 
    }

    # Assign the trust values to the trust settings
    $trustSettings = @{"settings" = $TrustSettingsValue}


    # Assign the trust settings to the ResourceForestSettings
    $resourceForestSettings = @{"resourceForestSettings" = $trustSettings}

    $actionStart = Get-Date

    Write-Host ([string]::Empty)
    Write-Host "Sending request to Azure. This action may take up to five minutes to complete. Please wait..."
    Set-AzResource -ResourceId $aadds.ResourceId -ApiVersion "2022-12-01" -Properties $resourceForestSettings -force
    $actionStop = Get-Date

    Write-Host "Elapsed Time: " ($actionStop - $actionStart)
}


# SIG # Begin signature block
# MIIr7gYJKoZIhvcNAQcCoIIr3zCCK9sCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAjbkihu0J+yKrC
# q5f9iJHLzdeJuk1vWLjflcIu7BcRQKCCEXgwggiIMIIHcKADAgECAhM2AAACBIY2
# eKH0vgR+AAIAAAIEMA0GCSqGSIb3DQEBCwUAMEExEzARBgoJkiaJk/IsZAEZFgNH
# QkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFNRSBDUyBDQSAwMTAe
# Fw0yNDExMDgxMjQ2MTVaFw0yNTExMDgxMjQ2MTVaMC8xLTArBgNVBAMTJE1pY3Jv
# c29mdCBBenVyZSBEZXBlbmRlbmN5IENvZGUgU2lnbjCCASIwDQYJKoZIhvcNAQEB
# BQADggEPADCCAQoCggEBAPMzJ8+5iuzPEvyWyqvQ8Lg6jR9oaO3Jf5qlRjxeD41Y
# bkqKFvk5zW3XfUzy9FaA4vhKYGTav3Afc6srskrKqEz64RPgkApueunqiytGXfNl
# Q7uP7iJJmBBXAcw23PR7cc6xrPvG+h5LDPHf9VT+iBsGyndA4SYH5oq8KVHF5H3j
# HfxNsgz3+YG5tJ6jH+/NptEg/NSoa3Xh78fBV1qX0PVlBGBFXt97ayY6NBwmWNYv
# UY7uLm3XzTNp7YG0WskxTD+vOij0XIc7rAe3EFpdrnWABFEiyaU591tWx48Iln/+
# TFC4K7alwjymJUcz5ia9YNoQVi3t+TbppVyHedzc6tMCAwEAAaOCBYkwggWFMCkG
# CSsGAQQBgjcVCgQcMBowDAYKKwYBBAGCN1sDATAKBggrBgEFBQcDAzA8BgkrBgEE
# AYI3FQcELzAtBiUrBgEEAYI3FQiGkOMNhNW0eITxiz6Fm90Wzp0SgWDigi2HkK4D
# AgFkAgEQMIICdgYIKwYBBQUHAQEEggJoMIICZDBiBggrBgEFBQcwAoZWaHR0cDov
# L2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL0NlcnRzL0JZMlBLSUNTQ0EwMS5B
# TUUuR0JMX0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcnQwUgYIKwYBBQUHMAKGRmh0
# dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0JZMlBLSUNTQ0EwMS5BTUUuR0JMX0FNRSUy
# MENTJTIwQ0ElMjAwMSgyKS5jcnQwUgYIKwYBBQUHMAKGRmh0dHA6Ly9jcmwyLmFt
# ZS5nYmwvYWlhL0JZMlBLSUNTQ0EwMS5BTUUuR0JMX0FNRSUyMENTJTIwQ0ElMjAw
# MSgyKS5jcnQwUgYIKwYBBQUHMAKGRmh0dHA6Ly9jcmwzLmFtZS5nYmwvYWlhL0JZ
# MlBLSUNTQ0EwMS5BTUUuR0JMX0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcnQwUgYI
# KwYBBQUHMAKGRmh0dHA6Ly9jcmw0LmFtZS5nYmwvYWlhL0JZMlBLSUNTQ0EwMS5B
# TUUuR0JMX0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcnQwga0GCCsGAQUFBzAChoGg
# bGRhcDovLy9DTj1BTUUlMjBDUyUyMENBJTIwMDEsQ049QUlBLENOPVB1YmxpYyUy
# MEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9
# QU1FLERDPUdCTD9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9Y2VydGlm
# aWNhdGlvbkF1dGhvcml0eTAdBgNVHQ4EFgQUw39+RvM9ICQzKxoTRcu71FIzSBIw
# DgYDVR0PAQH/BAQDAgeAMEUGA1UdEQQ+MDykOjA4MR4wHAYDVQQLExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xFjAUBgNVBAUTDTIzNjE2OSs1MDMxNTMwggHmBgNVHR8E
# ggHdMIIB2TCCAdWgggHRoIIBzYY/aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br
# aWluZnJhL0NSTC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3JshjFodHRwOi8vY3Js
# MS5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3JshjFodHRwOi8v
# Y3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3JshjFodHRw
# Oi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3JshjFo
# dHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEoMikuY3Js
# hoG9bGRhcDovLy9DTj1BTUUlMjBDUyUyMENBJTIwMDEoMiksQ049QlkyUEtJQ1ND
# QTAxLENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNl
# cyxDTj1Db25maWd1cmF0aW9uLERDPUFNRSxEQz1HQkw/Y2VydGlmaWNhdGVSZXZv
# Y2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50
# MB8GA1UdIwQYMBaAFJZRhOBrb3v+2Aarw/KF5imuavnUMB8GA1UdJQQYMBYGCisG
# AQQBgjdbAwEGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQAqhvUBfHIboRQv
# hZH+qh+g3/ifKd7J5mNS8Xa2FmDB3Nn+aqtVfjg0K3cXYOGQQPTTcBNJGFbrjRy2
# aqwhTqW/w7u1sCFmxMeN/fzHiiIxfCDFcjd2Q4c8N8BuZoZXgr5DONka2VJKTXLh
# g049b9vgWSNVEP8LT2sFfkZ6fuJ7WVWffWSDjWJmvKMjPl4y2boWRQtyN8War2h+
# oFEBEZDMaFZRqu/sDwFpJlarhEJs+qIZsTpKPJnHoCdrgX/MWmJpVqnzSpqajIfz
# CGY6ZQfnDPld6t+A6MLgGX/eGAlXmzLqcUzehzmrZGEEPSn3jrENGOis7Ql9/KtM
# 5d6oErXlMIII6DCCBtCgAwIBAgITHwAAAFHqj/accwyoOwAAAAAAUTANBgkqhkiG
# 9w0BAQsFADA8MRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYD
# QU1FMRAwDgYDVQQDEwdhbWVyb290MB4XDTIxMDUyMTE4NDQxNFoXDTI2MDUyMTE4
# NTQxNFowQTETMBEGCgmSJomT8ixkARkWA0dCTDETMBEGCgmSJomT8ixkARkWA0FN
# RTEVMBMGA1UEAxMMQU1FIENTIENBIDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
# MIIBCgKCAQEAyZpSCX0Bno1W1yqXMhT6BUlJZWpa4p3xFeiTHO4vm2Q6C/azR5xw
# xnyYHrkSGDtS2P9X+KDE64V20mmEQkubxnPNeOVnE2RvdPGxgwlq+BhS3ONdVsQP
# j79q7XgHM9HhzB9+qk0PC9KN1zm9p/seyiRS6JF1dbOqRf1pUl7FAVxmgiCFgV8h
# HIb/rDPXig7FDi3S0yEx2CUDVpIq8jEhG8anUFE1WYxM+ni0S5KHwwKPKV4qyGDo
# DO+9AmDoma3Chyu5WDlW5cdtqXTWsGPE3umtnX6AmlldUFLms4OVR4guKf+n5LIB
# CC6bTiocfXPomqYjYTKx7AGMfaVLaaXmhQIDAQABo4IE3DCCBNgwEgYJKwYBBAGC
# NxUBBAUCAwIAAjAjBgkrBgEEAYI3FQIEFgQUEmgkQiFHy9RrvjHPIKTACyN/P0cw
# HQYDVR0OBBYEFJZRhOBrb3v+2Aarw/KF5imuavnUMIIBBAYDVR0lBIH8MIH5Bgcr
# BgEFAgMFBggrBgEFBQcDAQYIKwYBBQUHAwIGCisGAQQBgjcUAgEGCSsGAQQBgjcV
# BgYKKwYBBAGCNwoDDAYJKwYBBAGCNxUGBggrBgEFBQcDCQYIKwYBBQUIAgIGCisG
# AQQBgjdAAQEGCysGAQQBgjcKAwQBBgorBgEEAYI3CgMEBgkrBgEEAYI3FQUGCisG
# AQQBgjcUAgIGCisGAQQBgjcUAgMGCCsGAQUFBwMDBgorBgEEAYI3WwEBBgorBgEE
# AYI3WwIBBgorBgEEAYI3WwMBBgorBgEEAYI3WwUBBgorBgEEAYI3WwQBBgorBgEE
# AYI3WwQCMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAS
# BgNVHRMBAf8ECDAGAQH/AgEAMB8GA1UdIwQYMBaAFCleUV5krjS566ycDaeMdQHR
# CQsoMIIBaAYDVR0fBIIBXzCCAVswggFXoIIBU6CCAU+GMWh0dHA6Ly9jcmwubWlj
# cm9zb2Z0LmNvbS9wa2lpbmZyYS9jcmwvYW1lcm9vdC5jcmyGI2h0dHA6Ly9jcmwy
# LmFtZS5nYmwvY3JsL2FtZXJvb3QuY3JshiNodHRwOi8vY3JsMy5hbWUuZ2JsL2Ny
# bC9hbWVyb290LmNybIYjaHR0cDovL2NybDEuYW1lLmdibC9jcmwvYW1lcm9vdC5j
# cmyGgapsZGFwOi8vL0NOPWFtZXJvb3QsQ049QU1FUm9vdCxDTj1DRFAsQ049UHVi
# bGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlv
# bixEQz1BTUUsREM9R0JMP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9v
# YmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2ludDCCAasGCCsGAQUFBwEBBIIB
# nTCCAZkwRwYIKwYBBQUHMAKGO2h0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2lp
# bmZyYS9jZXJ0cy9BTUVSb290X2FtZXJvb3QuY3J0MDcGCCsGAQUFBzAChitodHRw
# Oi8vY3JsMi5hbWUuZ2JsL2FpYS9BTUVSb290X2FtZXJvb3QuY3J0MDcGCCsGAQUF
# BzAChitodHRwOi8vY3JsMy5hbWUuZ2JsL2FpYS9BTUVSb290X2FtZXJvb3QuY3J0
# MDcGCCsGAQUFBzAChitodHRwOi8vY3JsMS5hbWUuZ2JsL2FpYS9BTUVSb290X2Ft
# ZXJvb3QuY3J0MIGiBggrBgEFBQcwAoaBlWxkYXA6Ly8vQ049YW1lcm9vdCxDTj1B
# SUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29u
# ZmlndXJhdGlvbixEQz1BTUUsREM9R0JMP2NBQ2VydGlmaWNhdGU/YmFzZT9vYmpl
# Y3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0aG9yaXR5MA0GCSqGSIb3DQEBCwUAA4IC
# AQBQECO3Tw/o317Rrd7yadqcswPx1LvIYymkaTN6KcmuRt6HKa0Xe73Ux2/AQ30T
# fgA9GBJngweRykKBusRzyOU17iIubJvy3gA21dwtqtB0DsoEv1U/ptVu2v++doTC
# J/i+GbssVXkgaX8H+6EOGEmT4evp4GbwR4HwWlc+Dvf8HH8PdUA2Z04CvcwIfckS
# ipbNm84jxJ8XjmTFTWscldL9edj2NsY6iGnyJFIyur2PS7VRYyV3p1VAJp91gj1j
# RQtWEyCB8P5g9nE3z8u0ANaU/hjwEQCrdGyravWgnf2JtG+bT26YAokbc8m+32zU
# tXRO+NK3tAjhOu2FdsG3qNrF4sc7y37R/C+7Pcb/cFfhttqsirepZii4xStcjMOD
# YuXzGm3IJs0b0owHG6oKd7ZOGvHpmmh9K8/DLriD/sq8bURD10qi/wuW8zM7IpLg
# 1vcR9dIK2mc0pj44pc6UX0XbttP/VEJgu3lT2eI9VjWtaKjx38xE9woSMyekPRtz
# TwgfuysF9DkJisr+yA4po/FPxpbBw9c/hBf32DH/GFxteS2pmjgKIbMP8sDukmEq
# 3lVvuWNJsybrZwQvQpvaM49fv+JKpLK5YWYEfwksYRR9wU8Hh/ID9hRCEkbUoQ2W
# 7mMpsp2Nbp/kcn4ivfolUy3Q9Yf0scsQ6WTLYpm+AoCUJTGCGcwwghnIAgEBMFgw
# QTETMBEGCgmSJomT8ixkARkWA0dCTDETMBEGCgmSJomT8ixkARkWA0FNRTEVMBMG
# A1UEAxMMQU1FIENTIENBIDAxAhM2AAACBIY2eKH0vgR+AAIAAAIEMA0GCWCGSAFl
# AwQCAQUAoIGuMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC
# AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCAOKjcwXDayQVgqiYMP
# 6+EWSlRdDVniGliQyUsiqX/XwzBCBgorBgEEAYI3AgEMMTQwMqAUgBIATQBpAGMA
# cgBvAHMAbwBmAHShGoAYaHR0cDovL3d3dy5taWNyb3NvZnQuY29tMA0GCSqGSIb3
# DQEBAQUABIIBANMQ1bVsj8jMJXLksrd+X+vd83XZNBIa4tVVxQ+Wn5GQeK04sCBc
# ZdFFlE6pH43cSnqubk37xckBTzwptTPfnJvjWkOiTpARTDHpqE6fhs2pAlTmzJna
# lFekgzNuepunTo270nHd8RnnPDhP86obFshJu1IB0Ax+kj9EetE5x26dyZii3Vri
# axY56pZ9j4rZmOmMKXXps7Gh8sRQuGkFaLzKKyd71QomgDAFb4KqBaDe27p6Lhxl
# ti2kHbfNvvCIyEVUYhs+RjjhZv10uo8/Qg5mTpXxhKyX2uKs0uRGgR2TooDiufSI
# ZwTBQXnZAkcnISljzoH+iq1vZORoBzqvWr2hgheUMIIXkAYKKwYBBAGCNwMDATGC
# F4Awghd8BgkqhkiG9w0BBwKgghdtMIIXaQIBAzEPMA0GCWCGSAFlAwQCAQUAMIIB
# UgYLKoZIhvcNAQkQAQSgggFBBIIBPTCCATkCAQEGCisGAQQBhFkKAwEwMTANBglg
# hkgBZQMEAgEFAAQgi74IslhF4QTM+NhU/kSIftLvY+QLtrwkgp2IL7jaXckCBmhb
# g14AUBgTMjAyNTA2MjUxNzI5MzcuMDY5WjAEgAIB9KCB0aSBzjCByzELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0
# IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjk2
# MDAtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2
# aWNloIIR6jCCByAwggUIoAMCAQICEzMAAAIE2OAOB5cyWJgAAQAAAgQwDQYJKoZI
# hvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
# BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEm
# MCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjUwMTMw
# MTk0MjQ3WhcNMjYwNDIyMTk0MjQ3WjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgT
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0
# aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjk2MDAtMDVFMC1EOTQ3MSUw
# IwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIICIjANBgkqhkiG
# 9w0BAQEFAAOCAg8AMIICCgKCAgEA8N0m3Hntneur5FhkyF4XxqqoEBsUF056uOF5
# VLzcxUrexC7TuAfd/Y8GRV+w60bf+H6cxjZBXRqXOxC+UvOqimL9+tHl41vnyL9Z
# QKgw99Xf6fAIvfwGc/DPec6NKw6StnLM/VgMkfRbVA8edlTrPaj9/6YKR74FLw/L
# Ov9yjSE85rPEAtbSd0zMNXEZ/QmYFSGM8Nog/2bzltLGxfw0XYDPFHbcYxSCk102
# iP2yYbEIHt08GsikNo/OUWnxRVQkefwoWqZKwUFhsDRWj86ZmDeOpj4jr1Ma4iEg
# vZ0Pxqw11CVsyw5nIa5q9m2gASXr78N9VGJU5S2WOs1Jo5IGkX6aM3fhpavU2NhN
# w4Ja+j7UxCoD7toTOr/DYlOZ078YQ58XZnH/FDe4KHlZRC12zpu4/MsNcTPSMskL
# lDFpKKwWjf+a/YOJb2JDKIUVxGAdLTGjj7dBZmZkDCwRaTUVZ1wU2uIWl759WnSq
# 708/FZX5x8ZB+q4gP4dgJamFob9GFC7BHB52g1oKgNva8vox9PezKSfxRxh8ZPnf
# ZB9i+WiT6QGLjZjDTwexQ0z1gMewKY6/yeTIVMdItO4Fdm6wGfSfUR4vnzD20vkJ
# uAKJwuYjk4/nSgrbVUbPoyirjutwi8KpZY751Aprkmrzl+eCFzrSnBWZHw3Tme3B
# OA4qD9UCAwEAAaOCAUkwggFFMB0GA1UdDgQWBBQadXZLQHBqVvypuqpvr7uDNRmi
# XzAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNVHR8EWDBWMFSg
# UqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3Nv
# ZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYIKwYBBQUHAQEE
# YDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz
# L2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNy
# dDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB
# /wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEAXnL+rEcNh0yzMlAtViSfhUfg4APS
# ZL9JRrCLeMuvQpjo/Eet6BW4UpnHaWpMajW6/L/Xck2+EQ8jaraIYol27a15kCuV
# +8v0PvhdMzKLU7U6Uz7xt3pbclfy7zteZqy6DUO1uFR+fGi7dN9LTkcbPFZwEEBe
# QZkEDDrmvhEIB+H9ReLheq5dxAteyQUidMIx0nmv59FmIhz0dKpM/zUQH/JUlFFd
# IGyDGsBiI5+/kSsgq/vJdcXTZCvxdFGLl94RtJxPvVnNC+AP3p5blDez2vbzlelY
# twTiUk9EWP2se4meOZXjPJKgsOwRT3EyJFs8aY69pwrYq55MOzgUOhTYMCLgL2DU
# 1O6+tFuNtWBTi+aU7DGXDQzjrANNcb+8pghes5JzBqUR7sNEW9gQCQvarlOwl1mz
# GwCS3WelyDSmq4kpgl9/zC3c3FuVzsnCtEIaETUX+Fql0bIRAWmNspibxzuPKEkm
# P5KbmLwUt5YwALize0afI1ku7fdeqWhnhO6a5qz/RSbKMtSxSphZ1vr4ONwDYQcr
# gBF6vQmsuaOyth+TRZ0ecI/0i0SsCtYslF/duotUxL4hIgIfz1ciWwA+JKIqYoNv
# Kf+hw7omDmdMFJJv2uVvKKyI6DnVN17CeItPAnzaeSO9wrLweUD2DHC6RfTTv9S7
# 6EAMN1D3S+eTOR0wggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAVMA0G
# CSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
# bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0
# aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3Jp
# dHkgMjAxMDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNV
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m
# dCBUaW1lLVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
# CgKCAgEA5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51yMo1V/YBf2xK4OK9
# uT4XYDP/XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKDRLemjkZr
# BxTzxXb1hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9cmmvHaus9ja+NSZk
# 2pg7uhp7M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+yOSxR
# nOlwaQ3KNi1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDuaRr3tpK56KTesy+uD
# RedGbsoy1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGa
# RnXNxF803RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2K26oElHovwUDo9Fz
# pk03dJQcNIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG
# 4tG9ahhaYQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZki1ugpoMhXV8wdJGU
# lNi5UPkLiWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLE
# hReTwDwV2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0CAwEAAaOCAd0w
# ggHZMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+
# gpE8RjUpzxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnpcjBcBgNV
# HSAEVTBTMFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYDVR0l
# BAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0P
# BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9
# lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5taWNyb3NvZnQu
# Y29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3Js
# MFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDovL3d3dy5taWNyb3Nv
# ZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJ
# KoZIhvcNAQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pcFLY+TkdkeLEG
# k5c9MTO1OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2
# LpypglYAA7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4U3UkV7nd
# n/OOPcbzaN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECWOKz3+SmJw7wXsFSF
# QrP8DJ6LGYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mjdAy8
# 7JGA0j3mSj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3UwxTSwethQ/gpY3UA8
# x1RtnWN0SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2f
# pCjcZxkoJLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVXVAmxaQFEfnyhYWxz
# /gq77EFmPWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQ
# KBqJC4822rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU5nR0W2rRnj7tfqAx
# M328y+l7vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGby
# oYIDTTCCAjUCAQEwgfmhgdGkgc4wgcsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX
# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg
# Q29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlv
# bnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjo5NjAwLTA1RTAtRDk0NzElMCMG
# A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIa
# AxUAuj2B0cPfvUh/tacMuqs1Rt5PZW6ggYMwgYCkfjB8MQswCQYDVQQGEwJVUzET
# MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV
# TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T
# dGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsFAAIFAOwGqpUwIhgPMjAyNTA2MjUx
# NzA0MjFaGA8yMDI1MDYyNjE3MDQyMVowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA
# 7AaqlQIBADAHAgEAAgIEOzAHAgEAAgITgzAKAgUA7Af8FQIBADA2BgorBgEEAYRZ
# CgQCMSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0G
# CSqGSIb3DQEBCwUAA4IBAQA2MfpNXCAJcBGEl7+f9zz9Z3OymyQbIP1N+yVBX8IC
# OY+AE1xyY2gmihz8Q4DE5BtKjCmNx4k7+z8uTm8Xkv3qK5KsnSA70viLyvcqH33H
# SDGBuA1Gyeu0NU9okIullXwQRqMzRTDpwMxPpOGMZQfss32nKzAGZgo3RboRQ3NH
# Ma0XYW7kJX6Wz4yMF4bHkrLAsAbUsBQV/Gy8CGUMkKzFY22H7a9rtGAJxx8kOQGT
# tWyqpVjLntSwtCHBxj/QKA8q2VjPlx7BRZ3+hqO1N/Fhh+Ak7vJmmK/Y8xGrwyr2
# MQ4zICYudhyVOd+BTDS4Y/tOtrf3/DB+Ab7SDUeezIncMYIEDTCCBAkCAQEwgZMw
# fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl
# ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd
# TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIE2OAOB5cyWJgAAQAA
# AgQwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRAB
# BDAvBgkqhkiG9w0BCQQxIgQgdKJbRwH0erRiBx2DBOBf1hPzaSpJqeyZMAIQmp5D
# J24wgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCD57Xhl/VsKvFXSTOpo38dR
# hCbLu/+pFOpdEkua3Hm5/jCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
# EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv
# ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD
# QSAyMDEwAhMzAAACBNjgDgeXMliYAAEAAAIEMCIEIFbskwUo1KUu2dts08oQ+afZ
# XoPPZ8oAwV0JWlQgCIXgMA0GCSqGSIb3DQEBCwUABIICAAwxTIQr6J7kq/cy2RcS
# 7mu0ePrs9eQZzF/B6QldQTnurV4Ht3UkNeCiu8eX/mMjWn9Fm/9mFMB8NLHgfVsN
# ViZFyllo3gZ6tN1ANRVIislp5+5RK3HjDiamNd9q5IPpZWEHK+DtToAyiSrzdfBb
# eJaxad6dpaDN1NoEPKWO3sqUH8lk1lyyc3PSHWyOaM0yNMnEjOEdfMtA3hDBWKbN
# xiM7jFfbKlrKW7b4tXNdiruqvjuKIv/1n/8iHhPH7KEYsjkyLLKUUx9c/TExdGcJ
# wBJ8pESl3iywO2xBki/Jkr9S9ueHGqU9/+nDX8MVDLCK5YjsPBz4DCIjjNBdc/7h
# ztaIXAdXSzBCtmfwHf6noL+VAyhzPI7Ll/eMq5iKj4/gdhTWQTHtAXD58XHx9bCO
# /Zaavrg0XUHxziw/iTtKQaurtCY+Wr1QsnB2ovP/Zx/l8n6MSzR/5AoJkYIDwu7n
# JGkc0xiBrkbTFZZTc768lAvlzwOdpUL3R9kqA5r3UPPq2IFGg5VCS2f5kPmA9zsw
# s3RftuREx6eyYfc+6MbwPWDHDKRj7VrlHsO1suk/QNVMvls9/Jy0M/Sdez2NeZr+
# tQB0qotXqIn37XTcLJZ19wpO8Lk4VbYLvqDslkvoUfpy5428iisS1M9zxM4ad0b+
# 8BcYhtL98GQM1KnVlVcFjVLz
# SIG # End signature block