fluent-plugin-s3 1.3.2 → 1.5.1

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: fbed7d556d0f9b4cda2531325a30beab6089f1c0355891ce806f80c19ea99dd6
4
- data.tar.gz: bb76ae613efd56b49c3b55d9e4dd47402df460331b16df92d89197101307b46d
3
+ metadata.gz: 48dc2fcbe8547c145e034ddf295fd5a08a586912d2b073d3f830396be3c185fc
4
+ data.tar.gz: 65b35293564a0a3041727e7e6e896c3f35f765f7c5c81697d7d5ab0e3e83d7ea
5
5
  SHA512:
6
- metadata.gz: 24b5c6f162b1e093dfd56668812104d00f81a32c6970d95f6f2e15524148f3bdde1a155172554f0c8b711b7c82021620ebad14429c7a54521442667230890571
7
- data.tar.gz: b80c299e39e34a331752eef996e0d4fe9420fd897b50f6936ae9049821311b9ff38aa8435b9dfd83730bc1cb6522b9b6640e3a31239e004db51777d5449cdfc9
6
+ metadata.gz: 4c3163351e8b8899cc229a8c6b768805e7d4d68e692e5e27df9694d0e5f295566c46c0b7499068d24e00ac3c025c9792e96ac4d433f7753b6d391aa2f3f3d9ed
7
+ data.tar.gz: b19605dda13a4d301bc6ad5151d0233923696d8627155b15dd5ec02a2fd0c2a68b585c33de923c4790dd3ff14eb1e4fa6e310fdd5dbb1eee2808ce7fb25a6143
@@ -0,0 +1,26 @@
1
+ name: linux
2
+ on:
3
+ - push
4
+ - pull_request
5
+ jobs:
6
+ build:
7
+ runs-on: ${{ matrix.os }}
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby: [ '2.4', '2.5', '2.6', '2.7' ]
12
+ os:
13
+ - ubuntu-latest
14
+ name: Ruby ${{ matrix.ruby }} unit testing on ${{ matrix.os }}
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby }}
20
+ - name: unit testing
21
+ env:
22
+ CI: true
23
+ run: |
24
+ gem install bundler rake
25
+ bundle install --jobs 4 --retry 3
26
+ bundle exec rake test
data/.travis.yml CHANGED
@@ -1,11 +1,10 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 2.1.10
5
- - 2.2.9
6
- - 2.3.6
7
- - 2.4.3
8
- - 2.5.0
4
+ - 2.4
5
+ - 2.5
6
+ - 2.6
7
+ - 2.7
9
8
  - ruby-head
10
9
 
11
10
  gemfile:
@@ -14,7 +13,6 @@ gemfile:
14
13
  branches:
15
14
  only:
16
15
  - master
17
- - v0.12
18
16
 
19
17
  before_install: gem update bundler
20
18
  script: bundle exec rake test
data/ChangeLog CHANGED
@@ -1,3 +1,25 @@
1
+ Release 1.5.1 - 2021/02/16
2
+
3
+ * out_s3: Fix assume_role_credentials regression
4
+
5
+ Release 1.5.0 - 2020/12/18
6
+
7
+ * out_s3: Fix IAM credentials handling. Prefer assume_role_credentials and region parameter bug.
8
+
9
+ Release 1.4.0 - 2020/08/02
10
+
11
+ * Remove uuidtools dependency
12
+ * in_s3: Add error info to polloing retry log
13
+
14
+ Release 1.3.4 - 2020/07/07
15
+
16
+ * Add sts_http_proxy and sts_endpoint_url to assume_role_credentials
17
+
18
+ Release 1.3.3 - 2020/06/25
19
+
20
+ * Allow fips/gov included endpoint
21
+ * Support sts_region parameter
22
+
1
23
  Release 1.3.2 - 2020/05/18
2
24
 
3
25
  * out_s3: Show warning message for object conflict case.
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem 'uuidtools'
4
-
5
3
  gemspec
data/README.md CHANGED
@@ -342,7 +342,7 @@ E.g., "logs/" in the example configuration above.
342
342
  time-slice in text that are formatted with **time_slice_format**.
343
343
  * %{index} is the sequential number starts from 0, increments when multiple files are uploaded to S3 in the same time slice.
344
344
  * %{file_extension} depends on **store_as** parameter.
345
- * %{uuid_flush} a uuid that is replaced everytime the buffer will be flushed. If you want to use this placeholder, install `uuidtools` gem first.
345
+ * %{uuid_flush} a uuid that is replaced everytime the buffer will be flushed.
346
346
  * %{hostname} is replaced with `Socket.gethostname` result.
347
347
  * %{hex_random} a random hex string that is replaced for each buffer chunk, not
348
348
  assured to be unique. This is used to follow a way of performance tuning, `Add
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.2
1
+ 1.5.1
@@ -118,11 +118,11 @@ module Fluent::Plugin
118
118
  def configure(conf)
119
119
  super
120
120
 
121
- if @s3_endpoint && @s3_endpoint.end_with?('amazonaws.com')
121
+ if @s3_endpoint && (@s3_endpoint.end_with?('amazonaws.com') && !['fips', 'gov'].any? { |e| @s3_endpoint.include?(e) })
122
122
  raise Fluent::ConfigError, "s3_endpoint parameter is not supported for S3, use s3_region instead. This parameter is for S3 compatible services"
123
123
  end
124
124
 
125
- if @sqs.endpoint && @sqs.endpoint.end_with?('amazonaws.com')
125
+ if @sqs.endpoint && (@sqs.endpoint.end_with?('amazonaws.com') && !['fips', 'gov'].any? { |e| @sqs.endpoint.include?(e) })
126
126
  raise Fluent::ConfigError, "sqs/endpoint parameter is not supported for SQS, use s3_region instead. This parameter is for SQS compatible services"
127
127
  end
128
128
 
@@ -192,7 +192,7 @@ module Fluent::Plugin
192
192
  end
193
193
  end
194
194
  rescue => e
195
- log.warn("SQS Polling Failed. Retry in #{@sqs.retry_error_interval} seconds")
195
+ log.warn("SQS Polling Failed. Retry in #{@sqs.retry_error_interval} seconds", error: e)
196
196
  sleep(@sqs.retry_error_interval)
197
197
  retry
198
198
  end
@@ -5,6 +5,7 @@ require 'aws-sdk-s3'
5
5
  require 'zlib'
6
6
  require 'time'
7
7
  require 'tempfile'
8
+ require 'securerandom'
8
9
 
9
10
  module Fluent::Plugin
10
11
  class S3Output < Output
@@ -39,6 +40,12 @@ module Fluent::Plugin
39
40
  config_param :duration_seconds, :integer, default: nil
40
41
  desc "A unique identifier that is used by third parties when assuming roles in their customers' accounts."
41
42
  config_param :external_id, :string, default: nil, secret: true
43
+ desc "The region of the STS endpoint to use."
44
+ config_param :sts_region, :string, default: nil
45
+ desc "A http proxy url for requests to aws sts service"
46
+ config_param :sts_http_proxy, :string, default: nil, secret: true
47
+ desc "A url for a regional sts api endpoint, the default is global"
48
+ config_param :sts_endpoint_url, :string, default: nil
42
49
  end
43
50
  # See the following link for additional params that could be added:
44
51
  # https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/STS/Client.html#assume_role_with_web_identity-instance_method
@@ -53,6 +60,8 @@ module Fluent::Plugin
53
60
  config_param :policy, :string, default: nil
54
61
  desc "The duration, in seconds, of the role session (900-43200)"
55
62
  config_param :duration_seconds, :integer, default: nil
63
+ desc "The region of the STS endpoint to use."
64
+ config_param :sts_region, :string, default: nil
56
65
  end
57
66
  config_section :instance_profile_credentials, multi: false do
58
67
  desc "Number of times to retry when retrieving credentials"
@@ -171,7 +180,7 @@ module Fluent::Plugin
171
180
 
172
181
  Aws.use_bundled_cert! if @use_bundled_cert
173
182
 
174
- if @s3_endpoint && @s3_endpoint.end_with?('amazonaws.com')
183
+ if @s3_endpoint && (@s3_endpoint.end_with?('amazonaws.com') && !['fips', 'gov'].any? { |e| @s3_endpoint.include?(e) })
175
184
  raise Fluent::ConfigError, "s3_endpoint parameter is not supported for S3, use s3_region instead. This parameter is for S3 compatible services"
176
185
  end
177
186
 
@@ -376,7 +385,7 @@ module Fluent::Plugin
376
385
  end
377
386
 
378
387
  def uuid_random
379
- ::UUIDTools::UUID.random_create.to_s
388
+ SecureRandom.uuid
380
389
  end
381
390
 
382
391
  # This is stolen from Fluentd
@@ -433,17 +442,6 @@ module Fluent::Plugin
433
442
  }
434
443
 
435
444
  if @s3_object_key_format.include?('%{uuid_flush}')
436
- # test uuidtools works or not
437
- begin
438
- require 'uuidtools'
439
- rescue LoadError
440
- raise Fluent::ConfigError, "uuidtools gem not found. Install uuidtools gem first"
441
- end
442
- begin
443
- uuid_random
444
- rescue => e
445
- raise Fluent::ConfigError, "Generating uuid doesn't work. Can't use %{uuid_flush} on this environment. #{e}"
446
- end
447
445
  @uuid_flush_enabled = true
448
446
  end
449
447
 
@@ -475,20 +473,47 @@ module Fluent::Plugin
475
473
  options = {}
476
474
  credentials_options = {}
477
475
  case
478
- when @aws_key_id && @aws_sec_key
479
- options[:access_key_id] = @aws_key_id
480
- options[:secret_access_key] = @aws_sec_key
481
476
  when @assume_role_credentials
482
477
  c = @assume_role_credentials
478
+ iam_user_credentials = @aws_key_id && @aws_sec_key ? Aws::Credentials.new(@aws_key_id, @aws_sec_key) : nil
479
+ region = c.sts_region || @s3_region
483
480
  credentials_options[:role_arn] = c.role_arn
484
481
  credentials_options[:role_session_name] = c.role_session_name
485
482
  credentials_options[:policy] = c.policy if c.policy
486
483
  credentials_options[:duration_seconds] = c.duration_seconds if c.duration_seconds
487
484
  credentials_options[:external_id] = c.external_id if c.external_id
488
- if @s3_region
489
- credentials_options[:client] = Aws::STS::Client.new(region: @s3_region)
485
+ credentials_options[:sts_endpoint_url] = c.sts_endpoint_url if c.sts_endpoint_url
486
+ credentials_options[:sts_http_proxy] = c.sts_http_proxy if c.sts_http_proxy
487
+ if c.sts_http_proxy && c.sts_endpoint_url
488
+ credentials_options[:client] = if iam_user_credentials
489
+ Aws::STS::Client.new(region: region, http_proxy: c.sts_http_proxy, endpoint: c.sts_endpoint_url, credentials: iam_user_credentials)
490
+ else
491
+ Aws::STS::Client.new(region: region, http_proxy: c.sts_http_proxy, endpoint: c.sts_endpoint_url)
492
+ end
493
+ elsif c.sts_http_proxy
494
+ credentials_options[:client] = if iam_user_credentials
495
+ Aws::STS::Client.new(region: region, http_proxy: c.sts_http_proxy, credentials: iam_user_credentials)
496
+ else
497
+ Aws::STS::Client.new(region: region, http_proxy: c.sts_http_proxy)
498
+ end
499
+ elsif c.sts_endpoint_url
500
+ credentials_options[:client] = if iam_user_credentials
501
+ Aws::STS::Client.new(region: region, endpoint: c.sts_endpoint_url, credentials: iam_user_credentials)
502
+ else
503
+ Aws::STS::Client.new(region: region, endpoint: c.sts_endpoint_url)
504
+ end
505
+ else
506
+ credentials_options[:client] = if iam_user_credentials
507
+ Aws::STS::Client.new(region: region, credentials: iam_user_credentials)
508
+ else
509
+ Aws::STS::Client.new(region: region)
510
+ end
490
511
  end
512
+
491
513
  options[:credentials] = Aws::AssumeRoleCredentials.new(credentials_options)
514
+ when @aws_key_id && @aws_sec_key
515
+ options[:access_key_id] = @aws_key_id
516
+ options[:secret_access_key] = @aws_sec_key
492
517
  when @web_identity_credentials
493
518
  c = @web_identity_credentials
494
519
  credentials_options[:role_arn] = c.role_arn
@@ -496,7 +521,9 @@ module Fluent::Plugin
496
521
  credentials_options[:web_identity_token_file] = c.web_identity_token_file
497
522
  credentials_options[:policy] = c.policy if c.policy
498
523
  credentials_options[:duration_seconds] = c.duration_seconds if c.duration_seconds
499
- if @s3_region
524
+ if c.sts_region
525
+ credentials_options[:client] = Aws::STS::Client.new(:region => c.sts_region)
526
+ elsif @s3_region
500
527
  credentials_options[:client] = Aws::STS::Client.new(:region => @s3_region)
501
528
  end
502
529
  options[:credentials] = Aws::AssumeRoleWebIdentityCredentials.new(credentials_options)
data/test/test_out_s3.rb CHANGED
@@ -9,7 +9,6 @@ require 'test/unit/rr'
9
9
  require 'zlib'
10
10
  require 'fileutils'
11
11
  require 'timecop'
12
- require 'uuidtools'
13
12
  require 'ostruct'
14
13
 
15
14
  include Fluent::Test::Helpers
@@ -349,17 +348,11 @@ EOC
349
348
 
350
349
  def test_write_with_custom_s3_object_key_format_containing_uuid_flush_placeholder
351
350
 
352
- begin
353
- require 'uuidtools'
354
- rescue LoadError
355
- pend("uuidtools not found. skip this test")
356
- end
357
-
358
351
  # Partial mock the S3Bucket, not to make an actual connection to Amazon S3
359
352
  setup_mocks(true)
360
353
 
361
354
  uuid = "5755e23f-9b54-42d8-8818-2ea38c6f279e"
362
- stub(::UUIDTools::UUID).random_create{ uuid }
355
+ stub(::SecureRandom).uuid{ uuid }
363
356
 
364
357
  s3_local_file_path = "/tmp/s3-test.txt"
365
358
  s3path = "log/events/ts=20110102-13/events_0-#{uuid}.gz"
@@ -567,6 +560,137 @@ EOC
567
560
  assert_equal(expected_credentials, credentials)
568
561
  end
569
562
 
563
+ def test_assume_role_with_iam_credentials
564
+ expected_credentials = Aws::Credentials.new("test_key_id", "test_sec_key")
565
+ sts_client = Aws::STS::Client.new(region: 'ap-northeast-1', credentials: expected_credentials)
566
+ mock(Aws::Credentials).new("test_key_id", "test_sec_key") { expected_credentials }
567
+ mock(Aws::STS::Client).new(region: 'ap-northeast-1', credentials: expected_credentials){ sts_client }
568
+ mock(Aws::AssumeRoleCredentials).new(role_arn: "test_arn",
569
+ role_session_name: "test_session",
570
+ client: sts_client){
571
+ expected_credentials
572
+ }
573
+ config = CONFIG_TIME_SLICE
574
+ config += %[
575
+ s3_region ap-northeast-1
576
+
577
+ <assume_role_credentials>
578
+ role_arn test_arn
579
+ role_session_name test_session
580
+ </assume_role_credentials>
581
+ ]
582
+ d = create_time_sliced_driver(config)
583
+ assert_nothing_raised { d.run {} }
584
+ client = d.instance.instance_variable_get(:@s3).client
585
+ credentials = client.config.credentials
586
+ assert_equal(expected_credentials, credentials)
587
+ end
588
+
589
+ def test_assume_role_credentials_with_region_and_sts_http_proxy
590
+ expected_credentials = Aws::Credentials.new("test_key", "test_secret")
591
+ expected_region = "ap-northeast-1"
592
+ expected_sts_http_proxy = 'http://example.com'
593
+ sts_client = Aws::STS::Client.new(region: expected_region, http_proxy: expected_sts_http_proxy)
594
+ mock(Aws::STS::Client).new(region:expected_region, http_proxy: expected_sts_http_proxy){ sts_client }
595
+ mock(Aws::AssumeRoleCredentials).new(role_arn: "test_arn",
596
+ role_session_name: "test_session",
597
+ client: sts_client,
598
+ sts_http_proxy: expected_sts_http_proxy){
599
+ expected_credentials
600
+ }
601
+ config = CONFIG_TIME_SLICE.split("\n").reject{|x| x =~ /.+aws_.+/}.join("\n")
602
+ config += %[
603
+ s3_region #{expected_region}
604
+ <assume_role_credentials>
605
+ role_arn test_arn
606
+ role_session_name test_session
607
+ sts_http_proxy #{expected_sts_http_proxy}
608
+ </assume_role_credentials>
609
+ ]
610
+ d = create_time_sliced_driver(config)
611
+ assert_nothing_raised { d.run {} }
612
+ client = d.instance.instance_variable_get(:@s3).client
613
+ credentials = client.config.credentials
614
+ assert_equal(expected_credentials, credentials)
615
+ end
616
+
617
+ def test_assume_role_credentials_with_sts_http_proxy
618
+ expected_credentials = Aws::Credentials.new("test_key", "test_secret")
619
+ expected_sts_http_proxy = 'http://example.com'
620
+ sts_client = Aws::STS::Client.new(region: "us-east-1", http_proxy: expected_sts_http_proxy)
621
+ mock(Aws::STS::Client).new(region: "us-east-1", http_proxy: expected_sts_http_proxy){ sts_client }
622
+ mock(Aws::AssumeRoleCredentials).new(role_arn: "test_arn",
623
+ role_session_name: "test_session",
624
+ client: sts_client,
625
+ sts_http_proxy: expected_sts_http_proxy){
626
+ expected_credentials
627
+ }
628
+ config = CONFIG_TIME_SLICE.split("\n").reject{|x| x =~ /.+aws_.+/}.join("\n")
629
+ config += %[
630
+ <assume_role_credentials>
631
+ role_arn test_arn
632
+ role_session_name test_session
633
+ sts_http_proxy #{expected_sts_http_proxy}
634
+ </assume_role_credentials>
635
+ ]
636
+ d = create_time_sliced_driver(config)
637
+ assert_nothing_raised { d.run {} }
638
+ client = d.instance.instance_variable_get(:@s3).client
639
+ credentials = client.config.credentials
640
+ assert_equal(expected_credentials, credentials)
641
+ end
642
+
643
+ def test_assume_role_credentials_with_sts_endpoint_url
644
+ expected_credentials = Aws::Credentials.new("test_key", "test_secret")
645
+ expected_sts_endpoint_url = 'http://example.com'
646
+ sts_client = Aws::STS::Client.new(region: "us-east-1", endpoint: expected_sts_endpoint_url)
647
+ mock(Aws::STS::Client).new(region: "us-east-1", endpoint: expected_sts_endpoint_url){ sts_client }
648
+ mock(Aws::AssumeRoleCredentials).new(role_arn: "test_arn",
649
+ role_session_name: "test_session",
650
+ client: sts_client,
651
+ sts_endpoint_url: expected_sts_endpoint_url){
652
+ expected_credentials
653
+ }
654
+ config = CONFIG_TIME_SLICE.split("\n").reject{|x| x =~ /.+aws_.+/}.join("\n")
655
+ config += %[
656
+ <assume_role_credentials>
657
+ role_arn test_arn
658
+ role_session_name test_session
659
+ sts_endpoint_url #{expected_sts_endpoint_url}
660
+ </assume_role_credentials>
661
+ ]
662
+ d = create_time_sliced_driver(config)
663
+ assert_nothing_raised { d.run {} }
664
+ client = d.instance.instance_variable_get(:@s3).client
665
+ credentials = client.config.credentials
666
+ assert_equal(expected_credentials, credentials)
667
+ end
668
+
669
+ def test_assume_role_credentials_with_sts_region
670
+ expected_credentials = Aws::Credentials.new("test_key", "test_secret")
671
+ expected_sts_region = 'ap-south-1'
672
+ sts_client = Aws::STS::Client.new(region: expected_sts_region)
673
+ mock(Aws::STS::Client).new(region: expected_sts_region){ sts_client }
674
+ mock(Aws::AssumeRoleCredentials).new(role_arn: "test_arn",
675
+ role_session_name: "test_session",
676
+ client: sts_client){
677
+ expected_credentials
678
+ }
679
+ config = CONFIG_TIME_SLICE.split("\n").reject{|x| x =~ /.+aws_.+/}.join("\n")
680
+ config += %[
681
+ <assume_role_credentials>
682
+ role_arn test_arn
683
+ role_session_name test_session
684
+ sts_region #{expected_sts_region}
685
+ </assume_role_credentials>
686
+ ]
687
+ d = create_time_sliced_driver(config)
688
+ assert_nothing_raised { d.run {} }
689
+ client = d.instance.instance_variable_get(:@s3).client
690
+ credentials = client.config.credentials
691
+ assert_equal(expected_credentials, credentials)
692
+ end
693
+
570
694
  def test_web_identity_credentials
571
695
  expected_credentials = Aws::Credentials.new("test_key", "test_secret")
572
696
  mock(Aws::AssumeRoleWebIdentityCredentials).new(
@@ -593,6 +717,36 @@ EOC
593
717
  assert_equal(expected_credentials, credentials)
594
718
  end
595
719
 
720
+ def test_web_identity_credentials_with_sts_region
721
+ expected_credentials = Aws::Credentials.new("test_key", "test_secret")
722
+ sts_client = Aws::STS::Client.new(region: 'us-east-1')
723
+ mock(Aws::STS::Client).new(region: 'us-east-1'){ sts_client }
724
+ mock(Aws::AssumeRoleWebIdentityCredentials).new(
725
+ role_arn: "test_arn",
726
+ role_session_name: "test_session",
727
+ web_identity_token_file: "test_file",
728
+ client: sts_client
729
+ ){
730
+ expected_credentials
731
+ }
732
+
733
+ config = CONFIG_TIME_SLICE.split("\n").reject{|x| x =~ /.+aws_.+/}.join("\n")
734
+ config += %[
735
+ s3_region us-west-2
736
+ <web_identity_credentials>
737
+ role_arn test_arn
738
+ role_session_name test_session
739
+ web_identity_token_file test_file
740
+ sts_region us-east-1
741
+ </web_identity_credentials>
742
+ ]
743
+ d = create_time_sliced_driver(config)
744
+ assert_nothing_raised { d.run {} }
745
+ client = d.instance.instance_variable_get(:@s3).client
746
+ credentials = client.config.credentials
747
+ assert_equal(expected_credentials, credentials)
748
+ end
749
+
596
750
  def test_instance_profile_credentials
597
751
  expected_credentials = Aws::Credentials.new("test_key", "test_secret")
598
752
  mock(Aws::InstanceProfileCredentials).new({}).returns(expected_credentials)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-s3
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-05-18 00:00:00.000000000 Z
12
+ date: 2021-02-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd
@@ -121,6 +121,7 @@ executables: []
121
121
  extensions: []
122
122
  extra_rdoc_files: []
123
123
  files:
124
+ - ".github/workflows/linux.yml"
124
125
  - ".gitignore"
125
126
  - ".travis.yml"
126
127
  - AUTHORS
@@ -162,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
163
  - !ruby/object:Gem::Version
163
164
  version: '0'
164
165
  requirements: []
165
- rubygems_version: 3.0.3
166
+ rubygems_version: 3.1.4
166
167
  signing_key:
167
168
  specification_version: 4
168
169
  summary: Amazon S3 output plugin for Fluentd event collector