logstash-filter-elasticsearch 4.3.1 → 4.4.1

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: 57e0e5b17b9f3c454be9379c9dc617fdaad05f961600ec6d002eee6b2841a515
4
- data.tar.gz: 5b484b241209b5bd9e067d798a6267ba9702734471b2ec99227238b5a2728fdb
3
+ metadata.gz: 460b1e72f53335af42fd95c998fb8fe158a705beeaf60e53d199aa8b9c64ab6f
4
+ data.tar.gz: 1d031b1b9783a30d7d849c320dc0ca7fec747192ee6e6a818b5873eb7a678875
5
5
  SHA512:
6
- metadata.gz: ebb1434c624d486b3f07ccf786b9a277ecf46fe57860a0e665fb487f685045bd3f9e1097ab2fe6457f740f0387b3a987502b98b734508742811196825aad969b
7
- data.tar.gz: 1bb0519e3894124b26a4c29ecae6683d8be668df51d40f20dd5cd1f231ba7666032bf353d685cd96ed63167e628998a2430e2f67b1594f3e0ae00be4760a9f9a
6
+ metadata.gz: 24c037f834fadb3d4c5f988d197f2bc3de60c657bc00be9d04ee97e979adcd18c8e99deefda37e836ab49976402b659e0cb6d71c4b2f1a0e01e0d7fc9703f0e3
7
+ data.tar.gz: 8bcf2cf0303eb4339b1ebdffeb01a2588c5826ec8178fdffd8d0fc755008f3fffbfa8edf31abc80c0e4078536f2c18d36e14919902ced4046d562f5ba9946b2d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 4.4.1
2
+ - Support Elastic Cloud API keys in the `api_key` option, which now accepts an `id:api_key` pair, its base64-encoded form, or an `essu_` Cloud API key, and rejects an unrecognized format at startup [#215](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/215)
3
+
4
+ ## 4.4.0
5
+ - Drop a support for Logstash 7.x by requiring `elasticsearch` gem >= 8. Logstash 8+ continues to work as before. [#213](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/213)
6
+
1
7
  ## 4.3.1
2
8
  - Added support for encoded and non encoded api-key formats on plugin configuration [#203](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/203)
3
9
 
data/docs/index.asciidoc CHANGED
@@ -307,8 +307,11 @@ Example:
307
307
  Authenticate using Elasticsearch API key. Note that this option also requires
308
308
  enabling the <<plugins-{type}s-{plugin}-ssl_enabled>> option.
309
309
 
310
- Format is `id:api_key` where `id` and `api_key` are as returned by the
311
- Elasticsearch {ref}/security-api-create-api-key.html[Create API key API].
310
+ The format is `id:api_key`, where `id` and `api_key` are as returned by the
311
+ Elasticsearch {ref}/security-api-create-api-key.html[Create API key API]. The
312
+ base64-encoded form of that pair is also accepted, as is an
313
+ https://www.elastic.co/docs/deploy-manage/api-keys/elastic-cloud-api-keys[Elastic Cloud API key]
314
+ (prefixed with `essu_`), which is used as-is.
312
315
 
313
316
  [id="plugins-{type}s-{plugin}-ca_trusted_fingerprint"]
314
317
  ===== `ca_trusted_fingerprint`
@@ -1,14 +1,13 @@
1
1
  # encoding: utf-8
2
- require "elasticsearch"
3
2
  require "base64"
4
-
3
+ require "elasticsearch"
4
+ require "elastic/transport/transport/http/manticore"
5
5
 
6
6
  module LogStash
7
7
  module Filters
8
8
  class ElasticsearchClient
9
9
 
10
10
  attr_reader :client
11
- attr_reader :es_transport_client_type
12
11
 
13
12
  BUILD_FLAVOR_SERVERLESS = 'serverless'.freeze
14
13
  DEFAULT_EAV_HEADER = { "Elastic-Api-Version" => "2023-10-31" }.freeze
@@ -44,7 +43,7 @@ module LogStash
44
43
 
45
44
  client_options = {
46
45
  hosts: hosts,
47
- transport_class: get_transport_client_class,
46
+ transport_class: ::Elastic::Transport::Transport::HTTP::Manticore,
48
47
  transport_options: transport_options,
49
48
  ssl: ssl_options,
50
49
  retry_on_failure: options[:retry_on_failure],
@@ -103,29 +102,37 @@ module LogStash
103
102
  def setup_api_key(api_key)
104
103
  return {} unless (api_key&.value)
105
104
 
106
- token = base64?(api_key.value) ? api_key.value : Base64.strict_encode64(api_key.value)
105
+ token = resolve_api_key(api_key.value)
107
106
  { 'Authorization' => "ApiKey #{token}" }
108
107
  end
109
108
 
109
+ # Resolves the `api_key` value into the credential used in the
110
+ # `Authorization: ApiKey` header. An already base64-encoded key and an
111
+ # Elastic Cloud API key are used as-is; a raw `id:api_key` pair is
112
+ # base64-encoded. An unrecognized value is rejected so a malformed key
113
+ # surfaces at startup rather than as a later authentication failure.
114
+ def resolve_api_key(key_value)
115
+ if base64?(key_value) || cloud_api_key?(key_value)
116
+ key_value
117
+ elsif key_value.match?(/\A[^:]+:[^:]+\z/)
118
+ Base64.strict_encode64(key_value)
119
+ else
120
+ raise LogStash::ConfigurationError, "Invalid api_key format. Expected a base64-encoded key, an 'id:api_key' pair, or a Cloud API key (essu_ prefix)."
121
+ end
122
+ end
123
+
124
+ # Elastic Cloud API keys (such as the unified Serverless keys) are opaque
125
+ # tokens prefixed with `essu_` that Elasticsearch accepts verbatim in the
126
+ # `Authorization: ApiKey` header, with no base64 encoding.
127
+ def cloud_api_key?(string)
128
+ string.match?(/\Aessu_.+/)
129
+ end
130
+
110
131
  def base64?(string)
111
132
  string == Base64.strict_encode64(Base64.strict_decode64(string))
112
133
  rescue ArgumentError
113
134
  false
114
135
  end
115
-
116
- def get_transport_client_class
117
- # LS-core includes `elasticsearch` gem. The gem is composed of two separate gems: `elasticsearch-api` and `elasticsearch-transport`
118
- # And now `elasticsearch-transport` is old, instead we have `elastic-transport`.
119
- # LS-core updated `elasticsearch` > 8: https://github.com/elastic/logstash/pull/17161
120
- # Following source bits are for the compatibility to support both `elasticsearch-transport` and `elastic-transport` gems
121
- require "elasticsearch/transport/transport/http/manticore"
122
- es_transport_client_type = "elasticsearch_transport"
123
- ::Elasticsearch::Transport::Transport::HTTP::Manticore
124
- rescue ::LoadError
125
- require "elastic/transport/transport/http/manticore"
126
- es_transport_client_type = "elastic_transport"
127
- ::Elastic::Transport::Transport::HTTP::Manticore
128
- end
129
136
  end
130
137
  end
131
138
  end
@@ -72,7 +72,8 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
72
72
  config :cloud_auth, :validate => :password
73
73
 
74
74
  # Authenticate using Elasticsearch API key.
75
- # format is id:api_key (as returned by https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html[Create API key])
75
+ # Format is either the `id:api_key` pair (as returned by https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-create-api-key.html[Create API key]),
76
+ # its base64-encoded form, or an https://www.elastic.co/docs/deploy-manage/api-keys/elastic-cloud-api-keys[Elastic Cloud API key] (prefixed with `essu_`) can be used.
76
77
  config :api_key, :validate => :password
77
78
 
78
79
  # Set the address of a forward HTTP proxy.
@@ -209,9 +210,6 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
209
210
  test_connection!
210
211
  validate_es_for_esql_support! if @query_type == "esql"
211
212
  setup_serverless
212
- if get_client.es_transport_client_type == "elasticsearch_transport"
213
- require_relative "elasticsearch/patches/_elasticsearch_transport_http_manticore"
214
- end
215
213
  end # def register
216
214
 
217
215
  def filter(event)
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-filter-elasticsearch'
4
- s.version = '4.3.1'
4
+ s.version = ::File.read('version').split("\n").first
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "Copies fields from previous log events in Elasticsearch to current events "
7
7
  s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.require_paths = ["lib"]
12
12
 
13
13
  # Files
14
- s.files = Dir["lib/**/*","spec/**/*","*.gemspec","*.md","CONTRIBUTORS","Gemfile","LICENSE","NOTICE.TXT", "vendor/jar-dependencies/**/*.jar", "vendor/jar-dependencies/**/*.rb", "VERSION", "docs/**/*"]
14
+ s.files = Dir["lib/**/*","spec/**/*","*.gemspec","*.md","CONTRIBUTORS","Gemfile","LICENSE","NOTICE.TXT", "vendor/jar-dependencies/**/*.jar", "vendor/jar-dependencies/**/*.rb", "VERSION", "version", "docs/**/*"]
15
15
 
16
16
  # Tests
17
17
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
21
21
 
22
22
  # Gem dependencies
23
23
  s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
24
- s.add_runtime_dependency 'elasticsearch', ">= 7.14.9", '< 9'
24
+ s.add_runtime_dependency 'elasticsearch', '>= 8', '< 10'
25
25
  s.add_runtime_dependency 'manticore', ">= 0.7.1"
26
26
  s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~> 1.3'
27
27
  s.add_runtime_dependency 'logstash-mixin-ca_trusted_fingerprint_support', '~> 1.0'
@@ -58,11 +58,6 @@ describe LogStash::Filters::Elasticsearch::DslExecutor do
58
58
 
59
59
  before(:each) do
60
60
  allow(LogStash::Filters::ElasticsearchClient).to receive(:new).and_return(client)
61
- if defined?(Elastic::Transport)
62
- allow(client).to receive(:es_transport_client_type).and_return('elastic_transport')
63
- else
64
- allow(client).to receive(:es_transport_client_type).and_return('elasticsearch_transport')
65
- end
66
61
  allow(client).to receive(:search).and_return(response)
67
62
  allow(plugin).to receive(:test_connection!)
68
63
  allow(plugin).to receive(:setup_serverless)
@@ -123,26 +118,6 @@ describe LogStash::Filters::Elasticsearch::DslExecutor do
123
118
  end
124
119
  end
125
120
 
126
- context 'when Elasticsearch 7.x gives us a totals object instead of an integer' do
127
- let(:plugin_config) do
128
- {
129
- "hosts" => ["localhost:9200"],
130
- "query" => "response: 404",
131
- "fields" => { "response" => "code" },
132
- "result_size" => 10
133
- }
134
- end
135
-
136
- let(:response) do
137
- LogStash::Json.load(File.read(File.join(File.dirname(__FILE__), "fixtures", "elasticsearch_7.x_hits_total_as_object.json")))
138
- end
139
-
140
- it "should enhance the current event with new data" do
141
- plugin.filter(event)
142
- expect(event.get("[@metadata][total_hits]")).to eq(13476)
143
- end
144
- end
145
-
146
121
  context "if something wrong happen during connection" do
147
122
 
148
123
  before(:each) do
@@ -307,11 +282,6 @@ describe LogStash::Filters::Elasticsearch::DslExecutor do
307
282
 
308
283
  before do
309
284
  allow(plugin).to receive(:get_client).and_return(client_double)
310
- if defined?(Elastic::Transport)
311
- allow(client_double).to receive(:es_transport_client_type).and_return('elastic_transport')
312
- else
313
- allow(client_double).to receive(:es_transport_client_type).and_return('elasticsearch_transport')
314
- end
315
285
  allow(client_double).to receive(:client).and_return(transport_double)
316
286
  end
317
287
 
@@ -4,6 +4,7 @@ require "logstash/plugin"
4
4
  require "logstash/filters/elasticsearch"
5
5
  require "logstash/json"
6
6
  require "cabin"
7
+ require "manticore"
7
8
  require "webrick"
8
9
  require "uri"
9
10
 
@@ -61,17 +62,9 @@ describe LogStash::Filters::Elasticsearch do
61
62
  allow(filter_client).to receive(:serverless?).and_return(true)
62
63
  allow(filter_client).to receive(:client).and_return(es_client)
63
64
 
64
- if defined?(Elastic::Transport)
65
- allow(es_client).to receive(:info)
66
- .with(a_hash_including(
67
- :headers => LogStash::Filters::ElasticsearchClient::DEFAULT_EAV_HEADER))
68
- .and_raise(Elastic::Transport::Transport::Errors::BadRequest.new)
69
- else
70
- allow(es_client).to receive(:info)
71
- .with(a_hash_including(
72
- :headers => LogStash::Filters::ElasticsearchClient::DEFAULT_EAV_HEADER))
73
- .and_raise(Elasticsearch::Transport::Transport::Errors::BadRequest.new)
74
- end
65
+ allow(es_client).to receive(:info)
66
+ .with(a_hash_including(:headers => LogStash::Filters::ElasticsearchClient::DEFAULT_EAV_HEADER))
67
+ .and_raise(Elastic::Transport::Transport::Errors::BadRequest.new)
75
68
  end
76
69
 
77
70
  it "raises an exception when Elastic Api Version is not supported" do
@@ -118,15 +111,15 @@ describe LogStash::Filters::Elasticsearch do
118
111
  "cluster_name": "docker-cluster",
119
112
  "cluster_uuid": "DyR1hN03QvuCWXRy3jtb0g",
120
113
  "version": {
121
- "number": "7.13.1",
114
+ "number": "8.0.0",
122
115
  "build_flavor": "default",
123
116
  "build_type": "docker",
124
117
  "build_hash": "9a7758028e4ea59bcab41c12004603c5a7dd84a9",
125
118
  "build_date": "2021-05-28T17:40:59.346932922Z",
126
119
  "build_snapshot": false,
127
- "lucene_version": "8.8.2",
128
- "minimum_wire_compatibility_version": "6.8.0",
129
- "minimum_index_compatibility_version": "6.0.0-beta1"
120
+ "lucene_version": "9.0.0",
121
+ "minimum_wire_compatibility_version": "7.17.0",
122
+ "minimum_index_compatibility_version": "7.0.0"
130
123
  },
131
124
  "tagline": "You Know, for Search"
132
125
  }
@@ -187,17 +180,6 @@ describe LogStash::Filters::Elasticsearch do
187
180
  end
188
181
  let(:plugin) { described_class.new(config) }
189
182
  let(:event) { LogStash::Event.new({}) }
190
-
191
- # elasticsearch-ruby 7.17.9 initialize two user agent headers, `user-agent` and `User-Agent`
192
- # hence, fail this header size test case
193
- xit "client should sent the expect user-agent" do
194
- plugin.register
195
-
196
- request = webserver.wait_receive_request
197
-
198
- expect(request.header['user-agent'].size).to eq(1)
199
- expect(request.header['user-agent'][0]).to match(/logstash\/\d*\.\d*\.\d* \(OS=.*; JVM=.*\) logstash-filter-elasticsearch\/\d*\.\d*\.\d*/)
200
- end
201
183
  end
202
184
  end
203
185
 
@@ -225,12 +207,7 @@ describe LogStash::Filters::Elasticsearch do
225
207
  # this spec is a safeguard to trigger an assessment of thread-safety should
226
208
  # we choose a different transport adapter in the future.
227
209
  transport_class = extract_transport(client).options.fetch(:transport_class)
228
- if defined?(Elastic::Transport)
229
- allow(client).to receive(:es_transport_client_type).and_return("elastic_transport")
230
- expect(transport_class).to equal ::Elastic::Transport::Transport::HTTP::Manticore
231
- else
232
- expect(transport_class).to equal ::Elasticsearch::Transport::Transport::HTTP::Manticore
233
- end
210
+ expect(transport_class).to equal ::Elastic::Transport::Transport::HTTP::Manticore
234
211
  end
235
212
 
236
213
  it 'uses a client with sufficient connection pool size' do
@@ -348,6 +325,31 @@ describe LogStash::Filters::Elasticsearch do
348
325
  it_behaves_like "a plugin that sets the ApiKey authorization header"
349
326
  end
350
327
 
328
+ context "with an Elastic Cloud API key (essu_ prefix)" do
329
+ # The suffix is intentionally not canonical base64: a Cloud key is opaque
330
+ # and must be forwarded verbatim regardless of its payload encoding.
331
+ let(:api_key_value) { "essu_VFZGblZreFhTekJ4ZDB4M2NHUnZRMEU2YzNWd1pYSnpaV055WlhRPQ==AAAAAAAA" }
332
+
333
+ it "sets the Authorization header verbatim without re-encoding" do
334
+ plugin.register
335
+ client = plugin.send(:get_client).client
336
+ auth_header = extract_transport(client).options[:transport_options][:headers]['Authorization']
337
+
338
+ expect(auth_header).to eql("ApiKey #{api_key_value}")
339
+ end
340
+ end
341
+
342
+ context "with an unrecognized api_key format" do
343
+ let(:api_key_value) { "not-a-valid-key" }
344
+
345
+ # `test_connection!` and `setup_serverless` are stubbed here, so the
346
+ # client is built explicitly, as in the other api_key examples.
347
+ it "fails to build a client with a configuration error" do
348
+ plugin.register
349
+ expect { plugin.send(:get_client) }.to raise_error(LogStash::ConfigurationError, /Invalid api_key format/)
350
+ end
351
+ end
352
+
351
353
  context 'user also set' do
352
354
  let(:config) { super().merge({ 'api_key' => 'foo:bar', 'user' => 'another' }) }
353
355
 
@@ -559,11 +561,6 @@ describe LogStash::Filters::Elasticsearch do
559
561
 
560
562
  before(:each) do
561
563
  allow(LogStash::Filters::ElasticsearchClient).to receive(:new).and_return(client)
562
- if defined?(Elastic::Transport)
563
- allow(client).to receive(:es_transport_client_type).and_return('elastic_transport')
564
- else
565
- allow(client).to receive(:es_transport_client_type).and_return('elasticsearch_transport')
566
- end
567
564
  allow(plugin).to receive(:test_connection!)
568
565
  allow(plugin).to receive(:setup_serverless)
569
566
  plugin.register
@@ -15,7 +15,7 @@ describe "SSL options" do
15
15
  before do
16
16
  allow(es_client_double).to receive(:close)
17
17
  allow(es_client_double).to receive(:ping).with(any_args).and_return(double("pong").as_null_object)
18
- allow(es_client_double).to receive(:info).with(any_args).and_return({"version" => {"number" => "7.5.0", "build_flavor" => "default"},
18
+ allow(es_client_double).to receive(:info).with(any_args).and_return({"version" => {"number" => "8.0.0", "build_flavor" => "default"},
19
19
  "tagline" => "You Know, for Search"})
20
20
  allow(Elasticsearch::Client).to receive(:new).and_return(es_client_double)
21
21
  end
@@ -1,32 +1,32 @@
1
1
  -----BEGIN CERTIFICATE-----
2
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
31
- 4O26CUzCDyhhBy+/wiuG6Fk37YskQBCgs37Mww==
2
+ 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
32
32
  -----END CERTIFICATE-----
@@ -1 +1 @@
1
- 241943c7ea305d5489fce87550f53c0655b2419dcd0e8e4c7a164abc8e82808c
1
+ f87c28293c97641f5d26976330f69af97be14900508bb66562696bdd15d19ec8
@@ -1,51 +1,52 @@
1
- -----BEGIN RSA PRIVATE KEY-----
2
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- xH2x5ftdGnhH6biWOK8MG1JpktPSAQb05cdpaRlDiaj+3rg5WcfcWxCNLROLOXPn
21
- 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
- 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
- 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
- 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
- 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
- yYXbcS9pyy5kiH0sK5MsF+uiRvEwkBF5dB1FtVryrYky3ObrYTFbrgseLHbA1PYS
27
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- O5w/J9fFuvg1gJlcxRgAz5tzX3EFH7cas3VKZmHKWGCVeoOYKVz3z9yvOat/18gw
42
- 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
- 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
- 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
- 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
- lgD9GPZyXAIp4cBmguRiWJyq1oH39Sb2noueHZBmGke2wyA9IWYVAUx1FH5oNA0z
47
- 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
- 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
- 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
- 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
51
- -----END RSA PRIVATE KEY-----
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCm+zeOQcnlqhyT
3
+ FjZ8CY9kJciUPHNBzWrBfcDfdGBZq+2/n95SySo5KgkfAnZW2Ma4NUHZozDJV48N
4
+ SVTDuXNwPO5MNh+pLS031W81t9t51muzk6lK6753j0Q2plwG0MhXav8A4Kv41Ugd
5
+ sNErMFha1rd25ht73J09oWYn/TCJe2m5AGpviWzzDMYGhdzvb8vinoRCmfreh9X8
6
+ U4DNJfgTBBaU/sKXdgbVMfUVUYv/+i6HIgxxBAsCzdX4tElRo4y9c1TK6ik1L7//
7
+ lgK+r2zOWwpUw9yq6+Q4WO+zyZEQAJ1z0S+xzA8KDW50SP4hGUS36n3ywtsq22ic
8
+ DMcKtfcT5+aYSGT++vNCtENJKbEOAP4dokvPuwBzkoUrLFdWV6VA/7a47UddIOXD
9
+ Y9U1tuYh82gLFuN69ykVoDFwH9U/Fw8bG5lOMEa3NqVCjEReUJpE3cjS4VB3Quga
10
+ HSbVf0ITCCzJriq/qRi0coknQ05Q/Mt+bPDkboSSrmn5xc1sFVmtIy4w9GCDSph2
11
+ G5VQsauZh4x2qEQFHgo64b1Fexzn4I1b+fIx/iawIBkJ+ViHb0uv1G9P+YKqfL2J
12
+ 8fo0wFHGnxkA2sggb9naim8VGJqGDWodnlLqN4IWztD/x5PQLwx+A1KZmfy0VVHB
13
+ mPITQJuyXJsYz/IgWyX500dZTB680QIDAQABAoIB/xgGYnfqqfc2rTsnIa+3Bb/j
14
+ BSOkOZu+HR4PJIZXYtrZYduwT3dEek6/PZC4n0404mKenFren/utcrz2pWYuc0Ld
15
+ gWvLCG3O54f2WDSNFNxIKDbY3VgU6H1LSlqSlQBmCcKKInvTLOsgb2qA25eF3TCK
16
+ CYY8lWJnhjgtK1rq6DuKW4EYDjhTYtmVfOhzWivDv2dbvKvYe7/eIMECmAWW8O/L
17
+ fB7z3guXb7mSS9uatV9Jymf8U3iZ8aZK91OmnOX3d3Mf+j3icwteqMFH/sfGIGGQ
18
+ YmwlF3Aq1dXwSzdoSPbZynhfdf1JiYsTY6ZXhOOTlHo3GD1VdoiJXlkVfY3iSyor
19
+ 2BdrNEg97xS1cPK8S1vctUYRjR0NYkl1OyOMraRsuHnrmGcHNOGKdG4IPjCgo7mP
20
+ EYjvmtp7tb+V4iJyFidkhpd1buts1hea0RZ/JpGwBP8H+64NHn/dHl1jttkHIhy8
21
+ CN9UR1Byuo5FZaPMwOud/rBdS/pU+Ma66kQg5d7MGKzNdk0pa1YUrniMHnvmF/6x
22
+ rsxnaWr+xnkvxsScFUCkfFVfcpuTUnY0IFL8ltFGZB9esQuKbyW1/wrcMOV7y5MH
23
+ Y0dfxLDI6FRC1FF6CQQ3c4lg5ZXOeE1RXUDFZz1a2hTy1kr4+7vogMOPp9FNoHU+
24
+ mao5VXUa8kL5LJgYhkkCggEBANU2KCtVv1aG6xcHNUMg/KQCdXU23uckN1Hu6iaP
25
+ JapyX/FuWCHr51bi2CjiC8wtYNULq6z9NXZOYaa5cscbE/khVsRp8+Ca5qI+tY16
26
+ PjVQh1IDQNgw7K+cTt1xdQiSJIWhDFfSEAbqFkDciNf9n4o0ZS4CXRLLIzjWtENc
27
+ Cc2pDHvI+mpYLNTNAYhZi8mz4Cjd4bmWlUf2FhkllX1esF7dOC4gEIyQ9EeA9dnH
28
+ n1RbACKxxIB0B3GT/xFt2Yri05mMXCPYbcrnNkv3/0HM0xns/8TtD0daQ6gXuFdZ
29
+ YqV4SI808e9SvRdV7+N3H+klkoY4xg2FoYKpXnjHEliVDoUCggEBAMh99dDeW9FB
30
+ jjl2EFsH4fDKD6o+iQNfFyAHGgFCzX/RGydE+f/idmLmKd9ldPQD6pltGLja/jrp
31
+ T3WoRTIfadA6VBYknVKGoFZ7OJKPv+1+6A2nJOjtYP40MkmVnCyu9TiMJ7H3i057
32
+ CxULEONeOLeF6ZJvC60pC5gnkaiv8bhIkSOL3/VitEmnL8yG2Hlh3+mcGYrBNWfZ
33
+ SPUw6GJl+tyzyBwcZsjzTZ845ilvhEWCMe9Egb/crZ5vmcaZodB7SfbA8tJo4Jwo
34
+ Swk8nY7YK/z6xv7toxTXJI3SRVbQ8PSr0Odbr/CQNDstl1g2SoGMongmt5njtI3c
35
+ hL6RLxDUpN0CggEASBpXfUgzO7zGtfPvFDOMnJ5kQG589SfvOVsVflK8hybEwW3y
36
+ ig4wHtb6COFg4fyamZGnzgmXUdnx9iMS6LiEiaS3pha6rcNUqZuRZDXp4bfI+3g0
37
+ Lqhk8oJmvUaIMIzTowkylmRonR3+xpKOCJUxpdhQOz37Ycams6sQLRNsEUvQ9++g
38
+ l+QXzSNDGGxH9L9K2CcpFc0R0NMs5/Yo1sv10y72t8qKLi87HQ9ElRCIFkvsAM+j
39
+ R1l1xvgosyk1/1zz+CJaapjfkFWerBRDE2qEHWljmaIdn6Cr7qWO5qNI0/KYfy2F
40
+ f8y4O7MJPCBl/z+AjLmYaKw/UWObmjagQqqtzQKCAQEApnrJalWpYloQEjCyJhSm
41
+ jX4Lge8JcG4+Uo7zDgb9gtwMsw/4k3zllvvN2z1w3sp9vEa115GotxxSqb0/L/6b
42
+ q5cziWt/4y3857LL6A9LbJcLc4LOCEhMWOjYtPdxRj1FTF48++80ksdjDWcx78qm
43
+ R+X/bGOfC3tgsEhzD+KBUeeX9S9JmYYLdHlKHIgAKtKVznKbVvdWNFRd25Nv830A
44
+ 0NDMImOHCefWFZd2rwN1jw4sDqURJFLHLB85Tor1rZsicK4JM6R4ldJzdEkL/7gK
45
+ 1rcaFEcZOs3nAYiPoSZAXrpo7iPZNWVYqacS2+HA/k/b/O8RV8yXeZCZ/W+q6Eva
46
+ VQKCAQEArJBEfTvVg4V3qp+2dcKZeBkWOeq53kA2Ey9Hn/FiNb/5jXzLjCkSF/jm
47
+ XNSNQTzEFlm7vl7Ii8g3stPSOvBqnGqNkVmWSUuMmJKn9vxpn/adcyU1bCiu5dfT
48
+ A+VOU6E7rMiQsODG3D8NrFGYthhaafoTVs6jI3eXMRjP1Z8Szw/WdE7uFbzYCVsP
49
+ ERKJIykm9fspmlm/zsV+Ka2vSs+dPdUqNBO1sYRVgJObyvOSHwUorFJiKInrY+3z
50
+ 7l0X7AgLgT9U19W5WrP+e1nAWeXQrzvAyWHnzBf9y7TW9z/D5p3aivKM70qf1DVN
51
+ hdh+Ptk6tdOWYuZaDnuuoeyq7+v6zw==
52
+ -----END PRIVATE KEY-----