logstream 0.0.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1fb012ea79dd2712ca5638f1f075bab10b06ea505816d817f5232945c4a0f8c
4
- data.tar.gz: abd25fcf634cc1a78aa48971a5b9419170c3458da5b588863fdec391c4737183
3
+ metadata.gz: 5c342a7bd87ef68659a38e1a178aa215300f799b40d3da2f20e39450d223c7b0
4
+ data.tar.gz: e7c15933144d09121045040fd829185c6a1d91d95af642bd7c3e0e820fbaa23c
5
5
  SHA512:
6
- metadata.gz: 25f698a764a85c1ff93e957799f3a47b1296a0c9c83a6066c13c1166297fd01e398eee6142407f67d9ed21e7a0eb87386d2ff26cd1ca4e953ee0d21f8a3e2657
7
- data.tar.gz: 57fcc2b040de10784dc01e45b8632c6c7eecab6ac5fb2bb11aa4bafb8601514bb4f1b19ad9c063585d1021442ddafe551fcedd1affc6459f80a7bb3df92f0ac9
6
+ metadata.gz: d4464befbf1bb3872679b1bd5e3b9688807068659ad02f6c34720009315b3986d60d7bae15bba562acc12147089eac0defdd83242eb4a2024def00593bef7f38
7
+ data.tar.gz: c2d90fbb124b7e7a12a7ea7bbb4a96d6ee758a7baf28138ba5017582e68fb846d4319185a15374a587172c3f649c4a03ca355da7ed5fb8c69f35d689bdc0fab0
@@ -0,0 +1,19 @@
1
+ FROM ubuntu:latest
2
+
3
+ RUN apt-get update \
4
+ && apt-get install -y \
5
+ curl \
6
+ make \
7
+ build-essential \
8
+ g++ \
9
+ libssl-dev \
10
+ ruby-dev
11
+ RUN mkdir /src
12
+
13
+ COPY . /src
14
+
15
+ RUN cd /src \
16
+ && gem build logstream \
17
+ && gem install logstream-*.gem
18
+
19
+ ENTRYPOINT ["/bin/bash"]
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Acquia, Inc.
3
+ Copyright (c) 2020 Acquia, Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -15,25 +15,24 @@ UI</a> as well.
15
15
 
16
16
  ## Quick start
17
17
 
18
- * Logstream works in conjunction with Acquia's <a
19
- href="http://cloudapi.acquia.com/">Cloud API</a>. If you haven't already,
20
- install your <a href="https://accounts.acquia.com/account/security">Acquia
21
- Cloud Drush integration</a> files, which includes your Cloud API credentials.
18
+ * Logstream works in conjunction with Acquia's [Cloud API](https://cloudapi-docs.acquia.com/). In order to use Cloud API you will need to generate credentials for your account. [Cloud API v2 authentication](https://docs.acquia.com/acquia-cloud/develop/api/auth/#generating-an-api-token) explains how to generate the credentials. Place the credentials in `$HOME/.acquia/cloudapiv2.conf` . This file is in JSON format with api_key and api_secret defined.
19
+ ```
20
+ {
21
+ "api_key" : "key",
22
+ "api_secret" : "secret"
23
+ }
24
+ ```
22
25
 
23
26
  * Install the Logstream CLI:
24
27
  ```
25
28
  $ gem install logstream
26
29
  ```
27
30
 
28
- * List all the sites you have access to:
29
- ```
30
- $ drush ac-site-list
31
- devcloud:mysite
32
- ```
31
+ * Find the UUID of the application you would like to stream logs for. Documentation on how to find applicaiton UUID can be found [here](https://docs.acquia.com/acquia-cloud/manage/applications/#obtaining-your-subscription-s-application-id)
33
32
 
34
33
  * Stream logs from the production environment:
35
34
  ```
36
- $ logstream tail devcloud:mysite prod
35
+ $ logstream tail 55ea1945-4aa6-4c56-bb7b-2108565e22d6 prod
37
36
  127.0.0.1 - - [11/Jun/2014:17:28:47 +0000] "GET / HTTP/1.1" 200 7708 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" http_host=mysite.com affinity="-" upstream_addr="10.218.29.150:80" hosting_site=mysite request_time=0.030 forwarded_for="64.80.128.4" upstream_status="200"
38
37
  ... etc ...
39
38
  ```
@@ -44,11 +43,10 @@ A variety of filtering and display options are available:
44
43
  $ logstream help tail
45
44
  ```
46
45
 
47
- ## API v1
46
+ ## API v2
48
47
 
49
- Logstream communicates over TCP using the WebSocket protocol. Use the <a
50
- href="http://cloudapi.acquia.com/#GET__sites__site_envs__env_logstream-instance_route">logstream
51
- Cloud API call</a> to retrieve the URL to connect to and an authenticated
48
+ Logstream communicates over TCP using the WebSocket protocol. Use the [logstream
49
+ Cloud API call](https://cloudapi-docs.acquia.com/#/Environments/getEnvironmentsLogstream) to retrieve the URL to connect to and an authenticated
52
50
  message to initial streaming for a particular Cloud environment.
53
51
 
54
52
  Messages use text data frames, and contain JSON-encoded hashes. Each message
@@ -73,7 +71,7 @@ default, the CLI enables the log types apache-request, php-error,
73
71
  drupal-watchdog, and varnish-request.
74
72
 
75
73
  ```
76
- $ logstream tail devcloud:mysite dev --debug
74
+ $ logstream tail 55ea1945-4aa6-4c56-bb7b-2108565e22d6 dev --debug
77
75
  -> connect to wss://logstream.acquia.com/ah_websocket/logstream/v1
78
76
  -> {"site":"devcloud:mysite","d":"deaefc1f42a4d18cb932c2eb9fa75115fba5ab83f1a3c564767ef1ce8dabf2cc","t":1404764927,"env":"dev","cmd":"stream-environment"}
79
77
  <- {"cmd":"connected","server":"logstream-api-61"}
@@ -1,45 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'rubygems'
4
- require 'net/https'
5
- require 'json'
6
4
  require 'thor'
5
+ require 'json'
7
6
  require 'logstream/client'
8
-
9
- # @todo: Yeah, this is terrible. Replace it with a real Cloud API gem.
10
- class QuickCloudAPI
11
- class Error < StandardError; end
12
-
13
- def self.get(path, opts = {})
14
- confpath = "#{ENV['HOME']}/.acquia/cloudapi.conf"
15
- begin
16
- json = File.read(confpath)
17
- config = JSON.load(json)
18
- rescue Errno::ENOENT, JSON::ParserError => e
19
- raise Error, "#{confpath} is missing or invalid. Download your Drush aliases from https://accounts.acquia.com/account/security to initialize it."
20
- end
21
- opts[:endpoint] ||= "https://cloudapi.acquia.com/v1"
22
- uri = URI.parse("#{opts[:endpoint]}#{path}.json")
23
- http = Net::HTTP.new(uri.host, uri.port)
24
- http.use_ssl = true
25
- http.ca_file = File.dirname(__FILE__) + "/../etc/ca.pem"
26
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
27
- request = Net::HTTP::Get.new(uri.request_uri)
28
- request.basic_auth(config['email'], config['key'])
29
- response = http.request(request)
30
- parsed = JSON.parse(response.body) rescue nil
31
- case response.code.to_i
32
- when 200
33
- raise Error, "Unexpected reply #{response.body}" unless parsed
34
- parsed
35
- else
36
- raise Error, "HTTP #{response.code}: #{response.body}"
37
- end
38
- end
39
- end
7
+ require 'logstream/cloudapi_v2'
40
8
 
41
9
  class LogTailorCLI < Thor
42
- desc "tail SITE ENV", "Stream log information for the specified site environment."
10
+ desc "tail APPLICATION_UUID ENV", "Stream log information for the specified application environment."
43
11
  method_option(:types, :type => :array, :aliases => '-t',
44
12
  :desc => "Only display listed log types",
45
13
  :default => %w(apache-request php-error drupal-watchdog varnish-request),
@@ -59,15 +27,30 @@ class LogTailorCLI < Thor
59
27
  :banner => "disp_time http_status log_type request_id server text"
60
28
  )
61
29
  method_option(:color, :type => :boolean, :default => true, :desc => 'Turn on or off colorized lines.')
62
- method_option(:endpoint, :type => :string, :desc => 'The Cloud API URL to connect to.')
63
30
  method_option(:debug, :type => :boolean, :default => false, :desc => 'Turn on debugging.')
64
- def tail(site, env)
31
+ def tail(application_uuid, env)
65
32
  begin
66
33
  shows = Hash[options[:show].map { |s| s.split('=') }.map { |k,v| [k, Regexp.new(v)] }] rescue {}
67
34
  hides = Hash[options[:hide].map { |h| h.split('=') }.map { |k,v| [k, Regexp.new(v)] }] rescue {}
68
35
 
69
36
  begin
70
- info = QuickCloudAPI.get("/sites/#{site}/envs/#{env}/logstream", { :endpoint => options[:endpoint] })
37
+ confpath = "#{ENV['HOME']}/.acquia/cloudapiv2.conf"
38
+ begin
39
+ json = File.read(confpath)
40
+ config = JSON.load(json)
41
+ rescue Errno::ENOENT, JSON::ParserError => e
42
+ raise Error, "#{confpath} is missing or invalid. Please configure your Cloud API v2 credentials"
43
+ end
44
+ cloudapi_client = Logstream::CloudAPIV2.new(config['api_key'], config['api_secret'])
45
+ environments = cloudapi_client.get_application_environments(application_uuid)
46
+ environment_uuid = nil
47
+ environments.each do |environment|
48
+ if environment['name'] == env
49
+ environment_uuid = environment['id']
50
+ end
51
+ end
52
+ raise Error, "No environment found with #{env} name." unless environment_uuid
53
+ stream_info = cloudapi_client.get_envirornment_logstream(environment_uuid)
71
54
  logstream = Logstream::Client.new({
72
55
  :columns => options[:columns],
73
56
  :types => options[:types],
@@ -76,8 +59,8 @@ class LogTailorCLI < Thor
76
59
  :no_color => !options[:color],
77
60
  :debug => options[:debug],
78
61
  })
79
- logstream.run(info['url'], info['msg'])
80
- rescue QuickCloudAPI::Error => e
62
+ logstream.run(stream_info['url'], stream_info['params'])
63
+ rescue Logstream::CloudAPIV2::Error => e
81
64
  puts "Cloud API error: #{e.message}"
82
65
  exit(1)
83
66
  end
@@ -85,5 +68,5 @@ class LogTailorCLI < Thor
85
68
  end
86
69
  end
87
70
 
88
- LogTailorCLI.start
71
+ LogTailorCLI.start(ARGV)
89
72
 
@@ -1 +1,2 @@
1
1
  require 'logstream/client'
2
+ require 'logstream/cloudapi_v2'
@@ -39,18 +39,28 @@ module Logstream
39
39
  debug("<- #{msg}")
40
40
  end
41
41
 
42
- def run(url, connect_message)
42
+ def run(url, info)
43
43
  EM.run do
44
44
  debug_send("connect to #{url}")
45
+ connect_message = {
46
+ 'cmd' => 'stream-environment',
47
+ 'site' => info['site'],
48
+ 'env' => info['environment'],
49
+ 't' => info['t'],
50
+ 'd' => info['hmac'],
51
+ }
45
52
  ws = Faye::WebSocket::Client.new(url)
46
53
  ws.on :open do
47
- debug_send(connect_message)
48
- ws.send(connect_message)
54
+ @running = false
49
55
  end
50
56
  ws.on :message do |body,type|
51
57
  debug_recv(body.data)
52
58
  msg = JSON.parse(body.data)
53
59
  case msg['cmd']
60
+ when 'connected'
61
+ debug_send(connect_message.to_json)
62
+ ws.send(connect_message.to_json) unless @running
63
+ @running = true
54
64
  when 'success'
55
65
  color('logtailor-error', msg['code']) do
56
66
  # puts "#{msg.inspect}"
@@ -0,0 +1,60 @@
1
+ require 'net/https'
2
+ require 'json'
3
+
4
+ module Logstream
5
+ class CloudAPIV2
6
+ class Error < StandardError; end
7
+
8
+ attr_accessor :client_id, :client_secret, :endpoint
9
+ CLOUDAPI_ENDPOINT = 'https://cloud.acquia.com/api'
10
+
11
+ def initialize(client_id, client_secret)
12
+ @client_id = client_id
13
+ @client_secret = client_secret
14
+ end
15
+
16
+ def get(path)
17
+ bearer_token = get_token
18
+ uri = URI.parse("#{CLOUDAPI_ENDPOINT}#{path}")
19
+ http = Net::HTTP.new(uri.host, uri.port)
20
+ http.use_ssl = true
21
+ request = Net::HTTP::Get.new(uri.request_uri)
22
+ request['Authorization'] = "Bearer #{bearer_token}"
23
+ response = http.request(request)
24
+ parsed = JSON.parse(response.body) rescue nil
25
+ case response.code.to_i
26
+ when 200
27
+ raise Error, "Unexpected reply #{response.body}" unless parsed
28
+ parsed
29
+ else
30
+ raise Error, "HTTP #{response.code}: #{response.body}"
31
+ end
32
+ end
33
+
34
+ def get_application_environments(application_uuid)
35
+ response = get("/applications/#{application_uuid}/environments") #, { :query => { "filter" => "name%3D#{env}"}})
36
+ raise Error, "No Environments found." if response['total'] == 0
37
+ raise Error, "Unexpected reply #{response}" unless response['_embedded']['items']
38
+ response['_embedded']['items']
39
+ end
40
+
41
+ def get_envirornment_logstream(environment_uuid)
42
+ response = get("/environments/#{environment_uuid}/logstream")
43
+ raise Error, "Unexpected reply #{response}" unless response['logstream']
44
+ response['logstream']
45
+ end
46
+
47
+ def get_token
48
+ uri = URI.parse("https://accounts.acquia.com/api/auth/oauth/token")
49
+ response = Net::HTTP.post_form(uri, 'client_id' => @client_id, 'client_secret' => @client_secret, 'grant_type' => 'client_credentials')
50
+ parsed = JSON.parse(response.body) rescue nil
51
+ case response.code.to_i
52
+ when 200
53
+ raise Error, "Unexpected reply #{response.body}" unless parsed["access_token"]
54
+ parsed["access_token"]
55
+ else
56
+ raise Error, "HTTP #{response.code}: #{response.body}"
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,26 @@
1
+ libpath = File.join(File.dirname(__FILE__), 'lib')
2
+ $LOAD_PATH.unshift(libpath) unless $LOAD_PATH.include?(libpath)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "logstream"
6
+ s.version = "2.0.0"
7
+ s.date = Time.now.strftime("%Y-%m-%d")
8
+
9
+ s.author = "Acquia Engineering"
10
+ s.homepage = "https://github.com/acquia/logstream"
11
+
12
+ s.licenses = ['MIT']
13
+
14
+ s.summary = "Acquia Logstream tools and library"
15
+ s.description = "Logstream is an Acquia service for streaming logs from Acquia Cloud."
16
+
17
+ s.files = Dir["[A-Z]*", "{bin,etc,lib,test}/**/*"]
18
+ s.bindir = "bin"
19
+ s.executables = Dir["bin/*"].map { |f| File.basename(f) }.select { |f| f =~ /^[\w\-]+$/ }
20
+ s.test_files = Dir["test/**/*"]
21
+
22
+ s.add_runtime_dependency('faye-websocket', ['~> 0.10.0'])
23
+ s.add_runtime_dependency('thor', ['~> 0.20.0'])
24
+
25
+ s.required_ruby_version = '>= 2.4'
26
+ end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstream
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Barry Jaspan
7
+ - Acquia Engineering
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.10.0
27
- - !ruby/object:Gem::Dependency
28
- name: json
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.7.7
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: 1.7.7
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: thor
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -53,20 +39,22 @@ dependencies:
53
39
  - !ruby/object:Gem::Version
54
40
  version: 0.20.0
55
41
  description: Logstream is an Acquia service for streaming logs from Acquia Cloud.
56
- email: barry.jaspan@acquia.com
42
+ email:
57
43
  executables:
58
44
  - logstream
59
45
  extensions: []
60
46
  extra_rdoc_files: []
61
47
  files:
48
+ - Dockerfile
62
49
  - Gemfile
63
50
  - Gemfile.lock
64
51
  - LICENSE
65
52
  - README.md
66
53
  - bin/logstream
67
- - etc/ca.pem
68
54
  - lib/logstream.rb
69
55
  - lib/logstream/client.rb
56
+ - lib/logstream/cloudapi_v2.rb
57
+ - logstream.gemspec
70
58
  homepage: https://github.com/acquia/logstream
71
59
  licenses:
72
60
  - MIT
@@ -86,8 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
74
  - !ruby/object:Gem::Version
87
75
  version: '0'
88
76
  requirements: []
89
- rubyforge_project:
90
- rubygems_version: 2.7.10
77
+ rubygems_version: 3.0.3
91
78
  signing_key:
92
79
  specification_version: 4
93
80
  summary: Acquia Logstream tools and library
data/etc/ca.pem DELETED
@@ -1,98 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIGvzCCBaegAwIBAgIQD1pdYvA5l5l2ezeWEsVwNTANBgkqhkiG9w0BAQUFADBm
3
- MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
- d3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
5
- ZSBDQS0zMB4XDTEyMDgyNzAwMDAwMFoXDTE1MDkwOTEyMDAwMFowfzELMAkGA1UE
6
- BhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxEzARBgNVBAcTCkJ1cmxpbmd0
7
- b24xEzARBgNVBAoTCkFjcXVpYSBJbmMxFzAVBgNVBAsTDkFjcXVpYSBIb3N0aW5n
8
- MRUwEwYDVQQDDAwqLmFjcXVpYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
9
- ggEKAoIBAQCVmcKz54qAbNO9NyP3hA96gzGRORSB9Bz4EOuFM1kfD/gvZoXoqk87
10
- NC/jPrvPAxNZDJ33IrO08WDWxBVi6UQ7Q9YYFgU1mm0se4qjwld7dtziDnaq2zXc
11
- x4Q+AVfBj92w+RsVDWA2mNtMSaDePqXGzLOz4muUCA5oCtMg2QD+XIEp1yt13nQb
12
- 5nW6PbY6kHHviepNX3wj7TdqTLNPdCVcK9BJz2YTjfHtBBxnGxR/m804RL9fYWKz
13
- r6XUbbf+gcKFwMqRI54Qs5cD20jmYnYgXFYwAx6HvOH9Lr969xMq5ePIQkKc66kG
14
- Opie8unjAQRgd6T7lL+zvpaen1UhJruhAgMBAAGjggNOMIIDSjAfBgNVHSMEGDAW
15
- gBRQ6nOJ2yn7EI+e5QEg1N55mUiD9zAdBgNVHQ4EFgQUJuo64qCLWo0Fvi6AsOYG
16
- IiNj+s8wIwYDVR0RBBwwGoIMKi5hY3F1aWEuY29tggphY3F1aWEuY29tMA4GA1Ud
17
- DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwYQYDVR0f
18
- BFowWDAqoCigJoYkaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL2NhMy1nMjcuY3Js
19
- MCqgKKAmhiRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vY2EzLWcyNy5jcmwwggHE
20
- BgNVHSAEggG7MIIBtzCCAbMGCWCGSAGG/WwBATCCAaQwOgYIKwYBBQUHAgEWLmh0
21
- dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5odG0wggFk
22
- BggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBz
23
- ACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBz
24
- ACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBD
25
- AGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwAeQBp
26
- AG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBo
27
- ACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBl
28
- ACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAg
29
- AHIAZQBmAGUAcgBlAG4AYwBlAC4wewYIKwYBBQUHAQEEbzBtMCQGCCsGAQUFBzAB
30
- hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRQYIKwYBBQUHMAKGOWh0dHA6Ly9j
31
- YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VDQS0zLmNy
32
- dDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBBQUAA4IBAQCwbrUX+rSNdiS1ivce
33
- pI3gzzlOG9FjcPPTfoLD/+eiysiTKe7d3Hb9urHZWGuEWWxXRl+6tND3TAt8ONpM
34
- ZCs+nls+qvspG8ApQMZLgak4kb4+CaLMi6ZpQ2JTI89iChonOjI0OP6dVDbGbTvV
35
- a7LKkiZw1xJNYUnhIiqOE1B9Ww3SUUpe1TLmiAYiiYiiuiyBxMz48sARHXnlEbWw
36
- 0dHOnU51tvG1zkv9sATYwv3LtIjf9pmXZnS1W0j5Ap0JeFbgFywVi0zSpbix0fzr
37
- pyArWETFKxirR2bCVFH0sVZ2q3/sznguUx1QgH+tese0hqHm2epRORcOi69mcDYi
38
- Cf5v
39
- -----END CERTIFICATE-----
40
- -----BEGIN CERTIFICATE-----
41
- MIIGWDCCBUCgAwIBAgIQCl8RTQNbF5EX0u/UA4w/OzANBgkqhkiG9w0BAQUFADBs
42
- MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
43
- d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
44
- ZSBFViBSb290IENBMB4XDTA4MDQwMjEyMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL
45
- MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
46
- LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
47
- Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR
48
- CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv
49
- KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5
50
- BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf
51
- 1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs
52
- zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d
53
- 32duXvsCAwEAAaOCAvowggL2MA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w
54
- ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3
55
- LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH
56
- AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy
57
- AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj
58
- AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg
59
- AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ
60
- AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt
61
- AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj
62
- AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl
63
- AHIAZQBuAGMAZQAuMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAm
64
- MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSB
65
- hzCBhDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGln
66
- aEFzc3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNl
67
- cnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSME
68
- GDAWgBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUB
69
- INTeeZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAB7ipUiebNtTOA/vphoqrOIDQ+2a
70
- vD6OdRvw/S4iWawTwGHi5/rpmc2HCXVUKL9GYNy+USyS8xuRfDEIcOI3ucFbqL2j
71
- CwD7GhX9A61YasXHJJlIR0YxHpLvtF9ONMeQvzHB+LGEhtCcAarfilYGzjrpDq6X
72
- dF3XcZpCdF/ejUN83ulV7WkAywXgemFhM9EZTfkI7qA5xSU1tyvED7Ld8aW3DiTE
73
- JiiNeXf1L/BXunwH1OH8zVowV36GEEfdMR/X/KLCvzB8XSSq6PmuX2p0ws5rs0bY
74
- Ib4p1I5eFdZCSucyb6Sxa1GDWL4/bcf72gMhy2oWGU4K8K2Eyl2Us1p292E=
75
- -----END CERTIFICATE-----
76
- -----BEGIN CERTIFICATE-----
77
- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
78
- MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
79
- d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
80
- ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
81
- MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
82
- LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
83
- RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
84
- +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
85
- PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
86
- xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
87
- Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
88
- hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
89
- EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
90
- MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
91
- FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
92
- nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
93
- eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
94
- hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
95
- Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
96
- vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
97
- +OkuE6N36B9K
98
- -----END CERTIFICATE-----