logstash-input-s3 3.6.0 → 3.8.2
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 +4 -4
- data/CHANGELOG.md +13 -0
- data/docs/index.asciidoc +34 -6
- data/lib/logstash/inputs/s3.rb +30 -16
- data/logstash-input-s3.gemspec +2 -1
- data/spec/inputs/s3_spec.rb +21 -9
- metadata +17 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1efe9981371c5b8306ef18f09c13fff78558b66ae2ee667bd2c576b8b88218e9
|
4
|
+
data.tar.gz: 843c506610bd7ca9c48759cb7339f80e65211c17df9c3a83c8a5ca6fe850f39f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cd8360c8eafce836259fada827ab42fc1972a42cec30bafe4ed7d61bea222bcc3db0c4a1ee19471a3727dffd7e9170ad48c0fe57baff5408e76e5ea60de3d44
|
7
|
+
data.tar.gz: 2cdeb2452504940dbd999d838d1abd905108ae748c9efa7ab9788a67b9e79c139f247c360c33393ce742189e27bb3a8763bde1725c95c76145884b0aa7a54039
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## 3.8.2
|
2
|
+
- Refactor: read sincedb time once per bucket listing [#233](https://github.com/logstash-plugins/logstash-input-s3/pull/233)
|
3
|
+
|
4
|
+
## 3.8.1
|
5
|
+
- Feat: cast true/false values for additional_settings [#232](https://github.com/logstash-plugins/logstash-input-s3/pull/232)
|
6
|
+
|
7
|
+
## 3.8.0
|
8
|
+
- Add ECS v8 support.
|
9
|
+
|
10
|
+
## 3.7.0
|
11
|
+
- Add ECS support. [#228](https://github.com/logstash-plugins/logstash-input-s3/pull/228)
|
12
|
+
- Fix missing file in cutoff time change. [#224](https://github.com/logstash-plugins/logstash-input-s3/pull/224)
|
13
|
+
|
1
14
|
## 3.6.0
|
2
15
|
- Fixed unprocessed file with the same `last_modified` in ingestion. [#220](https://github.com/logstash-plugins/logstash-input-s3/pull/220)
|
3
16
|
|
data/docs/index.asciidoc
CHANGED
@@ -31,6 +31,21 @@ Files ending in `.gz` are handled as gzip'ed files.
|
|
31
31
|
|
32
32
|
Files that are archived to AWS Glacier will be skipped.
|
33
33
|
|
34
|
+
[id="plugins-{type}s-{plugin}-ecs_metadata"]
|
35
|
+
==== Event Metadata and the Elastic Common Schema (ECS)
|
36
|
+
This plugin adds cloudfront metadata to event.
|
37
|
+
When ECS compatibility is disabled, the value is stored in the root level.
|
38
|
+
When ECS is enabled, the value is stored in the `@metadata` where it can be used by other plugins in your pipeline.
|
39
|
+
|
40
|
+
Here’s how ECS compatibility mode affects output.
|
41
|
+
[cols="<l,<l,e,<e"]
|
42
|
+
|=======================================================================
|
43
|
+
| ECS disabled | ECS v1 | Availability | Description
|
44
|
+
|
45
|
+
| cloudfront_fields | [@metadata][s3][cloudfront][fields] | available when the file is a CloudFront log | column names of log
|
46
|
+
| cloudfront_version | [@metadata][s3][cloudfront][version] | available when the file is a CloudFront log | version of log
|
47
|
+
|=======================================================================
|
48
|
+
|
34
49
|
[id="plugins-{type}s-{plugin}-options"]
|
35
50
|
==== S3 Input Configuration Options
|
36
51
|
|
@@ -47,6 +62,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
|
|
47
62
|
| <<plugins-{type}s-{plugin}-backup_to_dir>> |<<string,string>>|No
|
48
63
|
| <<plugins-{type}s-{plugin}-bucket>> |<<string,string>>|Yes
|
49
64
|
| <<plugins-{type}s-{plugin}-delete>> |<<boolean,boolean>>|No
|
65
|
+
| <<plugins-{type}s-{plugin}-ecs_compatibility>> |<<string,string>>|No
|
50
66
|
| <<plugins-{type}s-{plugin}-endpoint>> |<<string,string>>|No
|
51
67
|
| <<plugins-{type}s-{plugin}-exclude_pattern>> |<<string,string>>|No
|
52
68
|
| <<plugins-{type}s-{plugin}-gzip_pattern>> |<<string,string>>|No
|
@@ -96,12 +112,12 @@ the connection to s3. See full list in https://docs.aws.amazon.com/sdkforruby/ap
|
|
96
112
|
[source,ruby]
|
97
113
|
input {
|
98
114
|
s3 {
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
115
|
+
access_key_id => "1234"
|
116
|
+
secret_access_key => "secret"
|
117
|
+
bucket => "logstash-test"
|
118
|
+
additional_settings => {
|
119
|
+
force_path_style => true
|
120
|
+
follow_redirects => false
|
105
121
|
}
|
106
122
|
}
|
107
123
|
}
|
@@ -167,6 +183,18 @@ The name of the S3 bucket.
|
|
167
183
|
|
168
184
|
Whether to delete processed files from the original bucket.
|
169
185
|
|
186
|
+
[id="plugins-{type}s-{plugin}-ecs_compatibility"]
|
187
|
+
===== `ecs_compatibility`
|
188
|
+
|
189
|
+
* Value type is <<string,string>>
|
190
|
+
* Supported values are:
|
191
|
+
** `disabled`: does not use ECS-compatible field names
|
192
|
+
** `v1`,`v8`: uses metadata fields that are compatible with Elastic Common Schema
|
193
|
+
|
194
|
+
Controls this plugin's compatibility with the
|
195
|
+
{ecs-ref}[Elastic Common Schema (ECS)].
|
196
|
+
See <<plugins-{type}s-{plugin}-ecs_metadata>> for detailed information.
|
197
|
+
|
170
198
|
[id="plugins-{type}s-{plugin}-endpoint"]
|
171
199
|
===== `endpoint`
|
172
200
|
|
data/lib/logstash/inputs/s3.rb
CHANGED
@@ -9,6 +9,7 @@ require "stud/interval"
|
|
9
9
|
require "stud/temporary"
|
10
10
|
require "aws-sdk"
|
11
11
|
require "logstash/inputs/s3/patch"
|
12
|
+
require "logstash/plugin_mixins/ecs_compatibility_support"
|
12
13
|
|
13
14
|
require 'java'
|
14
15
|
|
@@ -27,6 +28,7 @@ class LogStash::Inputs::S3 < LogStash::Inputs::Base
|
|
27
28
|
java_import java.util.zip.ZipException
|
28
29
|
|
29
30
|
include LogStash::PluginMixins::AwsConfig::V2
|
31
|
+
include LogStash::PluginMixins::ECSCompatibilitySupport(:disabled, :v1, :v8 => :v1)
|
30
32
|
|
31
33
|
config_name "s3"
|
32
34
|
|
@@ -88,6 +90,12 @@ class LogStash::Inputs::S3 < LogStash::Inputs::Base
|
|
88
90
|
|
89
91
|
CUTOFF_SECOND = 3
|
90
92
|
|
93
|
+
def initialize(*params)
|
94
|
+
super
|
95
|
+
@cloudfront_fields_key = ecs_select[disabled: 'cloudfront_fields', v1: '[@metadata][s3][cloudfront][fields]']
|
96
|
+
@cloudfront_version_key = ecs_select[disabled: 'cloudfront_version', v1: '[@metadata][s3][cloudfront][version]']
|
97
|
+
end
|
98
|
+
|
91
99
|
def register
|
92
100
|
require "fileutils"
|
93
101
|
require "digest/md5"
|
@@ -130,6 +138,8 @@ class LogStash::Inputs::S3 < LogStash::Inputs::Base
|
|
130
138
|
def list_new_files
|
131
139
|
objects = []
|
132
140
|
found = false
|
141
|
+
current_time = Time.now
|
142
|
+
sincedb_time = sincedb.read
|
133
143
|
begin
|
134
144
|
@s3bucket.objects(:prefix => @prefix).each do |log|
|
135
145
|
found = true
|
@@ -138,9 +148,9 @@ class LogStash::Inputs::S3 < LogStash::Inputs::Base
|
|
138
148
|
@logger.debug('Ignoring', :key => log.key)
|
139
149
|
elsif log.content_length <= 0
|
140
150
|
@logger.debug('Object Zero Length', :key => log.key)
|
141
|
-
elsif
|
151
|
+
elsif log.last_modified <= sincedb_time
|
142
152
|
@logger.debug('Object Not Modified', :key => log.key)
|
143
|
-
elsif log.last_modified > (
|
153
|
+
elsif log.last_modified > (current_time - CUTOFF_SECOND).utc # file modified within last two seconds will be processed in next cycle
|
144
154
|
@logger.debug('Object Modified After Cutoff Time', :key => log.key)
|
145
155
|
elsif (log.storage_class == 'GLACIER' || log.storage_class == 'DEEP_ARCHIVE') && !file_restored?(log.object)
|
146
156
|
@logger.debug('Object Archived to Glacier', :key => log.key)
|
@@ -227,9 +237,6 @@ class LogStash::Inputs::S3 < LogStash::Inputs::Base
|
|
227
237
|
else
|
228
238
|
decorate(event)
|
229
239
|
|
230
|
-
event.set("cloudfront_version", metadata[:cloudfront_version]) unless metadata[:cloudfront_version].nil?
|
231
|
-
event.set("cloudfront_fields", metadata[:cloudfront_fields]) unless metadata[:cloudfront_fields].nil?
|
232
|
-
|
233
240
|
if @include_object_properties
|
234
241
|
event.set("[@metadata][s3]", object.data.to_h)
|
235
242
|
else
|
@@ -237,6 +244,8 @@ class LogStash::Inputs::S3 < LogStash::Inputs::Base
|
|
237
244
|
end
|
238
245
|
|
239
246
|
event.set("[@metadata][s3][key]", object.key)
|
247
|
+
event.set(@cloudfront_version_key, metadata[:cloudfront_version]) unless metadata[:cloudfront_version].nil?
|
248
|
+
event.set(@cloudfront_fields_key, metadata[:cloudfront_fields]) unless metadata[:cloudfront_fields].nil?
|
240
249
|
|
241
250
|
queue << event
|
242
251
|
end
|
@@ -345,14 +354,22 @@ class LogStash::Inputs::S3 < LogStash::Inputs::Base
|
|
345
354
|
end
|
346
355
|
|
347
356
|
def symbolized_settings
|
348
|
-
@symbolized_settings ||=
|
357
|
+
@symbolized_settings ||= symbolize_keys_and_cast_true_false(@additional_settings)
|
349
358
|
end
|
350
359
|
|
351
|
-
def
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
360
|
+
def symbolize_keys_and_cast_true_false(hash)
|
361
|
+
case hash
|
362
|
+
when Hash
|
363
|
+
symbolized = {}
|
364
|
+
hash.each { |key, value| symbolized[key.to_sym] = symbolize_keys_and_cast_true_false(value) }
|
365
|
+
symbolized
|
366
|
+
when 'true'
|
367
|
+
true
|
368
|
+
when 'false'
|
369
|
+
false
|
370
|
+
else
|
371
|
+
hash
|
372
|
+
end
|
356
373
|
end
|
357
374
|
|
358
375
|
def ignore_filename?(filename)
|
@@ -448,10 +465,7 @@ class LogStash::Inputs::S3 < LogStash::Inputs::Base
|
|
448
465
|
@sincedb_path = file
|
449
466
|
end
|
450
467
|
|
451
|
-
|
452
|
-
date > read
|
453
|
-
end
|
454
|
-
|
468
|
+
# @return [Time]
|
455
469
|
def read
|
456
470
|
if ::File.exists?(@sincedb_path)
|
457
471
|
content = ::File.read(@sincedb_path).chomp.strip
|
@@ -463,7 +477,7 @@ class LogStash::Inputs::S3 < LogStash::Inputs::Base
|
|
463
477
|
end
|
464
478
|
|
465
479
|
def write(since = nil)
|
466
|
-
since = Time.now
|
480
|
+
since = Time.now if since.nil?
|
467
481
|
::File.open(@sincedb_path, 'w') { |file| file.write(since.to_s) }
|
468
482
|
end
|
469
483
|
end
|
data/logstash-input-s3.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-input-s3'
|
4
|
-
s.version = '3.
|
4
|
+
s.version = '3.8.2'
|
5
5
|
s.licenses = ['Apache-2.0']
|
6
6
|
s.summary = "Streams events from files in a S3 bucket"
|
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"
|
@@ -27,4 +27,5 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency 'logstash-devutils'
|
28
28
|
s.add_development_dependency "logstash-codec-json"
|
29
29
|
s.add_development_dependency "logstash-codec-multiline"
|
30
|
+
s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~>1.2'
|
30
31
|
end
|
data/spec/inputs/s3_spec.rb
CHANGED
@@ -9,6 +9,7 @@ require_relative "../support/helpers"
|
|
9
9
|
require "stud/temporary"
|
10
10
|
require "aws-sdk"
|
11
11
|
require "fileutils"
|
12
|
+
require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
|
12
13
|
|
13
14
|
describe LogStash::Inputs::S3 do
|
14
15
|
let(:temporary_directory) { Stud::Temporary.pathname }
|
@@ -41,7 +42,9 @@ describe LogStash::Inputs::S3 do
|
|
41
42
|
expect_any_instance_of(LogStash::Inputs::S3).to receive(:list_new_files).and_return(TestInfiniteS3Object.new(s3_obj))
|
42
43
|
end
|
43
44
|
|
44
|
-
it_behaves_like "an interruptible input plugin"
|
45
|
+
it_behaves_like "an interruptible input plugin" do
|
46
|
+
let(:allowed_lag) { 16 } if LOGSTASH_VERSION.split('.').first.to_i <= 6
|
47
|
+
end
|
45
48
|
end
|
46
49
|
|
47
50
|
describe "#register" do
|
@@ -81,10 +84,10 @@ describe LogStash::Inputs::S3 do
|
|
81
84
|
end
|
82
85
|
|
83
86
|
describe "additional_settings" do
|
84
|
-
context
|
87
|
+
context "supported settings" do
|
85
88
|
let(:settings) {
|
86
89
|
{
|
87
|
-
"additional_settings" => { "force_path_style" => true },
|
90
|
+
"additional_settings" => { "force_path_style" => 'true', "ssl_verify_peer" => 'false', "profile" => 'logstash' },
|
88
91
|
"bucket" => "logstash-test",
|
89
92
|
}
|
90
93
|
}
|
@@ -92,7 +95,7 @@ describe LogStash::Inputs::S3 do
|
|
92
95
|
it 'should instantiate AWS::S3 clients with force_path_style set' do
|
93
96
|
expect(Aws::S3::Resource).to receive(:new).with({
|
94
97
|
:region => subject.region,
|
95
|
-
:force_path_style => true
|
98
|
+
:force_path_style => true, :ssl_verify_peer => false, :profile => 'logstash'
|
96
99
|
}).and_call_original
|
97
100
|
|
98
101
|
subject.send(:get_s3object)
|
@@ -192,6 +195,7 @@ describe LogStash::Inputs::S3 do
|
|
192
195
|
it 'should log that no files were found in the bucket' do
|
193
196
|
plugin = LogStash::Inputs::S3.new(config)
|
194
197
|
plugin.register
|
198
|
+
allow(plugin.logger).to receive(:info).with(/Using the provided sincedb_path/, anything)
|
195
199
|
expect(plugin.logger).to receive(:info).with(/No files found/, anything)
|
196
200
|
expect(plugin.list_new_files).to be_empty
|
197
201
|
end
|
@@ -494,12 +498,20 @@ describe LogStash::Inputs::S3 do
|
|
494
498
|
context 'cloudfront' do
|
495
499
|
let(:log_file) { File.join(File.dirname(__FILE__), '..', 'fixtures', 'cloudfront.log') }
|
496
500
|
|
497
|
-
|
498
|
-
|
501
|
+
describe "metadata", :ecs_compatibility_support, :aggregate_failures do
|
502
|
+
ecs_compatibility_matrix(:disabled, :v1) do |ecs_select|
|
503
|
+
before(:each) do
|
504
|
+
allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
|
505
|
+
end
|
499
506
|
|
500
|
-
|
501
|
-
|
502
|
-
|
507
|
+
it 'should extract metadata from cloudfront log' do
|
508
|
+
events = fetch_events(config)
|
509
|
+
|
510
|
+
events.each do |event|
|
511
|
+
expect(event.get ecs_select[disabled: "cloudfront_fields", v1: "[@metadata][s3][cloudfront][fields]"] ).to eq('date time x-edge-location c-ip x-event sc-bytes x-cf-status x-cf-client-id cs-uri-stem cs-uri-query c-referrer x-page-url c-user-agent x-sname x-sname-query x-file-ext x-sid')
|
512
|
+
expect(event.get ecs_select[disabled: "cloudfront_version", v1: "[@metadata][s3][cloudfront][version]"] ).to eq('1.0')
|
513
|
+
end
|
514
|
+
end
|
503
515
|
end
|
504
516
|
end
|
505
517
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-input-s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,6 +100,20 @@ dependencies:
|
|
100
100
|
- - ">="
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '1.2'
|
109
|
+
name: logstash-mixin-ecs_compatibility_support
|
110
|
+
prerelease: false
|
111
|
+
type: :runtime
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '1.2'
|
103
117
|
description: This gem is a Logstash plugin required to be installed on top of the
|
104
118
|
Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This
|
105
119
|
gem is not a stand-alone program
|
@@ -153,8 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
167
|
- !ruby/object:Gem::Version
|
154
168
|
version: '0'
|
155
169
|
requirements: []
|
156
|
-
|
157
|
-
rubygems_version: 2.6.13
|
170
|
+
rubygems_version: 3.1.6
|
158
171
|
signing_key:
|
159
172
|
specification_version: 4
|
160
173
|
summary: Streams events from files in a S3 bucket
|