s3-secure 0.2.0 → 0.5.0
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/.gitignore +1 -0
- data/CHANGELOG.md +16 -0
- data/LICENSE.txt +201 -22
- data/README.md +134 -16
- data/lib/s3_secure.rb +3 -2
- data/lib/s3_secure/access_logs.rb +30 -0
- data/lib/s3_secure/access_logs/base.rb +4 -0
- data/lib/s3_secure/access_logs/disable.rb +37 -0
- data/lib/s3_secure/access_logs/enable.rb +41 -0
- data/lib/s3_secure/access_logs/list.rb +25 -0
- data/lib/s3_secure/access_logs/show.rb +89 -0
- data/lib/s3_secure/aws_services.rb +1 -30
- data/lib/s3_secure/aws_services/s3.rb +54 -0
- data/lib/s3_secure/cli.rb +26 -0
- data/lib/s3_secure/command.rb +7 -0
- data/lib/s3_secure/encryption.rb +2 -0
- data/lib/s3_secure/encryption/disable.rb +4 -8
- data/lib/s3_secure/encryption/enable.rb +4 -8
- data/lib/s3_secure/encryption/list.rb +12 -16
- data/lib/s3_secure/encryption/show.rb +11 -6
- data/lib/s3_secure/help/batch.md +14 -0
- data/lib/s3_secure/help/encryption/disable.md +5 -0
- data/lib/s3_secure/help/encryption/enable.md +6 -0
- data/lib/s3_secure/help/encryption/list.md +5 -0
- data/lib/s3_secure/help/lifecycle/add.md +13 -0
- data/lib/s3_secure/help/lifecycle/list.md +22 -0
- data/lib/s3_secure/help/lifecycle/remove.md +5 -0
- data/lib/s3_secure/help/lifecycle/show.md +13 -0
- data/lib/s3_secure/help/policy/enforce_ssl.md +34 -0
- data/lib/s3_secure/help/policy/list.md +5 -0
- data/lib/s3_secure/help/policy/unforce_ssl.md +61 -0
- data/lib/s3_secure/help/summary.md +22 -0
- data/lib/s3_secure/lifecycle.rb +31 -0
- data/lib/s3_secure/lifecycle/add.rb +33 -0
- data/lib/s3_secure/lifecycle/base.rb +5 -0
- data/lib/s3_secure/lifecycle/builder.rb +47 -0
- data/lib/s3_secure/lifecycle/list.rb +24 -0
- data/lib/s3_secure/lifecycle/remove.rb +28 -0
- data/lib/s3_secure/lifecycle/show.rb +40 -0
- data/lib/s3_secure/policy.rb +2 -0
- data/lib/s3_secure/policy/document.rb +1 -1
- data/lib/s3_secure/policy/enforce.rb +3 -6
- data/lib/s3_secure/policy/list.rb +13 -17
- data/lib/s3_secure/policy/show.rb +8 -6
- data/lib/s3_secure/policy/unforce.rb +5 -8
- data/lib/s3_secure/remediate_all.rb +11 -0
- data/lib/s3_secure/summary.rb +13 -0
- data/lib/s3_secure/summary/item.rb +16 -0
- data/lib/s3_secure/summary/items.rb +65 -0
- data/lib/s3_secure/table.rb +18 -0
- data/lib/s3_secure/version.rb +1 -1
- data/lib/s3_secure/versioning.rb +29 -0
- data/lib/s3_secure/versioning/base.rb +4 -0
- data/lib/s3_secure/versioning/disable.rb +19 -0
- data/lib/s3_secure/versioning/enable.rb +19 -0
- data/lib/s3_secure/versioning/list.rb +24 -0
- data/lib/s3_secure/versioning/show.rb +27 -0
- data/s3-secure.gemspec +5 -2
- data/spec/lib/lifecycle/builder_spec.rb +85 -0
- metadata +71 -6
- data/Gemfile.lock +0 -89
- data/lib/s3_secure/help/hello.md +0 -5
data/lib/s3_secure/policy.rb
CHANGED
@@ -2,6 +2,8 @@ module S3Secure
|
|
2
2
|
class Policy < Command
|
3
3
|
desc "list", "List bucket policies"
|
4
4
|
long_desc Help.text("policy/list")
|
5
|
+
option :format, desc: "Format options: #{CliFormat.formats.join(', ')}"
|
6
|
+
option :policy, type: :boolean, desc: "Filter for policy: all, true, false"
|
5
7
|
def list
|
6
8
|
List.new(options).run
|
7
9
|
end
|
@@ -10,7 +10,7 @@ class S3Secure::Policy
|
|
10
10
|
|
11
11
|
# Returns JSON text
|
12
12
|
# Currently only support adding ForceSSLOnlyAccess document policy.
|
13
|
-
def policy_document(sid
|
13
|
+
def policy_document(sid)
|
14
14
|
enforcer_class = "S3Secure::Policy::Document::#{sid}"
|
15
15
|
enforcer_class += "Remove" if @remove
|
16
16
|
enforcer_class = enforcer_class.constantize # IE: ForceSSLOnlyAccess or ForceSSLOnlyAccessRemove
|
@@ -6,12 +6,9 @@ class S3Secure::Policy
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def run
|
9
|
-
|
9
|
+
show = S3Secure::Policy::Show.new(@options)
|
10
10
|
|
11
|
-
|
12
|
-
list.set_s3(@s3)
|
13
|
-
|
14
|
-
bucket_policy = list.get_policy(@bucket)
|
11
|
+
bucket_policy = show.policy
|
15
12
|
document = Document.new(@bucket, bucket_policy)
|
16
13
|
if document.has?(@sid)
|
17
14
|
puts "Bucket policy for #{@bucket} has ForceSSLOnlyAccess policy statement already:"
|
@@ -24,7 +21,7 @@ class S3Secure::Policy
|
|
24
21
|
# put_bucket_policy returns #<struct Aws::EmptyStructure>
|
25
22
|
#
|
26
23
|
policy_document = document.policy_document(@sid)
|
27
|
-
|
24
|
+
s3.put_bucket_policy(
|
28
25
|
bucket: @bucket,
|
29
26
|
policy: policy_document,
|
30
27
|
)
|
@@ -1,29 +1,25 @@
|
|
1
1
|
class S3Secure::Policy
|
2
2
|
class List < Base
|
3
3
|
def run
|
4
|
+
presenter = CliFormat::Presenter.new(@options)
|
5
|
+
presenter.header = ["Bucket", "Has Policy?"]
|
6
|
+
|
4
7
|
buckets.each do |bucket|
|
5
|
-
|
6
|
-
|
7
|
-
policy =
|
8
|
+
$stderr.puts "Getting policy for bucket #{bucket.color(:green)}"
|
9
|
+
show = Show.new(bucket: bucket)
|
10
|
+
policy = show.policy
|
8
11
|
|
9
|
-
|
10
|
-
|
12
|
+
row = [bucket, !!policy]
|
13
|
+
if @options[:policy].nil?
|
14
|
+
presenter.rows << row # always show policy
|
15
|
+
elsif @options[:policy]
|
16
|
+
presenter.rows << row if policy # only show if bucket has a policy
|
11
17
|
else
|
12
|
-
|
18
|
+
presenter.rows << row unless policy # only show if bucket doesnt have a policy
|
13
19
|
end
|
14
20
|
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def get_policy(bucket)
|
18
|
-
resp = @s3.get_bucket_policy(bucket: bucket)
|
19
|
-
data = JSON.load(resp.policy.read) # String
|
20
|
-
JSON.pretty_generate(data)
|
21
|
-
rescue Aws::S3::Errors::NoSuchBucketPolicy
|
22
|
-
end
|
23
21
|
|
24
|
-
|
25
|
-
def set_s3(client)
|
26
|
-
@s3 = client
|
22
|
+
presenter.show
|
27
23
|
end
|
28
24
|
end
|
29
25
|
end
|
@@ -1,12 +1,6 @@
|
|
1
1
|
class S3Secure::Policy
|
2
2
|
class Show < Base
|
3
3
|
def run
|
4
|
-
@s3 = s3_regional_client(@bucket)
|
5
|
-
|
6
|
-
list = S3Secure::Policy::List.new(@options)
|
7
|
-
list.set_s3(@s3)
|
8
|
-
|
9
|
-
policy = list.get_policy(@bucket)
|
10
4
|
if policy
|
11
5
|
puts "Bucket #{@bucket} is configured with this policy:"
|
12
6
|
puts policy
|
@@ -15,5 +9,13 @@ class S3Secure::Policy
|
|
15
9
|
puts "Bucket #{@bucket} is not configured bucket policy"
|
16
10
|
end
|
17
11
|
end
|
12
|
+
|
13
|
+
def policy
|
14
|
+
resp = s3.get_bucket_policy(bucket: @bucket)
|
15
|
+
data = JSON.load(resp.policy.read) # String
|
16
|
+
JSON.pretty_generate(data)
|
17
|
+
rescue Aws::S3::Errors::NoSuchBucketPolicy
|
18
|
+
end
|
19
|
+
memoize :policy
|
18
20
|
end
|
19
21
|
end
|
@@ -6,12 +6,9 @@ class S3Secure::Policy
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def run
|
9
|
-
|
9
|
+
show = S3Secure::Policy::Show.new(@options)
|
10
10
|
|
11
|
-
|
12
|
-
list.set_s3(@s3)
|
13
|
-
|
14
|
-
bucket_policy = list.get_policy(@bucket)
|
11
|
+
bucket_policy = show.policy
|
15
12
|
document = Document.new(@bucket, bucket_policy, remove: true)
|
16
13
|
if document.has?(@sid)
|
17
14
|
# Set encryption rules
|
@@ -23,15 +20,15 @@ class S3Secure::Policy
|
|
23
20
|
policy_document = document.policy_document(@sid)
|
24
21
|
|
25
22
|
if policy_document
|
26
|
-
|
23
|
+
s3.put_bucket_policy(
|
27
24
|
bucket: @bucket,
|
28
25
|
policy: policy_document,
|
29
26
|
)
|
30
27
|
else
|
31
|
-
|
28
|
+
s3.delete_bucket_policy(bucket: @bucket)
|
32
29
|
end
|
33
30
|
|
34
|
-
puts "Remove bucket policy
|
31
|
+
puts "Remove bucket policy statement from bucket #{@bucket}:"
|
35
32
|
puts policy_document if policy_document
|
36
33
|
else
|
37
34
|
puts "Bucket policy for #{@bucket} does not have ForceSSLOnlyAccess policy statement. Nothing to be done."
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module S3Secure
|
2
|
+
class RemediateAll < AbstractBase
|
3
|
+
def run
|
4
|
+
Encryption::Enable.new(bucket: @bucket).run
|
5
|
+
Policy::Enforce.new(bucket: @bucket, sid: "ForceSSLOnlyAccess").run
|
6
|
+
Versioning::Enable.new(bucket: @bucket).run
|
7
|
+
Lifecycle::Add.new(bucket: @bucket).run
|
8
|
+
AccessLogs::Enable.new(bucket: @bucket).run
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module S3Secure
|
2
|
+
class Summary < AbstractBase
|
3
|
+
def run
|
4
|
+
$stderr.puts("Determining bucket security-related settings. Can take a while for lots of buckets...")
|
5
|
+
data = [%w[Bucket SSL? Encrypted?]]
|
6
|
+
items = Items.new(@options, buckets)
|
7
|
+
items.filtered_items.each do |i|
|
8
|
+
data << [i.bucket, i.ssl, i.encrypted]
|
9
|
+
end
|
10
|
+
S3Secure::Table.new(@options, data).display
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class S3Secure::Summary
|
2
|
+
class Item
|
3
|
+
attr_reader :bucket
|
4
|
+
def initialize(bucket, properties={})
|
5
|
+
@bucket, @properties = bucket, properties
|
6
|
+
end
|
7
|
+
|
8
|
+
def method_missing(name, *args, &block)
|
9
|
+
if @properties.key?(name)
|
10
|
+
@properties[name]
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class S3Secure::Summary
|
2
|
+
class Items < S3Secure::AbstractBase
|
3
|
+
extend Memoist
|
4
|
+
|
5
|
+
# override initialize
|
6
|
+
def initialize(options, buckets)
|
7
|
+
@options, @buckets = options, buckets
|
8
|
+
@ssl, @encrypted = @options[:ssl], @options[:encrypted]
|
9
|
+
end
|
10
|
+
|
11
|
+
def filtered_items
|
12
|
+
items = all_items.select do |item|
|
13
|
+
case @ssl
|
14
|
+
when "yes", "no"
|
15
|
+
@ssl == item.ssl
|
16
|
+
else # any or fallback
|
17
|
+
true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
items.select do |item|
|
22
|
+
case @encrypted
|
23
|
+
when "yes", "no"
|
24
|
+
@encrypted == item.encrypted
|
25
|
+
else # any or fallback
|
26
|
+
true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Triggers loading of items
|
32
|
+
def all_items
|
33
|
+
load_items!
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_items!
|
37
|
+
@buckets.map do |bucket|
|
38
|
+
Item.new(bucket,
|
39
|
+
ssl: ssl?(bucket) ? "yes" : "no",
|
40
|
+
encrypted: encrypted?(bucket) ? "yes" : "no")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
memoize :load_items!
|
44
|
+
|
45
|
+
private
|
46
|
+
def ssl?(bucket)
|
47
|
+
list = S3Secure::Policy::List.new(@options)
|
48
|
+
|
49
|
+
bucket_policy = list.get_policy(bucket)
|
50
|
+
document = S3Secure::Policy::Document.new(bucket, bucket_policy)
|
51
|
+
document.has?("ForceSSLOnlyAccess")
|
52
|
+
end
|
53
|
+
memoize :ssl?
|
54
|
+
|
55
|
+
def encrypted?(bucket)
|
56
|
+
s3 = s3_regional_client(bucket)
|
57
|
+
list = S3Secure::Encryption::List.new(@options)
|
58
|
+
list.set_s3(s3)
|
59
|
+
|
60
|
+
rules = list.get_encryption_rules(bucket)
|
61
|
+
!!rules
|
62
|
+
end
|
63
|
+
memoize :encrypted?
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "text-table"
|
2
|
+
|
3
|
+
module S3Secure
|
4
|
+
class Table
|
5
|
+
attr_reader :data
|
6
|
+
def initialize(options, data)
|
7
|
+
@options = options
|
8
|
+
@data = data
|
9
|
+
end
|
10
|
+
|
11
|
+
def display
|
12
|
+
table = Text::Table.new
|
13
|
+
table.head = data.shift
|
14
|
+
table.rows = data
|
15
|
+
puts table
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/s3_secure/version.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
module S3Secure
|
2
|
+
class Versioning < Command
|
3
|
+
desc "list", "List bucket versionings"
|
4
|
+
long_desc Help.text("versioning/list")
|
5
|
+
option :format, desc: "Format options: #{CliFormat.formats.join(', ')}"
|
6
|
+
option :versioning, desc: "Filter for versioning: all, true, false"
|
7
|
+
def list
|
8
|
+
List.new(options).run
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "show BUCKET", "show bucket versioning"
|
12
|
+
long_desc Help.text("versioning/show")
|
13
|
+
def show(bucket)
|
14
|
+
Show.new(options.merge(bucket: bucket)).run
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "enable BUCKET", "enable bucket versioning"
|
18
|
+
long_desc Help.text("versioning/enable")
|
19
|
+
def enable(bucket)
|
20
|
+
Enable.new(options.merge(bucket: bucket)).run
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "disable BUCKET", "disable bucket versioning"
|
24
|
+
long_desc Help.text("versioning/disable")
|
25
|
+
def disable(bucket)
|
26
|
+
Disable.new(options.merge(bucket: bucket)).run
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class S3Secure::Versioning
|
2
|
+
class Disable < Base
|
3
|
+
def run
|
4
|
+
show = Show.new(@options)
|
5
|
+
if show.enabled?
|
6
|
+
s3.put_bucket_versioning(
|
7
|
+
bucket: @bucket,
|
8
|
+
versioning_configuration: {
|
9
|
+
# mfa_delete: "Disabled",
|
10
|
+
status: "Suspended",
|
11
|
+
},
|
12
|
+
)
|
13
|
+
puts "Versioning Suspended on bucket #{@bucket}"
|
14
|
+
else
|
15
|
+
puts "Bucket #{@bucket} is already has versioning already Suspended or not Enabled."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class S3Secure::Versioning
|
2
|
+
class Enable < Base
|
3
|
+
def run
|
4
|
+
show = Show.new(@options)
|
5
|
+
if show.enabled?
|
6
|
+
puts "Bucket #{@bucket} is has versioning already enabled."
|
7
|
+
else
|
8
|
+
s3.put_bucket_versioning(
|
9
|
+
bucket: @bucket,
|
10
|
+
versioning_configuration: {
|
11
|
+
# mfa_delete: "Disabled",
|
12
|
+
status: "Enabled",
|
13
|
+
},
|
14
|
+
)
|
15
|
+
puts "Versioning enabled on bucket #{@bucket}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class S3Secure::Versioning
|
2
|
+
class List < Base
|
3
|
+
def run
|
4
|
+
presenter = CliFormat::Presenter.new(@options)
|
5
|
+
presenter.header = ["Bucket", "Has Versioning?"]
|
6
|
+
|
7
|
+
buckets.each do |bucket|
|
8
|
+
$stderr.puts "Getting versioning for bucket #{bucket.color(:green)}"
|
9
|
+
|
10
|
+
show = Show.new(bucket: bucket)
|
11
|
+
row = [bucket, show.enabled?]
|
12
|
+
if @options[:versioning].nil?
|
13
|
+
presenter.rows << row # always show policy
|
14
|
+
elsif @options[:versioning]
|
15
|
+
presenter.rows << row if show.enabled? # only show if bucket has some encryption rules
|
16
|
+
else
|
17
|
+
presenter.rows << row unless show.enabled? # only show if bucket doesnt have any encryption rules
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
presenter.show
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class S3Secure::Versioning
|
2
|
+
class Show < Base
|
3
|
+
def run
|
4
|
+
if enabled?
|
5
|
+
puts "This S3 bucket has versioning enabled"
|
6
|
+
else
|
7
|
+
puts "This S3 bucket does not have versioning enabled"
|
8
|
+
end
|
9
|
+
details = get_versioning(@bucket).to_h
|
10
|
+
unless details.empty?
|
11
|
+
puts "Bucket versioning details: "
|
12
|
+
pp details
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def enabled?
|
17
|
+
versioning = get_versioning(@bucket)
|
18
|
+
versioning.status == "Enabled" # Can be Enabled, Suspended, or nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_versioning(bucket)
|
22
|
+
s3.get_bucket_versioning(bucket: bucket) # resp
|
23
|
+
rescue Aws::S3::Errors::ServerSideEncryptionConfigurationNotFoundError
|
24
|
+
end
|
25
|
+
memoize :get_versioning
|
26
|
+
end
|
27
|
+
end
|
data/s3-secure.gemspec
CHANGED
@@ -10,9 +10,10 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["tongueroo@gmail.com"]
|
11
11
|
spec.summary = "S3 Bucket security hardening tool"
|
12
12
|
spec.homepage = "https://github.com/tongueroo/s3-secure"
|
13
|
-
spec.license = "
|
13
|
+
spec.license = "Apache2.0"
|
14
14
|
|
15
|
-
|
15
|
+
git_installed = system("type git > /dev/null 2>&1")
|
16
|
+
spec.files = git_installed ? `git ls-files`.split($/) : Dir.glob("**/*")
|
16
17
|
spec.bindir = "exe"
|
17
18
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
@@ -20,8 +21,10 @@ Gem::Specification.new do |spec|
|
|
20
21
|
|
21
22
|
spec.add_dependency "activesupport"
|
22
23
|
spec.add_dependency "aws-sdk-s3"
|
24
|
+
spec.add_dependency "cli-format"
|
23
25
|
spec.add_dependency "memoist"
|
24
26
|
spec.add_dependency "rainbow"
|
27
|
+
spec.add_dependency "text-table"
|
25
28
|
spec.add_dependency "thor"
|
26
29
|
spec.add_dependency "zeitwerk"
|
27
30
|
|
@@ -0,0 +1,85 @@
|
|
1
|
+
describe S3Secure::Lifecycle::Builder do
|
2
|
+
subject { S3Secure::Lifecycle::Builder.new(rules) }
|
3
|
+
|
4
|
+
describe "already has s3-secure-automated-cleanup rule" do
|
5
|
+
let(:rules) {
|
6
|
+
[{:expiration=>{:expired_object_delete_marker=>true},
|
7
|
+
:id=>"s3-secure-automated-cleanup",
|
8
|
+
:status=>"Enabled",
|
9
|
+
:noncurrent_version_expiration=>{:noncurrent_days=>365},
|
10
|
+
:abort_incomplete_multipart_upload=>{:days_after_initiation=>30}}]
|
11
|
+
}
|
12
|
+
|
13
|
+
it "has?" do
|
14
|
+
result = subject.has?("s3-secure-automated-cleanup")
|
15
|
+
expect(result).to be true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "rules_with_addition" do
|
19
|
+
rules = subject.rules_with_addition
|
20
|
+
expect(rules.size).to eq 1 # no dups
|
21
|
+
result = has_lifecycle?(rules)
|
22
|
+
expect(result).to be true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "rules_with_removal" do
|
26
|
+
rules = subject.rules_with_removal
|
27
|
+
result = has_lifecycle?(rules)
|
28
|
+
expect(result).to be false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "doesnt have s3-secure-automated-cleanup rule" do
|
33
|
+
let(:rules) {
|
34
|
+
[{:rules=>
|
35
|
+
[{:expiration=>{:expired_object_delete_marker=>true},
|
36
|
+
:id=>"someother-policy",
|
37
|
+
:status=>"Enabled",
|
38
|
+
:noncurrent_version_expiration=>{:noncurrent_days=>365},
|
39
|
+
:abort_incomplete_multipart_upload=>{:days_after_initiation=>30}}]}]
|
40
|
+
}
|
41
|
+
|
42
|
+
it "has?" do
|
43
|
+
result = subject.has?("s3-secure-automated-cleanup")
|
44
|
+
expect(result).to be false
|
45
|
+
end
|
46
|
+
|
47
|
+
it "rules_with_addition" do
|
48
|
+
rules = subject.rules_with_addition
|
49
|
+
expect(rules.size).to eq 2 # no dups
|
50
|
+
result = has_lifecycle?(rules)
|
51
|
+
expect(result).to be true
|
52
|
+
end
|
53
|
+
|
54
|
+
it "rules_with_removal" do
|
55
|
+
rules = subject.rules_with_removal
|
56
|
+
result = has_lifecycle?(rules)
|
57
|
+
expect(result).to be false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "empty policy" do
|
62
|
+
let(:rules) { nil }
|
63
|
+
|
64
|
+
it "has?" do
|
65
|
+
result = subject.has?("s3-secure-automated-cleanup")
|
66
|
+
expect(result).to be false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "rules_with_addition" do
|
70
|
+
rules = subject.rules_with_addition
|
71
|
+
result = has_lifecycle?(rules)
|
72
|
+
expect(result).to be true
|
73
|
+
end
|
74
|
+
|
75
|
+
it "rules_with_removal" do
|
76
|
+
rules = subject.rules_with_removal
|
77
|
+
result = has_lifecycle?(rules)
|
78
|
+
expect(result).to be false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def has_lifecycle?(rules)
|
83
|
+
!!rules.detect { |rule| rule[:id] == S3Secure::Lifecycle::Builder::RULE_ID }
|
84
|
+
end
|
85
|
+
end
|