logstash-output-s3 4.0.3 → 4.0.5

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
  SHA1:
3
- metadata.gz: fa4450798ae34f2e3d086e2468afaae71f2d26a0
4
- data.tar.gz: 024ad272f37c82f91dd1c25e4636e6837dbc97b7
3
+ metadata.gz: 31a45d07d1d55ba2247ea058ca57be461f7773d9
4
+ data.tar.gz: c45f5e22b868918990ef27f5c2d2b1682f7ad93e
5
5
  SHA512:
6
- metadata.gz: e9b0b212a751b10ff9de9bc8d16695777ea53a4dfe5de72b91b3aa31c54f5ad7ce4a44da2e089d5d5b70d6f8c531e9dfdbf8696fcf81349f7b3f6ab40ca57dcf
7
- data.tar.gz: 1e3bb81b19480cae9370046f728d81feed5afc54eed8a58f81e865eb760a2090618f300052573c5bd66821f2c6c5790d7b81e490fcce5a68f7ead633658aeb87
6
+ metadata.gz: d05449f29cd48dbbf75372bae6a2b4a6722b23b34e3653f435f1edf49ee56caa473dc52972a4812888b600f8055c98b08ec4002f887cd38646941ffe05814887
7
+ data.tar.gz: 63ec9d6444fc8046aeaf05d81a7ea2a2e6e05b9d986538713d7e3357aa430ee1d3f6f49a7ae0ab15f1dd4950767aa8e13e8e1b8be72205167b132596f8348492
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 4.0.5
2
+ - Delete the file on disk after they are succesfully uploaded to S3 #122 #120
3
+ - Added logging when an exception occur in the Uploader's `on_complete` callback
4
+
5
+ ## 4.0.4
6
+ - Add support for `storage_class` configuration
7
+ - Fix compatibility with Logstash 2.4
8
+ - Add support for `aws:kms` server side encryption #104
9
+
1
10
  ## 4.0.3
2
11
  - When configuring the `canned_acl` options of the plugins the role was not applied correctly to the created object: #7
3
12
 
@@ -127,9 +127,23 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
127
127
  config :canned_acl, :validate => ["private", "public_read", "public_read_write", "authenticated_read"],
128
128
  :default => "private"
129
129
 
130
- # Specifies wether or not to use S3's AES256 server side encryption. Defaults to false.
130
+ # Specifies wether or not to use S3's server side encryption. Defaults to no encryption.
131
131
  config :server_side_encryption, :validate => :boolean, :default => false
132
132
 
133
+ # Specifies what type of encryption to use when SSE is enabled.
134
+ config :server_side_encryption_algorithm, :validate => ["AES256", "aws:kms"], :default => "AES256"
135
+
136
+ # The key to use when specified along with server_side_encryption => aws:kms.
137
+ # If server_side_encryption => aws:kms is set but this is not default KMS key is used.
138
+ # http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingKMSEncryption.html
139
+ config :ssekms_key_id, :validate => :string
140
+
141
+ # Specifies what S3 storage class to use when uploading the file.
142
+ # More information about the different storage classes can be found:
143
+ # http://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html
144
+ # Defaults to STANDARD.
145
+ config :storage_class, :validate => ["STANDARD", "REDUCED_REDUNDANCY", "STANDARD_IA"], :default => "STANDARD"
146
+
133
147
  # Set the directory where logstash will store the tmp files before sending it to S3
134
148
  # default to the current OS temporary directory in linux /tmp/logstash
135
149
  config :temporary_directory, :validate => :string, :default => File.join(Dir.tmpdir, "logstash")
@@ -183,7 +197,7 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
183
197
  raise LogStash::ConfigurationError, "Logstash must have the permissions to write to the temporary directory: #{@temporary_directory}"
184
198
  end
185
199
 
186
- if @validate_credentials_on_root_bucket && !WriteBucketPermissionValidator.valid?(bucket_resource)
200
+ if @validate_credentials_on_root_bucket && !WriteBucketPermissionValidator.new(@logger).valid?(bucket_resource)
187
201
  raise LogStash::ConfigurationError, "Logstash must have the privileges to write to root bucket `#{@bucket}`, check you credentials or your permissions."
188
202
  end
189
203
 
@@ -265,7 +279,9 @@ class LogStash::Outputs::S3 < LogStash::Outputs::Base
265
279
  def upload_options
266
280
  {
267
281
  :acl => @canned_acl,
268
- :server_side_encryption => @server_side_encryption ? :aes256 : nil,
282
+ :server_side_encryption => @server_side_encryption ? @server_side_encryption_algorithm : nil,
283
+ :ssekms_key_id => @server_side_encryption_algorithm == "aws:kms" ? @ssekms_key_id : nil,
284
+ :storage_class => @storage_class,
269
285
  :content_encoding => @encoding == "gzip" ? "gzip" : nil
270
286
  }
271
287
  end
@@ -50,8 +50,8 @@ module LogStash
50
50
  # we delete the root of the UUID, using a UUID also remove the risk of deleting unwanted file, it acts as
51
51
  # a sandbox.
52
52
  def delete!
53
- @fd.close
54
- ::FileUtils.rm_rf(@temp_path, :secure => true)
53
+ @fd.close rescue IOError # force close anyway
54
+ FileUtils.rm_r(@temp_path, :secure => true)
55
55
  end
56
56
 
57
57
  def empty?
@@ -42,11 +42,14 @@ module LogStash
42
42
  #
43
43
  # Thread might be stuck here, but I think its better than losing anything
44
44
  # its either a transient errors or something bad really happened.
45
- logger.error("Uploading failed, retrying", :exception => e, :path => file.path, :backtrace => e.backtrace)
45
+ logger.error("Uploading failed, retrying", :exception => e.class, :message => e.message, :path => file.path, :backtrace => e.backtrace)
46
46
  retry
47
47
  end
48
48
 
49
49
  options[:on_complete].call(file) unless options[:on_complete].nil?
50
+ rescue => e
51
+ logger.error("An error occured in the `on_complete` uploader", :exception => e.class, :message => e.message, :path => file.path, :backtrace => e.backtrace)
52
+ raise e # reraise it since we don't deal with it now
50
53
  end
51
54
 
52
55
  def stop
@@ -7,14 +7,18 @@ module LogStash
7
7
  module Outputs
8
8
  class S3
9
9
  class WriteBucketPermissionValidator
10
- include ::LogStash::Util::Loggable
11
-
12
- def self.valid?(bucket_resource)
10
+ attr_reader :logger
11
+
12
+ def initialize(logger)
13
+ @logger = logger
14
+ end
15
+
16
+ def valid?(bucket_resource)
13
17
  begin
14
18
  upload_test_file(bucket_resource)
15
19
  true
16
20
  rescue StandardError => e
17
- logger.error("Error validating bucket write permissions!",
21
+ logger.error("Error validating bucket write permissions!",
18
22
  :message => e.message,
19
23
  :class => e.class.name
20
24
  )
@@ -23,7 +27,7 @@ module LogStash
23
27
  end
24
28
 
25
29
  private
26
- def self.upload_test_file(bucket_resource)
30
+ def upload_test_file(bucket_resource)
27
31
  generated_at = Time.now
28
32
 
29
33
  key = "logstash-programmatic-access-test-object-#{generated_at}"
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-s3'
3
- s.version = '4.0.3'
3
+ s.version = '4.0.5'
4
4
  s.licenses = ['Apache-2.0']
5
5
  s.summary = "This plugin was created for store the logstash's events into Amazon Simple Storage Service (Amazon S3)"
6
6
  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"
@@ -26,7 +26,7 @@ describe "File Time rotation with stale write", :integration => true do
26
26
  clean_remote_files(prefix)
27
27
  subject.register
28
28
  subject.multi_receive_encoded(batch)
29
- sleep(1) # the periodic check should have kick int
29
+ sleep(5) # the periodic check should have kick in
30
30
  end
31
31
 
32
32
  after do
@@ -56,5 +56,9 @@ describe "File Time rotation with stale write", :integration => true do
56
56
  try(20) do
57
57
  expect(Dir.glob(File.join(download_directory, "**", "*.txt")).inject(0) { |sum, f| sum + IO.readlines(f).size }).to eq(number_of_events)
58
58
  end
59
+
60
+ try(10) do
61
+ expect(Dir.glob(File.join(temporary_directory, "**", "*.txt")).size).to eq(1) # we should only have 1 file left, since we did a rotation
62
+ end
59
63
  end
60
64
  end
@@ -34,6 +34,13 @@ describe LogStash::Outputs::S3::TemporaryFile do
34
34
  expect(File.exist?(subject.path)).to be_falsey
35
35
  end
36
36
 
37
+ it "successfully delete a file already closed" do
38
+ subject.close
39
+ expect(File.exist?(subject.path)).to be_truthy
40
+ subject.delete!
41
+ expect(File.exist?(subject.path)).to be_falsey
42
+ end
43
+
37
44
  it "returns the creation time" do
38
45
  expect(subject.ctime).to be < Time.now + 0.5
39
46
  end
@@ -4,12 +4,13 @@ require "logstash/outputs/s3/write_bucket_permission_validator"
4
4
  require "aws-sdk"
5
5
 
6
6
  describe LogStash::Outputs::S3::WriteBucketPermissionValidator do
7
+ let(:logger) { spy(:logger ) }
7
8
  let(:bucket_name) { "foobar" }
8
9
  let(:obj) { double("s3_object") }
9
10
  let(:client) { Aws::S3::Client.new(stub_responses: true) }
10
11
  let(:bucket) { Aws::S3::Bucket.new(bucket_name, :client => client) }
11
12
 
12
- subject { described_class }
13
+ subject { described_class.new(logger) }
13
14
 
14
15
  before do
15
16
  expect(bucket).to receive(:object).with(any_args).and_return(obj)
@@ -25,7 +25,7 @@ describe LogStash::Outputs::S3 do
25
25
 
26
26
  before do
27
27
  allow(subject).to receive(:bucket_resource).and_return(mock_bucket)
28
- allow(LogStash::Outputs::S3::WriteBucketPermissionValidator).to receive(:valid?).with(mock_bucket).and_return(true)
28
+ allow_any_instance_of(LogStash::Outputs::S3::WriteBucketPermissionValidator).to receive(:valid?).with(mock_bucket).and_return(true)
29
29
  end
30
30
 
31
31
  context "#register configuration validation" do
@@ -61,6 +61,67 @@ describe LogStash::Outputs::S3 do
61
61
  end
62
62
  end
63
63
 
64
+ describe "Service Side Encryption" do
65
+
66
+ context "when configured" do
67
+ it "should be configure" do
68
+ s3 = described_class.new(options.merge({ "server_side_encryption" => true }))
69
+ expect(s3.upload_options).to include(:server_side_encryption => "AES256")
70
+ end
71
+ end
72
+
73
+ context "when algorithm is configured" do
74
+ ["AES256", "aws:kms"].each do |sse|
75
+ it "should return the configured SSE: #{sse}" do
76
+ s3 = described_class.new(options.merge({ "server_side_encryption" => true, "server_side_encryption_algorithm" => sse }))
77
+ expect(s3.upload_options).to include(:server_side_encryption => sse)
78
+ end
79
+ end
80
+ end
81
+
82
+ context "when using SSE with KMS and custom key" do
83
+ it "should return the configured KMS key" do
84
+ s3 = described_class.new(options.merge({ "server_side_encryption" => true, "server_side_encryption_algorithm" => "aws:kms", "ssekms_key_id" => "test"}))
85
+ expect(s3.upload_options).to include(:server_side_encryption => "aws:kms")
86
+ expect(s3.upload_options).to include(:ssekms_key_id => "test")
87
+ end
88
+ end
89
+
90
+ context "when using SSE with KMS but no custom key" do
91
+ it "should return the configured KMS key" do
92
+ s3 = described_class.new(options.merge({ "server_side_encryption" => true, "server_side_encryption_algorithm" => "aws:kms"}))
93
+ expect(s3.upload_options).to include(:server_side_encryption => "aws:kms")
94
+ expect(s3.upload_options).to include(:ssekms_key_id => nil)
95
+ end
96
+ end
97
+
98
+ context "when not configured" do
99
+ it "should not be configured" do
100
+ s3 = described_class.new(options)
101
+ expect(s3.upload_options).to include(:server_side_encryption => nil)
102
+ expect(s3.upload_options).to include(:ssekms_key_id => nil)
103
+ end
104
+ end
105
+ end
106
+
107
+ describe "Storage Class" do
108
+ context "when configured" do
109
+ ["STANDARD", "REDUCED_REDUNDANCY", "STANDARD_IA"].each do |storage_class|
110
+ it "should return the configured storage class: #{storage_class}" do
111
+ s3 = described_class.new(options.merge({ "storage_class" => storage_class }))
112
+ expect(s3.upload_options).to include(:storage_class => storage_class)
113
+ end
114
+ end
115
+ end
116
+
117
+ context "when not configured" do
118
+ it "uses STANDARD as the default" do
119
+ s3 = described_class.new(options)
120
+ expect(s3.upload_options).to include(:storage_class => "STANDARD")
121
+ end
122
+ end
123
+ end
124
+
64
125
  describe "temporary directory" do
65
126
  let(:temporary_directory) { Stud::Temporary.pathname }
66
127
  let(:options) { super.merge({ "temporary_directory" => temporary_directory }) }
@@ -84,7 +145,7 @@ describe LogStash::Outputs::S3 do
84
145
 
85
146
  it "allow to not validate credentials" do
86
147
  s3 = described_class.new(options.merge({"validate_credentials_on_root_bucket" => false}))
87
- expect(LogStash::Outputs::S3::WriteBucketPermissionValidator).not_to receive(:valid?).with(any_args)
148
+ expect_any_instance_of(LogStash::Outputs::S3::WriteBucketPermissionValidator).not_to receive(:valid?).with(any_args)
88
149
  s3.register
89
150
  end
90
151
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-s3
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.3
4
+ version: 4.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-05 00:00:00.000000000 Z
11
+ date: 2017-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement