logstash-filter-elasticsearch 3.6.1 → 3.9.3

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: 54415da2d9bc4aa6d1d90ea0b65937aa4782c9a9614cafd2ac583d94c0780913
4
- data.tar.gz: 44eea0bc6efd2a0a2a5415320a872e03cd3883e122e8d7627c3873241d47720c
3
+ metadata.gz: 886cfa121f2af1a9efdcfff9f3f2e97be3456be2aecbb668b89d3517d8087ffc
4
+ data.tar.gz: 0f0a568d1bf012cd0845a6d9cb5782a6460a32332a493790b84f010e68c06fcd
5
5
  SHA512:
6
- metadata.gz: f148fcacc216cbbfca630e858ec93d85329487738dda440200ac2ea4f85253f2f4b6dc4a55cb859781be372a7ef15c727b5ded25015de1988302cd04e64de98e
7
- data.tar.gz: '003910ce329cf1945fb3f92c2aef9f096588eb33c85e8716dbba0b65dd770e168e3960b1751553c2d251bc43b2a36dbc3eef339720acc9d40a08e1d1d36db402'
6
+ metadata.gz: 3e15a05bd9d013a2145ce983b2699f94c619276d93a675d49695ef8b8cf1d48ef88e6dfb4edac975d11a85bc57c0e769566b35ec44b8b2776fca8e35300af65d
7
+ data.tar.gz: 667279291114a2a93cbbd211e6ec7ff7533eada83dbfc73377d0a67b759ae773e7787f9b1a11518e9101302653cf5b8b356936a211521f9f635cc58646826730
@@ -1,3 +1,27 @@
1
+ ## 3.9.3
2
+ - [DOC] Update links to use shared attributes [#144](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/144)
3
+
4
+ ## 3.9.2
5
+ - [DOC] Fixed links to restructured Logstash-to-cloud docs [#142](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/142)
6
+
7
+ ## 3.9.1
8
+ - [DOC] Document the permissions required in secured clusters [#140](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/140)
9
+
10
+ ## 3.9.0
11
+ - Add support to define a proxy with the proxy config option [#134](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/134)
12
+
13
+ ## 3.8.0
14
+ - Added api_key support [#132](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/132)
15
+
16
+ ## 3.7.2
17
+ - [DOC] Removed outdated compatibility notice [#131](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/131)
18
+
19
+ ## 3.7.1
20
+ - Fix: solves an issue where non-ascii unicode values in a template were not handled correctly [#128](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/128)
21
+
22
+ ## 3.7.0
23
+ - Feat: support cloud_id / cloud_auth configuration [#122](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/122)
24
+
1
25
  ## 3.6.1
2
26
  - Loosen restrictions on Elasticsearch gem ([#120](https://github.com/logstash-plugins/logstash-filter-elasticsearch/pull/120))
3
27
 
@@ -9,6 +9,9 @@ Contributors:
9
9
  * Richard Pijnenburg (electrical)
10
10
  * Suyog Rao (suyograo)
11
11
  * Adrian Solom (addrians)
12
+ * Colin Surprenant (colinsurprenant)
13
+ * Andres Rodriguez (roaksoax)
14
+ * Luca Belluccini (lucabelluccini)
12
15
 
13
16
  Note: If you've sent us patches, bug reports, or otherwise contributed to
14
17
  Logstash, and you aren't on the list above and want to be, please let us know
data/LICENSE CHANGED
@@ -1,13 +1,202 @@
1
- Copyright (c) 2012-2018 Elasticsearch <http://www.elastic.co>
2
1
 
3
- Licensed under the Apache License, Version 2.0 (the "License");
4
- you may not use this file except in compliance with the License.
5
- You may obtain a copy of the License at
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
6
5
 
7
- http://www.apache.org/licenses/LICENSE-2.0
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
8
7
 
9
- Unless required by applicable law or agreed to in writing, software
10
- distributed under the License is distributed on an "AS IS" BASIS,
11
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- See the License for the specific language governing permissions and
13
- limitations under the License.
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright 2020 Elastic and contributors
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Logstash Plugin
2
2
 
3
- [![Travis Build Status](https://travis-ci.org/logstash-plugins/logstash-filter-elasticsearch.svg)](https://travis-ci.org/logstash-plugins/logstash-filter-elasticsearch)
3
+ [![Travis Build Status](https://travis-ci.com/logstash-plugins/logstash-filter-elasticsearch.svg)](https://travis-ci.com/logstash-plugins/logstash-filter-elasticsearch)
4
4
 
5
5
  This is a plugin for [Logstash](https://github.com/elastic/logstash).
6
6
 
@@ -20,21 +20,12 @@ include::{include_path}/plugin_header.asciidoc[]
20
20
 
21
21
  ==== Description
22
22
 
23
- .Compatibility Note
24
- [NOTE]
25
- ================================================================================
26
- Starting with Elasticsearch 5.3, there's an {ref}/modules-http.html[HTTP setting]
27
- called `http.content_type.required`. If this option is set to `true`, and you
28
- are using Logstash 2.4 through 5.2, you need to update the Elasticsearch filter
29
- plugin to version 3.1.1 or higher.
30
-
31
- ================================================================================
32
-
33
23
  Search Elasticsearch for a previous log event and copy some fields from it
34
- into the current event. Below are two complete examples of how this filter might
24
+ into the current event. Below are two complete examples of how this filter might
35
25
  be used.
36
26
 
37
- The first example uses the legacy 'query' parameter where the user is limited to an Elasticsearch query_string.
27
+ The first example uses the legacy 'query' parameter where the user is limited to
28
+ an Elasticsearch query_string.
38
29
  Whenever logstash receives an "end" event, it uses this elasticsearch
39
30
  filter to find the matching "start" event based on some operation identifier.
40
31
  Then it copies the `@timestamp` field from the "start" event into a new field on
@@ -111,6 +102,20 @@ Notice also that when you use `query_template`, the Logstash attributes `result_
111
102
  and `sort` will be ignored. They should be specified directly in the JSON
112
103
  template, as shown in the example above.
113
104
 
105
+ [id="plugins-{type}s-{plugin}-auth"]
106
+ ==== Authentication
107
+
108
+ Authentication to a secure Elasticsearch cluster is possible using _one_ of the following options:
109
+
110
+ * <<plugins-{type}s-{plugin}-user>> AND <<plugins-{type}s-{plugin}-password>>
111
+ * <<plugins-{type}s-{plugin}-cloud_auth>>
112
+ * <<plugins-{type}s-{plugin}-api_key>>
113
+
114
+ [id="plugins-{type}s-{plugin}-autz"]
115
+ ==== Authorization
116
+
117
+ Authorization to a secure Elasticsearch cluster requires `read` permission at index level and `monitoring` permissions at cluster level.
118
+ The `monitoring` permission at cluster level is necessary to perform periodic connectivity checks.
114
119
 
115
120
  [id="plugins-{type}s-{plugin}-options"]
116
121
  ==== Elasticsearch Filter Configuration Options
@@ -121,13 +126,17 @@ This plugin supports the following configuration options plus the <<plugins-{typ
121
126
  |=======================================================================
122
127
  |Setting |Input type|Required
123
128
  | <<plugins-{type}s-{plugin}-aggregation_fields>> |<<hash,hash>>|No
129
+ | <<plugins-{type}s-{plugin}-api_key>> |<<password,password>>|No
124
130
  | <<plugins-{type}s-{plugin}-ca_file>> |a valid filesystem path|No
131
+ | <<plugins-{type}s-{plugin}-cloud_auth>> |<<password,password>>|No
132
+ | <<plugins-{type}s-{plugin}-cloud_id>> |<<string,string>>|No
125
133
  | <<plugins-{type}s-{plugin}-docinfo_fields>> |<<hash,hash>>|No
126
134
  | <<plugins-{type}s-{plugin}-enable_sort>> |<<boolean,boolean>>|No
127
135
  | <<plugins-{type}s-{plugin}-fields>> |<<array,array>>|No
128
136
  | <<plugins-{type}s-{plugin}-hosts>> |<<array,array>>|No
129
137
  | <<plugins-{type}s-{plugin}-index>> |<<string,string>>|No
130
138
  | <<plugins-{type}s-{plugin}-password>> |<<password,password>>|No
139
+ | <<plugins-{type}s-{plugin}-proxy>> |<<uri,uri>>|No
131
140
  | <<plugins-{type}s-{plugin}-query>> |<<string,string>>|No
132
141
  | <<plugins-{type}s-{plugin}-query_template>> |<<string,string>>|No
133
142
  | <<plugins-{type}s-{plugin}-result_size>> |<<number,number>>|No
@@ -160,6 +169,18 @@ Example:
160
169
  }
161
170
  }
162
171
 
172
+ [id="plugins-{type}s-{plugin}-api_key"]
173
+ ===== `api_key`
174
+
175
+ * Value type is <<password,password>>
176
+ * There is no default value for this setting.
177
+
178
+ Authenticate using Elasticsearch API key. Note that this option also requires
179
+ enabling the `ssl` option.
180
+
181
+ Format is `id:api_key` where `id` and `api_key` are as returned by the
182
+ Elasticsearch {ref}/security-api-create-api-key.html[Create API key API].
183
+
163
184
  [id="plugins-{type}s-{plugin}-ca_file"]
164
185
  ===== `ca_file`
165
186
 
@@ -168,6 +189,28 @@ Example:
168
189
 
169
190
  SSL Certificate Authority file
170
191
 
192
+ [id="plugins-{type}s-{plugin}-cloud_auth"]
193
+ ===== `cloud_auth`
194
+
195
+ * Value type is <<password,password>>
196
+ * There is no default value for this setting.
197
+
198
+ Cloud authentication string ("<username>:<password>" format) is an alternative for the `user`/`password` pair.
199
+
200
+ For more info, check out the
201
+ {logstash-ref}/connecting-to-cloud.html[Logstash-to-Cloud documentation].
202
+
203
+ [id="plugins-{type}s-{plugin}-cloud_id"]
204
+ ===== `cloud_id`
205
+
206
+ * Value type is <<string,string>>
207
+ * There is no default value for this setting.
208
+
209
+ Cloud ID, from the Elastic Cloud web console. If set `hosts` should not be used.
210
+
211
+ For more info, check out the
212
+ {logstash-ref}/connecting-to-cloud.html[Logstash-to-Cloud documentation].
213
+
171
214
  [id="plugins-{type}s-{plugin}-docinfo_fields"]
172
215
  ===== `docinfo_fields`
173
216
 
@@ -241,14 +284,26 @@ Field substitution (e.g. `index-name-%{date_field}`) is available
241
284
 
242
285
  Basic Auth - password
243
286
 
287
+ [id="plugins-{type}s-{plugin}-proxy"]
288
+ ===== `proxy`
289
+
290
+ * Value type is <<uri,uri>>
291
+ * There is no default value for this setting.
292
+
293
+ Set the address of a forward HTTP proxy.
294
+ An empty string is treated as if proxy was not set, and is useful when using
295
+ environment variables e.g. `proxy => '${LS_PROXY:}'`.
296
+
244
297
  [id="plugins-{type}s-{plugin}-query"]
245
298
  ===== `query`
246
299
 
247
300
  * Value type is <<string,string>>
248
301
  * There is no default value for this setting.
249
302
 
250
- Elasticsearch query string. Read the Elasticsearch query string documentation.
251
- for more info at: https://www.elastic.co/guide/en/elasticsearch/reference/master/query-dsl-query-string-query.html#query-string-syntax
303
+ Elasticsearch query string. More information is available in the
304
+ {ref}/query-dsl-query-string-query.html#query-string-syntax[Elasticsearch query
305
+ string documentation].
306
+
252
307
 
253
308
  [id="plugins-{type}s-{plugin}-query_template"]
254
309
  ===== `query_template`
@@ -256,8 +311,8 @@ for more info at: https://www.elastic.co/guide/en/elasticsearch/reference/master
256
311
  * Value type is <<string,string>>
257
312
  * There is no default value for this setting.
258
313
 
259
- File path to elasticsearch query in DSL format. Read the Elasticsearch query documentation
260
- for more info at: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
314
+ File path to elasticsearch query in DSL format. More information is available in
315
+ the {ref}/query-dsl.html[Elasticsearch query documentation].
261
316
 
262
317
  [id="plugins-{type}s-{plugin}-result_size"]
263
318
  ===== `result_size`
@@ -300,6 +355,5 @@ Tags the event on failure to look up previous log event information. This can be
300
355
  Basic Auth - username
301
356
 
302
357
 
303
-
304
358
  [id="plugins-{type}s-{plugin}-common-options"]
305
359
  include::{include_path}/{type}.asciidoc[]
@@ -3,15 +3,18 @@ require "logstash/filters/base"
3
3
  require "logstash/namespace"
4
4
  require_relative "elasticsearch/client"
5
5
  require "logstash/json"
6
+ require "logstash/util/safe_uri"
6
7
  java_import "java.util.concurrent.ConcurrentHashMap"
7
8
 
8
9
 
9
10
  class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
10
11
  config_name "elasticsearch"
11
12
 
13
+ DEFAULT_HOST = ::LogStash::Util::SafeURI.new("//localhost:9200")
14
+
12
15
  # List of elasticsearch hosts to use for querying.
13
- config :hosts, :validate => :array, :default => [ "localhost:9200" ]
14
-
16
+ config :hosts, :validate => :array, :default => [ DEFAULT_HOST ]
17
+
15
18
  # Comma-delimited list of index names to search; use `_all` or empty string to perform the operation on all indices.
16
19
  # Field substitution (e.g. `index-name-%{date_field}`) is available
17
20
  config :index, :validate => :string, :default => ""
@@ -42,6 +45,23 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
42
45
  # Basic Auth - password
43
46
  config :password, :validate => :password
44
47
 
48
+ # Cloud ID, from the Elastic Cloud web console. If set `hosts` should not be used.
49
+ #
50
+ # For more info, check out the https://www.elastic.co/guide/en/logstash/current/connecting-to-cloud.html#_cloud_id[Logstash-to-Cloud documentation]
51
+ config :cloud_id, :validate => :string
52
+
53
+ # Cloud authentication string ("<username>:<password>" format) is an alternative for the `user`/`password` configuration.
54
+ #
55
+ # For more info, check out the https://www.elastic.co/guide/en/logstash/current/connecting-to-cloud.html#_cloud_auth[Logstash-to-Cloud documentation]
56
+ config :cloud_auth, :validate => :password
57
+
58
+ # Authenticate using Elasticsearch API key.
59
+ # 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])
60
+ config :api_key, :validate => :password
61
+
62
+ # Set the address of a forward HTTP proxy.
63
+ config :proxy, :validate => :uri_or_empty
64
+
45
65
  # SSL
46
66
  config :ssl, :validate => :boolean, :default => false
47
67
 
@@ -59,6 +79,23 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
59
79
 
60
80
  attr_reader :clients_pool
61
81
 
82
+ ##
83
+ # @override to handle proxy => '' as if none was set
84
+ # @param value [Array<Object>]
85
+ # @param validator [nil,Array,Symbol]
86
+ # @return [Array(true,Object)]: if validation is a success, a tuple containing `true` and the coerced value
87
+ # @return [Array(false,String)]: if validation is a failure, a tuple containing `false` and the failure reason.
88
+ def self.validate_value(value, validator)
89
+ return super unless validator == :uri_or_empty
90
+
91
+ value = deep_replace(value)
92
+ value = hash_or_array(value)
93
+
94
+ return true, value.first if value.size == 1 && value.first.empty?
95
+
96
+ return super(value, :uri)
97
+ end
98
+
62
99
  def register
63
100
  @clients_pool = java.util.concurrent.ConcurrentHashMap.new
64
101
 
@@ -67,10 +104,16 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
67
104
  if File.zero?(@query_template)
68
105
  raise "template is empty"
69
106
  end
70
- file = File.open(@query_template, "rb")
107
+ file = File.open(@query_template, 'r')
71
108
  @query_dsl = file.read
72
109
  end
73
110
 
111
+ validate_authentication
112
+ fill_user_password_from_cloud_auth
113
+ fill_hosts_from_cloud_id
114
+
115
+ @hosts = Array(@hosts).map { |host| host.to_s } # for ES client URI#to_s
116
+
74
117
  test_connection!
75
118
  end # def register
76
119
 
@@ -138,17 +181,22 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
138
181
  end # def filter
139
182
 
140
183
  private
184
+
141
185
  def client_options
142
186
  {
187
+ :user => @user,
188
+ :password => @password,
189
+ :api_key => @api_key,
190
+ :proxy => @proxy,
143
191
  :ssl => @ssl,
144
- :hosts => @hosts,
145
192
  :ca_file => @ca_file,
146
- :logger => @logger
147
193
  }
148
194
  end
149
195
 
150
196
  def new_client
151
- LogStash::Filters::ElasticsearchClient.new(@user, @password, client_options)
197
+ # NOTE: could pass cloud-id/cloud-auth to client but than we would need to be stricter on ES version requirement
198
+ # and also LS parsing might differ from ES client's parsing so for consistency we do not pass cloud options ...
199
+ LogStash::Filters::ElasticsearchClient.new(@logger, @hosts, client_options)
152
200
  end
153
201
 
154
202
  def get_client
@@ -188,6 +236,76 @@ class LogStash::Filters::Elasticsearch < LogStash::Filters::Base
188
236
  total
189
237
  end
190
238
 
239
+ def hosts_default?(hosts)
240
+ # NOTE: would be nice if pipeline allowed us a clean way to detect a config default :
241
+ hosts.is_a?(Array) && hosts.size == 1 && hosts.first.equal?(DEFAULT_HOST)
242
+ end
243
+
244
+ def validate_authentication
245
+ authn_options = 0
246
+ authn_options += 1 if @cloud_auth
247
+ authn_options += 1 if (@api_key && @api_key.value)
248
+ authn_options += 1 if (@user || (@password && @password.value))
249
+
250
+ if authn_options > 1
251
+ raise LogStash::ConfigurationError, 'Multiple authentication options are specified, please only use one of user/password, cloud_auth or api_key'
252
+ end
253
+
254
+ if @api_key && @api_key.value && @ssl != true
255
+ raise(LogStash::ConfigurationError, "Using api_key authentication requires SSL/TLS secured communication using the `ssl => true` option")
256
+ end
257
+ end
258
+
259
+ def fill_user_password_from_cloud_auth
260
+ return unless @cloud_auth
261
+
262
+ @user, @password = parse_user_password_from_cloud_auth(@cloud_auth)
263
+ params['user'], params['password'] = @user, @password
264
+ end
265
+
266
+ def fill_hosts_from_cloud_id
267
+ return unless @cloud_id
268
+
269
+ if @hosts && !hosts_default?(@hosts)
270
+ raise LogStash::ConfigurationError, 'Both cloud_id and hosts specified, please only use one of those.'
271
+ end
272
+ @hosts = parse_host_uri_from_cloud_id(@cloud_id)
273
+ end
274
+
275
+ def parse_host_uri_from_cloud_id(cloud_id)
276
+ begin # might not be available on older LS
277
+ require 'logstash/util/cloud_setting_id'
278
+ rescue LoadError
279
+ raise LogStash::ConfigurationError, 'The cloud_id setting is not supported by your version of Logstash, ' +
280
+ 'please upgrade your installation (or set hosts instead).'
281
+ end
282
+
283
+ begin
284
+ cloud_id = LogStash::Util::CloudSettingId.new(cloud_id) # already does append ':{port}' to host
285
+ rescue ArgumentError => e
286
+ raise LogStash::ConfigurationError, e.message.to_s.sub(/Cloud Id/i, 'cloud_id')
287
+ end
288
+ cloud_uri = "#{cloud_id.elasticsearch_scheme}://#{cloud_id.elasticsearch_host}"
289
+ LogStash::Util::SafeURI.new(cloud_uri)
290
+ end
291
+
292
+ def parse_user_password_from_cloud_auth(cloud_auth)
293
+ begin # might not be available on older LS
294
+ require 'logstash/util/cloud_setting_auth'
295
+ rescue LoadError
296
+ raise LogStash::ConfigurationError, 'The cloud_auth setting is not supported by your version of Logstash, ' +
297
+ 'please upgrade your installation (or set user/password instead).'
298
+ end
299
+
300
+ cloud_auth = cloud_auth.value if cloud_auth.is_a?(LogStash::Util::Password)
301
+ begin
302
+ cloud_auth = LogStash::Util::CloudSettingAuth.new(cloud_auth)
303
+ rescue ArgumentError => e
304
+ raise LogStash::ConfigurationError, e.message.to_s.sub(/Cloud Auth/i, 'cloud_auth')
305
+ end
306
+ [ cloud_auth.username, cloud_auth.password ]
307
+ end
308
+
191
309
  def test_connection!
192
310
  get_client.client.ping
193
311
  end
@@ -10,23 +10,26 @@ module LogStash
10
10
 
11
11
  attr_reader :client
12
12
 
13
- def initialize(user, password, options={})
14
- ssl = options.fetch(:ssl, false)
15
- hosts = options[:hosts]
16
- @logger = options[:logger]
13
+ def initialize(logger, hosts, options = {})
14
+ ssl = options.fetch(:ssl, false)
15
+ user = options.fetch(:user, nil)
16
+ password = options.fetch(:password, nil)
17
+ api_key = options.fetch(:api_key, nil)
18
+ proxy = options.fetch(:proxy, nil)
17
19
 
18
- transport_options = {}
19
- if user && password
20
- token = ::Base64.strict_encode64("#{user}:#{password.value}")
21
- transport_options[:headers] = { Authorization: "Basic #{token}" }
22
- end
20
+ transport_options = {:headers => {}}
21
+ transport_options[:headers].merge!(setup_basic_auth(user, password))
22
+ transport_options[:headers].merge!(setup_api_key(api_key))
23
+
24
+ logger.warn "Supplied proxy setting (proxy => '') has no effect" if @proxy.eql?('')
25
+ transport_options[:proxy] = proxy.to_s if proxy && !proxy.eql?('')
23
26
 
24
27
  hosts.map! {|h| { host: h, scheme: 'https' } } if ssl
25
28
  # set ca_file even if ssl isn't on, since the host can be an https url
26
29
  ssl_options = { ssl: true, ca_file: options[:ca_file] } if options[:ca_file]
27
30
  ssl_options ||= {}
28
31
 
29
- @logger.info("New ElasticSearch filter client", :hosts => hosts)
32
+ logger.info("New ElasticSearch filter client", :hosts => hosts)
30
33
  @client = ::Elasticsearch::Client.new(hosts: hosts, transport_options: transport_options, transport_class: ::Elasticsearch::Transport::Transport::HTTP::Manticore, :ssl => ssl_options)
31
34
  end
32
35
 
@@ -34,6 +37,21 @@ module LogStash
34
37
  @client.search(params)
35
38
  end
36
39
 
40
+ private
41
+
42
+ def setup_basic_auth(user, password)
43
+ return {} unless user && password && password.value
44
+
45
+ token = ::Base64.strict_encode64("#{user}:#{password.value}")
46
+ { Authorization: "Basic #{token}" }
47
+ end
48
+
49
+ def setup_api_key(api_key)
50
+ return {} unless (api_key && api_key.value)
51
+
52
+ token = ::Base64.strict_encode64(api_key.value)
53
+ { Authorization: "ApiKey #{token}" }
54
+ end
37
55
  end
38
56
  end
39
57
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-filter-elasticsearch'
4
- s.version = '3.6.1'
4
+ s.version = '3.9.3'
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"
@@ -289,7 +289,168 @@ describe LogStash::Filters::Elasticsearch do
289
289
  end
290
290
 
291
291
  end
292
+ end
293
+
294
+ describe "client" do
295
+ let(:config) do
296
+ {
297
+ "query" => "response: unknown"
298
+ }
299
+ end
300
+ let(:plugin) { described_class.new(config) }
301
+ let(:event) { LogStash::Event.new({}) }
302
+
303
+ before(:each) do
304
+ allow(plugin).to receive(:test_connection!)
305
+ end
306
+
307
+ after(:each) do
308
+ Thread.current[:filter_elasticsearch_client] = nil
309
+ end
310
+
311
+ describe "cloud.id" do
312
+ let(:valid_cloud_id) do
313
+ 'sample:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2OjkyNDMkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA=='
314
+ end
315
+
316
+ let(:config) { super.merge({ 'cloud_id' => valid_cloud_id }) }
317
+
318
+ it "should set host(s)" do
319
+ plugin.register
320
+ client = plugin.send(:get_client).client
321
+ expect( client.transport.hosts ).to eql [{
322
+ :scheme => "https",
323
+ :host => "ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io",
324
+ :port => 9243,
325
+ :path => "",
326
+ :protocol => "https"
327
+ }]
328
+ end
329
+
330
+ context 'invalid' do
331
+ let(:config) { super.merge({ 'cloud_id' => 'invalid:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlv' }) }
332
+
333
+ it "should fail" do
334
+ expect { plugin.register }.to raise_error LogStash::ConfigurationError, /cloud_id.*? is invalid/
335
+ end
336
+ end
337
+
338
+ context 'hosts also set' do
339
+ let(:config) { super.merge({ 'cloud_id' => valid_cloud_id, 'hosts' => [ 'localhost:9200' ] }) }
340
+
341
+ it "should fail" do
342
+ expect { plugin.register }.to raise_error LogStash::ConfigurationError, /cloud_id and hosts/
343
+ end
344
+ end
345
+ end if LOGSTASH_VERSION > '6.0'
346
+
347
+ describe "cloud.auth" do
348
+ let(:config) { super.merge({ 'cloud_auth' => LogStash::Util::Password.new('elastic:my-passwd-00') }) }
349
+
350
+ it "should set authorization" do
351
+ plugin.register
352
+ client = plugin.send(:get_client).client
353
+ auth_header = client.transport.options[:transport_options][:headers][:Authorization]
354
+
355
+ expect( auth_header ).to eql "Basic #{Base64.encode64('elastic:my-passwd-00').rstrip}"
356
+ end
357
+
358
+ context 'invalid' do
359
+ let(:config) { super.merge({ 'cloud_auth' => 'invalid-format' }) }
360
+
361
+ it "should fail" do
362
+ expect { plugin.register }.to raise_error LogStash::ConfigurationError, /cloud_auth.*? format/
363
+ end
364
+ end
365
+
366
+ context 'user also set' do
367
+ let(:config) { super.merge({ 'cloud_auth' => 'elastic:my-passwd-00', 'user' => 'another' }) }
292
368
 
369
+ it "should fail" do
370
+ expect { plugin.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
371
+ end
372
+ end
373
+ end if LOGSTASH_VERSION > '6.0'
374
+
375
+ describe "api_key" do
376
+ context "without ssl" do
377
+ let(:config) { super.merge({ 'api_key' => LogStash::Util::Password.new('foo:bar') }) }
378
+
379
+ it "should fail" do
380
+ expect { plugin.register }.to raise_error LogStash::ConfigurationError, /api_key authentication requires SSL\/TLS/
381
+ end
382
+ end
383
+
384
+ context "with ssl" do
385
+ let(:config) { super.merge({ 'api_key' => LogStash::Util::Password.new('foo:bar'), "ssl" => true }) }
386
+
387
+ it "should set authorization" do
388
+ plugin.register
389
+ client = plugin.send(:get_client).client
390
+ auth_header = client.transport.options[:transport_options][:headers][:Authorization]
391
+
392
+ expect( auth_header ).to eql "ApiKey #{Base64.strict_encode64('foo:bar')}"
393
+ end
394
+
395
+ context 'user also set' do
396
+ let(:config) { super.merge({ 'api_key' => 'foo:bar', 'user' => 'another' }) }
397
+
398
+ it "should fail" do
399
+ expect { plugin.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
400
+ end
401
+ end
402
+ end
403
+ end if LOGSTASH_VERSION > '6.0'
404
+
405
+ describe "proxy" do
406
+ context 'valid' do
407
+ let(:config) { super.merge({ 'proxy' => 'http://localhost:1234' }) }
408
+
409
+ it "should set proxy" do
410
+ plugin.register
411
+ client = plugin.send(:get_client).client
412
+ proxy = client.transport.options[:transport_options][:proxy]
413
+
414
+ expect( proxy ).to eql "http://localhost:1234"
415
+ end
416
+ end
417
+
418
+ context 'invalid' do
419
+ let(:config) { super.merge({ 'proxy' => '${A_MISSING_ENV_VAR:}' }) }
420
+
421
+ it "should not set proxy" do
422
+ plugin.register
423
+ client = plugin.send(:get_client).client
424
+
425
+ expect( client.transport.options[:transport_options] ).to_not include(:proxy)
426
+ end
427
+ end
428
+ end
293
429
  end
294
430
 
431
+ describe "query template" do
432
+ let(:config) do
433
+ {
434
+ "query_template" => File.join(File.dirname(__FILE__), "fixtures", "query_template_unicode.json"),
435
+ }
436
+ end
437
+
438
+ let(:plugin) { described_class.new(config) }
439
+
440
+ let(:client) { double(:client) }
441
+
442
+ before(:each) do
443
+ allow(LogStash::Filters::ElasticsearchClient).to receive(:new).and_return(client)
444
+ allow(plugin).to receive(:test_connection!)
445
+ plugin.register
446
+ end
447
+
448
+ it "should read and send non-ascii query" do
449
+ expect(client).to receive(:search).with(
450
+ :body => { "query" => { "terms" => { "lock" => [ "잠금", "uzávěr" ] } } },
451
+ :index => "")
452
+
453
+ plugin.filter(LogStash::Event.new)
454
+ end
455
+ end
295
456
  end
@@ -0,0 +1,7 @@
1
+ {
2
+ "query": {
3
+ "terms": {
4
+ "lock": [ "잠금", "uzávěr" ]
5
+ }
6
+ }
7
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-filter-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.1
4
+ version: 3.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-12 00:00:00.000000000 Z
11
+ date: 2021-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,7 @@ files:
94
94
  - spec/filters/elasticsearch_spec.rb
95
95
  - spec/filters/fixtures/elasticsearch_7.x_hits_total_as_object.json
96
96
  - spec/filters/fixtures/query_template.json
97
+ - spec/filters/fixtures/query_template_unicode.json
97
98
  - spec/filters/fixtures/request_error.json
98
99
  - spec/filters/fixtures/request_size0_agg.json
99
100
  - spec/filters/fixtures/request_x_1.json
@@ -130,6 +131,7 @@ test_files:
130
131
  - spec/filters/elasticsearch_spec.rb
131
132
  - spec/filters/fixtures/elasticsearch_7.x_hits_total_as_object.json
132
133
  - spec/filters/fixtures/query_template.json
134
+ - spec/filters/fixtures/query_template_unicode.json
133
135
  - spec/filters/fixtures/request_error.json
134
136
  - spec/filters/fixtures/request_size0_agg.json
135
137
  - spec/filters/fixtures/request_x_1.json