CertificateValidation/Microsoft.AzureStack.PublicCertificateRequest.psm1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
function Write-AzsCertificateRequestFileInternal {
    <#
    .SYNOPSIS
        Internal function to call CSR using the standard Azure Stack request template.
    .DESCRIPTION
        Imports the standard Azure Stack certificate request template
        replaces deployment specific data such as subject and SAN.
        Detects if commas are used in the subject name and thus requiring a different X500NameFlag
    .EXAMPLE
        Write-AzsCertificateRequestFileInternal -subjectAltNames $completeSANs -subject $subject -KeyLength $KeyLength -HashAlgorithm $HashAlgorithm -OutputRequestPath $OutputRequestPath
    .INPUTS
        subjectAltNames - string - SubjectAlternativeNames
        subject - ordereddictionary - hashtable of deployment subject
        OutputRequestPath - string - path (parent must be valid) to where the CSRs should land.
        KeyLength - int - Defines the length of the public and private key
        HashAlgorithm - string - Hash Algorithm to be used for this request.
    .OUTPUTS
        Encoded CSR file - This is the file or content that should be presented to a CA to request certificates
        Clear Text INF file - this is a reference file to help debugging.
        Certreq log file - the output of the certreq.exe command, later streamed into overall AzsCertificateRequest.log
    .NOTES
    #>

    [cmdletbinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [System.Collections.Specialized.OrderedDictionary]$subject, 
            
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$subjectAltNames, 
            
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript( {Test-Path $_ -PathType Container})]
        $OutputRequestPath,
            
        [Parameter(Mandatory = $false)]
        [ValidateSet(2048, 4096, 8192)]
        [int]$KeyLength = 2048,

        [Parameter(Mandatory = $false)]
        [ValidateSet('SHA256', 'SHA384', 'SHA512')]
        [string]$HashAlgorithm = 'SHA256'
    )
    
    $thisFunction = $MyInvocation.MyCommand.Name
    try {
        #parse subject for comma and set appropropriate name flag to avoid error, and build subjectname
        $subjectStringArray = $subject.GetEnumerator()  | ForEach-Object { if ($_.Value) {"$($_.Name)=$($_.Value)"} }
        if ($subjectStringArray -notcontains ',') {
            Write-AzsReadinessLog -Message ("Subject {0} doesnt contain comma" -f $subjectStringArray) -Type Info -Function $thisFunction
            $stringString = $subjectStringArray -join ','
        }
        else {
            Write-AzsReadinessLog -Message ("Subject contains comma" -f $subjectStringArray) -Type Info -Function $thisFunction
            $stringString = $subjectStringArray -join ';'
            $X500NameFlags = "X500NameFlags = 0x40000000`n`r"
        }

        #Get INF Template and replace placeholders with user data
        $data = Import-PowerShellDataFile $PSScriptRoot\Microsoft.AzureStack.PublicCertificateRequestData.psd1
        $infTemplate = $data.requestINF
        $requestINF = $infTemplate.Replace('[[SubjectString]]', $stringString)
        $requestINF = $requestINF.Replace('[[X500]]', $X500NameFlags)
        $requestINF = $requestINF.Replace('[[SANStrings]]', $subjectAltNames)
        $requestINF = $requestINF.Replace('[[KeyLength]]', $KeyLength)
        $requestINF = $requestINF.Replace('[[HashAlgorithm]]', $HashAlgorithm)
        #Create filepaths for inf, req and log as [host|wildcard].region.external.fqdn-CertRequest-
        $infFilePath = "{0}\{1}_CertRequest_{2}_ClearTextDoNotUse.inf" -f $OutputRequestPath, $subjectAltNames.split('&')[0].Replace('dns=', '').Replace('.', '_').Replace('*', 'wildcard'), (Get-Date -f yyyyMMddHHmmss)
        Write-AzsReadinessLog -Message ("Setting infFilePath to {0}" -f $infFilePath) -Type Info -Function $thisFunction
        $csrFilePath = $infFilePath.Replace('_ClearTextDoNotUse', '').Replace('inf', 'req')
        $certReqLogPath = $csrFilePath.Replace('.req', '.log')

        #Create and print Inf template
        $requestINF | Out-File $infFilePath -Force
        #Create encoded cert request
        Write-AzsReadinessLog -Message ("Setting csrFilePath to {0}" -f $csrFilePath) -Type Info -Function $thisFunction

        $cmd = "-new $infFilePath $csrFilePath"
        $null = Start-Process -FilePath certreq.exe `
            -ArgumentList $cmd `
            -WindowStyle Hidden `
            -PassThru `
            -Wait `
            -RedirectStandardOutput $certReqLogPath
        Write-AzsReadinessLog -Message ("CSR generating for following SAN(s): {0}" -f $subjectAltNames) -Type Info -Function $thisFunction -toScreen
        Write-AzsReadinessLog -Message ("Present this CSR to your Certificate Authority for Certificate Generation: {0}" -f $csrFilePath) -Type Info -Function $thisFunction -toScreen
    }
    catch {
        Write-AzsReadinessLog -Message ("CSR generation failed with: {0}" -f $_.exception) -Type Error -Function $thisFunction
    }
    finally {
        # Move inf file to child directory called inf
        $infDest = ("{0}\{1}" -f (Split-Path $infFilePath -parent), 'Inf')
        if (-not (Test-Path $infDest)) {$null = New-Item -path $infDest  -ItemType Directory -Force}
        Move-Item -Path $infFilePath -Destination $infDest -Force -ErrorAction SilentlyContinue
        # Move log content to parent log and clean up log file.
        $certReqLogContent = Get-Content $certReqLogPath -ErrorAction SilentlyContinue | ForEach-Object {if ($_) {$_}}
        if (-not $certReqLogContent) {$certReqLogContent = '[missing]'}
        Write-AzsReadinessLog -Message ("Certreq.exe output: {0}" -f ($certReqLogContent -join '. ')) -Type Info -Function $thisFunction -toScreen
        Remove-item $certReqLogPath -Force
    }
}

function New-AzsCertificateSigningRequest {
    <#
    .SYNOPSIS
        Wrapper function to build SANs and call internal certreq.exe function for multiSAN CSR or SingleSAN CSR
    .DESCRIPTION
        Imports the standard Azure Stack SANs and builds the SAN list including PaaS if neccessary
        Calls internal function for once for multiSAN or multiple time for singleSAN (depending on the user input)
    .EXAMPLE
        $certificateRequestParams = @{
            'regionName' = azurestack
            'externalFQDN' = contoso.com
            'subject' = [ordered]@{"OU"="AzureStack";"O"="Microsoft";"L"="Redmond";"ST"="Washington";"C"="US"}
            'KeyLength' = 2048
            'HashAlgorithm' = SHA256
            'requestType' = MultipleCSR
            'includePaaS' = $false
            'OutputRequestPath' = '$ENV:USERPROFILE\Documents\AzsCertRequests'
        }
        Write-AzsCertificateRequestFile @certificateRequestParams
        Generates multiple CSRs for deployment of Azure Stack e.g. portal.azurestack.contoso.com, management.azurestack.contoso.com etc..
    .OUTPUTS
        None - This is a wrapper function that calls an internal function to generate the encoded CSR
    .PARAMETER RegionName
        Specifies the Azure Stack deployment's region name when deploymentdata.json is not used, must be alphanumeric.
    .PARAMETER externalFQDN
        Specifies the Azure Stack deployment's External FQDN, also aliased as ExternalFQDN and FQDN, must be valid DNSHostName
    .PARAMETER Subject
        Specifies an ordered dictionary of the subject for the certificate request generation.
    .PARAMETER KeyLength
        Defines the length of the public and private key for the certificate request generation. Default is 2048. Valid values 2048, 4096, 8192
    .PARAMETER HashAlgorithm
        Hash Algorithm to be used for the certificate request generation. Default is SHA256. Valid values SHA256, SHA384, SHA512
    .PARAMETER RequestType
        Specifies the SAN type of the certificate request. Valid values: MultipleCSR, SingleCSR.
        SingleCSR generates one certificate request for all services (not recommended for production). User will be prompted to confirm use.
        MultipleCSR generates multiple certificate requests, one for each service (strongly recommended in production environments).
    .PARAMETER IncludePaaS
        Specifies if PaaS services/hostnames should be added to the certificate request(s)
    .PARAMETER OutputRequestPath
        Specifies the destination path for certificate request files, directory must already exist.
    .PARAMETER IdentitySystem
        Specifies the Azure Stack deployment's Identity System valid values, AAD or ADFS, for Azure Active Directory and Active Directory Federated Services respectively
    .PARAMETER OutputPath
        Specifies custom path to save Readiness JSON report and Verbose log file.
    .LINK
        Generate Azure Stack Certificate Requests - https://aka.ms/AzsCSR
        Azure Stack Readiness Checker Tool - https://aka.ms/AzsReadinessChecker
    .NOTES
    #>

    [cmdletbinding()]
    [Alias("New-AzsCSR", "New-AzsCertificateRequest", "Write-AzsCertificateRequestFile")]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "Enter Azure Stack Region Name")]
        [string]$regionName, 
            
        [Parameter(Mandatory = $true, HelpMessage = "Enter Azure Stack External FQDN (without region name)")]
        [Alias("FQDN", "ExternalDomainName")]
        [ValidateScript( {[System.Uri]::CheckHostName($_) -eq 'dns' <#FQDN must be valid DNSHostName#>})]
        [string]$externalFQDN, 

        [Parameter(Mandatory = $true, HelpMessage = 'Provide subject name as an ordered hashtable e.g. $subject = [ordered]@{"OU"="AzureStack";"O"="Microsoft";"L"="Redmond";"ST"="Washington";"C"="US"}')]
        [System.Collections.Specialized.OrderedDictionary]$Subject,

        [Parameter(Mandatory = $false, HelpMessage = 'Provide Key Length: 2048, 4096 or 8192')]
        [ValidateSet(2048, 4096, 8192)]
        [int]$KeyLength = 2048,

        [Parameter(Mandatory = $false, HelpMessage = 'Provide Hash Algorithm: SHA256, SHA384 or SHA512')]
        [ValidateSet('SHA256', 'SHA384', 'SHA512')]
        [string]$HashAlgorithm = 'SHA256',
            
        [Parameter(Mandatory = $false, HelpMessage = "Enter Certificate Request generation type ('Single' = Request individual wildcard certificates, 'Multiple' = Request single multi domain wildcard certificates")]
        [ValidateSet('MultipleCSR', 'SingleCSR')]
        [string]$requestType = 'MultipleCSR',

        [Parameter(Mandatory = $false, HelpMessage = "Use if you want to add PaaS domain names to the certificate request")]
        [switch]$includePaaS,

        [Parameter(Mandatory = $true, HelpMessage = "Enter Azure Stack Identity System (AAD or ADFS)")]
        [ValidateSet('AAD', 'ADFS')]
        [string]$IdentitySystem,

        [Parameter(Mandatory = $true, HelpMessage = "Destination Path for Certificate Request(s)")]
        [ValidateScript( {Test-Path -Path $_ -PathType Container <# should be a valid directory path #>})]
        [string]$OutputRequestPath,

        [Parameter(Mandatory = $false, HelpMessage = "Directory path for log and report output")]
        [string]$OutputPath = "$ENV:TEMP\AzsReadinessChecker"

    )
    
    $thisFunction = $MyInvocation.MyCommand.Name
    $GLOBAL:OutputPath = $OutputPath
    Import-Module $PSScriptRoot\..\Microsoft.AzureStack.ReadinessChecker.Reporting.psm1 -Force
    Write-Header -invocation $MyInvocation -params $PSBoundParameters
    
    # Get template Data for SANs
    $data = Import-PowerShellDataFile $PSScriptRoot\Microsoft.AzureStack.PublicCertificateRequestData.psd1
    
    # Generate environment specific Deployment SANs, and force region and fqdn to lowercase
    $deploySANs = $data.deploySANs -f $regionName.ToLower(), $externalFQDN.ToLower()
    if ($IdentitySystem -eq 'ADFS') {
        $deploySANs += $data.adfsSANs -f $regionName.ToLower(), $externalFQDN.ToLower()
    }
    Write-AzsReadinessLog -Message ("Set Deployment SANs to: {0}" -f $deploySANs) -Type Info -Function $thisFunction

    # If applicable, Generate environment specific Deployment SANs, and force region and fqdn to lowercase
    if ($includePaaS) {
        $paasSANs = $data.paasSANs -f $regionName.ToLower(), $externalFQDN.ToLower()
        Write-AzsReadinessLog -Message ("Set PaaS SANs to: {0}" -f $paasSANs) -Type Info -Function $thisFunction
        $completeSANs = $deploySANs + $paasSANs
    }
    else {
        $completeSANs = $deploySANs
    }

    Write-AzsReadinessLog -Message ("Complete SAN list is: {0}" -f $completeSANs) -Type Info -Function $thisFunction

    # If the request type is for multiple SANs generate one request file with all SANs, else generate individual single SAN requests
    Write-AzsReadinessLog -Message ("CSR RequestType is: {0}" -f $requestType) -Type Info -Function $thisFunction
    if ($requestType -eq 'SingleCSR') {
        try {
            #suppress warning if this is pester.
            if ($OutputRequestPath -eq "$ENV:TEMP\PesterCSR") {
                $warnaction = 'SilentlyContinue'
            }
            else {
                $warnaction = 'Inquire'
            }
            Write-Warning "It is not recommended to use a single certificate across all public endpoints, the scope of a potential compromise is unneccessarily large." -WarningAction $warnaction
            $subject = Set-AzsCertificateCommonName -SubjectAlternativeNames $completeSANs -SubjectToChange $subject
            Write-AzsCertificateRequestFileInternal -subjectAltNames $completeSANs -subject $subject -KeyLength $KeyLength -HashAlgorithm $HashAlgorithm -OutputRequestPath $OutputRequestPath
        }
        catch {
            $_.exception
        }
    }
    elseif ($requestType -eq 'MultipleCSR') {
        foreach ($individualSAN in $completeSANs.split('&')) {
            if ($individualSAN -match '\*.appservice.|\*.scm.appservice.|\*.sso.appservice.') {
                Write-AzsReadinessLog -Message ("Skipping {0} as part of multi SAN request later" -f $individualSAN) -Type Warning -Function $thisFunction
            }
            else {
                $subject = Set-AzsCertificateCommonName -SubjectAlternativeNames $individualSAN -SubjectToChange $subject
                Write-AzsCertificateRequestFileInternal -subjectAltNames $individualSAN -subject $subject -KeyLength $KeyLength -HashAlgorithm $HashAlgorithm -OutputRequestPath $OutputRequestPath
            }
        }
        # special case for app service web default ssl is a multi SAN request
        if ($includePaaS)
        {
            $appSvcWebDefaultSSLSANs = $data.AppSvcWebTrafficDefault -f $regionName.ToLower(), $externalFQDN.ToLower()
            $subject = Set-AzsCertificateCommonName -SubjectAlternativeNames $appSvcWebDefaultSSLSANs -SubjectToChange $subject
            Write-AzsCertificateRequestFileInternal -subjectAltNames $appSvcWebDefaultSSLSANs -subject $subject -KeyLength $KeyLength -HashAlgorithm $HashAlgorithm -OutputRequestPath $OutputRequestPath
        }
    }
    else {
        Write-AzsReadinessLog -Message ("Unexpected RequestType: {0}" -f $requestType) -Type Error -Function $thisFunction
        throw ("Unexpected RequestType: $requestType" -f $thisFunction)
    }

    Write-Footer -invocation $MyInvocation
}

function Set-AzsCertificateCommonName {
    <#
    .SYNOPSIS
        Set's the CN of the subject to the first DNS name in the SAN
    .DESCRIPTION
        To avoid potential client problems the common name will be made consistent with
        the first DNS Name in the SubjectAlternativeNames
    .EXAMPLE
        Set-AzsCertificateCommonName -subjectAlternativeNames $SANs -SubjectToChange $subject
        This will set the common regardless of it's previous state or value.
    .INPUTS
        SubjectAlternativeNames - string - SANs to parse common from.
        SubjectToChange - OrderedDictionary - may or may not contain a common name.
    .OUTPUTS
        SubjectChanged - OrderedDictionary - with the new or replaced common name
    .NOTES
        General notes
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    [OutputType([System.Collections.Specialized.OrderedDictionary])]
    param ([string]$SubjectAlternativeNames,
        [System.Collections.Specialized.OrderedDictionary]$SubjectToChange
    )

    $thisFunction = $MyInvocation.MyCommand.Name

    # Write CN as first SAN, overwrite as needed.
    $commonName = $SubjectAlternativeNames.split('&')[0].Replace('dns=', '')
    if ($SubjectToChange.CN) {
        Write-AzsReadinessLog -Message ("Found CN = {0} and will remove it" -f $SubjectToChange.CN) -Type Info -Function $thisFunction
        $SubjectToChange.Remove('CN')
    }
    $SubjectToChange.Insert(0, 'CN', $commonName)
    Write-AzsReadinessLog -Message ("Inserted CN = {0}" -f $commonName) -Type Info -Function $thisFunction
    $SubjectChanged = $SubjectToChange
    $SubjectChanged
}
# SIG # Begin signature block
# MIIkiAYJKoZIhvcNAQcCoIIkeTCCJHUCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBNgIbIfx/8htg4
# SOHoDSwsfgjgnSaM+7+ylcwebJzMtqCCDYEwggX/MIID56ADAgECAhMzAAABA14l
# HJkfox64AAAAAAEDMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMTgwNzEyMjAwODQ4WhcNMTkwNzI2MjAwODQ4WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDRlHY25oarNv5p+UZ8i4hQy5Bwf7BVqSQdfjnnBZ8PrHuXss5zCvvUmyRcFrU5
# 3Rt+M2wR/Dsm85iqXVNrqsPsE7jS789Xf8xly69NLjKxVitONAeJ/mkhvT5E+94S
# nYW/fHaGfXKxdpth5opkTEbOttU6jHeTd2chnLZaBl5HhvU80QnKDT3NsumhUHjR
# hIjiATwi/K+WCMxdmcDt66VamJL1yEBOanOv3uN0etNfRpe84mcod5mswQ4xFo8A
# DwH+S15UD8rEZT8K46NG2/YsAzoZvmgFFpzmfzS/p4eNZTkmyWPU78XdvSX+/Sj0
# NIZ5rCrVXzCRO+QUauuxygQjAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUR77Ay+GmP/1l1jjyA123r3f3QP8w
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDM3OTY1MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAn/XJ
# Uw0/DSbsokTYDdGfY5YGSz8eXMUzo6TDbK8fwAG662XsnjMQD6esW9S9kGEX5zHn
# wya0rPUn00iThoj+EjWRZCLRay07qCwVlCnSN5bmNf8MzsgGFhaeJLHiOfluDnjY
# DBu2KWAndjQkm925l3XLATutghIWIoCJFYS7mFAgsBcmhkmvzn1FFUM0ls+BXBgs
# 1JPyZ6vic8g9o838Mh5gHOmwGzD7LLsHLpaEk0UoVFzNlv2g24HYtjDKQ7HzSMCy
# RhxdXnYqWJ/U7vL0+khMtWGLsIxB6aq4nZD0/2pCD7k+6Q7slPyNgLt44yOneFuy
# bR/5WcF9ttE5yXnggxxgCto9sNHtNr9FB+kbNm7lPTsFA6fUpyUSj+Z2oxOzRVpD
# MYLa2ISuubAfdfX2HX1RETcn6LU1hHH3V6qu+olxyZjSnlpkdr6Mw30VapHxFPTy
# 2TUxuNty+rR1yIibar+YRcdmstf/zpKQdeTr5obSyBvbJ8BblW9Jb1hdaSreU0v4
# 6Mp79mwV+QMZDxGFqk+av6pX3WDG9XEg9FGomsrp0es0Rz11+iLsVT9qGTlrEOla
# P470I3gwsvKmOMs1jaqYWSRAuDpnpAdfoP7YO0kT+wzh7Qttg1DO8H8+4NkI6Iwh
# SkHC3uuOW+4Dwx1ubuZUNWZncnwa6lL2IsRyP64wggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIWXTCCFlkCAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAQNeJRyZH6MeuAAAAAABAzAN
# BglghkgBZQMEAgEFAKCB3jAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgC9NDFMS7
# 0kfgj5XyUPzngfYUTRtnvKoHS+25s7ZZWUQwcgYKKwYBBAGCNwIBDDFkMGKgSIBG
# AE0AaQBjAHIAbwBzAG8AZgB0ACAAQQB6AHUAcgBlAFMAdABhAGMAawAgAFAAYQBy
# AHQAbgBlAHIAVABvAG8AbABrAGkAdKEWgBRodHRwOi8vQ29kZVNpZ25JbmZvIDAN
# BgkqhkiG9w0BAQEFAASCAQCbMn3kzq8uoCCDEePiGGpDjzlU2S7M8ZYdNDb9jO/v
# tJADXcrwB7mKIsS1CULc3Uz1H7RuV2VnqwH0K31TKSWh1ykyRduzYoNHbYI5pP7O
# qPB/DeopeScuMiohtOwoS3m3wFY2/QrJ5meQ95kGE4F/1fZSwIHlQtYTxNIII796
# Vcr5DEc40TIBULu+ydaq5jpVdwpFGuQiP1BzOWxtjodQhDjvCapc3AAaaZwpiUBi
# 84ytAjeI/chimuwmxWIA40CHLyRGVr8PzPgkSAEwcwMFmeXDUeueNPt6Gn6xaYFT
# v2PRhpE9JyZo8QugEdiYGkxUlaIIcLz+QA8+jQO7d7HwoYITtzCCE7MGCisGAQQB
# gjcDAwExghOjMIITnwYJKoZIhvcNAQcCoIITkDCCE4wCAQMxDzANBglghkgBZQME
# AgEFADCCAVgGCyqGSIb3DQEJEAEEoIIBRwSCAUMwggE/AgEBBgorBgEEAYRZCgMB
# MDEwDQYJYIZIAWUDBAIBBQAEIK1ZHNRn4FvU05aUrIU0AYL1YtQtNFJPqcpylbKs
# ve7cAgZb2dKzteAYEzIwMTgxMTAxMjE1MzUzLjA0MVowBwIBAYACAfSggdSkgdEw
# gc4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsT
# IE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFs
# ZXMgVFNTIEVTTjpDMEY0LTMwODYtREVGODElMCMGA1UEAxMcTWljcm9zb2Z0IFRp
# bWUtU3RhbXAgU2VydmljZaCCDx8wggT1MIID3aADAgECAhMzAAAA0BxqYGHC5+Gt
# AAAAAADQMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX
# YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg
# Q29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAy
# MDEwMB4XDTE4MDgyMzIwMjYyOFoXDTE5MTEyMzIwMjYyOFowgc4xCzAJBgNVBAYT
# AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD
# VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBP
# cGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpD
# MEY0LTMwODYtREVGODElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vy
# dmljZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJs+hjbXWs77xn3M
# KjwgBhWamzkgPLrX6kM0xhOnSbyG5WitejlIoyYoBicTQLWyDqyuZflDSzhrrgdh
# GKcO/aXLYczZxTfqG9rcTLVle02RqzqNK51fUh2p7c24gIaQ5Ma3J2EF5ItZDnu1
# bHhzT94U/JFvnoH3c5V7fmAyKuc01TEbXf5nQ9XnZJGMZNn7NQ9nLtysrVQ/xE1s
# p8dZ3Y9hkrpZJG/ftV3uhyoLv0ds/XElvylkvFNUKpaV8+iQTWhl8rGYdO0EOU/J
# PWsaSoKBX3sf8pZoB5ezL9ZF5dpa5o9XElUKelwSxGuC18WadKI2gTO75+DsUggE
# 9c6SRisCAwEAAaOCARswggEXMB0GA1UdDgQWBBQDgyiXqGsl8sRTMh+ZrTq8dxjF
# cTAfBgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEug
# SaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9N
# aWNUaW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsG
# AQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Rp
# bVN0YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoG
# CCsGAQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQClvCSWZAnfWvS/lFN/NhmRbjwg
# 9eBgXXyyl0YJWgwYPuorUZHkhc3R5PNNY0lNGk6RHjvbp0n22u6UR/BMN72jC2eB
# WdRNNlyjiPUFrWEudzStxPXBl9tBz1tdaaEQjcouhsBOMrtK1/Pj1VX1C9GCveV2
# eoYZtjmaIeDkIo4gY6v1cMW1Pe972NOolmXyrElWgp8dxSJ1h0bB8AqPzNwwiu3T
# 5oT1XsbTTBM1X124MgDm9rNkBSQmHq+z4fYeayXRKt7O1ycs65IYvkfBImt6cY+U
# FPiYR5mpGF0la6dB01Z8QaY3Wi9BmzsprJG72Xk6JryszvCRcNUX1wT5wIEsMIIG
# cTCCBFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0
# IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1
# WhcNMjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu
# Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
# cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC
# ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9p
# lGt0VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEw
# WbEwRA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeG
# MoQedGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJ
# UGKxXf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw
# 2k4GkbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0C
# AwEAAaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ
# 80N7fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8E
# BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2U
# kFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5j
# b20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmww
# WgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29m
# dC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYD
# VR0gAQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6
# Ly93d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYI
# KwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0
# AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9
# naOhIW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtR
# gkQS+7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzy
# mXlKkVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCf
# Mkon/VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3D
# nKOiPPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs
# 9/S/fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110
# mCIIYdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL
# 2IK0cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffI
# rE7aKLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxE
# PJdQcdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc
# 1bN+NR4Iuto229Nfj950iEkSoYIDrTCCApUCAQEwgf6hgdSkgdEwgc4xCzAJBgNV
# BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w
# HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29m
# dCBPcGVyYXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVT
# TjpDMEY0LTMwODYtREVGODElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAg
# U2VydmljZaIlCgEBMAkGBSsOAwIaBQADFQApKR+LcXEyVzc2v72d4dOjMT6OlaCB
# 3jCB26SB2DCB1TELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
# BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEp
# MCcGA1UECxMgTWljcm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xJzAlBgNV
# BAsTHm5DaXBoZXIgTlRTIEVTTjo1N0Y2LUMxRTAtNTU0QzErMCkGA1UEAxMiTWlj
# cm9zb2Z0IFRpbWUgU291cmNlIE1hc3RlciBDbG9jazANBgkqhkiG9w0BAQUFAAIF
# AN+FY3kwIhgPMjAxODExMDExOTM1MjFaGA8yMDE4MTEwMjE5MzUyMVowdDA6Bgor
# BgEEAYRZCgQBMSwwKjAKAgUA34VjeQIBADAHAgEAAgIciTAHAgEAAgIbsTAKAgUA
# 34a0+QIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMBoAowCAIBAAID
# FuNgoQowCAIBAAIDB6EgMA0GCSqGSIb3DQEBBQUAA4IBAQB1PgRQMBfYZpbjQ+xP
# UIqi/zxcL/H8yVU71XY6xejb85doJuyW8eCNdTEUQVXKXE1T1/Gcp9H+XFZLuVey
# EUDjO8vsCndgcW3ZRQUH32JAP2l2t+ibgv2wx3fIc48wJ4iMKT++MzBhe82Dl04x
# 8sjEv6HQ3iDBleI0RS210nDnPYakNl0jujielh5oJqJTeWu56/LkO1BkIhuQemdc
# qZF81SgSnKU6Ao0FaBR42AR2mg6N7EYsqxjChe996Gdc8Fe5vS8vYPT87wEiKgDT
# oSSroOY2UVKRLLWccNlJlBKGv4vg0ZIOQT8TubcNoL9GrJyXw8mLQFIzI6aO++P1
# ZEKgMYIC9TCCAvECAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
# bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw
# b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAC
# EzMAAADQHGpgYcLn4a0AAAAAANAwDQYJYIZIAWUDBAIBBQCgggEyMBoGCSqGSIb3
# DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgfZ8wGMOJ7sMneDLT
# 3do47Mkbu0bzXl56/thIUfPvjtowgeIGCyqGSIb3DQEJEAIMMYHSMIHPMIHMMIGx
# BBQpKR+LcXEyVzc2v72d4dOjMT6OlTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMw
# EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
# aWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0
# YW1wIFBDQSAyMDEwAhMzAAAA0BxqYGHC5+GtAAAAAADQMBYEFG8/trCD4uFRLd0e
# OmOcBD/p1lRdMA0GCSqGSIb3DQEBCwUABIIBADZohByOTaEqnyyJPV7fmYyM/uuY
# X6yYF7v7srfRP9jxjBgU+0uO5jKRrzjc7x/lLPHzpDsh5+QrL95WTZ6570LbHw/+
# zcFapVasrtZSQvphmd3hB8KoqhRfwymEhKHVRtVAjr9wNF20McciBo/186xuAxIZ
# t/SNYAZg53YfszperPS/jupH1YEwYHZieS3vSPvzthkoRh+EpHAziSYvrUawUmHR
# By8hISErsssw81hQfHdv1ZGgex8SabKJuSAt+XNu+VDY3WJiSu8dWPwMKoWsDbkI
# eFnNQHLkTUVwHTj6M01piZTReq5JyBNKAtrzxGu7HVpx7j8kRNLJZeThNBU=
# SIG # End signature block