Functions/Get-M365Doc.ps1

function Get-ValidSectionValue {
    [CmdletBinding()]
    param()
    $AllCommands = Get-ChildItem -Path "$PSScriptRoot\..\Internal\Collector" -File -Recurse -Depth 1
    return $AllCommands.Name.Replace(".ps1","").Replace("Get-","")
}

function Get-ValidComponentsValue {
    [CmdletBinding()]
    param()
    $AllCommands = Get-ChildItem -Path "$PSScriptRoot\..\Internal\Collector" -Directory 
    return $AllCommands.Name
}

Function Get-M365Doc(){
    <#
    .DESCRIPTION
    This Script documents an settings of your Microsoft 365 environment with almost all settings, which are available over the Graph API.
 
    The Script is using the MSAL.PS Module and requires you to run Connect-Documentation. Therefore you have to install them first.
 
    .PARAMETER Components
        The components for which the available sections should be returned.
 
    .PARAMETER ExcludeSections
        The specified sections are excluded from the collection process. The following sections are available:
 
        AzureAD AADAdministrativeUnit
        AzureAD AADAuthMethod
        AzureAD AADBranding
        AzureAD AADConditionalAccess
        AzureAD AADConditionalAccessSplit
        AzureAD AADDirectoryRole
        AzureAD AADDomain
        AzureAD AADIdentityProvider
        AzureAD AADOrganization
        AzureAD AADPolicy
        AzureAD AADSubscription
 
        CloudPrint CPConnector
        CloudPrint
         
        InformationProtection MIPLabel
 
        Intune MdmAdmxConfigurationProfile
        Intune MdmAppleConfiguration
        Intune MdmAutopilotProfile
        Intune MdmCompliancePolicy
        Intune MdmConfigurationPolicy
        Intune MdmConfigurationProfile
        Intune MdmDeviceCategory
        Intune MdmEnrollmentConfiguration
        Intune MdmExchangeConnector
        Intune MdmPartner
        Intune MdmPowerShellScript
        Intune MdmSecurityBaseline
        Intune MdmTermsAndCondition
        Intune MdmWindowsUpdate
        Intune MobileApp
        Intune MobileAppConfiguration
        Intune MobileAppDetailed
        Intune MobileAppManagement
 
        Windows365 W365Image
        Windows365 W365OnPremConnection
        Windows365 W365ProvisionProfile
        Windows365 W365UserSetting
 
    .PARAMETER IncludeSections
        Only the specified sections are collected. Keep in mind that you have also to specify the corresponding Component. For example if
        you choose to include AADConditionalAccess section, but specify Intune as a Component, then nothing will be collected.
 
        AzureAD AADAdministrativeUnit
        AzureAD AADAuthMethod
        AzureAD AADBranding
        AzureAD AADConditionalAccess
        AzureAD AADConditionalAccessSplit
        AzureAD AADDirectoryRole
        AzureAD AADDomain
        AzureAD AADIdentityProvider
        AzureAD AADOrganization
        AzureAD AADPolicy
        AzureAD AADSubscription
 
        CloudPrint CPConnector
        CloudPrint
         
        InformationProtection MIPLabel
 
        Intune MdmAdmxConfigurationProfile
        Intune MdmAppleConfiguration
        Intune MdmAutopilotProfile
        Intune MdmCompliancePolicy
        Intune MdmConfigurationPolicy
        Intune MdmConfigurationProfile
        Intune MdmDeviceCategory
        Intune MdmEnrollmentConfiguration
        Intune MdmExchangeConnector
        Intune MdmPartner
        Intune MdmPowerShellScript
        Intune MdmSecurityBaseline
        Intune MdmTermsAndCondition
        Intune MdmWindowsUpdate
        Intune MobileApp
        Intune MobileAppConfiguration
        Intune MobileAppDetailed
        Intune MobileAppManagement
 
        Windows365 W365Image
        Windows365 W365OnPremConnection
        Windows365 W365ProvisionProfile
        Windows365 W365UserSetting
 
    .PARAMETER BackupFile
        Path to a previously generated JSON file.
      
 
    .EXAMPLE Online
    $doc = Get-M365Doc -Components Intune -ExcludeSections "MobileAppDetailed"
 
    .EXAMPLE Backup
    Retrieves data from backup file. created with Output-M365Doc
     
    $doc = Get-M365Doc -BackupFile c:\temp\backup.json
 
    .Example Select Sections in UI with Out-GridView allowing selection of sections
    $Selection = Get-M365DocValidSection | Out-GridView -OutputMode Multiple
    $Sections = $Selection | Select-Object -ExpandProperty SectionName
    $Components = $Selection | Select-Object -ExpandProperty Component -Unique
    $doc = Get-M365Doc -Components $Components -IncludeSections $Sections
 
    .NOTES
    Author: Thomas Kurth/baseVISION
    Date: 01.04.2021
 
    History
        See Release Notes in Github.
 
    #>

    [OutputType('Doc')]
    [CmdletBinding(DefaultParameterSetName="Online-Exclude")]
    Param(
 
        [Parameter(ParameterSetName="Online-Exclude",Mandatory=$true)]
        [Parameter(ParameterSetName="Online-Include",Mandatory=$true)]
        [ArgumentCompleter(
            {
                
                param(
                    $Command, 
                    $Parameter, 
                    $WordToComplete, 
                    $CommandAst, 
                    $FakeBoundParams)

                Get-ValidComponentsValue 
            }
        )]
        [ValidateScript(
            {
                $_ -in (Get-ValidComponentsValue)
            }
        )]
        [string[]]$Components,

        [Parameter(ParameterSetName="Online-Exclude",Mandatory=$false)]
        [ArgumentCompleter(
            {
                
                param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)

                Get-ValidSectionValue 
            }
        )]
        [ValidateScript(
            {
                $_ -in (Get-ValidSectionValue)
            }
        )]
        [string[]]$ExcludeSections,

        [Parameter(ParameterSetName="Online-Include",Mandatory=$true)]
        [ArgumentCompleter(
            {
                
                param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)

                Get-ValidSectionValue 
            }
        )]
        [ValidateScript(
            {
                $_ -in (Get-ValidSectionValue)
            }
        )]
        [string[]]$IncludeSections,

        [Parameter(ParameterSetName="Backup",Mandatory=$true)]
        [ValidateScript({
            if($_ -notmatch "(\.json)"){
                throw "The file specified in the path argument must be a valid M365 documentation backup of type json."
            }
            return $true 
        })]
        [System.IO.FileInfo]$BackupFile

    )
    ## Manual Variable Definition
    ########################################################
    #$DebugPreference = "Continue"
    $ScriptName = "Get-M365Doc"

    if( $PsCmdlet.ParameterSetName -eq "Backup"){
        [Doc]$Doc = Get-Content -Path $BackupFile | ConvertFrom-Json
        return $Doc
    } else {

        #region Initialization
        ########################################################
        Write-Verbose "Start Script $Scriptname"
        # Authentication
        # verify token
        if (-not ($script:token -and $script:token.ExpiresOn.LocalDateTime -ge $(Get-Date))) {
            throw "Please connect first via Connect-M365Doc"
        }

        $Data = New-Object Doc
        $org = Invoke-DocGraph -Path "/organization"
        $Data.Organization = $org.Value.displayName
        $Data.Components = $Components
        $Data.SubSections = @()
        $Data.CreationDate = Get-Date
        $Data.Translated = $false

        #endregion

        #region Collection Script
        ########################################################

        foreach($Component in $Components){
            # Get all collector commands
            $AllCommands = Get-ChildItem -Path "$PSScriptRoot\..\Internal\Collector\$Component" -File 
            
            #Exclude excluded commands
            if( $PsCmdlet.ParameterSetName -eq "Online-Exclude"){
                $SelectedCommands = @()
                foreach($AllCommand in $AllCommands){
                    $Excluded = $false
                    foreach($ExcludeSection in $ExcludeSections){
                        if($AllCommand -match $ExcludeSection){
                            $Excluded = $true
                            Write-Verbose  "Section $AllCommand will be excluded."
                        }
                    }
                    
                    if($Excluded -eq $false){
                        $SelectedCommands += $AllCommand
                    }
                }
            }

            #Include only Included commands from the current component
            if($PsCmdlet.ParameterSetName -eq "Online-Include"){
                $SelectedCommands = @()
                foreach($AllCommand in $AllCommands){
                    $Included = $false
                    foreach($IncludeSection in $IncludeSections){
                        if($AllCommand -match $IncludeSection){
                            $Included = $true
                            Write-Verbose  "Section $AllCommand will be included."
                        }
                    }
                    
                    if($Included){
                        $SelectedCommands += $AllCommand
                    }
                }
            }

            # Start data collection
            $progress = 0
            $CollectedData = @()
            foreach($SelectedCommand in $SelectedCommands){
                $progress++
                Write-Progress -Id 1 -Activity "Collecting Data" -Status (($SelectedCommand.Name -replace ".ps1","") -replace "Get-","") -PercentComplete (($progress / $SelectedCommands.count) * 100)
                $CollectedData += Invoke-Expression -Command ($SelectedCommand.Name -replace ".ps1","")
            }
            Write-Progress -Id 1 -Activity "Collecting Data" -Status "Finished collection" -Completed
            
            # Build return object, depending if multiple components are documented in subsections.
            if($Components.count -gt 1){
                $DocSec = New-Object DocSection
                $DocSec.Title = $Component
                $DocSec.Text = ""
                $DocSec.SubSections = $CollectedData
                $Data.SubSections += $DocSec
            } else {
                $Data.SubSections = $CollectedData
            }

        }

        #endregion

        #region Finishing
        ########################################################
        
        return $Data
        
        Write-Information "End Script $Scriptname"
        #endregion
    }
}

# SIG # Begin signature block
# MIIoLAYJKoZIhvcNAQcCoIIoHTCCKBkCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAOC0Arcms2aDXD
# YDwBtxUU//shbrpehA3kc5GWBZzAeqCCIS8wggWNMIIEdaADAgECAhAOmxiO+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
# twGpn1eqXijiuZQwggauMIIElqADAgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqG
# SIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy
# dXN0ZWQgUm9vdCBHNDAeFw0yMjAzMjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMx
# CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMy
# RGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcg
# Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXH
# JQPE8pE3qZdRodbSg9GeTKJtoLDMg/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMf
# UBMLJnOWbfhXqAJ9/UO0hNoR8XOxs+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w
# 1lbU5ygt69OxtXXnHwZljZQp09nsad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRk
# tFLydkf3YYMZ3V+0VAshaG43IbtArF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYb
# qMFkdECnwHLFuk4fsbVYTXn+149zk6wsOeKlSNbwsDETqVcplicu9Yemj052FVUm
# cJgmf6AaRyBD40NjgHt1biclkJg6OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP6
# 5x9abJTyUpURK1h0QCirc0PO30qhHGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzK
# QtwYSH8UNM/STKvvmz3+DrhkKvp1KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo
# 80VgvCONWPfcYd6T/jnA+bIwpUzX6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjB
# Jgj5FBASA31fI7tk42PgpuE+9sJ0sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXche
# MBK9Rp6103a50g5rmQzSM7TNsQIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB
# /wIBADAdBgNVHQ4EFgQUuhbZbU2FL3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU
# 7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoG
# CCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29j
# c3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDig
# NqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v
# dEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZI
# hvcNAQELBQADggIBAH1ZjsCTtm+YqUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd
# 4ksp+3CKDaopafxpwc8dB+k+YMjYC+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiC
# qBa9qVbPFXONASIlzpVpP0d3+3J0FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl
# /Yy8ZCaHbJK9nXzQcAp876i8dU+6WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeC
# RK6ZJxurJB4mwbfeKuv2nrF5mYGjVoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYT
# gAnEtp/Nh4cku0+jSbl3ZpHxcpzpSwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/
# a6fxZsNBzU+2QJshIUDQtxMkzdwdeDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37
# xJV77QpfMzmHQXh6OOmc4d0j/R0o08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmL
# NriT1ObyF5lZynDwN7+YAN8gFk8n+2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0
# YgkPCr2B2RP+v6TR81fZvAT6gt4y3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJ
# RyvmfxqkhQ/8mJb2VVQrH4D6wPIOK+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIG
# sDCCBJigAwIBAgIQCK1AsmDSnEyfXs2pvZOu2TANBgkqhkiG9w0BAQwFADBiMQsw
# CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
# ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw
# HhcNMjEwNDI5MDAwMDAwWhcNMzYwNDI4MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEX
# MBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0
# ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMIICIjAN
# BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1bQvQtAorXi3XdU5WRuxiEL1M4zr
# PYGXcMW7xIUmMJ+kjmjYXPXrNCQH4UtP03hD9BfXHtr50tVnGlJPDqFX/IiZwZHM
# gQM+TXAkZLON4gh9NH1MgFcSa0OamfLFOx/y78tHWhOmTLMBICXzENOLsvsI8Irg
# nQnAZaf6mIBJNYc9URnokCF4RS6hnyzhGMIazMXuk0lwQjKP+8bqHPNlaJGiTUyC
# EUhSaN4QvRRXXegYE2XFf7JPhSxIpFaENdb5LpyqABXRN/4aBpTCfMjqGzLmysL0
# p6MDDnSlrzm2q2AS4+jWufcx4dyt5Big2MEjR0ezoQ9uo6ttmAaDG7dqZy3SvUQa
# khCBj7A7CdfHmzJawv9qYFSLScGT7eG0XOBv6yb5jNWy+TgQ5urOkfW+0/tvk2E0
# XLyTRSiDNipmKF+wc86LJiUGsoPUXPYVGUztYuBeM/Lo6OwKp7ADK5GyNnm+960I
# HnWmZcy740hQ83eRGv7bUKJGyGFYmPV8AhY8gyitOYbs1LcNU9D4R+Z1MI3sMJN2
# FKZbS110YU0/EpF23r9Yy3IQKUHw1cVtJnZoEUETWJrcJisB9IlNWdt4z4FKPkBH
# X8mBUHOFECMhWWCKZFTBzCEa6DgZfGYczXg4RTCZT/9jT0y7qg0IU0F8WD1Hs/q2
# 7IwyCQLMbDwMVhECAwEAAaOCAVkwggFVMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYD
# VR0OBBYEFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB8GA1UdIwQYMBaAFOzX44LScV1k
# TN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcD
# AzB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2lj
# ZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29t
# L0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0
# cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmww
# HAYDVR0gBBUwEzAHBgVngQwBAzAIBgZngQwBBAEwDQYJKoZIhvcNAQEMBQADggIB
# ADojRD2NCHbuj7w6mdNW4AIapfhINPMstuZ0ZveUcrEAyq9sMCcTEp6QRJ9L/Z6j
# fCbVN7w6XUhtldU/SfQnuxaBRVD9nL22heB2fjdxyyL3WqqQz/WTauPrINHVUHmI
# moqKwba9oUgYftzYgBoRGRjNYZmBVvbJ43bnxOQbX0P4PpT/djk9ntSZz0rdKOtf
# JqGVWEjVGv7XJz/9kNF2ht0csGBc8w2o7uCJob054ThO2m67Np375SFTWsPK6Wrx
# oj7bQ7gzyE84FJKZ9d3OVG3ZXQIUH0AzfAPilbLCIXVzUstG2MQ0HKKlS43Nb3Y3
# LIU/Gs4m6Ri+kAewQ3+ViCCCcPDMyu/9KTVcH4k4Vfc3iosJocsL6TEa/y4ZXDlx
# 4b6cpwoG1iZnt5LmTl/eeqxJzy6kdJKt2zyknIYf48FWGysj/4+16oh7cGvmoLr9
# Oj9FpsToFpFSi0HASIRLlk2rREDjjfAVKM7t8RhWByovEMQMCGQ8M4+uKIw8y4+I
# Cw2/O/TOHnuO77Xry7fwdxPm5yg/rBKupS8ibEH5glwVZsxsDsrFhsP2JjMMB0ug
# 0wcCampAMEhLNKhRILutG4UI4lkNbcoFUCvqShyepf2gpx8GdOfy1lKQ/a+FSCH5
# Vzu0nAPthkX0tGFuv2jiJmCG6sivqf6UHedjGzqGVnhOMIIGvDCCBKSgAwIBAgIQ
# C65mvFq6f5WHxvnpBOMzBDANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEX
# MBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0
# ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTI0MDkyNjAw
# MDAwMFoXDTM1MTEyNTIzNTk1OVowQjELMAkGA1UEBhMCVVMxETAPBgNVBAoTCERp
# Z2lDZXJ0MSAwHgYDVQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyNDCCAiIwDQYJ
# KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL5qc5/2lSGrljC6W23mWaO16P2RHxjE
# iDtqmeOlwf0KMCBDEr4IxHRGd7+L660x5XltSVhhK64zi9CeC9B6lUdXM0s71EOc
# Re8+CEJp+3R2O8oo76EO7o5tLuslxdr9Qq82aKcpA9O//X6QE+AcaU/byaCagLD/
# GLoUb35SfWHh43rOH3bpLEx7pZ7avVnpUVmPvkxT8c2a2yC0WMp8hMu60tZR0Cha
# V76Nhnj37DEYTX9ReNZ8hIOYe4jl7/r419CvEYVIrH6sN00yx49boUuumF9i2T8U
# uKGn9966fR5X6kgXj3o5WHhHVO+NBikDO0mlUh902wS/Eeh8F/UFaRp1z5SnROHw
# SJ+QQRZ1fisD8UTVDSupWJNstVkiqLq+ISTdEjJKGjVfIcsgA4l9cbk8Smlzddh4
# EfvFrpVNnes4c16Jidj5XiPVdsn5n10jxmGpxoMc6iPkoaDhi6JjHd5ibfdp5uzI
# Xp4P0wXkgNs+CO/CacBqU0R4k+8h6gYldp4FCMgrXdKWfM4N0u25OEAuEa3Jyidx
# W48jwBqIJqImd93NRxvd1aepSeNeREXAu2xUDEW8aqzFQDYmr9ZONuc2MhTMizch
# NULpUEoA6Vva7b1XCB+1rxvbKmLqfY/M/SdV6mwWTyeVy5Z/JkvMFpnQy5wR14GJ
# cv6dQ4aEKOX5AgMBAAGjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/
# BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEE
# AjALBglghkgBhv1sBwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8w
# HQYDVR0OBBYEFJ9XLAN3DigVkGalY17uT5IfdqBbMFoGA1UdHwRTMFEwT6BNoEuG
# SWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQw
# OTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQG
# CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKG
# TGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJT
# QTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIB
# AD2tHh92mVvjOIQSR9lDkfYR25tOCB3RKE/P09x7gUsmXqt40ouRl3lj+8QioVYq
# 3igpwrPvBmZdrlWBb0HvqT00nFSXgmUrDKNSQqGTdpjHsPy+LaalTW0qVjvUBhcH
# zBMutB6HzeledbDCzFzUy34VarPnvIWrqVogK0qM8gJhh/+qDEAIdO/KkYesLyTV
# OoJ4eTq7gj9UFAL1UruJKlTnCVaM2UeUUW/8z3fvjxhN6hdT98Vr2FYlCS7Mbb4H
# v5swO+aAXxWUm3WpByXtgVQxiBlTVYzqfLDbe9PpBKDBfk+rabTFDZXoUke7zPgt
# d7/fvWTlCs30VAGEsshJmLbJ6ZbQ/xll/HjO9JbNVekBv2Tgem+mLptR7yIrpaid
# RJXrI+UzB6vAlk/8a1u7cIqV0yef4uaZFORNekUgQHTqddmsPCEIYQP7xGxZBIhd
# mm4bhYsVA6G2WgNFYagLDBzpmk9104WQzYuVNsxyoVLObhx3RugaEGru+SojW4dH
# PoWrUhftNpFC5H7QEY7MhKRyrBe7ucykW7eaCuWBsBb4HOKRFVDcrZgdwaSIqMDi
# CLg4D+TPVgKx2EgEdeoHNHT9l3ZDBD+XgbF+23/zBjeCtxz+dL/9NWR6P2eZRi7z
# cEO1xwcdcqJsyz/JceENc2Sg8h3KeFUCS7tpFk7CrDqkMIIHdDCCBVygAwIBAgIQ
# BPG5oE62GYY8FB/9PX286TANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJVUzEX
# MBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0
# ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMB4XDTIz
# MTAwOTAwMDAwMFoXDTI2MTEyMDIzNTk1OVowfDELMAkGA1UEBhMCQ0gxEjAQBgNV
# BAgTCVNvbG90aHVybjEOMAwGA1UEBxMFT2x0ZW4xFjAUBgNVBAoTDWJhc2VWSVNJ
# T04gQUcxGTAXBgNVBAsTEEludGVybmFsIFNjcmlwdHMxFjAUBgNVBAMTDWJhc2VW
# SVNJT04gQUcwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC59opyk0SC
# GVo7wUn0nEzHJa2NgMzMro0Rz/YTL2Pd4Mqzky1INofqMJnBUijLSCFUzupCniYO
# rtXFPL4sX4S8o5RntwEUAz0EX57SvtbKmrTOWgQEH//tglyeqDDN1ygVva2/U15X
# CATmHNuOmn1ka2n5Y6vQ+INBPu4jtYczPsKPJ5nIF/TrCSe2fCd64rI3dcvNadsl
# vAZHSS765ZnLGeL8io7oCJ/6vl90553aCKLMVWsM8lFny272h34OYAnsHwCbkqLc
# SfGUTIcveg6iWKCeStmW35PIUMA4bIDZ/XBX7cyFgKeAYMiX6yNxAgEDw5sBQsxT
# buIWB21aY9zk1qeJsdGRR1eBedZzMwWalMGdvAlXkIkYwPAG1JTxOdt506akXqIi
# H6cpvEsQ5UX3RY+sbzqunqi7gGMfP52O5r0Y79bdHceYYKykyXnf6vzvjPH4HTVB
# EDvwkMp0Q1prpb1U4gIe1nyzUIhKuPDt28jjlybCikgGK9XB4Kjk5eavV4FwoVuw
# fbC0Z2g7mHXZpbvJcSbSypgxYdGw38NeAJtbkCrujW/sJI2lxJlb7AE1x/2y6t0w
# vPBPq9ujcbCptLGuN4tsc6Kef1xX17ZE4DgTs8xAuXI+999xef1BYC+RNib+Axul
# d6lABNy6l8TNOdKYcwnARsCo/Reptx+1yQIDAQABo4ICAzCCAf8wHwYDVR0jBBgw
# FoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0OBBYEFGbzURuqIENghe4I9LYT
# oJoHVFfKMD4GA1UdIAQ3MDUwMwYGZ4EMAQQBMCkwJwYIKwYBBQUHAgEWG2h0dHA6
# Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAww
# CgYIKwYBBQUHAwMwgbUGA1UdHwSBrTCBqjBToFGgT4ZNaHR0cDovL2NybDMuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hB
# Mzg0MjAyMUNBMS5jcmwwU6BRoE+GTWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEu
# Y3JsMIGUBggrBgEFBQcBAQSBhzCBhDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au
# ZGlnaWNlcnQuY29tMFwGCCsGAQUFBzAChlBodHRwOi8vY2FjZXJ0cy5kaWdpY2Vy
# dC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQy
# MDIxQ0ExLmNydDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQB4Nu0DwKMW
# ZISOOreOAzu60c6E3nojAhXIvhG5ULE/JHBnWqD1FHMrot61HBD3r09NJd8kU0/U
# lYYdGSSYpQf/KTkB1PPy9MUtZ5hBKt1jm1/bjocwXONqywZCdEx05Ssg5/7J4YNH
# LuS0FkZYIjFFla1P+doiXWWCmUvHc75rmJFXp5MarbSezWZeckfKNDhig9bvtiKA
# oWp4nRJz/szPE72yiqvfulEeuAKO5liyjoTFGiu/LxxcUg0sX7ZzKiJdeKKZZsoD
# qDFa175nJGAZuCZiBMIOoZIftsLIgnLugeFxJTmY5q5fhvUiABXAkN9+tmlCFwOA
# DLfDhRKU7zCZnrXop2+PX8Ubr/taHX/d/LF018MbHyHYcDoLnCNuYw81rHBLgK5r
# swi2BVCAfHcWsotSQZlmg2iBIpfe9cCQXV7MM55zyQ54mAejXjx6wBWnL2YxZYFv
# ABs6fHKIL24yzXfnFLESRqLYAWN81hsgqaYQLqXbV013HPdFEsnNuwExxZn8gce8
# PYvvTaw0OjDg3Xe8Otl9PYb5NtGDMp+raIIDc5dIzDCh/PbhFPGQOh8EpvvJIqec
# ToVnB7i7c0ehQ6R+uwzLGma6Cc6kWJF/aUrRDO671bixbT7g8Q+eiQya/KaWkOV0
# 7kAiq53Sq5B927vRyZPOkdU88zP3AINHcDGCBlMwggZPAgEBMH0waTELMAkGA1UE
# BhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2Vy
# dCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENB
# MQIQBPG5oE62GYY8FB/9PX286TANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3
# AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG
# AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCB7Aye+lAS5
# 41nz2JXUXsD9kFyceMX7e+XS8i76889r7TANBgkqhkiG9w0BAQEFAASCAgANeo7w
# GNPg0K9uHre1n4c+hT4ua5j+yKMijm8ieO+/KKjcnzb9nCytKA9xbc0FMvVh8hAs
# iUji1da+ATI8+5GCUYZ5upv8ZXTXUIg1KMSH3qKmeM9jAD6j0X1/UacIaP/obPn9
# WRucGGoKOUySEeiJ/RdZGla3pSHuHkKIosR6f9DPQXdFLNDlaCOwM6lVtnZcCqT5
# FXFflJVtOCnsWBRFtX+rO4PXhyOkCpdjJzG6Y32wsfiqLuw9YO2m3tDgXrQy8ht/
# utJpfrgRbRs5vpjXFrh0yAyFwfBBrV6zs9rJY377SORb8JWoF0pifos/t4Vo42aS
# 49gLueSV9WX5YuO+9ChA1Ko1p55Hksr7caNzVVVnV1bERmhIezQQCiYG23fV0CjU
# 6ZxPay3Jbf3gvTOGUX7ywQa1nX08PFondYiybBVtW8iUyQosRYJArmCE4YS7zA6o
# DZyM6cMQdSRSjBhgIihT9JgJnS6vLNAo2f8ctPGMate6TuJWrnuYAFhULhK8QCyi
# T0uuF/PlJRSjk1RW7SE5BcRdT+yIAQAyAlPNWEtRu1BPFtv9SeqrIeic1PdYLP4J
# ns6jpbGvzpvE1sZ9+06RgAPBXhNxl70j0XA5vAIGeWpAf+JxC0ze8gorIZ3J6peJ
# 6v628ZS5Y7R9HnkD0Tg6E9W9KhOZJ1l14ZkAHqGCAyAwggMcBgkqhkiG9w0BCQYx
# ggMNMIIDCQIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
# SW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1
# NiBUaW1lU3RhbXBpbmcgQ0ECEAuuZrxaun+Vh8b56QTjMwQwDQYJYIZIAWUDBAIB
# BQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0y
# NTAzMjgwMzU2MDdaMC8GCSqGSIb3DQEJBDEiBCBmqv7q98ciNHCI5em/pEkb9tDU
# ysfhhMsDHqfBiOCtdDANBgkqhkiG9w0BAQEFAASCAgCoKMIgxZHpbS10qKu69Vm2
# //XVOR/HhFVC1QzkQnPTFEltOoKZcUSO1pSsbOCgHKfxUjmam8wchNl03c5FsDLm
# YO/t8F2DgG3B2MUxjLQvarpj3CmT8q9Xk8bn50joOy3MsxwV7A0TeLQq5e7lbrnM
# x0diXh5OTp8GhpuCJrfMKRJoxPn17wg2T2jk8vp8x6Sb0YUTJUQhoe9c4VFyEsJu
# PlpYQrIGvSUHR5YQ6k6xp62gveb7GVNaPBx2tJuipnsEBlVYIboD+QbFHkDY98bB
# QkVu0Rek1HHNGGHvatxai2iucaqbWN1/w13SUk4zFN5O20ASjYuBVIeRl59yHjYo
# Mbz771AaXrOYPL7U21xe751kDskjYufmjOmpxsK5W9PdeIFA5zNLj/o3NqM0yxVe
# liFMfkfPbxBbpx/FowJLvXAPw0fysBQWGUE9Z/adobvZtr8qji0V4xB8IOFeJDAB
# OFHux8Q9u/JNg0qVi+1tJ+OEH9Z2dmadSAdFJIATKxL/Naa3l2957aRZnnzeBn6N
# 3tzhd86tw+TUMZAiFZoqeQmanxOg9hCbvyZ0l2ZlpfpqfQFMeVokftJZOSkTz4wy
# ePY+UXRnQTAi3FIjS0faOBSFJr9O1A9HQGT5inMOOWZB41c29xD5kn8NPlrtYAuy
# LxfVY4M/xDlmGKlvi/LDSg==
# SIG # End signature block