logstream 0.0.8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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-----