public/New-CsFixedNumberDiversion.ps1
#PerformScriptSigning Function New-UcmCsFixedNumberDiversion { <# .SYNOPSIS Diverts a number associated with Microsoft Teams Via Microsoft Calling plans or Telstra Calling to an external PSTN number .DESCRIPTION Diverts a number associated with Microsoft Teams Via Microsoft Calling plans or Telstra Calling to an external PSTN number by performing the following actions - Creates a Resource Account with named "PSTN_FWD_<inboundNumber>@domain.onmicrosoft.com" by default (Configurable using -AccountPrefix) - Licences the account with a Virtual Phone System Licence - Licences the account with an appropriate calling licence specified using -LicenceType - Creates an AutoAttendant with a 24 hour schedule - Configures a forward rule in the AutoAttendant Note: All accounts will be "Cloud born" and use your tenants onmicrosoft domain as syncing accounts is a PITA Warning: The script presently only supports Cloud Numbers, attempting to use Direct Routing numbers will fail. .EXAMPLE PS> New-UcmCsFixedNumberDiversion -OriginalNumber +61370105550 -TargetNumber +61755501234 -Domain Contoso.onmicrosoft.com -Country AU -LicenceType MCOPSTNEAU2 Forwards the number 61370105550 to 61755501234 .PARAMETER OriginalNumber The number of the new AutoAttendant. IE: The number to wish to forward FROM .PARAMETER TargetNumber The number the AutoAttendant will forward calls to. IE: the number to wish to forward TO .PARAMETER Domain This is the domain name that will be used to create the resource accounts for the diversion. This should be an "onmicrosoft" domain or fully AzureAD domain to minimise any directory sync issues For example "Contoso.onmicrosoft.com" .PARAMETER LicenceType How will we licence the AutoAttendant to make PSTN calls, Valid options are, MCOPSTN1, MCOPSTN2, MCOPSTNEAU2 Note, we presently dont support direct routing. I'll get there. .PARAMETER Country As we are setting licence's for the virtual users, we need to know what country to licence them in. Make sure to use upper case! .PARAMETER AccountPrefix (optional) This is the name that will be placed before the inbound phone number in the account name, used if you have a special naming convention for service accounts "PSTN_FWD_" by default .PARAMETER AADisplayName (optional) The name to assign to the AutoAttendant "<Original Number> Forward" by default .INPUTS This function accepts both parameter and pipline input .OUTPUT This Cmdet returns a PSCustomObject with multiple Keys to indicate status $Return.Status $Return.Message Return.Status can return one of three values "OK" : The Auto Attendent was created "Error" : Something went wrong creating the AA, check the output for more information. "Unknown" : Cmdlet reached the end of the function without returning anything, this shouldnt happen, if it does please log an issue on Github Return.Message returns descriptive text based on the outcome, mainly for logging or reporting .NOTES Version: 1.2 Date: 02/04/2023 .VERSION HISTORY 1.2 Updates for UcmPsTools public module Added Country Validation Added account creation error checking Updated timeframe handling to support updated Teams backend storing all new timeframes as global Resolved an issue with E164 formatted numbers causing AAD Account issues Resolved an issue with E164 formatted numbers causing invalid forward destinations Resoved issues with 'CallHandlingAssociations' parmeter stripping Updated to use Set-CsPhoneNumberAssignment instead of 'Set-CsOnlineVoiceApplicationInstance' 1.1: Documentation changes 1.0: Initial Public Release .REQUIRED FUNCTIONS/MODULES Modules AzureAD (Install-Module AzureAD) MSOnline (Install-Module MSOnline) UcmPSTools (Install-Module UcmPsTools) Includes Cmdlets below. Cmdlets Write-UcmLog: https://github.com/Atreidae/UcmPsTools/blob/main/public/Write-UcmLog.ps1 Write-HTMLReport: https://github.com/Atreidae/UcmPsTools/blob/main/public/Write-HTMLReport.ps1 (optional) New-UcmTeamsResourceAccount New-UcmOffice365User Grant-UcmOffice365UserLicence Test-UcmO365ServicePlan .REQUIRED PERMISSIONS 'Office365 User Admin' and 'Teams Admin' or better .LINK https://www.UcMadScientist.com https://github.com/Atreidae/UcmPSTools .ACKNOWLEDGEMENTS Stack Overflow, disabling services: https://stackoverflow.com/questions/50492591/how-can-i-disable-and-enable-office-365-apps-for-all-users-at-once-using-powersh Alex Verboon, Powershell script to remove Office 365 Service Plans from a User: https://www.verboon.info/2015/12/powershell-script-to-remove-office-365-service-plans-from-a-user/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope='Function')] #Todo https://github.com/Atreidae/UcmPSTools/issues/27 Param ( [Parameter(ValueFromPipelineByPropertyName=$true, mandatory=$true, Position=1)] [string]$OriginalNumber, [Parameter(ValueFromPipelineByPropertyName=$true, mandatory=$true, Position=2)] [string]$TargetNumber, [Parameter(ValueFromPipelineByPropertyName=$true, Position=3)] [string]$AccountPrefix="PSTN_FWD_", [Parameter(ValueFromPipelineByPropertyName=$true, mandatory=$true, Position=4)] [string]$Domain, [Parameter(ValueFromPipelineByPropertyName=$true, mandatory=$true, Position=5)] [string]$LicenceType, [Parameter(ValueFromPipelineByPropertyName=$true, mandatory=$true, Position=6, HelpMessage='The 2 letter country code for the users country, must be in capitals. eg: AU')] [ValidateSet("AF","AX","AL","DZ","AS","AD","AO","AI","AQ","AG","AR","AM","AW","AU","AT","AZ","BS","BH","BD","BB","BY","BE","BZ","BJ","BM","BT","BO","BQ","BA","BW","BV","BR","IO","BN","BG","BF","BI","CV","KH","CM","CA","KY","CF","TD","CL","CN","CX","CC","CO","KM","CG","CD","CK","CR","CI","HR","CU","CW","CY","CZ","DK","DJ","DM","DO","EC","EG","SV","GQ","ER","EE","SZ","ET","FK","FO","FJ","FI","FR","GF","PF","TF","GA","GM","GE","DE","GH","GI","GR","GL","GD","GP","GU","GT","GG","GN","GW","GY","HT","HM","VA","HN","HK","HU","IS","IN","ID","IR","IQ","IE","IM","IL","IT","JM","JP","JE","JO","KZ","KE","KI","KP","KR","KW","KG","LA","LV","LB","LS","LR","LY","LI","LT","LU","MO","MG","MW","MY","MV","ML","MT","MH","MQ","MR","MU","YT","MX","FM","MD","MC","MN","ME","MS","MA","MZ","MM","NA","NR","NP","NL","NC","NZ","NI","NE","NG","NU","NF","MK","MP","NO","OM","PK","PW","PS","PA","PG","PY","PE","PH","PN","PL","PT","PR","QA","RE","RO","RU","RW","BL","SH","KN","LC","MF","PM","VC","WS","SM","ST","SA","SN","RS","SC","SL","SG","SX","SK","SI","SB","SO","ZA","GS","SS","ES","LK","SD","SR","SJ","SE","CH","SY","TW","TJ","TZ","TH","TL","TG","TK","TO","TT","TN","TR","TM","TC","TV","UG","UA","AE","GB","US","UM","UY","UZ","VU","VE","VN","VG","VI","WF","EH","YE","ZM","ZW")][String]$Country, [Parameter(ValueFromPipelineByPropertyName=$true, Position=7)] [string]$AADisplayName ) BEGIN { $StartTime = Get-Date $Script:LogFileLocation = $PSCommandPath -replace '.ps1','.log' #Needing to actually figure out a better way of doing this for the module TODO Write-UcmLog -Message "$ScriptVersion script started at $StartTime" -Severity 1 -Component $Function Write-UcmLog -Message "Perfoming connection checks" -Severity 2 -Component $Function #Check to see if we are connected to SFBO $Test = (Test-UcmSFBOConnection -reconnect) If ($Test.Status -eq "Error") { Write-UcmLog -Message "Couldnt configure diversions." -Severity 3 -Component $function Write-UcmLog -Message "Test-SFBOConnection could not locate an SFBO connection" -Severity 2 -Component $function $Return.Status = "Error" $Return.Message = "No SFBO Connection ( $($test.message) )" Return $Return } #Check to see if we are connected to MSOL $Test = (Test-UcmMSOLConnection -reconnect) If ($Test.Status -eq "Error") { Write-UcmLog -Message "Couldnt configure diversions." -Severity 3 -Component $function Write-UcmLog -Message "Test-UcmMSOLConnection could not locate an MSOL connection" -Severity 2 -Component $function $Return.Status = "Error" $Return.Message = "No MSOL Connection ( $($test.message) )" Return $Return } #Everything went well, lets get ready for pipline #Create an object to store all our pipeline objects $Objects= @() } PROCESS { #Check to see if we got something on the pipeline, if we did. process it if ($OriginalNumber) { Write-UcmLog -Message "Executing process block with Diversion for $originalNumber" -Severity 2 -Component $Function $OriginalNumber = ($OriginalNumber).TrimStart("tel:+") $OriginalNumber = ($OriginalNumber).TrimStart("+") $TargetNumber = ($TargetNumber).TrimStart("tel:+") $TargetNumber = ($TargetNumber).TrimStart("+") if ($null -eq $AADisplayName) {$AADisplayName = ($OriginalNumber + " Forward")} $AADisplayName = ($OriginalNumber + " Forward") #todo fix the damn naming problem Write-UcmLog -Message "Displayname $AADisplayName" -Severity 2 -Component $Function #Create the resource account $UPN = ($AccountPrefix + $OriginalNumber + "@" + $domain) #Check for Resource Account #Powershell throws an error if the account isnt found, so lets trap it and use that instead Try { $AAAccount = (get-csonlineapplicationinstance -Identity $upn -ErrorAction Stop) Write-UcmLog -Message "Found Existing Resource Account, skipping creation" -Severity 2 -Component $function Write-UcmLog -Message $AAAccount -Severity 2 -Component $function } #we didnt find the account, make it Catch { Write-UcmLog -Message "Creating Required Resource Account" -Severity 2 -Component $function $AAAccounttemp = (New-UcmTeamsResourceAccount -upn $upn -ResourceType Autoattendant -displayname "$originalnumber forward") Write-UcmLog -Message "waiting for account to appear in AzureAD" -Severity 2 -Component $function #start checking for the account For ($i = 0; $i -lt 7) { #Check we havent been waiting too long if ($i -gt 5) { Write-UcmLog -Message "Account has not appeared after 60 seconds!" -Severity 3 -Component $function Write-UcmLog -Message "Aborting account $AADisplayName" -Severity 3 -Component $function Return } Write-UcmLog -Message "Waiting 10 seconds" -Severity 2 -Component $function Start-sleep -seconds 10 Try { $AAAccount = (get-csonlineapplicationinstance -Identity $upn -ErrorAction stop) Write-UcmLog -Message "Account found" -Severity 2 -Component $function Continue } Catch { Write-UcmLog -Message "Account not found, trying again" -Severity 2 -Component $function $i ++ } } } #todo, better error handling #If ($AAAccount.status -eq "Error") {Throw "something went wrong creating the resource account"} #Licence the account for Phone system $Licence1 = (Grant-UcmOffice365UserLicence -licencetype PHONESYSTEM_VIRTUALUSER -country $country -upn $upn) #Licence the account for PSTN calling $Licence2 = (Grant-UcmOffice365UserLicence -licencetype $licencetype -country $country -upn $upn) #todo, better error handling If ($licence1.status -eq "Error" -or $Licence2.status -eq "Error") {Throw "Something went wrong assinging licences"} #Pull the user and make it a callable object #$operatorObjectId = (Get-CsOnlineUser $UPN).ObjectId #$operatorEntity = New-CsAutoAttendantCallableEntity -Identity $operatorObjectId -Type User #check to see if the Autoattendant already exists Write-UcmLog -Message "Checking for Existing Autoattendant" -Severity 2 -Component $function $o=$null $o=(Get-CsAutoAttendant -NameFilter $AADisplayName) If ($o -eq $BeNullOrEmpty) { Write-UcmLog -Message "New-CsAutoAttendantCallableEntity" -Severity 1 -Component $function $CallForwardEntity = New-CsAutoAttendantCallableEntity -Identity "tel:+$TargetNumber" -Type ExternalPSTN Write-UcmLog -Message "New-CsAutoAttendantMenuOption" -Severity 1 -Component $function $DiversionMenuOption = New-CsAutoAttendantMenuOption -Action TransferCallToTarget -DtmfResponse Automatic -CallTarget $CallForwardEntity Write-UcmLog -Message "New-CsAutoAttendantMenu" -Severity 1 -Component $function $DiversionMenu = New-CsAutoAttendantMenu -Name "Fixed Diversion" -MenuOptions @($DiversionMenuOption) Write-UcmLog -Message "New-CsAutoAttendantCallFlow" -Severity 1 -Component $function $DiversionCallFlow = New-CsAutoAttendantCallFlow -Name "Fixed Diversion" -Menu $DiversionMenu Write-UcmLog -Message "New-CsAutoAttendant $o=New-CsAutoAttendant -Name $AADisplayName -DefaultCallFlow $DiversionCallFlow -CallHandlingAssociations @($afterHoursCallHandlingAssociation) -Language 'en-AU' -TimeZoneId 'AUS Eastern Standard Time'" -Severity 1 -Component $function #$o=New-CsAutoAttendant -Name $AADisplayName -DefaultCallFlow $DiversionCallFlow -CallHandlingAssociations @($afterHoursCallHandlingAssociation) -Language "en-AU" -TimeZoneId "AUS Eastern Standard Time" $o=New-CsAutoAttendant -Name $AADisplayName -DefaultCallFlow $DiversionCallFlow -Language "en-AU" -TimeZoneId "AUS Eastern Standard Time" Write-UcmLog -Message "App instance lookup" -Severity 1 -Component $function $applicationInstanceId = (Get-CsOnlineUser $UPN).ObjectId Write-UcmLog -Message "New-CsOnlineApplicationInstanceAssociation" -Severity 2 -Component $function New-CsOnlineApplicationInstanceAssociation -Identities @($applicationInstanceId) -ConfigurationId $O.identity -ConfigurationType AutoAttendant Write-UcmLog -Message "Get-csAutoAttendant" -Severity 1 -Component $function Get-csAutoAttendant -Identity $o.identity } Else { Write-UcmLog -Message "Found Existing Autoattendant, Checking for Resource Account" -Severity 2 -Component $function if ([bool]$o.ApplicationInstances -eq $false) { Write-UcmLog -Message "Resource Account Association Missing, fixing" -Severity 3 -Component $function Write-UcmLog -Message "App instance lookup" -Severity 1 -Component $function $applicationInstanceId = (Get-CsOnlineUser $UPN).identity Start-sleep -seconds 10 Write-UcmLog -Message "New-CsOnlineApplicationInstanceAssociation" -Severity 2 -Component $function [void](New-CsOnlineApplicationInstanceAssociation -Identities @($applicationInstanceId) -ConfigurationId $O.identity -ConfigurationType AutoAttendant) } } #Assign the phone number to the resource account Write-UcmLog -Message "Assigning Number to Resource Account" -Severity 2 -Component $function #Set-CsOnlineApplicationInstance -Identity $AAUPN -OnpremPhoneNumber $telephoneNumber ## Direct Routing version! #Set-CsOnlineVoiceApplicationInstance -Identity $UPN -TelephoneNumber $telephoneNumber -verbose ##Deprecated Set-CsPhoneNumberAssignment -Identity $UPN -PhoneNumber "+$OriginalNumber" -PhoneNumberType CallingPlan ##todo update for more calling types } Else { Throw "Nothing to process" } #endregion FunctionWork } END { #region FunctionSetup, Set Default Variables for HTML Reporting and Write Log $function = 'END-Block' # Log why we were called Write-UcmLog -Message "$($MyInvocation.InvocationName) called with $($MyInvocation.Line)" -Severity 1 -Component $function Write-UcmLog -Message "Parameters" -Severity 3 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Keys)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Parameters Values" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$($PsBoundParameters.Values)" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "Optional Arguments" -Severity 1 -Component $function -LogOnly Write-UcmLog -Message "$Args" -Severity 1 -Component $function -LogOnly #endregion FunctionSetup Write-UcmLog -Message "Executing process block with Attendant $DisplayName" -Severity 1 -Component $Function } }#end function # SIG # Begin signature block # MIIRwgYJKoZIhvcNAQcCoIIRszCCEa8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUvDbnXr8F4AoqfKC2n2krR9pN # nd6ggg4OMIIGsDCCBJigAwIBAgIQCK1AsmDSnEyfXs2pvZOu2TANBgkqhkiG9w0B # AQwFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVk # IFJvb3QgRzQwHhcNMjEwNDI5MDAwMDAwWhcNMzYwNDI4MjM1OTU5WjBpMQswCQYD # VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD # ZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEg # Q0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1bQvQtAorXi3XdU5 # WRuxiEL1M4zrPYGXcMW7xIUmMJ+kjmjYXPXrNCQH4UtP03hD9BfXHtr50tVnGlJP # DqFX/IiZwZHMgQM+TXAkZLON4gh9NH1MgFcSa0OamfLFOx/y78tHWhOmTLMBICXz # ENOLsvsI8IrgnQnAZaf6mIBJNYc9URnokCF4RS6hnyzhGMIazMXuk0lwQjKP+8bq # HPNlaJGiTUyCEUhSaN4QvRRXXegYE2XFf7JPhSxIpFaENdb5LpyqABXRN/4aBpTC # fMjqGzLmysL0p6MDDnSlrzm2q2AS4+jWufcx4dyt5Big2MEjR0ezoQ9uo6ttmAaD # G7dqZy3SvUQakhCBj7A7CdfHmzJawv9qYFSLScGT7eG0XOBv6yb5jNWy+TgQ5urO # kfW+0/tvk2E0XLyTRSiDNipmKF+wc86LJiUGsoPUXPYVGUztYuBeM/Lo6OwKp7AD # K5GyNnm+960IHnWmZcy740hQ83eRGv7bUKJGyGFYmPV8AhY8gyitOYbs1LcNU9D4 # R+Z1MI3sMJN2FKZbS110YU0/EpF23r9Yy3IQKUHw1cVtJnZoEUETWJrcJisB9IlN # Wdt4z4FKPkBHX8mBUHOFECMhWWCKZFTBzCEa6DgZfGYczXg4RTCZT/9jT0y7qg0I # U0F8WD1Hs/q27IwyCQLMbDwMVhECAwEAAaOCAVkwggFVMBIGA1UdEwEB/wQIMAYB # Af8CAQAwHQYDVR0OBBYEFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB8GA1UdIwQYMBaA # FOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK # BggrBgEFBQcDAzB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9v # Y3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4 # oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJv # b3RHNC5jcmwwHAYDVR0gBBUwEzAHBgVngQwBAzAIBgZngQwBBAEwDQYJKoZIhvcN # AQEMBQADggIBADojRD2NCHbuj7w6mdNW4AIapfhINPMstuZ0ZveUcrEAyq9sMCcT # Ep6QRJ9L/Z6jfCbVN7w6XUhtldU/SfQnuxaBRVD9nL22heB2fjdxyyL3WqqQz/WT # auPrINHVUHmImoqKwba9oUgYftzYgBoRGRjNYZmBVvbJ43bnxOQbX0P4PpT/djk9 # ntSZz0rdKOtfJqGVWEjVGv7XJz/9kNF2ht0csGBc8w2o7uCJob054ThO2m67Np37 # 5SFTWsPK6Wrxoj7bQ7gzyE84FJKZ9d3OVG3ZXQIUH0AzfAPilbLCIXVzUstG2MQ0 # HKKlS43Nb3Y3LIU/Gs4m6Ri+kAewQ3+ViCCCcPDMyu/9KTVcH4k4Vfc3iosJocsL # 6TEa/y4ZXDlx4b6cpwoG1iZnt5LmTl/eeqxJzy6kdJKt2zyknIYf48FWGysj/4+1 # 6oh7cGvmoLr9Oj9FpsToFpFSi0HASIRLlk2rREDjjfAVKM7t8RhWByovEMQMCGQ8 # M4+uKIw8y4+ICw2/O/TOHnuO77Xry7fwdxPm5yg/rBKupS8ibEH5glwVZsxsDsrF # hsP2JjMMB0ug0wcCampAMEhLNKhRILutG4UI4lkNbcoFUCvqShyepf2gpx8GdOfy # 1lKQ/a+FSCH5Vzu0nAPthkX0tGFuv2jiJmCG6sivqf6UHedjGzqGVnhOMIIHVjCC # BT6gAwIBAgIQDyLHeeRvkUFg5QtSFTT8FjANBgkqhkiG9w0BAQsFADBpMQswCQYD # VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD # ZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEg # Q0ExMB4XDTIzMDIyMzAwMDAwMFoXDTI2MDIyMzIzNTk1OVowXjELMAkGA1UEBhMC # QVUxETAPBgNVBAgTCFZpY3RvcmlhMRAwDgYDVQQHEwdCZXJ3aWNrMRQwEgYDVQQK # EwtKYW1lcyBBcmJlcjEUMBIGA1UEAxMLSmFtZXMgQXJiZXIwggIiMA0GCSqGSIb3 # DQEBAQUAA4ICDwAwggIKAoICAQC47oExh25TrxvApIYdMRYvjOdZCb8WwgeTemm3 # ZY7BElIWu6+gzRGqQe8RFsN7oIgin5pvjTYIToxt1CCag2A5o8L0NtULmxJEegc+ # VaF24DZQqI4qGQGH/Qnglqys6+yPkwLnfeSxpeWe4u49HUUGDFIxHCh42MlCLp/f # fHT49QhhpO+LyeLnDoUs6DmahyIb6NeE2cW5AYRXEesW7GRNfXzygBSlVWJOgvcy # V5Y4IvAZVx2hKKMTjYFIz4/RYMg7fwYZEJ2LRJ/GnVazobKAvh6ZBet5KwVNI9EI # 29DtWQyK/RoPOguTRcB5VuiZVlv0xjBYM7iJuH2Soa3StQYVxL/5gjZCC9WOs4NR # EIGU3XmHoogFDvoT1vf1izMPFQzdZfgPvy/XXsbgTVo5ncesJ6WtZwqwCXG1K0XW # IPZqTHolc1MyU6K1bEHO+7YWLpKgM9THl644G7PEhcKpNDsHlfvLVQdYhI55UJtc # iyMrTw11CNECvk3GK1mrluvKsrxdaH6G3Sp9VVHRtef6OZ5SlzkM5ID4egB2bXRb # R/69bEuZr5hhm+v2lBSWIbZj/Mva6i/a/TAvy4vvPLo3DRcASkYZDC4T8gDMzmpG # Xs4jAc9sfTL9z+o5u1PLJHFGRjJ+Wa2CgSftCdbKLjn+AY9m8ipc8jmOBKNY9yGI # pQWapQIDAQABo4ICAzCCAf8wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0 # TkIwHQYDVR0OBBYEFOBsg1xudlbXVSql8pWbiHoTyZS/MA4GA1UdDwEB/wQEAwIH # gDATBgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRw # Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmlu # Z1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hB # Mzg0MjAyMUNBMS5jcmwwPgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcC # ARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGUBggrBgEFBQcBAQSBhzCB # hDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUF # BzAChlBodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVk # RzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAA # MA0GCSqGSIb3DQEBCwUAA4ICAQBOh5vRXqTCQzv0T1F2EgDkq5VnljlHsa7Ov/d/ # lpOvr8NebBiatxbhfhPCnToY7BD2f7YVsUuQ+VDdcIYsskcU5spBHcFYidg2jGu4 # 59FGMaS765XStDwGGTN/360gEsNYSnKWYL4+8jYWHlzRO0jHloyWz+gF5dYWzdDJ # u1dudLIJ0RgrEVJeLSgIBWygLL5EyIzOPlrxztsILMSbdPTQLeBIm7ipOk4EACx1 # hhBVUsUoCAlASH+yCKDU4v2HFd7SzrkRUrf7XJ2Na2YsiHjiTGqHIE86KyvxGDhT # 3n2/jX23Nh/bkWHurHwTfaTCOQ44ZlAbnZQjBlmrFn5hPMXRpciiQFmrKTPD/nuo # 9MVnCciHEpHJ63/JZNF/eno1122/wVkL7MuRlCVHN7L/wuNQxQk3ARdIju6OD/Gi # Mwg0Qih6HVWJtkHK3ExoUKKKUZCOvIeHxzp+K6FWUupPZKUgWzn4AHMxm6zr+Sde # laIAACqAkxYsDYKbM7WlNi3uIH2HeXqU9uSDt5tgPpImrog/ab4HrhpDfITRgT1c # cxaWQezpJEPC+kqVD41T3wlEie1Qm4vYWg+oBVEMBxVLh6CYbeppCRTEXRGnAiCH # /Ma1uwyWnNCWxrhd1uSi6sj4ISzgnFyGCvsI0gavKpS5AQhapJgk6/fULTFeS+Ee # kRH9FDGCAx4wggMaAgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD # ZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2ln # bmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQDyLHeeRvkUFg5QtSFTT8FjAJ # BgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0B # CQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAj # BgkqhkiG9w0BCQQxFgQU43XOXk8u3F1WEdawU/NpQhLv4aMwDQYJKoZIhvcNAQEB # BQAEggIAZTmKkJ02pAVNYcF5jGos6APvOP7V76lhDF6TvNGFUy/yy5+hSlV5+rAz # TpjOI2RtArBMS/dtm5tD6EmiGYl51PApCnv5TEywsoeN+qxbdXL3dheMaWtdT2HV # waAQpYbjP+pG287Yby0Mhbt3phmyRXvWsUPUgEPiahag557uc6Tw/dctmqmZfcU7 # SdFyLSBtwLW5GYwwxSLBqLsl3M4C0qbmtluJindNcDCaTRdVGvInycAAFLFOoTBD # YeL2gwo/B0LvOxr2Muppc85EMzbPzDzaETDQwpM9/BbwkyCzIStM5Ut03r5k2gM1 # 5m9S760XeQUcBOzq3v270i2LwQ+URwuo6UqbJG8TVTEC0z48W9nTV9KQ88/UJHwN # oN81HG83w1CneL1lw1M5mfnW6HNh51BwgnZDrhro/rwpjk6ltFVkeacMsJ4rk69L # P46H9SZuZZXNy7ph2lqj/+rY7mQMaJVFj74DfdSnet1ZqAl+rMdi05RooEwR0K99 # yEkFLcgT46arPthqY31KXGPY0IGbhThavGw2q2INO5Y4ak63zITT0COwkMjsRD36 # 7BmWDj0MbKeGu8lRZGURfNuoP4dg2i2YvTBlbH52R4pX3k0XEGzX8bhTEgHLYdrn # v7mmL7zb4Xwq/QSFkHmjPpCQptzKDDyw80c3YoKivjZmbIRnrEw= # SIG # End signature block |