Framework/Helpers/ActiveDirectoryHelper.ps1
Set-StrictMode -Version Latest class ActiveDirectoryHelper { static [PSObject] GetADAppServicePrincipalByAppId($ApplicationId) { $TenantId = (Get-AzureRmContext -ErrorAction Stop).Tenant.Id $ApiVersion = "1.6" $GraphApiUrl = [WebRequestHelper]::GraphApiUri + $TenantId + "/servicePrincipals/{0}?api-version=$ApiVersion" $uri = [string]::Format($GraphApiUrl + "&`$filter=(appId eq '{1}')", [string]::Empty , $ApplicationId); $resultObject = [WebRequestHelper]::InvokeGetWebRequest($uri); #this returns array of objects. Actual object is present at 1st index if($resultObject) { return $resultObject[0] } else { return $null } } static [void] UpdateADAppServicePrincipalCredential( $ApplicationID, [System.Security.Cryptography.X509Certificates.X509Certificate2] $PublicCert, [System.DateTime] $NotBefore = (Get-Date).AddDays(-1), [System.DateTime] $NotAfter = $NotBefore.AddMonths(6), [string] $Delete = "False" ) { #Initialization $TenantId = (Get-AzureRmContext -ErrorAction Stop).Tenant.Id $ApiVersion = "1.6" $GraphApiUrl = [WebRequestHelper]::GraphApiUri + $TenantId + "/servicePrincipals/{0}?api-version=$ApiVersion" $addMode = $False; $startDateString = $NotBefore.ToString("O"); $endDateString = $NotAfter.ToString("O"); if($Delete -eq "False") { if(-not $PublicCert) { throw "Public Certificate cannot be null" } } $servicePrincipal = [ActiveDirectoryHelper]::GetADAppServicePrincipalByAppId($ApplicationID) if($Delete -eq "False") { if($null -eq $servicePrincipal) { $addMode = $True; $servicePrincipal = New-Object -TypeName PSObject; $servicePrincipal | Add-Member -MemberType NoteProperty -Name appId -Value $ApplicationID -PassThru } $publicCertString = [System.Convert]::ToBase64String($PublicCert.GetRawCertData()); $credentialObject = New-Object -TypeName PSObject $credentialObject | Add-Member -MemberType NoteProperty -Name endDate -Value $endDateString -PassThru ` | Add-Member -MemberType NoteProperty -Name startDate -Value $startDateString -PassThru $credentialObject | Add-Member -MemberType NoteProperty -Name type -Value "AsymmetricX509Cert" -PassThru ` | Add-Member -MemberType NoteProperty -Name usage -Value "Verify" -PassThru ` | Add-Member -MemberType NoteProperty -Name value -Value $publicCertString if ([bool](Get-Member -InputObject $servicePrincipal -Name "keyCredentials")) { [System.Collections.ArrayList]$keys = $servicePrincipal.keyCredentials $credentialList = $keys.Add($credentialObject) $servicePrincipal.keyCredentials = $keys } else { $servicePrincipal | Add-Member -MemberType NoteProperty -Name keyCredentials -Value @($credentialObject) } } elseif($Delete -eq "True") { $servicePrincipal.keyCredentials = $servicePrincipal.keyCredentials | Where-Object { [System.DateTime]::Parse($_.startDate).ToUniversalTime() -ne $NotBefore.ToUniversalTime() ` -and [System.DateTime]::Parse($_.endDate).ToUniversalTime() -ne $NotAfter.ToUniversalTime() ` } } elseif($Delete -eq "All") { $servicePrincipal.keyCredentials = @() } $body = ConvertTo-Json -InputObject $servicePrincipal $operation = [string]::Empty; $requestUri = [string]::Empty; $GraphAPIAccessToken = Get-AzSDKAccessToken -ResourceAppIdURI "https://graph.windows.net/"; if($addMode) { $operation = "POST"; $requestUri = [string]::Format($GraphApiUrl, [string]::Empty); } else { $operation = "PATCH"; $requestUri = [string]::Format($GraphApiUrl, $servicePrincipal.objectId); } $updateResult = Invoke-RestMethod ` -Method $operation ` -Uri $requestUri ` -Headers @{ Authorization = "Bearer " + $GraphAPIAccessToken } ` -ContentType "application/json" ` -Body $body ` -UseBasicParsing if($null -eq $updateResult) { Throw "There was a problem while updating the service principal with new certificate" } } static [PSObject] GetADAppByAppId($ApplicationId) { $TenantId = (Get-AzureRmContext -ErrorAction Stop).Tenant.Id $ApiVersion = "1.6" $GraphApiUrl = [WebRequestHelper]::GraphApiUri + $TenantId + "/applications/{0}?api-version=$ApiVersion" $uri = [string]::Format($GraphApiUrl + "&`$filter=(appId eq '{1}')", [string]::Empty , $ApplicationId); $resultObject = [WebRequestHelper]::InvokeGetWebRequest($uri); #this returns array of objects. Actual object is present at 1st index if($resultObject) { return $resultObject[0] } else { return $null } } static [void] UpdateADAppCredential( $ApplicationID, [System.Security.Cryptography.X509Certificates.X509Certificate2] $PublicCert, [System.DateTime] $NotBefore = (Get-Date).AddDays(-1), [System.DateTime] $NotAfter = $NotBefore.AddMonths(6), [string] $Delete = "False" ) { #Initialization $TenantId = (Get-AzureRmContext -ErrorAction Stop).Tenant.Id $ApiVersion = "1.6" $GraphApiUrl = [WebRequestHelper]::GraphApiUri + $TenantId + "/applications/{0}?api-version=$ApiVersion" $addMode = $False; $startDateString = $NotBefore.ToString("O"); $endDateString = $NotAfter.ToString("O"); if($Delete -eq "False") { if(-not $PublicCert) { throw "Public Certificate cannot be null" } } $ADApplication = [ActiveDirectoryHelper]::GetADAppByAppId($ApplicationID) if($Delete -eq "False") { if($null -eq $ADApplication) { $addMode = $True; $ADApplication = New-Object -TypeName PSObject; $ADApplication | Add-Member -MemberType NoteProperty -Name appId -Value $ApplicationID -PassThru } $publicCertString = [System.Convert]::ToBase64String($PublicCert.GetRawCertData()); $credentialObject = New-Object -TypeName PSObject $credentialObject | Add-Member -MemberType NoteProperty -Name endDate -Value $endDateString -PassThru ` | Add-Member -MemberType NoteProperty -Name startDate -Value $startDateString -PassThru $credentialObject | Add-Member -MemberType NoteProperty -Name type -Value "AsymmetricX509Cert" -PassThru ` | Add-Member -MemberType NoteProperty -Name usage -Value "Verify" -PassThru ` | Add-Member -MemberType NoteProperty -Name value -Value $publicCertString if ([bool](Get-Member -InputObject $ADApplication -Name "keyCredentials")) { [System.Collections.ArrayList]$keys = $ADApplication.keyCredentials $credentialList = $keys.Add($credentialObject) $ADApplication.keyCredentials = $keys } else { $ADApplication | Add-Member -MemberType NoteProperty -Name keyCredentials -Value @($credentialObject) } } elseif($Delete -eq "True") { $ADApplication.keyCredentials = $ADApplication.keyCredentials | Where-Object { [System.DateTime]::Parse($_.startDate).ToUniversalTime() -ne $NotBefore.ToUniversalTime() ` -and [System.DateTime]::Parse($_.endDate).ToUniversalTime() -ne $NotAfter.ToUniversalTime() ` } } elseif($Delete -eq "All") { $ADApplication.keyCredentials = @() } $body = ConvertTo-Json -InputObject $ADApplication $operation = [string]::Empty; $requestUri = [string]::Empty; $GraphAPIAccessToken = Get-AzSDKAccessToken -ResourceAppIdURI "https://graph.windows.net/"; if($addMode) { $operation = "POST"; $requestUri = [string]::Format($GraphApiUrl, [string]::Empty); } else { $operation = "PATCH"; $requestUri = [string]::Format($GraphApiUrl, $ADApplication.objectId); } $updateResult = Invoke-RestMethod ` -Method $operation ` -Uri $requestUri ` -Headers @{ Authorization = "Bearer " + $GraphAPIAccessToken } ` -ContentType "application/json" ` -Body $body ` -UseBasicParsing if($null -eq $updateResult) { Throw "There was a problem while updating the service principal with new certificate" } } static [PSObject] NewSelfSignedCertificate($AppName,$CertStartDate,$CertEndDate,$Provider) { $newCertificate = New-SelfSignedCertificate -DnsName $AppName ` -Subject "CN=$AppName" ` -CertStoreLocation Cert:\CurrentUser\My ` -KeyExportPolicy Exportable ` -NotBefore $CertStartDate ` -NotAfter $CertEndDate ` -Type DocumentEncryptionCert ` -KeyUsage DataEncipherment ` -KeySpec KeyExchange ` -KeyUsageProperty Decrypt ` -Provider $Provider ` -ErrorAction Stop return $newCertificate } } # SIG # Begin signature block # MIIkAQYJKoZIhvcNAQcCoIIj8jCCI+4CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD+DMQyggZWUadd # pUEZzGy+DhF4eIvY4xqXW2oUXcVJCaCCDZMwggYRMIID+aADAgECAhMzAAAAjoeR # pFcaX8o+AAAAAACOMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMTYxMTE3MjIwOTIxWhcNMTgwMjE3MjIwOTIxWjCBgzEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9Q # UjEeMBwGA1UEAxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMIIBIjANBgkqhkiG9w0B # AQEFAAOCAQ8AMIIBCgKCAQEA0IfUQit+ndnGetSiw+MVktJTnZUXyVI2+lS/qxCv # 6cnnzCZTw8Jzv23WAOUA3OlqZzQw9hYXtAGllXyLuaQs5os7efYjDHmP81LfQAEc # wsYDnetZz3Pp2HE5m/DOJVkt0slbCu9+1jIOXXQSBOyeBFOmawJn+E1Zi3fgKyHg # 78CkRRLPA3sDxjnD1CLcVVx3Qv+csuVVZ2i6LXZqf2ZTR9VHCsw43o17lxl9gtAm # +KWO5aHwXmQQ5PnrJ8by4AjQDfJnwNjyL/uJ2hX5rg8+AJcH0Qs+cNR3q3J4QZgH # uBfMorFf7L3zUGej15Tw0otVj1OmlZPmsmbPyTdo5GPHzwIDAQABo4IBgDCCAXww # HwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0OBBYEFKvI1u2y # FdKqjvHM7Ww490VK0Iq7MFIGA1UdEQRLMEmkRzBFMQ0wCwYDVQQLEwRNT1BSMTQw # MgYDVQQFEysyMzAwMTIrYjA1MGM2ZTctNzY0MS00NDFmLWJjNGEtNDM0ODFlNDE1 # ZDA4MB8GA1UdIwQYMBaAFEhuZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEsw # SaBHoEWGQ2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0Nv # ZFNpZ1BDQTIwMTFfMjAxMS0wNy0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsG # AQUFBzAChkVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p # Y0NvZFNpZ1BDQTIwMTFfMjAxMS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAgEARIkCrGlT88S2u9SMYFPnymyoSWlmvqWaQZk62J3SVwJR # avq/m5bbpiZ9CVbo3O0ldXqlR1KoHksWU/PuD5rDBJUpwYKEpFYx/KCKkZW1v1rO # qQEfZEah5srx13R7v5IIUV58MwJeUTub5dguXwJMCZwaQ9px7eTZ56LadCwXreUM # tRj1VAnUvhxzzSB7pPrI29jbOq76kMWjvZVlrkYtVylY1pLwbNpj8Y8zon44dl7d # 8zXtrJo7YoHQThl8SHywC484zC281TllqZXBA+KSybmr0lcKqtxSCy5WJ6PimJdX # jrypWW4kko6C4glzgtk1g8yff9EEjoi44pqDWLDUmuYx+pRHjn2m4k5589jTajMW # UHDxQruYCen/zJVVWwi/klKoCMTx6PH/QNf5mjad/bqQhdJVPlCtRh/vJQy4njpI # BGPveJiiXQMNAtjcIKvmVrXe7xZmw9dVgh5PgnjJnlQaEGC3F6tAE5GusBnBmjOd # 7jJyzWXMT0aYLQ9RYB58+/7b6Ad5B/ehMzj+CZrbj3u2Or2FhrjMvH0BMLd7Hald # G73MTRf3bkcz1UDfasouUbi1uc/DBNM75ePpEIzrp7repC4zaikvFErqHsEiODUF # he/CBAANa8HYlhRIFa9+UrC4YMRStUqCt4UqAEkqJoMnWkHevdVmSbwLnHhwCbww # ggd6MIIFYqADAgECAgphDpDSAAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD # VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe # MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv # ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5 # MDlaFw0yNjA3MDgyMTA5MDlaMH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIw # MTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQ # TTS68rZYIZ9CGypr6VpQqrgGOBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULT # iQ15ZId+lGAkbK+eSZzpaF7S35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYS # L+erCFDPs0S3XdjELgN1q2jzy23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494H # DdVceaVJKecNvqATd76UPe/74ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZ # PrGMXeiJT4Qa8qEvWeSQOy2uM1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5 # bmR/U7qcD60ZI4TL9LoDho33X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGS # rhwjp6lm7GEfauEoSZ1fiOIlXdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADh # vKwCgl/bwBWzvRvUVUvnOaEP6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON # 7E1JMKerjt/sW5+v/N2wZuLBl4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xc # v3coKPHtbcMojyyPQDdPweGFRInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqw # iBfenk70lrC8RqBsmNLg1oiMCwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMC # AQAwHQYDVR0OBBYEFEhuZOVQBdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQM # HgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1Ud # IwQYMBaAFHItOgIxkEO5FAVO4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0 # dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0Nl # ckF1dDIwMTFfMjAxMV8wM18yMi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUF # BzAChkJodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0Nl # ckF1dDIwMTFfMjAxMV8wM18yMi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGC # Ny4DMIGDMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp # b3BzL2RvY3MvcHJpbWFyeWNwcy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcA # YQBsAF8AcABvAGwAaQBjAHkAXwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZI # hvcNAQELBQADggIBAGfyhqWY4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4s # PvjDctFtg/6+P+gKyju/R6mj82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKL # UtCw/WvjPgcuKZvmPRul1LUdd5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7 # pKkFDJvtaPpoLpWgKj8qa1hJYx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft # 0N3zDq+ZKJeYTQ49C/IIidYfwzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4 # MnEnGn+x9Cf43iw6IGmYslmJaG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxv # FX1Fp3blQCplo8NdUmKGwx1jNpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG # 0QaxdR8UvmFhtfDcxhsEvt9Bxw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf # 0AApxbGbpT9Fdx41xtKiop96eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkY # S//WsyNodeav+vyL6wuA6mk7r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrv # QQqxP/uozKRdwaGIm1dxVk5IRcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIV # xDCCFcACAQEwgZUwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAA # AI6HkaRXGl/KPgAAAAAAjjANBglghkgBZQMEAgEFAKCBsDAZBgkqhkiG9w0BCQMx # DAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkq # hkiG9w0BCQQxIgQgF3N18kpaAftIn+NE3lH0HWz/X9x0KswUAQGkGvtikC8wRAYK # KwYBBAGCNwIBDDE2MDSgEoAQAEEAegBTAEQASwAyADUAMqEegBxodHRwczovL2Fr # YS5tcy9henNka29zc2RvY3MgMA0GCSqGSIb3DQEBAQUABIIBAHN0On79CWRqTRGm # q7LuVKzqsFgm8gXt+8r86h1l4I0RiAIHkVyaFNAfn9CmfLFI097PKa8O3dY3vybo # oyPgs2k7HpJC/z3mfcvRBHpr7uUXBXI6w+jp6QH99dwckvlnspjirkYPERLr7N54 # b5JNTrqT5shVdoY8vOO8WKH+uImVCuxMWIvasr1pq0NoGjJSDYukiHycQE8nft9L # h2aOi+0uwJ9jch34LyZYsv3HVEVFvJy6/vUPCx/8KAWFIHmg6PfN4lidaB20xrpq # 12KHOZfl+2uXMQUz/+GjPSqAPmRVP2uIOZ2UaLlzmi4KcrygoEhEjB4x3s2LvYnC # 3NwjXiShghNMMIITSAYKKwYBBAGCNwMDATGCEzgwghM0BgkqhkiG9w0BBwKgghMl # MIITIQIBAzEPMA0GCWCGSAFlAwQCAQUAMIIBPQYLKoZIhvcNAQkQAQSgggEsBIIB # KDCCASQCAQEGCisGAQQBhFkKAwEwMTANBglghkgBZQMEAgEFAAQgNs6bFiyt/uln # yVqS7oJgfEE30wX8phkUXAnH//qnM/kCBlmSFyJyuBgTMjAxNzA5MDUwOTM3MTku # MTk3WjAHAgEBgAIB9KCBuaSBtjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjENMAsGA1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0Ug # RVNOOkIxQjctRjY3Ri1GRUMyMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFt # cCBTZXJ2aWNloIIOzzCCBnEwggRZoAMCAQICCmEJgSoAAAAAAAIwDQYJKoZIhvcN # AQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD # VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAw # BgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEw # MB4XDTEwMDcwMTIxMzY1NVoXDTI1MDcwMTIxNDY1NVowfDELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt # U3RhbXAgUENBIDIwMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCp # HQ28dxGKOiDs/BOX9fp/aZRrdFQQ1aUKAIKF++18aEssX8XD5WHCdrc+Zitb8BVT # JwQxH0EbGpUdzgkTjnxhMFmxMEQP8WCIhFRDDNdNuDgIs0Ldk6zWczBXJoKjRQ3Q # 6vVHgc2/JGAyWGBG8lhHhjKEHnRhZ5FfgVSxz5NMksHEpl3RYRNuKMYa+YaAu99h # /EbBJx0kZxJyGiGKr0tkiVBisV39dx898Fd1rL2KQk1AUdEPnAY+Z3/1ZsADlkR+ # 79BL/W7lmsqxqPJ6Kgox8NpOBpG2iAg16HgcsOmZzTznL0S6p/TcZL2kAcEgCZN4 # zfy8wMlEXV4WnAEFTyJNAgMBAAGjggHmMIIB4jAQBgkrBgEEAYI3FQEEAwIBADAd # BgNVHQ4EFgQU1WM6XIoxkPNDe3xGG8UzaFqFbVUwGQYJKwYBBAGCNxQCBAweCgBT # AHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgw # FoAU1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov # L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0 # XzIwMTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0 # cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAx # MC0wNi0yMy5jcnQwgaAGA1UdIAEB/wSBlTCBkjCBjwYJKwYBBAGCNy4DMIGBMD0G # CCsGAQUFBwIBFjFodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vUEtJL2RvY3MvQ1BT # L2RlZmF1bHQuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAFAAbwBs # AGkAYwB5AF8AUwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4IC # AQAH5ohRDeLG4Jg/gXEDPZ2joSFvs+umzPUxvs8F4qn++ldtGTCzwsVmyWrf9efw # eL3HqJ4l4/m87WtUVwgrUYJEEvu5U4zM9GASinbMQEBBm9xcF/9c+V4XNZgkVkt0 # 70IQyK+/f8Z/8jd9Wj8c8pl5SpFSAK84Dxf1L3mBZdmptWvkx872ynoAb0swRCQi # PM/tA6WWj1kpvLb9BOFwnzJKJ/1Vry/+tuWOM7tiX5rbV0Dp8c6ZZpCM/2pif93F # SguRJuI57BlKcWOdeyFtw5yjojz6f32WapB4pm3S4Zz5Hfw42JT0xqUKloakvZ4a # rgRCg7i1gJsiOCC1JeVk7Pf0v35jWSUPei45V3aicaoGig+JFrphpxHLmtgOR5qA # xdDNp9DvfYPw4TtxCd9ddJgiCGHasFAeb73x4QDf5zEHpJM692VHeOj4qEir995y # fmFrb3epgcunCaw5u+zGy9iCtHLNHfS4hQEegPsbiSpUObJb2sgNVZl6h3M7COaY # LeqN4DMuEin1wC9UJyH3yKxO2ii4sanblrKnQqLJzxlBTeCG+SqaoxFmMNO7dDJL # 32N79ZmKLxvHIa9Zta7cRDyXUHHXodLFVeNp3lfB0d4wwP3M5k37Db9dT+mdHhk4 # L7zPWAUu7w2gUDXa7wknHNWzfjUeCLraNtvTX4/edIhJEjCCBNowggPCoAMCAQIC # EzMAAACxcRN533X2NcgAAAAAALEwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTAwHhcNMTYwOTA3MTc1NjU3WhcNMTgwOTA3MTc1NjU3 # WjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UE # CxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOkIxQjctRjY3Ri1GRUMy # MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIBIjANBgkq # hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqQklG1Y1lu8ob0P7deumuRn4JvRi2GE # rmK94vgbnWPmd0j/9arA7539HD1dpG1uhYbmnAxc+qsuvMM0fpEvttTK4lZSU7ss # 5rJfWmbFn/J8kSGI8K9iBaB6hQkJuIX4si9ppNr9R3oZI3HbJ/yRkKUPk4hozpY6 # CkehRc0/Zfu6tQiyqI7mClXYZTXjw+rLsh3/gdBvYDd38zFBllaf+3uimKQgUTXG # jbKfqZZk3tEU3ibWVPUxAmmxlG3sWTlXmU31fCw/6TVzGg251lq+Q46OjbeH9vB2 # TOcqEso4Nai3J1CdMAYUdlelVVtgQdIx/c+5Hvrw0Y6W7uGBAWnW5wIDAQABo4IB # GzCCARcwHQYDVR0OBBYEFE5XPfeLLhRLV7L8Il7Tz7cnRBA7MB8GA1UdIwQYMBaA # FNVjOlyKMZDzQ3t8RhvFM2hahW1VMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9j # cmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1RpbVN0YVBDQV8y # MDEwLTA3LTAxLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6 # Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljVGltU3RhUENBXzIwMTAt # MDctMDEuY3J0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJ # KoZIhvcNAQELBQADggEBAHPujfu0W8PBTpjfYaPrAKIBLKcljT4+YnWbbgGvmXU8 # OvIUDBkkv8gNGGHRO5DSySaCARIzgn2yIheAqh6GwM2yKrfb4eVCYPe1CTlCseS5 # TOv+Tn/95mXj+NxTqvuNmrhgCVr0CQ7b3xoKcwDcQbg7TmerDgbIv2k7cEqbYbU/ # B3MtSX8Zjjf0ZngdKoX0JYkAEDbZchOrRiUtDJItegPKZPf6CjeHYjrmKwvTOVCz # v3lW0uyh1yb/ODeRH+VqENSHCboFiEiq9KpKMOpek1VvQhmI2KbTlRvK869gj1Nw # uUHH8c3WXu4A0X1+CBmU8t0gvd/fFlQvw04veKWh986hggN4MIICYAIBATCB46GB # uaSBtjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsG # A1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOkIxQjctRjY3Ri1G # RUMyMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiUKAQEw # CQYFKw4DAhoFAAMVADq635MoZeR60+ej9uKnRG5YqlPSoIHCMIG/pIG8MIG5MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMQ0wCwYDVQQLEwRNT1BS # MScwJQYDVQQLEx5uQ2lwaGVyIE5UUyBFU046NERFOS0wQzVFLTNFMDkxKzApBgNV # BAMTIk1pY3Jvc29mdCBUaW1lIFNvdXJjZSBNYXN0ZXIgQ2xvY2swDQYJKoZIhvcN # AQEFBQACBQDdWK0XMCIYDzIwMTcwOTA1MDQ1NjU1WhgPMjAxNzA5MDYwNDU2NTVa # MHYwPAYKKwYBBAGEWQoEATEuMCwwCgIFAN1YrRcCAQAwCQIBAAIBIAIB/zAHAgEA # AgIY4zAKAgUA3Vn+lwIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMB # oAowCAIBAAIDFuNgoQowCAIBAAIDB6EgMA0GCSqGSIb3DQEBBQUAA4IBAQA+ZEd4 # ooPHiKXaGoIJl7xct64OrgoneiQ1Q/WdfJxEl3cjN5B2vRUuQX+6hq5knZBRNSvQ # hFHIumBL52FqmEl0yu4JrEcavJhNtK+rZYIdiYW/IJN+eYjR7Ca7UiPnqC0AovLC # q7CH9Pa2LZrFMTw3OEfjCa5O4ZZ2eVaBP0Ts30GgU+BVK7RQ1OnnV3rRL3vwFs9m # 4RHh92aifGO3xwvmONclucmsupzvizd0YzkG5kFkIj38HaPpRKiR+/z1e1s/qQ5W # 90R5AVKCgBS/r47n+pjTrHtHKX65tYUnd1FCED51VBM/yI372NQ/ts1ncTv5dpIN # p/KxiiIUcI+/YNj1MYIC9TCCAvECAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg # UENBIDIwMTACEzMAAACxcRN533X2NcgAAAAAALEwDQYJYIZIAWUDBAIBBQCgggEy # MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQg1h85 # uj+qqSdVsy/oGm7/eG/qGmQ4AP5w5ZPdZqwMKiowgeIGCyqGSIb3DQEJEAIMMYHS # MIHPMIHMMIGxBBQ6ut+TKGXketPno/bip0RuWKpT0jCBmDCBgKR+MHwxCzAJBgNV # BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m # dCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAAsXETed919jXIAAAAAACxMBYEFF50 # WhcZSLtM19KqNcuqdWzh7UwDMA0GCSqGSIb3DQEBCwUABIIBAJgozAJmQu9DdK4Q # eaHLEF+VNgWreqCFDQ6O766VDvoszfDEYWF4qE+MORpc3p1bXTs5ZxHiczFEECWE # s5Gh/GGm90q7bxLXs+kmv7Lhx9TqGovcdZN10scAC7UTfwZwwz1JW562X1UbG+bL # fuzgiwZBeLy9swCF8PsBGTlPsL4+f9CC6BIAML2JfbRbT55byJreDVEtcib/VcPN # qO7xaE7qI5Jzvkv948qyEqGSRvWwdcBqNjMf2Al31EkkwrVe7gUTOSbFzbzIYMCo # yFACQx/OMArpBdKeEgqJsx/EheZU+lumkaK1i2nVVIqWHF+LnQ52+KhazI/XcBtb # mJsW/dk= # SIG # End signature block |