public/provisioning.ps1

function Update-NimbusDependencies {
    Param(
        [Parameter(Mandatory = $false)]
        [ValidateSet('portal_nimbload_com' , 'portal_luware_cloud', 'portal_stage_nimbdev_com', 'portal_uat_nimbdev_com')]
        [string]$env = 'placeholder',
        [Parameter(Mandatory = $false)]
        [object]$webhookData
    )

    Check-Module

    # Initialize the variables
    if ( $inRunbook ) {
        $cred = Get-AutomationPSCredential -Name nimbusCredentials
        $env = Get-AutomationVariable -Name nimbusEnvironment
        $callbackUrl = Get-AutomationVariable -Name callBackUrl
        $callbackUrl = [Text.Encoding]::Utf8.GetString( [Convert]::FromBase64String( $callbackUrl ) )
    } else {
        $cred = New-CredentialsPrompt "AzureAd"
    }

    $pstnNumbers = [System.Collections.ArrayList]@()
    $callingBotPermissions = "Calls.Initiate.All", "Calls.InitiateGroupCall.All", "Calls.JoinGroupCall.All", "Calls.JoinGroupCallAsGuest.All", "OnlineMeetings.ReadWrite.All","Calls.AccessMedia.All"
    $generalBotPermissions = "Directory.Read.All", "Group.Read.All", "User.Read.All"
    $mediaBotPermissions = "Calls.AccessMedia.All","Calls.Initiate.All","Calls.InitiateGroupCall.All","Calls.JoinGroupCall.All","Calls.JoinGroupCallAsGuest.All"

    $nimbusDomain = $mapper.$env.domain
    $nimbusAppId = $mapper.$env.nimbusAppId
    $mediaBotId = $mapper.$env.mediaBotId

    New-AzureAdLogin $cred
    New-MsolLogin $cred
    New-SkypeOnlineLogin $cred
    $webSession, $tenant = New-NimbusLogin -domain $nimbusDomain

    # Retrieve pending changes
    if ( $inRunbook ) {
        try {
            $uri = "https://{0}/api/provisioning/v1/tenants/{1}/service-details/{2}" -f $nimbusDomain, $tenant, $webhookData.teamId 
            $teams = Invoke-WebRequest -WebSession $webSession -Uri $uri -UseBasicParsing |
                ConvertFrom-Json
        }
        catch {
            Write-Output "Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)"
            Write-Output "Could not get changes for your tenant. Exiting."
            Write-Output $_.Exception.Message
            Cleanup-Environment -exitCode 1
        }
        $teamJson = $teams | ConvertTo-Json -Compress -ErrorAction SilentlyContinue
        $webhookDataJson = $webhookData | ConvertTo-Json -Compress -ErrorAction SilentlyContinue
        if ( -not $teams -or ( Compare-Object $teamJson $webhookDataJson ) ) {
            Write-Output "Configuration mismatch, sending failure email."
            Write-Output $webhookDataJson
            $webhookData | Add-Member -MemberType NoteProperty -Name failed -Value $true -Force
            Invoke-RestMethod `
                -Method:Post `
                -UseBasicParsing `
                -Uri $callbackUrl `
                -Body ( $webhookData | ConvertTo-Json -Compress -Depth 5 ) `
                -ContentType 'application/json'
            Cleanup-Environment -exitCode 1
        }
    } else {
    try {
        $teams = Invoke-WebRequest `
            -WebSession $webSession `
            -Uri "https://$nimbusDomain/api/facade/v1/provisioning/tenants/$tenant/service-details" |
                ConvertFrom-Json
    }
    catch {
        Write-Output "Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)"
        Write-Output "Could not get changes for your tenant. Exiting"
        Cleanup-Environment -exitCode 1
    }
    }

    try {
        Write-Output "Granting permissions for main Nimbus App"
        Update-ServicePrincipal -appId $nimbusAppId -permissions $generalBotPermissions
        Update-ServicePrincipal -appId $mediaBotId -permissions $mediaBotPermissions
        Write-Output " [Done]"
    }
    catch {
        Write-Output "[Failed]"
    }

    if ( Read-HostProxy "Would you like to re-grant all permissions to all the bots configured in your tenant? (Default is No)" ) {
        try {
            $botIds = Invoke-WebRequest `
                        -WebSession $webSession `
                        -Uri "https://$nimbusDomain/api/facade/v1/provisioning/tenants/$tenant/bot-ids" |
                            ConvertFrom-Json

            Write-Output "Granting permissions for all $($botIds.Length) configured bots in your tenant"
            foreach ( $botId in $botIds ) {
                Update-ServicePrincipal -appId $botId -permissions $callingBotPermissions
                Set-CsApplicationMeetingConfiguration -AllowRemoveParticipantAppIds @{Add="$($botId)"}
                Write-Output "Bot $botId - All permissions were granted"
            }
            Write-Output " [Done]"
        } catch {
            Write-Output ( $_.Exception | Format-List -Force | Out-String ) -ErrorAction Continue
            Write-Output ( $_.InvocationInfo | Format-List -Force | Out-String ) -ErrorAction Continue
            Write-Output "Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)"
            Write-Output "Could not get existing botIds. Will continue with pending changes."
        }
    } else {
        Write-Output "Skip re-granting all permissions"
    }

    # Apply updates (prompt user if using interactive mode)
    Write-Output "Fetched Changes for $($teams | Measure-Object | Select-Object -ExpandProperty count) Teams..."
    foreach ($team in $teams) {
        Write-Output "============================================================="
        Write-Output "============================================================="
        Write-Output "Team: $($team.teamName)"
        Write-Output "-------------------------------------------------------------"

        if ( -not [string]::IsNullOrEmpty($team.applicationId) -and $team.isSuspended ) {
            if ( Read-HostProxy "Would you like to delete the ApplicationInstance of '$($team.teamName)'? The team is suspended. (Default is No)" ) {
                Write-Output "Removing ApplicationInstance for '$($team.teamName)'..."
                try {
                    Remove-AzureADUser -ObjectId $team.applicationId -ErrorAction SilentlyContinue
                    Sync-CsOnlineApplicationInstance -ObjectId $team.applicationId -ErrorAction SilentlyContinue
                }
                catch {
                    Write-Output "[Failed]"
                    Write-Output "Application Instance doesn't exist anymore"
                }
                finally {
                    $team.applicationId = $null
                    Invoke-WebRequest `
                        -WebSession $webSession `
                        -Method:Post `
                        -Uri "https://$nimbusDomain/api/provisioning/v1/tenants/$tenant/service-details/apply" `
                        -ContentType "application/json" `
                        -Body ($team | ConvertTo-Json) |
                            Out-Null
                    Write-Output " [Done]"
                }
            } else {
                Write-Output "Skip removing ApplicationInstance for '$($team.teamName)'"
            }
        }
        elseif ( [string]::IsNullOrEmpty($team.applicationId) ) {
            Write-Output "Values to be set:"
            Write-Output ($team.teamServiceDetails | Format-Table | Out-String)
            if ([string]::IsNullOrEmpty($team.teamServiceDetails.upn)) {
                Write-Output "No Upn is set. Please configure this team correctly."
                Write-Output "============================================================="
                continue
            }
            if ( Read-HostProxy "Would you like to create an ApplicationInstance for '$($team.teamName)'? (Default is No)" ) {
                try {
                    Write-Output "Granting permissions for Calling Bot Application"
                    Update-ServicePrincipal -appId $team.botId -permissions 
                    Set-CsApplicationMeetingConfiguration -AllowRemoveParticipantAppIds @{Add="$($team.botId)"}
                    Write-Output " [Done]"
                }
                catch {
                    Write-Output "[Failed]"
                }

                Write-Output "Creating ApplicationInstance for '$($team.teamName)'..."
                try {
                    try {
                        $app = New-CsOnlineApplicationInstance -UserPrincipalName $team.teamServiceDetails.upn -DisplayName $team.teamServiceDetails.name -ApplicationId $team.botId
                    }
                    catch [System.Management.Automation.RemoteException] {
                        if ($Error[0].Exception -match "provided UserPrincipalName is already used") {
                            try {
                                Write-Output " Upn already used. Generating new one..."
                                $team.teamServiceDetails = Invoke-WebRequest `
                                    -WebSession $webSession `
                                    -Uri "https://$nimbusDomain/api/teammanager/v1/tenants/$tenant/teams/$($team.teamId)/service-details/regenerate-upn" |
                                    ConvertFrom-Json
                                Write-Output " [Done]"
                            }
                            catch {
                                Write-Output "[Failed]"
                                Write-Output " Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)"
                                Write-Output "[Failed]"
                                continue
                            }
                            $app = New-CsOnlineApplicationInstance -UserPrincipalName $team.teamServiceDetails.upn -DisplayName $team.teamServiceDetails.name -ApplicationId $team.botId
                        }
                        else {
                            Cleanup-Environment -exitCode 1
                        }
                    }
                    Sync-CsOnlineApplicationInstance -ObjectId $app.ObjectId
                    $team.applicationId = $app.ObjectId
                    $isDone = Update-Pstn -teamToCheck $team
                    if ( -not $isDone ) {
                        $pstnNumbers.Add($team) | Out-Null
                        Write-Output "[Pending]"
                        Write-Output " Could not yet complete PSTN number assignment will try again at the end."
                    }
                    else {
                        Invoke-WebRequest `
                            -WebSession $webSession `
                            -Method:Post `
                            -Uri "https://$nimbusDomain/api/provisioning/v1/tenants/$tenant/service-details/apply" `
                            -ContentType "application/json" `
                            -Body ($team | ConvertTo-Json) |
                                Out-Null
                        Write-Output " [Done]"
                    }
                }
                catch [System.Management.Automation.RemoteException] {
                    Write-Output "[Failed]"
                    Write-Output " Could not create ApplicationInstance $($_.Exception)"
                    Write-Output " Please check your configuration."
                    continue
                }
                catch {
                    Write-Output "[Failed]"
                    Write-Output " Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)"
                    Write-Output " An Error occurred sending the update to Nimbus."
                    continue
                }
            } else {
                Write-Output "Skip creating ApplicationInstance for '$($team.teamName)'"
            }
        }
        else {
            Write-Output "Values to be updated:"
            Write-Output ( $team.teamServiceDetails | Format-Table | Out-String )
            if ( Read-HostProxy "Would you like to update the ApplicationInstance for '$($team.teamName)'? (Default is No)" ) {
                try {
                    Write-Output "Updating ApplicationInstance for '$($team.teamName)'..."
                    if ( -not [string]::IsNullOrEmpty($team.teamServiceDetails.upn) ) {
                        try {
                            Write-Output " Setting new UPN..."
                            Set-MsolUserPrincipalName -ObjectId $team.applicationId -NewUserPrincipalName $team.teamServiceDetails.upn
                            Write-Output " [Done]"
                        }
                        catch [Microsoft.Online.Administration.Automation.MicrosoftOnlineException] {
                            if ($_.Exception -match "user principal name already exists") {
                                Write-Output "[Failed]"
                                Write-Output " $($_.Exception)"
                                try {
                                    Write-Output " Regenerating UPN..."
                                    $team.teamServiceDetails = Invoke-WebRequest `
                                        -WebSession $webSession `
                                        -Uri "https://$nimbusDomain/api/teammanager/v1/tenants/$tenant/teams/$($team.teamId)/service-details/regenerate-upn" |
                                            ConvertFrom-Json
                                    Set-MsolUserPrincipalName -ObjectId $team.applicationId -NewUserPrincipalName $team.teamServiceDetails.upn
                                    Write-Output " [Done]"
                                }
                                catch {
                                    Write-Output "[Failed]"
                                    Write-Output " $($_.Exception)"
                                    $team.teamServiceDetails.PsObject.Properties.Remove('upn')
                                }
                            }
                            else {
                                Write-Output "[Failed]"
                                Write-Output " $($_.Exception)"
                                $team.teamServiceDetails.PsObject.Properties.Remove('upn')
                            }
                        }
                    }
                    if ( -not [string]::IsNullOrEmpty($team.teamServiceDetails.name) ) {
                        Set-CsOnlineApplicationInstance -Identity $team.applicationId -DisplayName $team.teamServiceDetails.name |
                            Out-Null
                    }
                    $isDone = Update-Pstn -teamToCheck $team
                    Sync-CsOnlineApplicationInstance -ObjectId $team.applicationId
                    if ( -not $isDone ) {
                        $pstnNumbers.Add($team) | Out-Null
                        Write-Output "[Pending]"
                        Write-Output " Could not yet complete PSTN number assignment will try again at the end."
                    }
                    else {
                        Invoke-WebRequest `
                            -WebSession $webSession `
                            -Method:Post `
                            -Uri "https://$nimbusDomain/api/provisioning/v1/tenants/$tenant/service-details/apply" `
                            -ContentType "application/json" `
                            -Body ( $team | ConvertTo-Json -Compress -Depth 5 ) |
                                Out-Null
                        Write-Output " [Done]"
                    }
                }
                catch [System.Management.Automation.RemoteException] {
                    Write-Output "[Failed]"
                    Write-Output " Could not update ApplicationInstance $($_.Exception)"
                    Write-Output " Please check your configuration."
                    continue
                }
                catch [System.Net.WebException] {
                    Write-Output "[Failed]"
                    Write-Output " Web Request Failed. StatusCode: $($_.Exception.Response.StatusCode.Value__)"
                    Write-Output " An Error occurred sending the update to Nimbus."
                    continue
                }
                catch {
                    Write-Output "[Failed]"
                    Write-Output " An unexpected error occurred: $($_.Exception.Response.StatusCode.Value__)"
                }
            } else {
                Write-Output "Skip updating ApplicationInstance for '$($team.teamName)'"
            }
            Write-Output "============================================================="
        }
        Write-Output ""
        Write-Output ""
    }

    $tries = 0
    while ( $pstnNumbers.Count -gt 0 -and $tries -lt 10 ) {
        Write-Output "Retry to set pending PSTN number changes in 1 minute."
        0..12 | Foreach-Object {
            Write-Output "."
            Start-Sleep -Seconds 5
        }
        for ( $i = 0; $i -lt $pstnNumbers.Count; $i++ ) {
            $team = $pstnNumbers[$i]
            Write-Output "============================================================="
            Write-Output "Team '$($team.teamName)'"
            $isDone = Add-PhoneNumber -ObjectId $team.applicationId -PstnNumber $team.teamServiceDetails.pstnNumber
            if ( $isDone ) {
                $pstnNumbers.RemoveAt($i)
                Update-NimbusServicePrincipal -team $team
                Write-Output " [Done]"
                if ( $pstnNumber.Count -eq 0 ) {
                    break
                }
                $i--
            }
            else {
                if ( $tries -eq 9 ) {
                    Write-Output "[Failed]"
                }
                else {
                    Write-Output "[Pending]"
                }
            }
        }
        $tries++
    }

    if ( $pstnNumbers.Count -gt 0 ) {
        Write-Output "Unfortunately, not all numbers could be set."
        foreach ( $team in $pstnNumbers ) {
            $team.teamServiceDetails.PsObject.Properties.Remove('pstnNumber')
            Update-NimbusServicePrincipal -team $team
        }
    }

    Cleanup-Environment
}

# SIG # Begin signature block
# MIINMwYJKoZIhvcNAQcCoIINJDCCDSACAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQULd4NG5DXJWp00i14Mz5z/fCm
# iU+gggpxMIIFGjCCBAKgAwIBAgIQAZyhpG3mRP4nVXpkMz8jhDANBgkqhkiG9w0B
# AQsFADB2MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
# VQQLExB3d3cuZGlnaWNlcnQuY29tMTUwMwYDVQQDEyxEaWdpQ2VydCBTSEEyIEhp
# Z2ggQXNzdXJhbmNlIENvZGUgU2lnbmluZyBDQTAeFw0xOTA1MjEwMDAwMDBaFw0y
# MjA1MjUxMjAwMDBaMFkxCzAJBgNVBAYTAkNIMRAwDgYDVQQIDAdaw7xyaWNoMRAw
# DgYDVQQHDAdaw7xyaWNoMRIwEAYDVQQKEwlMdXdhcmUgQUcxEjAQBgNVBAMTCUx1
# d2FyZSBBRzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANx3Pfx2CKUz
# Ot9W7Scb5rrrnI7m7jOkVG4X2Owj+hJJuEjTA3wIfA/6ay4Wa/Qv+MMdlsv6NRt4
# TgYUMRexmfGgKT7iy4AIebBuyS1lg2gmT/25xGtqO3TPqfhstLNEfcKMaMM2ZEZm
# vCZbiAs3zP1G2oS94DWcCnDCjmPPll30nlOig+ZQGqBuhvNiZ/DGhnYRtrHoRx40
# 7iZjcixgPjkey9IGN6WEUYnhJ712npXTWWUIpiSZ2U475DxLWbEQ7bPHnLsivVNg
# 59f4Jnf8pyqhNelrbGrTeLOuF4JyE5a8Mt2Bc58NCLWT4I9bz8N/7Uk3+RZFtD3O
# Cv4nO2h7mG0CAwEAAaOCAb8wggG7MB8GA1UdIwQYMBaAFGedDyAJDMyKOuWCRnJi
# /PHMkOVAMB0GA1UdDgQWBBQthLJG1fU0R5j9FwY+vNZOT2lf4DAOBgNVHQ8BAf8E
# BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwbQYDVR0fBGYwZDAwoC6gLIYqaHR0
# cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtY3MtZzEuY3JsMDCgLqAshipo
# dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1jcy1nMS5jcmwwTAYDVR0g
# BEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGln
# aWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYgGCCsGAQUFBwEBBHwwejAkBggrBgEF
# BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFIGCCsGAQUFBzAChkZodHRw
# Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEySGlnaEFzc3VyYW5j
# ZUNvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQAD
# ggEBAEl5ctCYW1yDBEcpCwfycyG6vhbpQ8U2wfOQeQI5DmXImLS3spcyXO+Xfn13
# Eh/BL0gXFIi1ybM0wRG/EimU1ag/uQpCtsTRWfq2vJ96LqLf8UxRYGVw+N+IM/8e
# dXAKLexYb/ta4cvByjbJpoiJAJtYN32OclXRD5ph8yehuflmu+rw9TCVuPCa7hkO
# mah1L3n59tGneFGd9ZbWvqknQUAZcuKQrOofTKDb9oZKYjk2JJF7aTcjnHMuDo/X
# t+uHNCmhAuPyEy5Fa+RwdFptPLhudGH3WtNr4+5As2UsBDxm3gHxCiTUMIdnXChj
# 9jLvqhx3P5Rtsl4VZbBcqy/nqo4wggVPMIIEN6ADAgECAhALfhCQPDhJD/ovZ5qH
# oae5MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdp
# Q2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRp
# Z2lDZXJ0IEhpZ2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAw
# WhcNMjgxMDIyMTIwMDAwWjB2MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNl
# cnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTUwMwYDVQQDEyxEaWdp
# Q2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIENvZGUgU2lnbmluZyBDQTCCASIwDQYJ
# KoZIhvcNAQEBBQADggEPADCCAQoCggEBALRKXn0HD0HexPV2Fja9cf/PP09zS5zR
# Df5Ky1dYXoUW3QIVVJnwjzwvTQJ4EGjI2DVLP8H3Z86YHK4zuS0dpApUk8SFot81
# sfXxPKezNPtdSMlGyWJEvEiZ6yhJU8M9j8AO3jWY6WJR3z1rQGHuBEHaz6dcVpbR
# +Uy3RISHmGnlgrkT5lW/yJJwkgoxb3+LMqvPa1qfYsQ+7r7tWaRTfwvxUoiKewpn
# JMuQzezSTTRMsOG1n5zG9m8szebKU3QBn2c13jhJLc7tOUSCGXlOGrK1+7t48Elm
# p8/6XJZ1kosactn/UJJTzD7CQzIJGoYTaTz7gTIzMmR1cygmHQgwOwcCAwEAAaOC
# AeEwggHdMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1Ud
# JQQMMAoGCCsGAQUFBwMDMH8GCCsGAQUFBwEBBHMwcTAkBggrBgEFBQcwAYYYaHR0
# cDovL29jc3AuZGlnaWNlcnQuY29tMEkGCCsGAQUFBzAChj1odHRwOi8vY2FjZXJ0
# cy5kaWdpY2VydC5jb20vRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3J0
# MIGPBgNVHR8EgYcwgYQwQKA+oDyGOmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5jcmwwQKA+oDyGOmh0dHA6Ly9j
# cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5j
# cmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0dHBz
# Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYEFGed
# DyAJDMyKOuWCRnJi/PHMkOVAMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSYJhoIAu9j
# ZCvDMA0GCSqGSIb3DQEBCwUAA4IBAQBqDv9+E3wGpUvALoz5U2QJ4rpYkTBQ7Myf
# 4dOoL0hGNhgp0HgoX5hWQA8eur2xO4dc3FvYIA3tGhZN1REkIUvxJ2mQE+sRoQHa
# /bVOeVl1vTgqasP2jkEriqKL1yxRUdmcoMjjTrpsqEfSTtFoH4wCVzuzKWqOaiAq
# ufIAYmS6yOkA+cyk1LqaNdivLGVsFnxYId5KMND66yRdBsmdFretSkXTJeIM8ECq
# XE2sfs0Ggrl2RmkI2DK2gv7jqVg0QxuOZ2eXP2gxFjY4lT6H98fDr516dxnZ3pO1
# /W4r/JT5PbdMEjUsML7ojZ4FcJpIE/SM1ucerDjnqPOtDLd67GftMYICLDCCAigC
# AQEwgYowdjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcG
# A1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTE1MDMGA1UEAxMsRGlnaUNlcnQgU0hBMiBI
# aWdoIEFzc3VyYW5jZSBDb2RlIFNpZ25pbmcgQ0ECEAGcoaRt5kT+J1V6ZDM/I4Qw
# CQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcN
# AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw
# IwYJKoZIhvcNAQkEMRYEFMkh4SGgQabqriDM16rVEWoJ/gLfMA0GCSqGSIb3DQEB
# AQUABIIBAC7GSJ5b6NTJXYUpRcTanBxST5NO1VDQbrFH0k8jLQvrKuJmxl0jLHNN
# bm5yPJuyPg5zG1eC5uYVi3URbi1JTQpG50cQp/Lq1HykvdU90uzt0HDvDpeSvKe9
# ZMsvwoulx9nOMLGHVbOYURLRd/1lggniNe1lgisFrDnKVGensxmvDsCMPo9+N15a
# z1vTiYvefB8ycbDE/dF0hrXQQHJdsI3VyBELOam4yH7CZWo5VcAPy3mYqixuMwmf
# L5T3AxeKyw2jI7Ch7AgMhfwdZ9Ppz2qUD1K6ICP/afgofvuyV6X7R4qXy3t6wyFJ
# LIxiu/4OE6rgY+KoPyKbCvUOk+lBioQ=
# SIG # End signature block