Install-NdesServer.ps1

<#PSScriptInfo

.VERSION 4.2

.GUID a52391cf-9c38-4304-8c9b-89f151461f3c

.AUTHOR Richard Hicks

.COMPANYNAME Richard M. Hicks Consulting, Inc.

.COPYRIGHT Copyright (C) 2025-2026 Richard M. Hicks Consulting, Inc. All Rights Reserved.

.LICENSE Licensed under the MIT License. See LICENSE file in the project root for full license information.

.LICENSEURI https://github.com/richardhicks/ndes/blob/main/LICENSE

.PROJECTURI https://github.com/richardhicks/ndes/

.TAGS NDES, SCEP, Intune, PKI, ADCS, Certificate, Microsoft, Windows

#>


<#

.SYNOPSIS
    Installs and configures the Network Device Enrollment Service (NDES) role on Windows Server to support the Microsoft Intune Certificate Connector.

.PARAMETER RaName
    The name of the NDES registration authority (RA).

.PARAMETER CaConfig
    The configuration of the CA to use for NDES. The syntax is 'CA server FQDN\CA common name'. Use certutil.exe -dump to find the CA configuration.

.PARAMETER EnrollmentTemplate
    The name of the NDES certificate template. This is different than the display name of the template shown in the Certification Authority (CA) management console.

.PARAMETER Thumbprint
    The thumbprint of the TLS certificate to use for the NDES service.

.PARAMETER ServiceAccount
    The service account to use for the NDES service. Use the format domain\username. If using a Group Managed Service Account (gMSA), use the format domain\username$ and include the GroupManagedServiceAccount parameter. For standard domain service accounts, the script prompts for the account password and validates it against the domain.

.PARAMETER GroupManagedServiceAccount
    This parameter is optional. If specified, the NDES service will be configured to use a Group Managed Service Account (gMSA) for the SCEP IIS application pool. If RemoveLegacyCertificates is not specified, the gMSA is also granted read access to the RA certificate private keys. If RemoveLegacyCertificates is specified, ensure replacement RA certificates are enrolled from certificate templates that grant the gMSA read access to the private key.

.PARAMETER Fqdn
    This parameter is optional. It is the custom fully qualified domain name (FQDN) for the NDES service when configured behind a load balancer.

.PARAMETER RemoveLegacyCertificates
    This parameter is optional. If specified, any legacy certificates issued to the NDES server will be removed.

.PARAMETER RemoveDefaultTemplates
    This parameter is optional. If specified, the default NDES certificate templates (CEPEncryption, EnrollmentAgentOffline, and IPSECIntermediateOffline) will be unpublished from the CA.

.PARAMETER AutoEnrollment
    This parameter is optional. If specified, a scheduled task will be created to restart the SCEP IIS application pool on certificate renewal events.

.PARAMETER Restart
    This parameter is optional. If specified, the server will be restarted after the NDES role is installed and configured.

.EXAMPLE
    .\Install-NdesServer.ps1 -RaName 'Richard M. Hicks Consulting NDES RA' -CaConfig 'ca1.corp.example.net\Richard M. Hicks Consulting Issuing CA' -Template 'IntuneSCEPEnrollment' -Thumbprint 'B9413E2A1B2F5BFA0AD8A16118198ACC256D0CF9' -ServiceAccount 'corp\svc_ndes' -Restart

    This example installs and configures the NDES role on the local server using the specified parameters. The server will be restarted after the NDES role is installed and configured.

.EXAMPLE
    .\Install-NdesServer.ps1 -RaName 'Richard M. Hicks Consulting NDES RA' -CaConfig 'ca1.corp.example.net\Richard M. Hicks Consulting Issuing CA' -Template 'IntuneSCEPEnrollment' -Thumbprint 'B9413E2A1B2F5BFA0AD8A16118198ACC256D0CF9' -ServiceAccount 'corp\gmsa_ndes$' -GroupManagedServiceAccount

    This example installs and configures the NDES role on the local server using a Group Managed Service Account (gMSA) for the SCEP IIS application pool.

.EXAMPLE
    .\Install-NdesServer.ps1 -RaName 'Richard M. Hicks Consulting NDES RA' -CaConfig 'ca1.corp.example.net\Richard M. Hicks Consulting Issuing CA' -Template 'IntuneSCEPEnrollment' -Thumbprint 'B9413E2A1B2F5BFA0AD8A16118198ACC256D0CF9' -ServiceAccount 'corp\gmsa_ndes$' -GroupManagedServiceAccount -AutoEnrollment

    This example installs and configures the NDES role on the local server using a Group Managed Service Account (gMSA) for the SCEP IIS application pool and creates a scheduled task to restart the SCEP IIS application pool on certificate renewal events.

.EXAMPLE
    .\Install-NdesServer.ps1 -RaName 'Richard M. Hicks Consulting NDES RA' -CaConfig 'ca1.corp.example.net\Richard M. Hicks Consulting Issuing CA' -Template 'IntuneSCEPEnrollment' -Thumbprint 'B9413E2A1B2F5BFA0AD8A16118198ACC256D0CF9' -ServiceAccount 'corp\svc_ndes' -Fqdn 'ndes.corp.example.net'

    This example installs and configures the NDES role on the local server using the specified parameters and a custom FQDN for the NDES service.

.EXAMPLE
    .\Install-NdesServer.ps1 -RaName 'Richard M. Hicks Consulting NDES RA' -CaConfig 'ca1.corp.example.net\Richard M. Hicks Consulting Issuing CA' -Template 'IntuneSCEPEnrollment' -Thumbprint 'B9413E2A1B2F5BFA0AD8A16118198ACC256D0CF9' -ServiceAccount 'corp\svc_ndes' -RemoveLegacyCertificates

    This example installs and configures the NDES role on the local server using the specified parameters and removes any legacy certificates issued to the NDES server.

.DESCRIPTION
    This script installs and configures the Network Device Enrollment Service (NDES) role on Windows Server to support the Microsoft Intune Certificate Connector. It also configures the server to use a specific TLS certificate and enrollment certificate template for NDES.

    In addition, this script performs several post-installation tasks to ensure the NDES service is properly configured, optimized, and secured.

    As part of post-installation hardening, permissions on the HKLM\SOFTWARE\Microsoft\Cryptography\MSCEP registry key are restricted to SYSTEM, Administrators, and the NDES service account, and auditing of configuration changes to this key is enabled (Security log events require the 'Audit Registry' subcategory to be enabled via Group Policy). If the Microsoft Intune Certificate Connector service runs as a custom account instead of SYSTEM, grant that account read access to this registry key manually. Note that changing the SCEP application pool identity after installation will cause NDES to fail until the registry key permissions are updated.

    IMPORTANT NOTE: This script is for configuring NDES to support the Microsoft Intune Certificate Connector. Settings configured by this script will not work with other deployment scenarios.

.LINK
    https://github.com/richardhicks/ndes/blob/main/Install-NdesServer.ps1

.LINK
    https://www.richardhicks.com/

.NOTES
    Version: 4.2
    Creation Date: November 29, 2023
    Last Updated: August 12, 2026
    Author: Richard Hicks
    Organization: Richard M. Hicks Consulting, Inc.
    Contact: rich@richardhicks.com
    Website: https://www.richardhicks.com/

#>


#Requires -Version 5.1
#Requires -RunAsAdministrator

[CmdletBinding(SupportsShouldProcess)]

Param (

    [Parameter(Mandatory, HelpMessage = 'Enter a name for the NDES registration authority (RA)')]
    [ValidateNotNullOrEmpty()]
    [string]$RaName,
    [Parameter(Mandatory, HelpMessage = 'Enter the configuration of the certification authority (CA) to use for NDES. The syntax is `[CA server FQDN`]\`[CA common name`]. Use certutil.exe -dump to find the CA configuration')]
    [ValidateNotNullOrEmpty()]
    [string]$CaConfig,
    [Parameter(Mandatory, HelpMessage = 'Enter the name of the NDES certificate enrollment template')]
    [ValidateNotNullOrEmpty()]
    [Alias('Template')]
    [string]$EnrollmentTemplate,
    [Parameter(Mandatory, HelpMessage = 'Enter the thumbprint of the TLS certificate to use for the NDES service')]
    [ValidateNotNullOrEmpty()]
    # Ensure the thumbprint is 40 characters in length and contains only hexadecimal characters
    [ValidatePattern('^[0-9A-Fa-f]{40}$')]
    [string]$Thumbprint,
    [Parameter(Mandatory, HelpMessage = 'Enter the name of the service account to use for the NDES service. Use the format domain\username. If using a Group Managed Service Account (gMSA), use the format domain\username$')]
    [ValidateNotNullOrEmpty()]
    [string]$ServiceAccount,
    [switch]$GroupManagedServiceAccount,
    [string]$Fqdn,
    [switch]$RemoveLegacyCertificates,
    [switch]$RemoveDefaultTemplates,
    [switch]$AutoEnrollment,
    [switch]$Restart

)

# Ensure verbose output is always displayed and captured in the transcript
$VerbosePreference = 'Continue'

# Create log directory if it doesn't exist
Write-Verbose 'Starting transcript...'
$LogPath = "$env:ProgramData\RMHCI\PowerShell"

If (-not (Test-Path -Path $LogPath)) {

    # Logging is exempt from -WhatIf so the transcript can always be created
    [void](New-Item -Path $LogPath -ItemType Directory -Force -WhatIf:$False)

}

# Start transcript. Exempt from -WhatIf so -WhatIf runs are always logged and Stop-Transcript in the Finally block always succeeds
Start-Transcript -Path "$LogPath\Install-NdesServer_$(Get-Date -Format 'yyyyMMdd-HHmmss').log" -WhatIf:$False

# Record the invocation and bound parameters in the transcript for troubleshooting
Write-Verbose "Invocation: $($MyInvocation.Line.Trim())"
Write-Verbose 'Bound parameters:'
ForEach ($Parameter in $PSBoundParameters.GetEnumerator()) {

    Write-Verbose " -$($Parameter.Key): $($Parameter.Value)"

}

# Begin configuration
Try {

    # Honor -WhatIf and -Confirm for the script as a whole
    If (-not $PSCmdlet.ShouldProcess($env:ComputerName, 'Install and configure the NDES role')) {

        Return

    }

    # Validate the service account
    If ($GroupManagedServiceAccount) {

        # Validate the gMSA account format using a regular expression. The expected format is 'domain\username$'
        $Pattern = '^[^\\]+\\[^\\]+\$$'

        If ($ServiceAccount -match $Pattern) {

            Write-Verbose "Group Managed Service Account (gMSA) $ServiceAccount format is valid."

        }

        Else {

            # Display a warning and exit if the gMSA account isn't formatted correctly
            Write-Warning "The gMSA account $ServiceAccount is not formatted correctly. The correct format is <domain>\<user>$."
            Return

        }

    }

    Else {

        # A trailing $ indicates a gMSA. Exit rather than prompt for a password a gMSA doesn't have
        If ($ServiceAccount -match '\$$') {

            Write-Warning "The service account $ServiceAccount appears to be a Group Managed Service Account (gMSA). Run the script again with the GroupManagedServiceAccount parameter."
            Return

        }

        # Validate the service account format using a regular expression. The expected format is 'domain\username'
        If ($ServiceAccount -notmatch '^[^\\]+\\[^\\]+$') {

            # Display a warning and exit if the service account isn't formatted correctly
            Write-Warning "The service account $ServiceAccount is not formatted correctly. The correct format is <domain>\<user>."
            Return

        }

        # Prompt for the NDES service account password
        $Credential = Get-Credential -UserName $ServiceAccount -Message 'Enter the password for the NDES service account'

        If ($Null -eq $Credential) {

            # Display a warning and exit if the credential prompt was cancelled
            Write-Warning 'No password supplied for the NDES service account. Run the script again and enter the password when prompted.'
            Return

        }

        # Validate the NDES service account credentials against the domain
        Write-Verbose "Validating credentials for NDES service account $ServiceAccount..."
        Add-Type -AssemblyName System.DirectoryServices.AccountManagement
        $PrincipalContext = $Null

        Try {

            # Validate using the account name from the ServiceAccount parameter so it remains authoritative even if the username was altered at the credential prompt
            # GetNetworkCredential exposes the password as plain text in process memory only for the duration of validation
            $SamAccountName = ($ServiceAccount -split '\\')[1]
            $PrincipalContext = [System.DirectoryServices.AccountManagement.PrincipalContext]::new('Domain')
            $CredentialsValid = $PrincipalContext.ValidateCredentials($SamAccountName, $Credential.GetNetworkCredential().Password, 'Negotiate')

        }

        Catch {

            Throw "Unable to validate credentials for '$ServiceAccount'. Verify the server is joined to the domain and a domain controller is reachable. Error: $_"

        }

        Finally {

            # Dispose of the principal context to release the underlying directory connection
            If ($PrincipalContext) {

                $PrincipalContext.Dispose()

            }

        }

        If (-not $CredentialsValid) {

            # Display a warning and exit if credential validation fails
            Write-Warning "The credentials for $ServiceAccount are invalid. Verify the username and password and run the script again."
            Return

        }

        Write-Verbose "Credentials for NDES service account $ServiceAccount validated successfully."

        # Extract the password as a secure string for NDES service configuration
        $Password = $Credential.Password

    }

    # Resolve the service account to a SID. This confirms the account exists in the domain (the only
    # existence check for gMSAs at this point) and is required later to grant standard accounts the
    # 'Log on as a service' right.
    Write-Verbose "Validating service account '$ServiceAccount'..."
    Try {

        $NtAccount = New-Object System.Security.Principal.NTAccount($ServiceAccount)
        $ServiceAccountSid = $NtAccount.Translate([System.Security.Principal.SecurityIdentifier])

    }

    Catch {

        Throw "Could not resolve account '$ServiceAccount' to a SID. Verify the account exists and the format is 'domain\user'. Error: $_"

    }

    # Validate TLS certificate
    Write-Verbose "Validating TLS certificate with thumbprint $Thumbprint..."
    $Certificate = Get-ChildItem -Path cert:\LocalMachine\My\$Thumbprint -ErrorAction SilentlyContinue

    If ($Null -eq $Certificate) {

        # Display a warning and exit if the certificate isn't found
        Write-Warning "Unable to find certificate with thumbprint $Thumbprint."
        Return

    }

    Write-Verbose "Certificate with thumbprint $Thumbprint found."

    # Verify the certificate has an associated private key
    If (-not $Certificate.HasPrivateKey) {

        Write-Warning "Certificate with thumbprint $Thumbprint does not have an associated private key."
        Return

    }

    # Verify the certificate is time valid
    $Now = Get-Date

    If (($Certificate.NotBefore -gt $Now) -or ($Certificate.NotAfter -lt $Now)) {

        Write-Warning "Certificate with thumbprint $Thumbprint is expired or not yet valid (valid from $($Certificate.NotBefore) to $($Certificate.NotAfter))."
        Return

    }

    # Verify the certificate supports server authentication. A certificate without an EKU extension is valid for all purposes
    $ServerAuthOid = '1.3.6.1.5.5.7.3.1'
    $Eku = $Certificate.Extensions | Where-Object { $_ -is [System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension] }

    If ($Eku -and -not ($Eku.EnhancedKeyUsages | Where-Object { $_.Value -eq $ServerAuthOid })) {

        Write-Warning "Certificate with thumbprint $Thumbprint does not include the Server Authentication enhanced key usage."
        Return

    }

    # Grant the service account the "Log on as a service" right (not required for Group Managed Service Accounts (gMSA))
    If (-not $GroupManagedServiceAccount) {

        Write-Verbose "Granting 'Log on as a service' right to NDES service account $ServiceAccount..."

        If (-not ([System.Management.Automation.PSTypeName]'LsaApi').Type) {

            Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;

public class LsaApi
{
    [StructLayout(LayoutKind.Sequential)]
    public struct LSA_UNICODE_STRING
    {
        public ushort Length;
        public ushort MaximumLength;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string Buffer;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LSA_OBJECT_ATTRIBUTES
    {
        public int Length;
        public IntPtr RootDirectory;
        public LSA_UNICODE_STRING ObjectName;
        public uint Attributes;
        public IntPtr SecurityDescriptor;
        public IntPtr SecurityQualityOfService;
    }

    [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
    public static extern uint LsaOpenPolicy(
        ref LSA_UNICODE_STRING SystemName,
        ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
        uint DesiredAccess,
        out IntPtr PolicyHandle);

    [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
    public static extern uint LsaAddAccountRights(
        IntPtr PolicyHandle,
        IntPtr AccountSid,
        LSA_UNICODE_STRING[] UserRights,
        uint CountOfRights);

    [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
    public static extern uint LsaClose(IntPtr ObjectHandle);

    [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
    public static extern uint LsaNtStatusToWinError(uint Status);
}
'@


        }

        Function Grant-LogOnAsService {

            Param (

                [System.Security.Principal.SecurityIdentifier]$Sid

            )

            # Marshal the SID to unmanaged memory
            $SidBytes = New-Object byte[] $Sid.BinaryLength
            $Sid.GetBinaryForm($SidBytes, 0)
            $SidPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SidBytes.Length)
            [System.Runtime.InteropServices.Marshal]::Copy($SidBytes, 0, $SidPtr, $SidBytes.Length)

            Try {

                $objAttr = New-Object LsaApi+LSA_OBJECT_ATTRIBUTES
                $objAttr.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($objAttr)
                $EmptyName = New-Object LsaApi+LSA_UNICODE_STRING
                $PolicyHandle = [IntPtr]::Zero

                # POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES = 0x00000010 | 0x00000800
                $Status = [LsaApi]::LsaOpenPolicy([ref]$EmptyName, [ref]$objAttr, 0x00000810, [ref]$PolicyHandle)

                If ($Status -ne 0) {

                    $WinErr = [LsaApi]::LsaNtStatusToWinError($Status)
                    Throw "LsaOpenPolicy failed. Win32 error: $WinErr"

                }

                Try {

                    $Right = New-Object LsaApi+LSA_UNICODE_STRING
                    $Right.Buffer = 'SeServiceLogonRight'
                    $Right.Length = [uint16]($Right.Buffer.Length * 2)
                    $Right.MaximumLength = [uint16]($Right.Buffer.Length * 2 + 2)

                    $Status = [LsaApi]::LsaAddAccountRights($PolicyHandle, $SidPtr, @($Right), 1)

                    If ($Status -ne 0) {

                        $WinErr = [LsaApi]::LsaNtStatusToWinError($Status)
                        Throw "LsaAddAccountRights failed. Win32 error: $WinErr"

                    }

                    Write-Verbose "Successfully granted 'Log on as a service' to '$ServiceAccount' (SID: $($Sid.Value))."

                }

                Finally {

                    [void]([LsaApi]::LsaClose($PolicyHandle))

                }

            }

            Finally {

                [System.Runtime.InteropServices.Marshal]::FreeHGlobal($SidPtr)

            }

        }

        Grant-LogOnAsService -Sid $ServiceAccountSid

    }

    # Install NDES role and supporting features
    Try {

        Write-Verbose 'Installing NDES role and supporting features...'
        $Install = Install-WindowsFeature -Name @('ADCS-Device-Enrollment', 'Web-Filtering', 'Web-ASP-Net', 'Web-ASP-Net45', 'Web-WMI', 'NET-HTTP-Activation', 'NET-WCF-HTTP-Activation45', 'RSAT-AD-PowerShell') -IncludeManagementTools -ErrorAction Stop

    }

    Catch {

        Write-Warning $_.Exception.Message
        Write-Warning 'An error occurred while installing the NDES role and supporting features. Correct the issue and run the script again.'
        Return

    }

    # Check if the installation was successful (catches silent failures not thrown as exceptions)
    If (-not $Install.Success) {

        Write-Warning 'NDES role or supporting features installation failed. Review the transcript, correct the issue, and run the script again.'
        Return

    }

    # Check if the installation requires a restart
    If ($Install.RestartNeeded -ne 'No') {

        Write-Warning 'A restart is required to complete the NDES role installation. Restart the server and run the script again.'
        Return

    }

    # Backup IIS configuration
    Write-Verbose 'Backing up IIS configuration...'
    $BackupName = "NDES_Install_$((Get-Date).ToString('yyyyMMdd-HHmmss'))"
    [void](& "$env:SystemRoot\System32\inetsrv\appcmd.exe" add backup $BackupName 2>&1)

    If ($LASTEXITCODE -ne 0) {

        Write-Warning "IIS configuration backup failed (exit code $LASTEXITCODE). Proceeding, but a pre-change backup may not exist."

    }

    Else {

        Write-Verbose "IIS configuration backup '$BackupName' created."

    }

    # Install gMSA on local computer and verify functionality (requires RSAT-AD-PowerShell, installed above)
    If ($GroupManagedServiceAccount) {

        # Extract the gMSA SAM account name (strip domain prefix)
        $AccountName = ($ServiceAccount -split '\\')[1]

        # Install the gMSA on the local computer to enable managed password retrieval
        Write-Verbose "Installing gMSA $ServiceAccount on local computer..."
        Try {

            Install-ADServiceAccount -Identity $AccountName -ErrorAction Stop
            Write-Verbose "gMSA $ServiceAccount successfully installed on local computer."

        }

        Catch {

            Throw "Failed to install gMSA '$ServiceAccount' on local computer. Verify the account exists and this computer is authorized to retrieve its managed password. Error: $_"

        }

        # Test gMSA functionality
        Write-Verbose "Testing gMSA $ServiceAccount functionality..."
        $ServiceAccountTest = Test-ADServiceAccount -Identity $AccountName

        If ($ServiceAccountTest) {

            Write-Verbose "gMSA $ServiceAccount is correctly configured and functional."

        }

        Else {

            Write-Warning "gMSA $ServiceAccount is not correctly configured. Verify this computer is a member of the gMSA's PrincipalsAllowedToRetrieveManagedPassword group and that the KDS Root Key has been created."

        }

    }

    # Add NDES service account to local IIS_IUSRS group if required. Adding unconditionally and handling the
    # 'member exists' error avoids Get-LocalGroupMember, which fails if the group contains orphaned SIDs
    Write-Verbose "Adding NDES service account $ServiceAccount to local IIS_IUSRS group..."
    Try {

        Add-LocalGroupMember -Group IIS_IUSRS -Member $ServiceAccount -ErrorAction Stop

    }

    Catch {

        If ($_.FullyQualifiedErrorId -like 'MemberExists,*') {

            Write-Verbose "NDES service account $ServiceAccount is already a member of the local IIS_IUSRS group."

        }

        Else {

            Throw

        }

    }

    # Configure NDES
    Write-Verbose 'Configuring NDES...'
    If ($GroupManagedServiceAccount) {

        # Define configuration parameters when using a Group Managed Service Account (gMSA)
        $Params = @{

            ApplicationPoolIdentity = $True
            RaName                  = $RaName
            SigningProviderName     = 'Microsoft Strong Cryptographic Provider'
            SigningKeyLength        = 2048
            EncryptionProviderName  = 'Microsoft Strong Cryptographic Provider'
            EncryptionKeyLength     = 2048
            CaConfig                = $CaConfig
            Force                   = $True
            ErrorAction             = 'Stop'

        }

    }

    Else {

        # Define configuration parameters when using a standard domain service account
        $Params = @{

            ServiceAccountName     = $ServiceAccount
            ServiceAccountPassword = $Password
            RaName                 = $RaName
            SigningProviderName    = 'Microsoft Strong Cryptographic Provider'
            SigningKeyLength       = 2048
            EncryptionProviderName = 'Microsoft Strong Cryptographic Provider'
            EncryptionKeyLength    = 2048
            CaConfig               = $CaConfig
            Force                  = $True
            ErrorAction            = 'Stop'

        }

    }

    Try {

        # Install NDES
        [void](Install-AdcsNetworkDeviceEnrollmentService @Params)

    }

    Catch {

        # If an error occurs, display a warning and exit the script
        Write-Warning -Message $_.Exception.Message
        Write-Warning 'An error occurred while installing the NDES role. Remove the configuration using the following PowerShell command and run the script again: Uninstall-AdcsNetworkDeviceEnrollmentService -Force'

        If ($_.Exception.HResult -eq -2147024893) {

            Write-Warning "IMPORTANT: The IIS configuration file may be corrupt. Be sure to run the following command before running the script again: & $env:SystemDrive\Windows\System32\inetsrv\appcmd.exe restore backup $BackupName."

        }

        Return

    }

    # Set service principal names (SPNs) for the FQDN and short name. Only required when using a custom FQDN for the NDES service
    If ($Fqdn) {

        ForEach ($Spn in @("http/$Fqdn", "http/$($Fqdn -Replace '(\w+)\..+', '$1')")) {

            Write-Verbose "Registering service principal name (SPN) $Spn for $ServiceAccount..."
            $SpnResult = & setspn.exe -s $Spn $ServiceAccount 2>&1

            If ($LASTEXITCODE -ne 0) {

                Write-Warning "Failed to register SPN $Spn for $ServiceAccount. Resolve the issue or register the SPN manually. Error: $SpnResult"

            }

            Else {

                Write-Verbose "SPN $Spn registered successfully."

            }

        }

    }

    # Disable IE enhanced security. This is required to install the Intune Certificate Connector
    Write-Verbose 'Disabling IE enhanced security...'
    Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}' -Name 'IsInstalled' -Type DWORD -Value '0'
    Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}' -Name 'IsInstalled' -Type DWORD -Value '0'

    # Define NDES certificate templates using the same enrollment template for all three purposes (Encryption, GeneralPurpose, and Signature) for simplicity
    # Note that it is possible (and sometimes preferable) to specify different templates for each purpose if more granular control is required
    Write-Verbose 'Defining NDES certificate template...'
    Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP\ -Name  EncryptionTemplate -Value $EnrollmentTemplate -Force
    Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP\ -Name  GeneralPurposeTemplate -Value $EnrollmentTemplate -Force
    Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP\ -Name  SignatureTemplate -Value $EnrollmentTemplate -Force

    # Enable NDES long URL support
    Write-Verbose 'Enabling IIS long URL support...'
    [void](New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\' -Name MaxFieldLength -Type DWORD -Value 65534 -Force)
    [void](New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\' -Name MaxRequestBytes -Type DWORD -Value 65534 -Force)

    # Update NDES max URL length and max query string values in IIS request filtering
    Write-Verbose 'Setting URL length and max query string values...'
    Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.webServer/security/requestFiltering/requestLimits' -Name 'maxUrl' -Value 65534
    Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.webServer/security/requestFiltering/requestLimits' -Name 'maxQueryString' -Value 65534

    # Remove HTTP site binding if present. The binding may already be removed if the script has run previously.
    # Get-WebBinding parameter filtering is unreliable, so filter on the protocol property and pipe the results
    # to Remove-WebBinding to ensure the removal targets exactly the bindings found
    $HttpBindings = Get-WebBinding -Name 'Default Web Site' | Where-Object { $_.protocol -eq 'http' }

    If ($HttpBindings) {

        Write-Verbose 'Removing HTTP site binding in IIS...'
        [void]($HttpBindings | Remove-WebBinding -Confirm:$false)

    }

    Else {

        Write-Verbose 'HTTP site binding not found. Skipping removal.'

    }

    # Disable IIS default document
    Write-Verbose 'Disabling IIS default document...'
    [void](Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.webServer/defaultDocument' -Name 'Enabled' -Value 'False')

    # Remove default IIS files
    Write-Verbose 'Removing default IIS files...'
    [void](Remove-Item -Path $env:systemdrive\Inetpub\wwwroot\iisstart.* -ErrorAction SilentlyContinue)

    # Remove NDES administration page IIS application if present. The application may already be removed if the script has run previously
    If (Get-WebApplication -Site 'Default Web Site' -Name 'CertSrv/mscep_admin') {

        Write-Verbose 'Removing NDES administration page IIS application...'
        Remove-WebApplication -Site 'Default Web Site' -Name 'CertSrv/mscep_admin' -Confirm:$false

    }

    Else {

        Write-Verbose 'NDES administration page IIS application not found. Skipping removal.'

    }

    # Check for existing certificate binding in IIS. Filter on the protocol property and pipe the results
    # to Remove-WebBinding for the same reasons noted for the HTTP binding removal above
    $HttpsBindings = Get-WebBinding -Name 'Default Web Site' | Where-Object { $_.protocol -eq 'https' }

    If ($HttpsBindings) {

        # Remove existing web binding
        Write-Verbose 'Removing existing HTTPS binding...'
        [void]($HttpsBindings | Remove-WebBinding -Confirm:$false)

    }

    # Configure TLS certificate binding in IIS
    [void](New-WebBinding -Name 'Default Web Site' -Ipaddress '*' -Port 443 -Protocol 'HTTPS' -SslFlags 0)
    (Get-WebBinding -Name 'Default Web Site').AddSslCertificate($Thumbprint, 'My')

    # Configure IIS SCEP application pool to use a Group Managed Service Account (gMSA)
    If ($GroupManagedServiceAccount) {

        Write-Verbose 'Configuring IIS SCEP application pool to use a Group Managed Service Account (gMSA)...'
        [void](Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.applicationHost/applicationPools/add[@name="SCEP"]/processModel' -Name 'identityType' -Value 'SpecificUser')
        [void](Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.applicationHost/applicationPools/add[@name="SCEP"]/processModel' -Name 'userName' -Value $ServiceAccount)

    }

    # Restrict permissions on the MSCEP registry key to SYSTEM, Administrators, and the NDES service
    # account. For gMSA deployments, the initial NDES configuration granted the SCEP application pool
    # virtual account (IIS AppPool\SCEP) permissions on this key and the application pool now runs as
    # the gMSA, so those permissions are mirrored to the gMSA and the legacy application pool entries
    # removed. For standard domain service account deployments, the application pool already runs as
    # the service account
    Write-Verbose "Restricting MSCEP registry key permissions to $ServiceAccount..."
    $MscepRegistryKey = 'HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP'

    # Read the DACL and SACL together so both are updated in a single operation
    $Acl = Get-Acl -Path $MscepRegistryKey -Audit

    # Disable inheritance and discard inherited entries when the ACL is written. PurgeAccessRules
    # cannot remove inherited entries (preserved copies are only created when the ACL is written),
    # so preserving inherited entries would leave the broad-read grants in place. Explicit entries
    # for SYSTEM and Administrators are added below to replace their inherited grants
    $Acl.SetAccessRuleProtection($True, $False)

    # Replace the inherited SYSTEM (S-1-5-18) and Administrators (S-1-5-32-544) grants with
    # explicit entries
    $Acl.AddAccessRule((New-Object System.Security.AccessControl.RegistryAccessRule((New-Object System.Security.Principal.SecurityIdentifier('S-1-5-18')), 'FullControl', 'ContainerInherit', 'None', 'Allow')))
    $Acl.AddAccessRule((New-Object System.Security.AccessControl.RegistryAccessRule((New-Object System.Security.Principal.SecurityIdentifier('S-1-5-32-544')), 'FullControl', 'ContainerInherit', 'None', 'Allow')))

    # Mirror explicit application pool identity entries to the service account (present in gMSA
    # deployments), preserving rights, inheritance, and propagation so MSCEP subkeys remain covered
    $AppPoolAces = @($Acl.Access | Where-Object { -not $_.IsInherited -and $_.IdentityReference.Value -eq 'IIS AppPool\SCEP' })

    ForEach ($Ace in $AppPoolAces) {

        $ServiceAccountRule = New-Object System.Security.AccessControl.RegistryAccessRule($ServiceAccountSid, $Ace.RegistryRights, $Ace.InheritanceFlags, $Ace.PropagationFlags, $Ace.AccessControlType)
        $Acl.AddAccessRule($ServiceAccountRule)

    }

    # Ensure the service account retains access when no application pool entries exist (standard
    # domain service account deployments, or reruns where the entries were already removed by a
    # previous run of this script)
    $SidRules = $Acl.GetAccessRules($True, $False, [System.Security.Principal.SecurityIdentifier])

    If (-not ($SidRules | Where-Object { $_.IdentityReference -eq $ServiceAccountSid })) {

        $ServiceAccountRule = New-Object System.Security.AccessControl.RegistryAccessRule($ServiceAccountSid, 'FullControl', 'ContainerInherit', 'None', 'Allow')
        $Acl.AddAccessRule($ServiceAccountRule)

    }

    # Remove every explicit entry not belonging to SYSTEM, Administrators, or the service account.
    # Sweeping against an identity allowlist (rather than purging a fixed list of SIDs) also removes
    # the application pool entries, capability SIDs, CREATOR OWNER, and any leftover entries from
    # previous runs of this script
    $AllowedSids = @('S-1-5-18', 'S-1-5-32-544', $ServiceAccountSid.Value)

    ForEach ($Identity in ($Acl.Access | Where-Object { -not $_.IsInherited } | Select-Object -ExpandProperty IdentityReference -Unique)) {

        If ($Identity -is [System.Security.Principal.SecurityIdentifier]) {

            $Sid = $Identity

        }

        Else {

            $Sid = $Identity.Translate([System.Security.Principal.SecurityIdentifier])

        }

        If ($AllowedSids -notcontains $Sid.Value) {

            $Acl.PurgeAccessRules($Sid)

        }

    }

    # Add an audit rule (SACL) to record successful and failed attempts by any identity to modify
    # the NDES template configuration (value changes, subkey create/delete, permission or owner
    # changes). Read operations are not audited to avoid Security log noise
    $EveryoneSid = New-Object System.Security.Principal.SecurityIdentifier('S-1-1-0')
    $AuditRule = New-Object System.Security.AccessControl.RegistryAuditRule($EveryoneSid, 'SetValue, CreateSubKey, Delete, ChangePermissions, TakeOwnership', 'ContainerInherit', 'None', 'Success, Failure')
    $Acl.AddAuditRule($AuditRule)

    Set-Acl -Path $MscepRegistryKey -AclObject $Acl
    Write-Verbose 'MSCEP registry key permissions restricted and change auditing enabled.'

    # The audit rule is only effective if the Object Access > Registry audit subcategory is enabled.
    # The subcategory GUID is used for locale independence. Enabling audit policy is deliberately
    # left to the administrator (typically via Group Policy) rather than changed by this script
    $AuditPolicy = & auditpol.exe /get /subcategory:"{0CCE921E-69AE-11D9-BED3-505054503030}" /r 2>&1 | ConvertFrom-Csv

    If ($AuditPolicy.'Inclusion Setting' -notmatch 'Success') {

        Write-Warning "The 'Audit Registry' audit subcategory is not enabled. The MSCEP audit rule will not generate Security log events until it is enabled via Group Policy (Advanced Audit Policy Configuration > Object Access > Audit Registry)."

    }

    # Update RA certificate private key permissions for gMSA deployments. The initial NDES
    # configuration granted key access to the SCEP application pool identity; the application pool
    # now runs as the gMSA. Skip this update when RemoveLegacyCertificates is specified, as those
    # certificates will be removed and their replacements enrolled from certificate templates that
    # define gMSA key permissions
    If ($GroupManagedServiceAccount) {

        If (-not $RemoveLegacyCertificates) {

            Write-Verbose "Updating RA certificate private key permissions for $ServiceAccount..."
            $AppPoolSid = (New-Object System.Security.Principal.NTAccount('IIS AppPool\SCEP')).Translate([System.Security.Principal.SecurityIdentifier])
            $RaCertificates = @(Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Subject -match [regex]::Escape($RaName) -and $_.HasPrivateKey })

            If ($RaCertificates.Count -eq 0) {

                Write-Warning "No RA certificates matching '$RaName' with private keys were found. Verify NDES enrolled its RA certificates successfully."

            }

            ForEach ($RaCertificate in $RaCertificates) {

                $PrivateKey = $RaCertificate.PrivateKey

                If ($Null -eq $PrivateKey) {

                    Write-Warning "Unable to access the private key for RA certificate $($RaCertificate.Thumbprint). Grant $ServiceAccount read access to the private key manually."
                    Continue

                }

                # Grant the gMSA read access and remove the legacy application pool identity entry so key
                # access does not depend on the application pool SID injected into the worker process
                $KeyFile = Join-Path -Path "$env:ProgramData\Microsoft\Crypto\RSA\MachineKeys" -ChildPath $PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
                $KeyAcl = Get-Acl -Path $KeyFile
                $KeyAcl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule($ServiceAccountSid, 'Read', 'Allow')))
                $KeyAcl.PurgeAccessRules($AppPoolSid)
                Set-Acl -Path $KeyFile -AclObject $KeyAcl
                Write-Verbose "Updated private key permissions for RA certificate $($RaCertificate.Thumbprint)."

            }

        }

        Else {

            Write-Verbose 'Skipping RA certificate private key permission update. Legacy RA certificates will be removed and replacement certificates enrolled from templates that define gMSA key permissions.'

        }

    }

    # Restart IIS
    Write-Verbose 'Restarting IIS...'
    [void](Restart-Service -Name W3SVC -Force)

    # Configure the SHA256 hash algorithm for certificate requests
    [void](New-Item -Path 'HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP\HashAlgorithm\' -Force)
    [void](New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP\HashAlgorithm\' -PropertyType String -Name HashAlgorithm -Value SHA256 -Force)

    # Advertise only strong algorithms (SHA-512, SHA-256, and AES) in the SCEP GetCACaps response. This change is
    # not critical because the SCEP exchange is protected with TLS, but it is made to align with security best practices
    Write-Verbose 'Configuring SCEP CA capabilities algorithms...'
    $Path = 'HKLM:\SOFTWARE\Microsoft\Cryptography\MSCEP\CACapabilitiesAlgorithms'

    If (-Not (Test-Path -Path $Path)) {

        [void](New-Item -Path $Path -Force)

    }

    $Params = @{

        Path         = $Path
        Name         = 'CACapabilitiesAlgorithms'
        Value        = @('SHA-512', 'SHA-256', 'AES')
        PropertyType = 'MultiString'
        Force        = $true

    }

    [void](New-ItemProperty @Params)

    If ($AutoEnrollment) {

        # Enable verbose logging for certificate enrollment events
        Write-Verbose 'Enabling verbose logging for certificate enrollment events...'
        [void](Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Cryptography\AutoEnrollment\ -Name AEEventLogLevel -Value 0)

        # Disable overlapped recycling so the old worker process releases the RA certificates before the new one starts
        Write-Verbose 'Disabling overlapped recycling for the SCEP application pool...'
        [void](Set-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.applicationHost/applicationPools/add[@name="SCEP"]/recycling' -Name 'disallowOverlappingRotation' -Value $True)

        # Create scheduled task to restart the SCEP IIS application pool on certificate renewal events
        Write-Verbose 'Creating scheduled task to restart SCEP IIS application pool on certificate renewal events...'
        $User = 'NT AUTHORITY\SYSTEM'
        $Action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NonInteractive -NoLogo -NoProfile Restart-WebAppPool -Name SCEP'
        $CIMTriggerClass = Get-CimClass -ClassName MSFT_TaskEventTrigger -Namespace Root/Microsoft/Windows/TaskScheduler:MSFT_TaskEventTrigger
        $Trigger = New-CimInstance -CimClass $CIMTriggerClass -ClientOnly
        $Trigger.Subscription =
        @'
<QueryList><Query Id="0" Path="Application"><Select Path="Application">*[System[Provider[@Name='Microsoft-Windows-CertificateServicesClient-CertEnroll'] and EventID=20]]</Select></Query></QueryList>
'@

        $Trigger.Enabled = $True

        # Register scheduled task
        Write-Verbose 'Registering scheduled task...'
        [void](Register-ScheduledTask -TaskName 'Restart SCEP IIS Application Pool on Certificate Enrollment' -User $User -Action $Action -Trigger $Trigger -RunLevel Highest -Force)

    }

    # Remove legacy CEP Encryption and Exchange Enrollment Agent (Offline request) certificates
    If ($RemoveLegacyCertificates) {

        Write-Verbose 'Removing legacy certificates...'
        $LegacyCertificates = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Subject -match $RaName }
        ForEach ($LegacyCertificate in $LegacyCertificates) {

            Write-Verbose "Removing legacy certificate $($LegacyCertificate.Thumbprint)..."
            Remove-Item -Path Cert:\LocalMachine\My\$($LegacyCertificate.Thumbprint) -Force

        }

        Write-Warning 'Legacy certificates have been removed. Ensure the server has enrolled for new certificates.'

    }

    # Unpublish default NDES certificate templates
    If ($RemoveDefaultTemplates) {

        Write-Verbose 'Unpublishing default NDES certificate templates from the CA...'
        $Result = & certutil.exe -config "$CaConfig" -setcatemplates '-CEPEncryption,EnrollmentAgentOffline,IPSECIntermediateOffline' 2>&1

        If ($LASTEXITCODE -ne 0) {

            Write-Warning "Failed to remove default NDES certificate templates. Verify the NDES service account has CA administrator permissions or remove them manually. Error: $Result"

        }

        Else {

            Write-Verbose 'Default NDES certificate templates (CEPEncryption, EnrollmentAgentOffline, IPSECIntermediateOffline) successfully unpublished from the CA.'

        }

    }

    # Record that installation and configuration completed so post-transcript steps run only on success
    $InstallComplete = $True

}

Finally {

    # Stop transcript
    Write-Verbose 'Stopping transcript...'
    Stop-Transcript

}

# Restart the server or display post-installation instructions (skipped if the script exited early above)
If ($InstallComplete) {

    If ($Restart) {

        Write-Verbose 'Restarting server...'
        Restart-Computer -Force

    }

    Else {

        Write-Warning 'A restart is required to complete the installation and configuration of the NDES role.'

    }

}

# SIG # Begin signature block
# MIIk7AYJKoZIhvcNAQcCoIIk3TCCJNkCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBHmVtA0XJdt1Ws
# f10cYMQ+LRh7e2K9piKeW4TkiJa7v6CCH6YwggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwggW0MIIDnKADAgECAhAOxitIKuZQm69NGxw+uiH/MA0GCSqG
# SIb3DQEBDAUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5j
# LjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNB
# NDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjYwNTE2MDAwMDAwWhcNMjcwODE3MjM1
# OTU5WjCBhjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV
# BAcTDU1pc3Npb24gVmllam8xJDAiBgNVBAoTG1JpY2hhcmQgTS4gSGlja3MgQ29u
# c3VsdGluZzEkMCIGA1UEAxMbUmljaGFyZCBNLiBIaWNrcyBDb25zdWx0aW5nMFkw
# EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOooTPiege6mCA4AriPO+Xh3mymiiZ+3k
# kn31uJifB2ojzzfY7VkAVKhgj+rcVBnofnj2b8OhvAJ4YaQ2Iwuc6aOCAgMwggH/
# MB8GA1UdIwQYMBaAFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB0GA1UdDgQWBBQJvGhl
# Ahwi6UKROatrFKBmPLmd5TA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUF
# BwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDgYDVR0PAQH/BAQDAgeA
# MBMGA1UdJQQMMAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6
# Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5n
# UlNBNDA5NlNIQTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEz
# ODQyMDIxQ0ExLmNybDCBlAYIKwYBBQUHAQEEgYcwgYQwJAYIKwYBBQUHMAGGGGh0
# dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBcBggrBgEFBQcwAoZQaHR0cDovL2NhY2Vy
# dHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0
# MDk2U0hBMzg0MjAyMUNBMS5jcnQwCQYDVR0TBAIwADANBgkqhkiG9w0BAQwFAAOC
# AgEAbaKnnRcJAMHjuWSc2PG/QhJ0jj4hQVwJIbddYDJNxPmD0cxuuorSiR9gX2nl
# ajqNI9N7Kl+FB3oheRTGh/wp4JgZMpCq0qS0zGJ/N6Js+HmVtbkFaPyYxJMXbIWq
# p9zKkoXtSXkpR6nGZnzYkn3EBcRlu4R6hIJHzM/C2PUztH/Hd4fGIryyD69iHvKx
# zotYdlHHY6+X1ACaQnuCz3TLxs3/CDKhPUXesKcISnXHmm4uCwyVdtGyl7wPuZVk
# +rfCIOeWn+XG5J7L8xwhXCPSJ5fKJ5m8/H5cICLR0I7hI4SUiybE1nG5CZ1hKhbW
# abSfNer1dHH/vSYi80YGXCej/88vZeCGQ9/rrjugsg0yN7WCPqNKjEMTYGWkrt37
# lp4cJqULS+alUbL6x1HBdoBStDE2CFmPivL7cCCtnudqCA6b3XB416/FlRo8t4Lw
# Dc2ty+RDKirWM84Zj3ANTVs5fi43rxClBQwngGdqi5TjriKHGTkEKYRIFTViy6Ie
# JDIboOkCFJU5vM7Curvh4rQnw+aM4CyjwnDwnzwcKQVZC3Iy1T4h/FvmpSgu5ouM
# wjdzaR3cSh4OPDRrfBl1YIOoZEOHcshCaHDC46t8+UyAf70BMlrB7Nj84ORTuKTi
# IlU062VzGeREc1KHJqp/S3/NtArpVUVQEgibRxQ99KJCOV8wggawMIIEmKADAgEC
# AhAIrUCyYNKcTJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVT
# MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
# b20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0Mjkw
# MDAwMDBaFw0zNjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5E
# aWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2Rl
# IFNpZ25pbmcgUlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYw
# n6SOaNhc9es0JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43i
# CH00fUyAVxJrQ5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1
# hz1RGeiQIXhFLqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd
# 6BgTZcV/sk+FLEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObar
# YBLj6Na59zHh3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18eb
# MlrC/2pgVItJwZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYo
# X7BzzosmJQayg9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDz
# d5Ea/ttQokbIYViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8S
# kXbev1jLchApQfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZ
# YIpkVMHMIRroOBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxW
# EQIDAQABo4IBWTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg
# 67Y7+F8Rhvv+YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4c
# D08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUF
# BwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEG
# CCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
# cnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5k
# aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTAT
# MAcGBWeBDAEDMAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6P
# vDqZ01bgAhql+Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V
# 1T9J9Ce7FoFFUP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+
# 3NiAGhEZGM1hmYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcn
# P/2Q0XaG3RywYFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgU
# kpn13c5UbdldAhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6Q
# B7BDf5WIIIJw8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3
# kuZOX956rEnPLqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKL
# QcBIhEuWTatEQOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47v
# tevLt/B3E+bnKD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0
# qFEgu60bhQjiWQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0
# YW6/aOImYIbqyK+p/pQd52MbOoZWeE4wgga0MIIEnKADAgECAhANx6xXBf8hmS5A
# QyIMOkmGMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxE
# aWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMT
# GERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAwMDBaFw0zODAx
# MTQyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5j
# LjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNB
# NDA5NiBTSEEyNTYgMjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
# AoICAQC0eDHTCphBcr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMsVO1DahGPNRcy
# bEKq+RuwOnPhof6pvF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4kftn5B1IpYzT
# qpyFQ/4Bt0mAxAHeHYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8BLuxBG5AvftB
# dsOECS1UkxBvMgEdgkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3
# mmdglTcaarps0wjUjsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwFt+cVFBURJg6z
# MUjZa/zbCclF83bRVFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS
# 5xLrfxnGpTXiUOeSLsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq6gbylsXQskBB
# BnGy3tW/AMOMCZIVNSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqL
# XvJWnY0v5ydPpOjL6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7ps
# NOdgJMoiwOrUG2ZdSoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl9VnePs6BaaeE
# WvjJSjNm2qA+sdFUeEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCC
# AVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunkBnx6yuKQVvYv
# 1Ensy04wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/
# BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggr
# BgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVo
# dHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0
# LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20v
# RGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjAL
# BglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4HPRF2cTC9vgvI
# tTSmf83Qh8WIGjB/T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qEJPe36zwbSI/m
# S83afsl3YTj+IQhQE7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgX
# f9r5nWMQwr8Myb9rEVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe9Vj2AIMD8liy
# rukZ2iA/wdG2th9y1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1UH410ANVko43+
# Cdmu4y81hjajV/gxdEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6A47OvgRaPs+2
# ykgcGV00TYr2Lr3ty9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjsYg39OlV8cipD
# oq7+qNNjqFzeGxcytL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0vw9vODRzW6Ax
# nJll38F0cuJG7uEBYTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAl
# Z66RzIg9sC+NJpud/v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1
# MIDpMPx0LckTetiSuEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZs
# q8WhbaM2tszWkPZPubdcMIIG7TCCBNWgAwIBAgIQCoDvGEuN8QWC0cR2p5V0aDAN
# BgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs
# IEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5n
# IFJTQTQwOTYgU0hBMjU2IDIwMjUgQ0ExMB4XDTI1MDYwNDAwMDAwMFoXDTM2MDkw
# MzIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu
# MTswOQYDVQQDEzJEaWdpQ2VydCBTSEEyNTYgUlNBNDA5NiBUaW1lc3RhbXAgUmVz
# cG9uZGVyIDIwMjUgMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANBG
# rC0Sxp7Q6q5gVrMrV7pvUf+GcAoB38o3zBlCMGMyqJnfFNZx+wvA69HFTBdwbHwB
# SOeLpvPnZ8ZN+vo8dE2/pPvOx/Vj8TchTySA2R4QKpVD7dvNZh6wW2R6kSu9RJt/
# 4QhguSssp3qome7MrxVyfQO9sMx6ZAWjFDYOzDi8SOhPUWlLnh00Cll8pjrUcCV3
# K3E0zz09ldQ//nBZZREr4h/GI6Dxb2UoyrN0ijtUDVHRXdmncOOMA3CoB/iUSROU
# INDT98oksouTMYFOnHoRh6+86Ltc5zjPKHW5KqCvpSduSwhwUmotuQhcg9tw2YD3
# w6ySSSu+3qU8DD+nigNJFmt6LAHvH3KSuNLoZLc1Hf2JNMVL4Q1OpbybpMe46Yce
# NA0LfNsnqcnpJeItK/DhKbPxTTuGoX7wJNdoRORVbPR1VVnDuSeHVZlc4seAO+6d
# 2sC26/PQPdP51ho1zBp+xUIZkpSFA8vWdoUoHLWnqWU3dCCyFG1roSrgHjSHlq8x
# ymLnjCbSLZ49kPmk8iyyizNDIXj//cOgrY7rlRyTlaCCfw7aSUROwnu7zER6EaJ+
# AliL7ojTdS5PWPsWeupWs7NpChUk555K096V1hE0yZIXe+giAwW00aHzrDchIc2b
# Qhpp0IoKRR7YufAkprxMiXAJQ1XCmnCfgPf8+3mnAgMBAAGjggGVMIIBkTAMBgNV
# HRMBAf8EAjAAMB0GA1UdDgQWBBTkO/zyMe39/dfzkXFjGVBDz2GM6DAfBgNVHSME
# GDAWgBTvb1NK6eQGfHrK4pBW9i/USezLTjAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0l
# AQH/BAwwCgYIKwYBBQUHAwgwgZUGCCsGAQUFBwEBBIGIMIGFMCQGCCsGAQUFBzAB
# hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXQYIKwYBBQUHMAKGUWh0dHA6Ly9j
# YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFRpbWVTdGFtcGlu
# Z1JTQTQwOTZTSEEyNTYyMDI1Q0ExLmNydDBfBgNVHR8EWDBWMFSgUqBQhk5odHRw
# Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBp
# bmdSU0E0MDk2U0hBMjU2MjAyNUNBMS5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIw
# CwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQBlKq3xHCcEua5gQezRCESe
# Y0ByIfjk9iJP2zWLpQq1b4URGnwWBdEZD9gBq9fNaNmFj6Eh8/YmRDfxT7C0k8FU
# FqNh+tshgb4O6Lgjg8K8elC4+oWCqnU/ML9lFfim8/9yJmZSe2F8AQ/UdKFOtj7Y
# MTmqPO9mzskgiC3QYIUP2S3HQvHG1FDu+WUqW4daIqToXFE/JQ/EABgfZXLWU0zi
# TN6R3ygQBHMUBaB5bdrPbF6MRYs03h4obEMnxYOX8VBRKe1uNnzQVTeLni2nHkX/
# QqvXnNb+YkDFkxUGtMTaiLR9wjxUxu2hECZpqyU1d0IbX6Wq8/gVutDojBIFeRlq
# AcuEVT0cKsb+zJNEsuEB7O7/cuvTQasnM9AWcIQfVjnzrvwiCZ85EE8LUkqRhoS3
# Y50OHgaY7T/lwd6UArb+BOVAkg2oOvol/DJgddJ35XTxfUlQ+8Hggt8l2Yv7roan
# cJIFcbojBcxlRcGG0LIhp6GvReQGgMgYxQbV1S3CrWqZzBt1R9xJgKf47CdxVRd/
# ndUlQ05oxYy2zRWVFjF7mcr4C34Mj3ocCVccAvlKV9jEnstrniLvUxxVZE/rptb7
# IRE2lskKPIJgbaP5t2nGj/ULLi49xTcBZU8atufk+EMF/cWuiC7POGT75qaL6vdC
# vHlshtjdNXOCIUjsarfNZzGCBJwwggSYAgEBMH0waTELMAkGA1UEBhMCVVMxFzAV
# BgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVk
# IEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQDsYrSCrm
# UJuvTRscProh/zANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKAC
# gAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsx
# DjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCDpdhoFq+fSGvlM1lcDmju3
# c+yBoeAzuBpVIrxkQrKcZzALBgcqhkjOPQIBBQAERzBFAiA9u3098RAqovk5q38/
# kycj81y65PKDaWOJsc+Xr4A//QIhAP8Z86fDX7fhcjuVwsBRiyQovCHwAKFp9Zma
# XZoZIpY7oYIDJjCCAyIGCSqGSIb3DQEJBjGCAxMwggMPAgEBMH0waTELMAkGA1UE
# BhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2Vy
# dCBUcnVzdGVkIEc0IFRpbWVTdGFtcGluZyBSU0E0MDk2IFNIQTI1NiAyMDI1IENB
# MQIQCoDvGEuN8QWC0cR2p5V0aDANBglghkgBZQMEAgEFAKBpMBgGCSqGSIb3DQEJ
# AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI2MDgxMjIwMzQxNFowLwYJ
# KoZIhvcNAQkEMSIEIIfFwbtIbzkL2Uwhk39kgg2q+PqbMN4JtfHMODlf2qJNMA0G
# CSqGSIb3DQEBAQUABIICADNgQpORPmoWKKIXJj7icC5V30EMWNS8NBll7qyArxN5
# c7jQ4zLWvbYQSirtn4VN9zekzSBzPzvJCM64k5JAxFVF/QCOqDKwP/oylraPmtp5
# JTuQjN+IfJpxkNq98ZfqtTziq8je7R7Kpm+fLh/k7+AlHBaWsMCVb78yA/mQF3aB
# CSSrEqXITo4ENc2rYvlzhSeQ5Csx1AxQBKbLLQLkiO+jiwdk6OBvxVouR8ijZtPJ
# LSq+UZDS4bIOrj31R2JrRSLZuhvHpAgySLhFJWQ5epvbLJ7onK7FJKpdyCQmtpJ6
# vUyvqR3gjuM4VT4qICM4K/aGZ+WyYToNXOxcwuybUNSTJjBhgpjSnRYY0v+c0mhR
# VSBBDRRHM83OL1bb24NidUP1sHeHGcj0AYePhFnKCGSTc3LZDbeMXSAj3JVLJPu5
# VVpiYtE15Gngtmg1wWb8qfYo1GDvhgDivPDjdR0RIjH3qeiUjtlkqhGpLQztzKp+
# lo+GPsVG+Y3moXlPOYbh94STth3iBZEwJsG2+Gf5gzCXNfmC9IwdKyMckX7KmLxJ
# c9cdHdzswU+VH0dvYtM5IUKr/7OzFgTLO2sh1oVhkEfIZqF40l04bduyFMgQYTGH
# 0kA94CAGJGUl2WgNbewk1oKAqxaPOudFkwFK3+4yANoZofimwS9XpCIFWGTH3yGT
# SIG # End signature block