OZOAD.psm1

Function Get-OZOADBitLockerRecovery {
    <#
        .SYNOPSIS
        See description.
        .DESCRIPTION
        Returns BitLocker recovery information for a given AD computer object.
        .PARAMETER ComputerName
        The AD computer to query for BitLocker recovery information.
        .EXAMPLE
        Get-OZOADBitLockerRecovery -ComputerName "DESKTOP-OZO80202"
        .LINK
        https://github.com/onezeroone-dev/OZO-PowerShell-Module/blob/main/Documentation/Get-OZOADBitLockerRecovery.md
    #>

    param(
        [Parameter(Mandatory=$true,HelpMessage="Computer name")][String]$ComputerName
    )
    Get-ADObject -Filter 'objectClass -eq "msFVE-RecoveryInformation"' -SearchBase (Get-ADComputer -Identity $ComputerName -ErrorAction Stop).DistinguishedName -Properties CN,whenCreated,msFVE-RecoveryPassword | Sort-Object whenCreated -Descending | Select-Object @{Name="Created";Expression={$_.whenCreated}},@{Name="PasswordID";Expression={[regex]::Matches($_.CN, '(?<={).+?(?=})').Value}},@{Name="Password";Expression={$_."msFVE-RecoveryPassword"}}
}

Function Get-OZOADComputers {
    param (
        [Parameter(Mandatory=$false,HelpMessage='List of computers')][System.Collections.Generic.List[String]]$ComputerList = @(),
        [Parameter(Mandatory=$false,HelpMessage='File containing computers')][String]$ComputerFile = $null,
        [Parameter(Mandatory=$false,HelpMessage='List of properties to obtain for each computer')][Array]$ComputerProperties = "*",
        [Switch]$Enabled
    )
    <#
        .SYNOPSIS
        See description.
        .DESCRIPTION
        Returns an array of AD computers including specified properties.
        .PARAMETER ComputerFile
        A file containing computers to query (one per line). May be combined with ComputerList. Returns all computers when ComputerFile and ComputerList are not provided.
        .PARAMETER ComputerList
        A comma-separated list of computers to query. May be combined with ComputerFile. Returns all computers when ComputerFile and ComputerList are omitted.
        .PARAMETER ComputrProperties
        A comma-separated list of properties to return. When omitted, returns all properties.
        .PARAMETER Enabled
        Return only enabled computers.
        .EXAMPLE
        Get-OZOADComputers -ComputerList "DESKTOP-OZO80202","DESKTOP-OZO80203" -ComputerProperties "createTimeStamp","PrimaryGroup" | Format-Table
        .EXAMPLE
        Get-OZOADComputers -ComputerFile "C:\Temp\computers.txt" -ComputerProperties "createTimeStamp","PrimaryGroup" | Export-Csv -Path "C:\Temp\ozoADComputers.csv"
        .LINK
        https://github.com/onezeroone-dev/OZO-PowerShell-Module/blob/main/Documentation/Get-OZOADUsers.md
    #>

    # Declare variables
    [System.Collections.Generic.List[PSCustomObject]] $ozoADComputers = @()
    # Determine if ComputerFile is provided
    If ([String]::IsNullOrEmpty($ComputerFile) -eq $false) {
        # ComputerFile is provided; append contents to ComputerList
        $ComputerList.Add((Get-Content -Path $ComputerFile -ErrorAction Stop))
    }
    # Determine if ComputerList has content
    If ($ComputerList.Count -gt 0) {
        # ComputerList has content; query identified users
        ForEach ($computer in ($ComputerList | Select-Object -Unique)) {
            $ozoADComputers.Add((Get-AdComputer -Identity $computer -Properties $ComputerProperties -ErrorAction Stop))
        }
    } Else {
        # ComputerList does not have content; query all computers
        $ozoADComputers = (Get-ADComputer -Filter * -ResultSetSize $null -Properties $ComputerProperties)
    }
    # Determine if Enabled is specified
    If ($Enabled -eq $true) {
        # Enabled is specified; return only enabled computers
        return $PSCmdlet.WriteObject(($ozoADComputers | Where-Object {$_.Enabled -eq $true} | Select-Object -Property $ComputerProperties))
    } Else {
        # Enabled is not specified; return all computers
        return $PSCmdlet.WriteObject(($ozoADComputers | Select-Object -Property $ComputerProperties))
    }
}

Function Get-OZOADUsers {
    <#
        .SYNOPSIS
        See description.
        .DESCRIPTION
        Returns an array of AD users including specified properties.
        .PARAMETER UserFile
        A file containing users to query (one per line). May be combined with UserList. Returns all users when UserFile and UserList are not provided.
        .PARAMETER UserList
        A comma-separated list of users to query. May be combined with UserFile. Returns all users when UserFile and UserList are omitted.
        .PARAMETER UserProperties
        A comma-separated list of properties to return. When omitted, returns all properties.
        .PARAMETER Enabled
        Return only enabled users.
        .EXAMPLE
        Get-OZOADUsers -UserList "msantos","gkaplan" -UserProperties "DisplayName","EmailAddress" | Format-Table
        .EXAMPLE
        Get-OZOADUsers -UserFile "C:\Temp\users.txt" -UserProperties "DisplayName","EmailAddress" | Export-Csv -Path "C:\Temp\ozoADUsers.csv"
        .LINK
        https://github.com/onezeroone-dev/OZO-PowerShell-Module/blob/main/Documentation/Get-OZOADUsers.md
    #>

    param (
        [Parameter(Mandatory=$false,HelpMessage='List of users')][System.Collections.Generic.List[String]]$UserList = @(),
        [Parameter(Mandatory=$false,HelpMessage='File containing users')][String]$UserFile = $null,
        [Parameter(Mandatory=$false,HelpMessage='List of properties to obtain for each user')][Array]$UserProperties = "*",
        [Switch]$Enabled
    )

    # Declare variables
    [System.Collections.Generic.List[PSCustomObject]] $ozoADUsers = @()
    # Determine if UserFile is provided
    If ([String]::IsNullOrEmpty($UserFile) -eq $false) {
        # UserFile is provided; append contents to UserList
        $UserList.Add((Get-Content -Path $UserFile -ErrorAction Stop))
    }
    # Determine if UserList has content
    If ($UserList.Count -gt 0) {
        # UserList has content; query identified users
        ForEach ($user in ($UserList | Select-Object -Unique)) {
            $ozoADUsers.Add((Get-AdUser -Identity $user -Properties $UserProperties -ErrorAction Stop))
        }
    } Else {
        # UserList does not have content; query all users
        $ozoADUsers = (Get-ADUser -Filter * -ResultSetSize $null -Properties $UserProperties)
    }
    # Determine if Enabled is specified
    If ($Enabled -eq $true) {
        # Enabled is specified; return only enabled users
        return $PSCmdlet.WriteObject(($ozoADUsers | Where-Object {$_.Enabled -eq $true} | Select-Object -Property $UserProperties))
    } Else {
        # Enabled is not specified; return all users
        return $PSCmdlet.WriteObject(($ozoADUsers | Select-Object -Property $UserProperties))
    }
}

Function New-OZOADExtendedRightsMap {
    <#
        .SYNOPSIS
        See description.
        .DESCRIPTION
        Creates a extended rights map which can be used for AD delegation tasks.
        .EXAMPLE
        [Hashtable]$erMap = (New-OZOADExtendedRightsMap)
        .LINK
        https://github.com/onezeroone-dev/OZO-PowerShell-Module/blob/main/Documentation/New-OZOADExtendedRightsMap.md
    #>

    # Declare variables
    [PSCustomObject] $rootdse = Get-ADRootDSE
    [Hashtable] $extendedrightsmap = @{}
    # Define parameters
    $ExtendedMapParams = @{
        SearchBase = ($rootdse.ConfigurationNamingContext)
        LDAPFilter = "(&(objectclass=controlAccessRight)(rightsguid=*))"
        Properties = ("displayName", "rightsGuid")
    }
    # Populate the hashtable
    Get-ADObject @ExtendedMapParams | ForEach-Object { $extendedrightsmap[$_.displayName] = [System.GUID]$_.rightsGuid }
    # Return
    return $extendedrightsmap
}

Function New-OZOADGuidMap {
    <#
        .SYNOPSIS
        See description
        .DESCRIPTION
        Returns aa GUID map which can be used for AD delegation tasks.
        .EXAMPLE
        [Hashtable]$guidMap = (New-OZOADGuidMap)
        .OUTPUTS
        Hashtable
        .LINK
        https://github.com/onezeroone-dev/OZO-PowerShell-Module/blob/main/Documentation/New-OZOADGuidMap.md
    #>

    # Declare variables
    [PsCustomObject] $rootdse = Get-ADRootDSE
    [Hashtable] $guidmap = @{}
    # Define parameters
    $GuidMapParams = @{
        SearchBase = ($rootdse.SchemaNamingContext)
        LDAPFilter = "(schemaidguid=*)"
        Properties = ("lDAPDisplayName", "schemaIDGUID")
    }
    # Populate the hashtable
    Get-ADObject @GuidMapParams | ForEach-Object { $guidmap[$_.lDAPDisplayName] = [System.GUID]$_.schemaIDGUID }
    # Return
    return $guidmap
}

Function Set-OZOADPad {
    <#
        .SYNOPSIS
        See description.
        .DESCRIPTION
        Enables or disables Protection from Accidental Deletion for a given OU and all child OUs. Default action is Enable.
        .PARAMETER OrganizationalUnitDN
        The distinguished name of the organizational unit to process.
        .PARAMETER Disable
        Disable Protection from Accidental Deletion for the OU and all child OUs.
        .EXAMPLE
        Set-OZOADPad -OrganizationalUnitDN "OU=People,DC=contoso,DC=com"
        .EXAMPLE
        Set-OZOADPad -OrganizationalUnitDN "OU=People,DC=contoso,DC=com" -Disable
        .LINK
        https://github.com/onezeroone-dev/OZO-PowerShell-Module/blob/main/Documentation/Set-OZOADPad.md
    #>

    param(
        [Parameter(Mandatory=$true,HelpMessage="The distinguished name of the organizational unit to process")][String]$OrganizationalUnitDN,
        [Parameter(Mandatory=$false,HelpMessage="Enable or disable Protection from Accidental Deletion")][Switch]$Disable
    )
    # Declare variables
    [Boolean] $Enable = $true
    # Determine if Disable is specified
    If ($Disable -eq $true) { $Enable = $false }
    # Set the flag
    Get-ADOrganizationalUnit -Filter * -SearchBase $OrganizationalUnitDN -SearchScope Subtree | ForEach-Object { Set-ADOrganizationalUnit -Identity $_.DistinguishedName -ProtectedFromAccidentalDeletion $Enable }
}

Export-ModuleMember -Function Get-OZOADBitLockerRecovery,Get-OZOADComputers,Get-OZOADUsers,New-OZOADExtendedRightsMap,New-OZOADGuidMap,Set-OZOADPad

# SIG # Begin signature block
# MIIfcgYJKoZIhvcNAQcCoIIfYzCCH18CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDZGs/ayXwsKtQ4
# PsTnpnPrVYa/juTH81Hr7EYTjoqyhqCCDPgwggZyMIIEWqADAgECAghkM1HTxzif
# CDANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx
# EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8G
# A1UEAwwoU1NMLmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTAe
# Fw0xNjA2MjQyMDQ0MzBaFw0zMTA2MjQyMDQ0MzBaMHgxCzAJBgNVBAYTAlVTMQ4w
# DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENv
# cnAxNDAyBgNVBAMMK1NTTC5jb20gQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBD
# QSBSU0EgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCfgxNzqrDG
# bSHL24t6h3TQcdyOl3Ka5LuINLTdgAPGL0WkdJq/Hg9Q6p5tePOf+lEmqT2d0bKU
# Vz77OYkbkStW72fL5gvjDjmMxjX0jD3dJekBrBdCfVgWQNz51ShEHZVkMGE6ZPKX
# 13NMfXsjAm3zdetVPW+qLcSvvnSsXf5qtvzqXHnpD0OctVIFD+8+sbGP0EmtpuNC
# GVQ/8y8Ooct8/hP5IznaJRy4PgBKOm8yMDdkHseudQfYVdIYyQ6KvKNc8HwKp4WB
# wg6vj5lc02AlvINaaRwlE81y9eucgJvcLGfE3ckJmNVz68Qho+Uyjj4vUpjGYDdk
# jLJvSlRyGMwnh/rNdaJjIUy1PWT9K6abVa8mTGC0uVz+q0O9rdATZlAfC9KJpv/X
# gAbxwxECMzNhF/dWH44vO2jnFfF3VkopngPawismYTJboFblSSmNNqf1x1KiVgMg
# Lzh4gL32Bq5BNMuURb2bx4kYHwu6/6muakCZE93vUN8BuvIE1tAx3zQ4XldbyDge
# VtSsSKbt//m4wTvtwiS+RGCnd83VPZhZtEPqqmB9zcLlL/Hr9dQg1Zc0bl0EawUR
# 0tOSjAknRO1PNTFGfnQZBWLsiePqI3CY5NEv1IoTGEaTZeVYc9NMPSd6Ij/D+KNV
# t/nmh4LsRR7Fbjp8sU65q2j3m2PVkUG8qQIDAQABo4H7MIH4MA8GA1UdEwEB/wQF
# MAMBAf8wHwYDVR0jBBgwFoAU3QQJB6L1en1SUxKSle44gCUNplkwMAYIKwYBBQUH
# AQEEJDAiMCAGCCsGAQUFBzABhhRodHRwOi8vb2NzcHMuc3NsLmNvbTARBgNVHSAE
# CjAIMAYGBFUdIAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwOwYDVR0fBDQwMjAwoC6g
# LIYqaHR0cDovL2NybHMuc3NsLmNvbS9zc2wuY29tLXJzYS1Sb290Q0EuY3JsMB0G
# A1UdDgQWBBRUwv4QlQCTzWr158DX2bJLuI8M4zAOBgNVHQ8BAf8EBAMCAYYwDQYJ
# KoZIhvcNAQELBQADggIBAPUPJodwr5miyvXWyfCNZj05gtOII9iCv49UhCe204MH
# 154niU2EjlTRIO5gQ9tXQjzHsJX2vszqoz2OTwbGK1mGf+tzG8rlQCbgPW/M9r1x
# xs19DiBAOdYF0q+UCL9/wlG3K7V7gyHwY9rlnOFpLnUdTsthHvWlM98CnRXZ7WmT
# V7pGRS6AvGW+5xI+3kf/kJwQrfZWsqTU+tb8LryXIbN2g9KR+gZQ0bGAKID+260P
# Z+34fdzZcFt6umi1s0pmF4/n8OdX3Wn+vF7h1YyfE7uVmhX7eSuF1W0+Z0duGwdc
# +1RFDxYRLhHDsLy1bhwzV5Qe/kI0Ro4xUE7bM1eV+jjk5hLbq1guRbfZIsr0WkdJ
# LCjoT4xCPGRo6eZDrBmRqccTgl/8cQo3t51Qezxd96JSgjXktefTCm9r/o35pNfV
# HUvnfWII+NnXrJlJ27WEQRQu9i5gl1NLmv7xiHp0up516eDap8nMLDt7TAp4z5T3
# NmC2gzyKVMtODWgqlBF1JhTqIDfM63kXdlV4cW3iSTgzN9vkbFnHI2LmvM4uVEv9
# XgMqyN0eS3FE0HU+MWJliymm7STheh2ENH+kF3y0rH0/NVjLw78a3Z9UVm1F5VPz
# iIorMaPKPlDRADTsJwjDZ8Zc6Gi/zy4WZbg8Zv87spWrmo2dzJTw7XhQf+xkR6Od
# MIIGfjCCBGagAwIBAgIQZ2iSsNbwOsjnLExSAX6F6DANBgkqhkiG9w0BAQsFADB4
# MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24x
# ETAPBgNVBAoMCFNTTCBDb3JwMTQwMgYDVQQDDCtTU0wuY29tIENvZGUgU2lnbmlu
# ZyBJbnRlcm1lZGlhdGUgQ0EgUlNBIFIxMB4XDTI0MTExNjEwMzUyOFoXDTI1MTEx
# NjEwMzUyOFowZTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCENvbG9yYWRvMQ8wDQYD
# VQQHDAZEZW52ZXIxGDAWBgNVBAoMD0FuZHJldyBMaWV2ZXJ0ejEYMBYGA1UEAwwP
# QW5kcmV3IExpZXZlcnR6MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA
# vIBAQzK0aahepOrPmvCEqfd6dMZC4GvV7kflKwrn4QPJGfqhFmUtadP1e3ange8O
# QZ3/w7UjOTAUNUHfhjbSgUBlKjbS6EWQKZuRFzI3SNkMJkcjTX4uS2P4QsnwM+SW
# IE5me3CTssdjtgue+Iiy53TMgW8JpoxiULVxmm3bhCRUAgxWeT6tzjytR1UyGcMc
# cm/YE6TOgsCHiZoo4X4HJD9iHDrNldArq04Jl6FsADxEswttKyfqpIRJLoAysVl1
# f8CEDBwhszJrEXBnAlWViJFfNY+dKP4jhf7lLqSvPCuADqP2jvM0Ym5I8qDGMz9j
# XPSMLF58MFB4vM4viS7nLRFJ8S1Q98vQvB8W4kk0WPuiZbZTHsROzohE1VSbLnIY
# ag5dDOWI8L6yutAsfdZFYFmSTKcMSiOj5VbK4LhAJUL2G8vPwpTGFgr+cEp0p62F
# P0WXK+/cRfGqodI5S+bg+9rQTD9zf829DwraSRAt5P5zrQk4WPst3JW/vIKNx7cV
# AgMBAAGjggGVMIIBkTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFFTC/hCVAJPN
# avXnwNfZsku4jwzjMHoGCCsGAQUFBwEBBG4wbDBIBggrBgEFBQcwAoY8aHR0cDov
# L2NlcnQuc3NsLmNvbS9TU0xjb20tU3ViQ0EtQ29kZVNpZ25pbmctUlNBLTQwOTYt
# UjEuY2VyMCAGCCsGAQUFBzABhhRodHRwOi8vb2NzcHMuc3NsLmNvbTBRBgNVHSAE
# SjBIMAgGBmeBDAEEATA8BgwrBgEEAYKpMAEDAwEwLDAqBggrBgEFBQcCARYeaHR0
# cHM6Ly93d3cuc3NsLmNvbS9yZXBvc2l0b3J5MBMGA1UdJQQMMAoGCCsGAQUFBwMD
# ME0GA1UdHwRGMEQwQqBAoD6GPGh0dHA6Ly9jcmxzLnNzbC5jb20vU1NMY29tLVN1
# YkNBLUNvZGVTaWduaW5nLVJTQS00MDk2LVIxLmNybDAdBgNVHQ4EFgQUSj8HrSK7
# f/j+Dz31jJFhOF7rJUMwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IC
# AQBf4lcc6FUJ1W/opNz8yjS9qLUy9cQt0s35BhasB5QoTbDaW4jv9xnFGhQVg6n+
# jhL0i94Vsywd/MRBb8lYGpuBZnS/7LHuRZu7qUuud+IMDyRHIyBK6koN5bfyA5VY
# c7bFbNpbe1s1hMWke8di4qgMLZKDfyG/RtA0swf5t4UgQLPP0h+koZ8X8V5+P0V0
# 1HsdXyXd+ojo38EoZyCKfQL2aAwMPwzZfCbmI5SRXNOc6K8oqXzQcendhlKSfVBo
# Zgpi+1updqbD4jmJfYdK5AYPxJ3YH6td6ETtr8owL+bmX8lQjlXPOwVnC11rVlNB
# VjqtaJRUClLtiNiYSTKVfjdmGVJ4+sNov0dWhHc0A9o5NX/05VVYTlImuJpnG5Og
# o7w6kWRdsgE8gM58jWf7XfI6aQS0Np/z2B+ZBj0K93khEHBX7cvvORa92LCHiVeP
# km+zEAMXgxIPs/e8cmcc/o3CORgzEwxlH9Z3UOWCuXSHD3P2RPNDAY+WPdjSHm9f
# JFlGq+f9iKyedxYa/NNjNag/5EbZ+Z2NldtSMNeFdsejGJ/TJHF1PyJd4aXx9J1i
# B/IZBOoJYyh9xpQ3ljZUKE/4otPi7INpuDFwgWiUHZZJVvrGTWwxH1Yhf8P+VpFf
# aNqsBuvklUcUDs3RNE0f1qlgFfcnAepFF+RiBRqmsj29fjGCEdAwghHMAgEBMIGM
# MHgxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3Rv
# bjERMA8GA1UECgwIU1NMIENvcnAxNDAyBgNVBAMMK1NTTC5jb20gQ29kZSBTaWdu
# aW5nIEludGVybWVkaWF0ZSBDQSBSU0EgUjECEGdokrDW8DrI5yxMUgF+hegwDQYJ
# YIZIAWUDBAIBBQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYK
# KwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG
# 9w0BCQQxIgQgqMxrpBjy2PwJ6Wk+gDKEy0lBT1tFSyvj+MWLTmLQGhcwDQYJKoZI
# hvcNAQEBBQAEggGAQ2uuPRx91hqOmiiH7YZenKGMQSeBsxUcqxuJrHZ5pDNYJ1hC
# N+gzyQa36nJfCrbnIhZNrkpbkIhpPFKKrynAjI3jM83rfmr+N7M0q1hFRnBKkF8/
# VUzQWrT66ekfVIJXV7QQNqscVWqyMLz2uVnQ+dIDv055nfCdQ2O+6mj+Yd/jv/v/
# 6Uke+0p5auY+TeXbH56QuMNfISLUn3nHXRDCxbIwWLidtz0TD8w6jPPJjmunvDq3
# Kv6Tbc3Qzmv8QKdGvKLCr7J05ZDpzNP1T3d7lb5cf4E7EVAGFJCUsHvMvdJjO8xU
# TNJ2p1U2KW7vUuRBoZxoA43JxpQzVdrot+9ns6F+sltLdrsGgR1xDnkJloYy+v2H
# fPcYCwKTlN/1vjP2pnV15PlTT82JrvGhNF/M/i/OEEawIBrokqkwHGHpcLxXoNhB
# K5qCkeY2WFrlFTB6rLE/PdDnYe2f8bcCjFxWnmVZtKJdQI/1MhS6qcxo87QpS7Q6
# G7egOtt1iyYSQHcuoYIPFjCCDxIGCisGAQQBgjcDAwExgg8CMIIO/gYJKoZIhvcN
# AQcCoIIO7zCCDusCAQMxDTALBglghkgBZQMEAgEwdwYLKoZIhvcNAQkQAQSgaARm
# MGQCAQEGDCsGAQQBgqkwAQMGATAxMA0GCWCGSAFlAwQCAQUABCAiKtg5eaFwEHIF
# cGUMFS9u7ig2rKZ273f68FTNaLk//wIIIX3hK8Mza6kYDzIwMjUwMzAzMDYzMzAx
# WjADAgEBoIIMADCCBPwwggLkoAMCAQICEFparOgaNW60YoaNV33gPccwDQYJKoZI
# hvcNAQELBQAwczELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQH
# DAdIb3VzdG9uMREwDwYDVQQKDAhTU0wgQ29ycDEvMC0GA1UEAwwmU1NMLmNvbSBU
# aW1lc3RhbXBpbmcgSXNzdWluZyBSU0EgQ0EgUjEwHhcNMjQwMjE5MTYxODE5WhcN
# MzQwMjE2MTYxODE4WjBuMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO
# BgNVBAcMB0hvdXN0b24xETAPBgNVBAoMCFNTTCBDb3JwMSowKAYDVQQDDCFTU0wu
# Y29tIFRpbWVzdGFtcGluZyBVbml0IDIwMjQgRTEwWTATBgcqhkjOPQIBBggqhkjO
# PQMBBwNCAASnYXL1MOl6xIMUlgVC49zonduUbdkyb0piy2i8t3JlQEwA74cjK8g9
# mRC8GH1cAAVMIr8M2HdZpVgkV1LXBLB8o4IBWjCCAVYwHwYDVR0jBBgwFoAUDJ0Q
# JY6apxuZh0PPCH7hvYGQ9M8wUQYIKwYBBQUHAQEERTBDMEEGCCsGAQUFBzAChjVo
# dHRwOi8vY2VydC5zc2wuY29tL1NTTC5jb20tdGltZVN0YW1waW5nLUktUlNBLVIx
# LmNlcjBRBgNVHSAESjBIMDwGDCsGAQQBgqkwAQMGATAsMCoGCCsGAQUFBwIBFh5o
# dHRwczovL3d3dy5zc2wuY29tL3JlcG9zaXRvcnkwCAYGZ4EMAQQCMBYGA1UdJQEB
# /wQMMAoGCCsGAQUFBwMIMEYGA1UdHwQ/MD0wO6A5oDeGNWh0dHA6Ly9jcmxzLnNz
# bC5jb20vU1NMLmNvbS10aW1lU3RhbXBpbmctSS1SU0EtUjEuY3JsMB0GA1UdDgQW
# BBRQTySs77U+YxMjCZIm7Lo6luRdIjAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcN
# AQELBQADggIBAJigjwMAkbyrxGRBf0Ih4r+rbCB57lTuwViC6nH2fZSciMogpqSz
# rSeVZ2eIb5vhj9rT7jqWXZn02Fncs4YTrA1QyxJW36yjC4jl5/bsFCaWuXzGXt2Y
# 6Ifp//A3Z0sNTMWTTBobmceM3sqnovdX9ToRFP+29r5yQnPcgRTI2PvrVSqLxY9E
# yk9/0cviM3W29YBl080ENblRcu3Y8RsfzRtVT/2snuDocRxvRYmd0TPaMgIj2xII
# 651QnPp1hiq9xU0AyovLzbsi5wlR5Ip4i/i8+x+HwYJNety5cYtdWJ7uQP6YaZtW
# /jNoHp76qNftq/IlSx6xEYBRjFBxHSq2fzhUQ5oBawk2OsZ2j0wOf7q7AqjCt6t/
# +fbmWjrAWYWZGj/RLjltqdFPBpIKqdhjVIxaGgzVhaE/xHKBg4k4DfFZkBYJ9BWu
# P93Tm+paWBDwXI7Fg3alGsboErWPWlvwMAmpeJUjeKLZY26JPLt9ZWceTVWuIyuj
# erqb5IMmeqLJm5iFq/Qy4YPGyPiolw5w1k9OeO4ErmS2FKvk1ejvw4SWR+S1VyWn
# ktY442WaoStxBCCVWZdMWFeB+EpL8uoQNq1MhSt/sIUjUudkyZLIbMVQjj7b6gPX
# nD6mS8FgWiCAhuM1a/hgA+6o1sJWizHdmcpYDhyNzorf9KVRE6iR7rcmMIIG/DCC
# BOSgAwIBAgIQbVIYcIfoI02FYADQgI+TVjANBgkqhkiG9w0BAQsFADB8MQswCQYD
# VQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0b24xGDAWBgNV
# BAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBSb290IENlcnRp
# ZmljYXRpb24gQXV0aG9yaXR5IFJTQTAeFw0xOTExMTMxODUwMDVaFw0zNDExMTIx
# ODUwMDVaMHMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwH
# SG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxLzAtBgNVBAMMJlNTTC5jb20gVGlt
# ZXN0YW1waW5nIElzc3VpbmcgUlNBIENBIFIxMIICIjANBgkqhkiG9w0BAQEFAAOC
# Ag8AMIICCgKCAgEArlEQE9L5PCCgIIXeyVAcZMnh/cXpNP8KfzFI6HJaxV6oYf3x
# h/dRXPu35tDBwhOwPsJjoqgY/Tg6yQGBqt65t94wpx0rAgTVgEGMqGri6vCI6rEt
# SZVy9vagzTDHcGfFDc0Eu71mTAyeNCUhjaYTBkyANqp9m6IRrYEXOKdd/eREsqVD
# mhryd7dBTS9wbipm+mHLTHEFBdrKqKDM3fPYdBOro3bwQ6OmcDZ1qMY+2Jn1o0l4
# N9wORrmPcpuEGTOThFYKPHm8/wfoMocgizTYYeDG/+MbwkwjFZjWKwb4hoHT2WK8
# pvGW/OE0Apkrl9CZSy2ulitWjuqpcCEm2/W1RofOunpCm5Qv10T9tIALtQo73GHI
# lIDU6xhYPH/ACYEDzgnNfwgnWiUmMISaUnYXijp0IBEoDZmGT4RTguiCmjAFF5OV
# NbY03BQoBb7wK17SuGswFlDjtWN33ZXSAS+i45My1AmCTZBV6obAVXDzLgdJ1A1r
# yyXz4prLYyfJReEuhAsVp5VouzhJVcE57dRrUanmPcnb7xi57VPhXnCuw26hw1Hd
# +ulK3jJEgbc3rwHPWqqGT541TI7xaldaWDo85k4lR2bQHPNGwHxXuSy3yczyOg57
# TcqqG6cE3r0KR6jwzfaqjTvN695GsPAPY/h2YksNgF+XBnUD9JBtL4c34AcCAwEA
# AaOCAYEwggF9MBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAU3QQJB6L1
# en1SUxKSle44gCUNplkwgYMGCCsGAQUFBwEBBHcwdTBRBggrBgEFBQcwAoZFaHR0
# cDovL3d3dy5zc2wuY29tL3JlcG9zaXRvcnkvU1NMY29tUm9vdENlcnRpZmljYXRp
# b25BdXRob3JpdHlSU0EuY3J0MCAGCCsGAQUFBzABhhRodHRwOi8vb2NzcHMuc3Ns
# LmNvbTA/BgNVHSAEODA2MDQGBFUdIAAwLDAqBggrBgEFBQcCARYeaHR0cHM6Ly93
# d3cuc3NsLmNvbS9yZXBvc2l0b3J5MBMGA1UdJQQMMAoGCCsGAQUFBwMIMDsGA1Ud
# HwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmxzLnNzbC5jb20vc3NsLmNvbS1yc2EtUm9v
# dENBLmNybDAdBgNVHQ4EFgQUDJ0QJY6apxuZh0PPCH7hvYGQ9M8wDgYDVR0PAQH/
# BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQCSGXUNplpCzxkH2fL8lPrAm/AV6USW
# Wi9xM91Q5RN7mZN3D8T7cm1Xy7qmnItFukgdtiUzLbQokDJyFTrF1pyLgGw/2hU3
# FJEywSN8crPsBGo812lyWFgAg0uOwUYw7WJQ1teICycX/Fug0KB94xwxhsvJBiRT
# pQyhu/2Kyu1Bnx7QQBA1XupcmfhbQrK5O3Q/yIi//kN0OkhQEiS0NlyPPYoRboHW
# C++wogzV6yNjBbKUBrMFxABqR7mkA0x1Kfy3Ud08qyLC5Z86C7JFBrMBfyhfPpKV
# lIiiTQuKz1rTa8ZW12ERoHRHcfEjI1EwwpZXXK5J5RcW6h7FZq/cZE9kLRZhvnRK
# tb+X7CCtLx2h61ozDJmifYvuKhiUg9LLWH0Or9D3XU+xKRsRnfOuwHWuhWch8G7k
# EmnTG9CtD9Dgtq+68KgVHtAWjKk2ui1s1iLYAYxnDm13jMZm0KpRM9mLQHBK5Gb4
# dFgAQwxOFPBslf99hXWgLyYE33vTIi9p0gYqGHv4OZh1ElgGsvyKdUUJkAr5hfbD
# X6pYScJI8v9VNYm1JEyFAV9x4MpskL6kE2Sy8rOqS9rQnVnIyPWLi8N9K4GZvPit
# /Oy+8nFL6q5kN2SZbox5d69YYFe+rN1sDD4CpNWwBBTI/q0V4pkgvhL99IV2Xasj
# HZf4peSrHdL4RjGCAlgwggJUAgEBMIGHMHMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI
# DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxLzAt
# BgNVBAMMJlNTTC5jb20gVGltZXN0YW1waW5nIElzc3VpbmcgUlNBIENBIFIxAhBa
# WqzoGjVutGKGjVd94D3HMAsGCWCGSAFlAwQCAaCCAWEwGgYJKoZIhvcNAQkDMQ0G
# CyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNTAzMDMwNjMzMDFaMCgGCSqG
# SIb3DQEJNDEbMBkwCwYJYIZIAWUDBAIBoQoGCCqGSM49BAMCMC8GCSqGSIb3DQEJ
# BDEiBCCZ+PunCeULAOXX+rikBHvrWIiBXxWU6hAMDFUXYV16jTCByQYLKoZIhvcN
# AQkQAi8xgbkwgbYwgbMwgbAEIJ1xf43CN2Wqzl5KsOH1ddeaF9Qc7tj9r+8D/T29
# iUfnMIGLMHekdTBzMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNV
# BAcMB0hvdXN0b24xETAPBgNVBAoMCFNTTCBDb3JwMS8wLQYDVQQDDCZTU0wuY29t
# IFRpbWVzdGFtcGluZyBJc3N1aW5nIFJTQSBDQSBSMQIQWlqs6Bo1brRiho1XfeA9
# xzAKBggqhkjOPQQDAgRHMEUCIQDu9dpNMCUIG7BHxyLShBWC6osIdQZD1mX6VwTi
# hKUgJgIgTIO6ogB5G/9GKbZY7U0k6zdFXTMu7NPQQYOSp337YjU=
# SIG # End signature block