s3-secure 0.4.2 → 0.6.1
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 +15 -0
- data/LICENSE.txt +201 -22
- data/README.md +39 -14
- 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/s3.rb +61 -0
- data/lib/s3_secure/aws_services.rb +4 -30
- data/lib/s3_secure/backwards_compatibility.rb +20 -0
- data/lib/s3_secure/cli/access_logs.rb +32 -0
- data/lib/s3_secure/{abstract_base.rb → cli/base.rb} +4 -3
- data/lib/s3_secure/{batch.rb → cli/batch.rb} +1 -1
- data/lib/s3_secure/{encryption.rb → cli/encryption.rb} +10 -6
- data/lib/s3_secure/cli/help.rb +11 -0
- data/lib/s3_secure/cli/lifecycle.rb +33 -0
- data/lib/s3_secure/cli/policy.rb +31 -0
- data/lib/s3_secure/cli/public_access.rb +32 -0
- data/lib/s3_secure/cli/remediate_all.rb +12 -0
- data/lib/s3_secure/cli/say.rb +7 -0
- data/lib/s3_secure/{summary.rb → cli/summary.rb} +3 -3
- data/lib/s3_secure/cli/versioning.rb +31 -0
- data/lib/s3_secure/cli.rb +25 -3
- data/lib/s3_secure/command.rb +7 -0
- data/lib/s3_secure/encryption/base.rb +2 -2
- data/lib/s3_secure/encryption/disable.rb +6 -10
- data/lib/s3_secure/encryption/enable.rb +6 -12
- data/lib/s3_secure/encryption/list.rb +13 -17
- data/lib/s3_secure/encryption/show.rb +16 -10
- data/lib/s3_secure/help/batch.md +14 -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/list.md +5 -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/base.rb +2 -2
- data/lib/s3_secure/policy/checker.rb +1 -1
- data/lib/s3_secure/policy/document.rb +1 -1
- data/lib/s3_secure/policy/enforce.rb +7 -11
- data/lib/s3_secure/policy/list.rb +14 -18
- data/lib/s3_secure/policy/show.rb +12 -11
- data/lib/s3_secure/policy/unforce.rb +8 -11
- data/lib/s3_secure/public_access/base.rb +10 -0
- data/lib/s3_secure/public_access/block.rb +18 -0
- data/lib/s3_secure/public_access/list.rb +24 -0
- data/lib/s3_secure/public_access/show.rb +27 -0
- data/lib/s3_secure/public_access/unblock.rb +12 -0
- data/lib/s3_secure/summary/item.rb +1 -1
- data/lib/s3_secure/summary/items.rb +6 -9
- data/lib/s3_secure/version.rb +1 -1
- 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/lib/s3_secure.rb +6 -2
- data/s3-secure.gemspec +6 -3
- data/spec/lib/lifecycle/builder_spec.rb +85 -0
- metadata +77 -11
- data/lib/s3_secure/help.rb +0 -9
- data/lib/s3_secure/policy.rb +0 -27
@@ -0,0 +1,47 @@
|
|
1
|
+
module S3Secure::Lifecycle
|
2
|
+
class Builder
|
3
|
+
# Note: put_bucket_lifecycle_configuration and put_bucket_lifecycle understand different payloads.
|
4
|
+
# put_bucket_lifecycle is old and shouldnt be used
|
5
|
+
RULE_ID = Base::RULE_ID
|
6
|
+
DEFAULT_RULE = {
|
7
|
+
expiration: {expired_object_delete_marker: true},
|
8
|
+
id: RULE_ID,
|
9
|
+
status: "Enabled",
|
10
|
+
prefix: "",
|
11
|
+
noncurrent_version_expiration: {noncurrent_days: 365},
|
12
|
+
abort_incomplete_multipart_upload: {days_after_initiation: 30}
|
13
|
+
}
|
14
|
+
|
15
|
+
def initialize(rules)
|
16
|
+
@rules = rules || []
|
17
|
+
end
|
18
|
+
|
19
|
+
def has?(id)
|
20
|
+
!!@rules.detect { |rule| rule[:id] == id }
|
21
|
+
end
|
22
|
+
|
23
|
+
def rules_with_addition(prefix=nil)
|
24
|
+
rules = @rules.dup
|
25
|
+
unless has?(RULE_ID)
|
26
|
+
rule = DEFAULT_RULE
|
27
|
+
rule[:prefix] = prefix if prefix
|
28
|
+
rules << rule
|
29
|
+
end
|
30
|
+
rules
|
31
|
+
end
|
32
|
+
|
33
|
+
def rules_with_removal
|
34
|
+
rules = @rules.dup
|
35
|
+
rules.delete_if { |rule| rule[:id] == RULE_ID }
|
36
|
+
rules
|
37
|
+
end
|
38
|
+
|
39
|
+
def build(type)
|
40
|
+
if type == :remove
|
41
|
+
remove_lifecycle
|
42
|
+
else
|
43
|
+
add_lifecycle
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module S3Secure::Lifecycle
|
2
|
+
class List < Base
|
3
|
+
def run
|
4
|
+
presenter = CliFormat::Presenter.new(@options)
|
5
|
+
presenter.header = ["Bucket", "Has Lifecycle Rules?"]
|
6
|
+
|
7
|
+
buckets.each do |bucket|
|
8
|
+
$stderr.puts "Getting lifecycle policy for bucket #{bucket.color(:green)}"
|
9
|
+
|
10
|
+
show = Show.new(bucket: bucket)
|
11
|
+
row = [bucket, show.any?]
|
12
|
+
if @options[:lifecycle].nil?
|
13
|
+
presenter.rows << row # always show policy
|
14
|
+
elsif @options[:lifecycle]
|
15
|
+
presenter.rows << row if status # only show if bucket has some encryption rules
|
16
|
+
else
|
17
|
+
presenter.rows << row unless status # 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,28 @@
|
|
1
|
+
module S3Secure::Lifecycle
|
2
|
+
class Remove < Base
|
3
|
+
RULE_ID = Base::RULE_ID
|
4
|
+
|
5
|
+
def run
|
6
|
+
show = Show.new(@options)
|
7
|
+
unless show.has?(RULE_ID)
|
8
|
+
say "Bucket #{@bucket} already does not have the #{RULE_ID} lifecycle rule."
|
9
|
+
return
|
10
|
+
end
|
11
|
+
|
12
|
+
builder = Builder.new(show.get_lifecycle_rules(@bucket))
|
13
|
+
rules = builder.rules_with_removal
|
14
|
+
if rules.empty?
|
15
|
+
s3.delete_bucket_lifecycle(bucket: @bucket)
|
16
|
+
else
|
17
|
+
# update config with removal
|
18
|
+
s3.put_bucket_lifecycle_configuration(
|
19
|
+
bucket: @bucket, # required
|
20
|
+
# content_md5: "ContentMD5",
|
21
|
+
lifecycle_configuration: {rules: rules}
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
say "Removed the #{RULE_ID} lifecycle rule on bucket #{@bucket}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module S3Secure::Lifecycle
|
2
|
+
class Show < Base
|
3
|
+
RULE_ID = Base::RULE_ID
|
4
|
+
|
5
|
+
def run
|
6
|
+
if any?
|
7
|
+
say "This S3 bucket has lifecycle rules"
|
8
|
+
else
|
9
|
+
say "This S3 bucket does not have lifecycle rules"
|
10
|
+
end
|
11
|
+
|
12
|
+
if any?
|
13
|
+
say "Bucket lifecycle details: "
|
14
|
+
pp get_lifecycle(@bucket).to_h
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def any?
|
19
|
+
rules = get_lifecycle_rules(@bucket)
|
20
|
+
!!(rules && !rules.empty?)
|
21
|
+
end
|
22
|
+
|
23
|
+
def has?(rule_id)
|
24
|
+
rules = get_lifecycle_rules(@bucket)
|
25
|
+
rules && rules.detect { |rule| rule[:id] == rule_id }
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_lifecycle(bucket)
|
29
|
+
s3.get_bucket_lifecycle_configuration(bucket: bucket) # resp
|
30
|
+
rescue Aws::S3::Errors::NoSuchLifecycleConfiguration
|
31
|
+
end
|
32
|
+
memoize :get_lifecycle
|
33
|
+
|
34
|
+
# Also used by add and remove
|
35
|
+
def get_lifecycle_rules(bucket)
|
36
|
+
resp = get_lifecycle(bucket)
|
37
|
+
resp.rules.map(&:to_h) if resp
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
module S3Secure::Policy
|
2
2
|
class Enforce < Base
|
3
3
|
def initialize(options={})
|
4
4
|
super
|
@@ -6,16 +6,13 @@ 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
|
-
|
18
|
-
|
14
|
+
say "Bucket policy for #{@bucket} has ForceSSLOnlyAccess policy statement already:"
|
15
|
+
say bucket_policy
|
19
16
|
else
|
20
17
|
# Set encryption rules
|
21
18
|
# Ruby docs: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#put_bucket_policy-instance_method
|
@@ -24,12 +21,11 @@ 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
|
)
|
31
|
-
|
32
|
-
puts policy_document
|
28
|
+
say "Add bucket policy to bucket #{@bucket}:"
|
33
29
|
end
|
34
30
|
end
|
35
31
|
end
|
@@ -1,29 +1,25 @@
|
|
1
|
-
|
1
|
+
module 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,19 +1,20 @@
|
|
1
|
-
|
1
|
+
module 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
|
-
|
12
|
-
|
13
|
-
# puts policy.map(&:to_h)
|
5
|
+
say "Bucket #{@bucket} is configured with this policy:"
|
6
|
+
say policy
|
14
7
|
else
|
15
|
-
|
8
|
+
say "Bucket #{@bucket} is not configured bucket policy"
|
16
9
|
end
|
17
10
|
end
|
11
|
+
|
12
|
+
def policy
|
13
|
+
resp = s3.get_bucket_policy(bucket: @bucket)
|
14
|
+
data = JSON.load(resp.policy.read) # String
|
15
|
+
JSON.pretty_generate(data)
|
16
|
+
rescue Aws::S3::Errors::NoSuchBucketPolicy
|
17
|
+
end
|
18
|
+
memoize :policy
|
18
19
|
end
|
19
20
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
module S3Secure::Policy
|
2
2
|
class Unforce < Base
|
3
3
|
def initialize(options={})
|
4
4
|
super
|
@@ -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,18 +20,18 @@ 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
|
-
|
35
|
-
|
31
|
+
say "Remove bucket policy statement from bucket #{@bucket}:"
|
32
|
+
say policy_document if policy_document
|
36
33
|
else
|
37
|
-
|
34
|
+
say "Bucket policy for #{@bucket} does not have ForceSSLOnlyAccess policy statement. Nothing to be done."
|
38
35
|
end
|
39
36
|
end
|
40
37
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module S3Secure::PublicAccess
|
2
|
+
class Block < Base
|
3
|
+
def run
|
4
|
+
resp = s3.put_public_access_block(
|
5
|
+
bucket: @bucket,
|
6
|
+
public_access_block_configuration: {
|
7
|
+
block_public_acls: true,
|
8
|
+
ignore_public_acls: true,
|
9
|
+
block_public_policy: true,
|
10
|
+
restrict_public_buckets: true,
|
11
|
+
},
|
12
|
+
)
|
13
|
+
say "Public access blocked for bucket: #{@bucket}"
|
14
|
+
resp
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module S3Secure::PublicAccess
|
2
|
+
class List < Base
|
3
|
+
def run
|
4
|
+
presenter = CliFormat::Presenter.new(@options)
|
5
|
+
presenter.header = ["Bucket", "Block Public Access?"]
|
6
|
+
|
7
|
+
buckets.each do |bucket|
|
8
|
+
say "Getting bucket public access configuration for bucket #{bucket.color(:green)}"
|
9
|
+
|
10
|
+
blocked = Show.new(bucket: bucket).blocked?
|
11
|
+
row = [bucket, blocked]
|
12
|
+
if @options[:blocked].nil?
|
13
|
+
presenter.rows << row # always show policy
|
14
|
+
elsif @options[:blocked]
|
15
|
+
presenter.rows << row if blocked # only show if bucket is blocked
|
16
|
+
else
|
17
|
+
presenter.rows << row unless blocked # only show if bucket is unblocked
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
presenter.show
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module S3Secure::PublicAccess
|
2
|
+
class Show < Base
|
3
|
+
def run
|
4
|
+
resp = s3.get_public_access_block(
|
5
|
+
bucket: @bucket,
|
6
|
+
)
|
7
|
+
say(resp.to_h)
|
8
|
+
resp
|
9
|
+
rescue Aws::S3::Errors::NoSuchPublicAccessBlockConfiguration
|
10
|
+
say "No public access block configuration found for bucket: #{@bucket}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def blocked?
|
14
|
+
resp = s3.get_public_access_block(
|
15
|
+
bucket: @bucket,
|
16
|
+
)
|
17
|
+
resp.to_h[:public_access_block_configuration] == {
|
18
|
+
block_public_acls: true,
|
19
|
+
block_public_policy: true,
|
20
|
+
ignore_public_acls: true,
|
21
|
+
restrict_public_buckets: true,
|
22
|
+
}
|
23
|
+
rescue Aws::S3::Errors::NoSuchPublicAccessBlockConfiguration
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
class Items < S3Secure::
|
1
|
+
module S3Secure::Summary
|
2
|
+
class Items < S3Secure::CLI::Base
|
3
3
|
extend Memoist
|
4
4
|
|
5
5
|
# override initialize
|
@@ -44,11 +44,9 @@ class S3Secure::Summary
|
|
44
44
|
|
45
45
|
private
|
46
46
|
def ssl?(bucket)
|
47
|
-
|
48
|
-
list = S3Secure::Policy::List.new(@options)
|
49
|
-
list.set_s3(s3)
|
47
|
+
show = S3Secure::Policy::Show.new(@options.merge(bucket: bucket))
|
50
48
|
|
51
|
-
bucket_policy =
|
49
|
+
bucket_policy = show.run
|
52
50
|
document = S3Secure::Policy::Document.new(bucket, bucket_policy)
|
53
51
|
document.has?("ForceSSLOnlyAccess")
|
54
52
|
end
|
@@ -56,10 +54,9 @@ class S3Secure::Summary
|
|
56
54
|
|
57
55
|
def encrypted?(bucket)
|
58
56
|
s3 = s3_regional_client(bucket)
|
59
|
-
|
60
|
-
list.set_s3(s3)
|
57
|
+
show = S3Secure::Encryption::Show.new(@options.merge(bucket: bucket))
|
61
58
|
|
62
|
-
rules =
|
59
|
+
rules = show.run
|
63
60
|
!!rules
|
64
61
|
end
|
65
62
|
memoize :encrypted?
|
data/lib/s3_secure/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
module 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
|
+
say "Versioning Suspended on bucket #{@bucket}"
|
14
|
+
else
|
15
|
+
say "Bucket #{@bucket} is already has versioning already Suspended or not Enabled."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module S3Secure::Versioning
|
2
|
+
class Enable < Base
|
3
|
+
def run
|
4
|
+
show = Show.new(@options)
|
5
|
+
if show.enabled?
|
6
|
+
say "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
|
+
say "Versioning enabled on bucket #{@bucket}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module 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
|
+
module S3Secure::Versioning
|
2
|
+
class Show < Base
|
3
|
+
def run
|
4
|
+
if enabled?
|
5
|
+
say "This S3 bucket has versioning enabled"
|
6
|
+
else
|
7
|
+
say "This S3 bucket does not have versioning enabled"
|
8
|
+
end
|
9
|
+
details = get_versioning(@bucket).to_h
|
10
|
+
unless details.empty?
|
11
|
+
say "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/lib/s3_secure.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
$:.unshift(File.expand_path("../", __FILE__))
|
2
|
+
require "active_support"
|
3
|
+
require "active_support/core_ext/module" # for delegate
|
4
|
+
require "active_support/core_ext/string"
|
5
|
+
require "cli_format"
|
2
6
|
require "json"
|
3
7
|
require "memoist"
|
4
8
|
require "rainbow/ext/string"
|
5
9
|
require "s3_secure/version"
|
6
|
-
require "active_support/core_ext/module" # for delegate
|
7
|
-
require "active_support/core_ext/string"
|
8
10
|
|
9
11
|
require "s3_secure/autoloader"
|
10
12
|
S3Secure::Autoloader.setup
|
@@ -12,3 +14,5 @@ S3Secure::Autoloader.setup
|
|
12
14
|
module S3Secure
|
13
15
|
class Error < StandardError; end
|
14
16
|
end
|
17
|
+
|
18
|
+
require_relative "s3_secure/backwards_compatibility"
|
data/s3-secure.gemspec
CHANGED
@@ -9,10 +9,11 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Tung Nguyen"]
|
10
10
|
spec.email = ["tongueroo@gmail.com"]
|
11
11
|
spec.summary = "S3 Bucket security hardening tool"
|
12
|
-
spec.homepage = "https://github.com/
|
13
|
-
spec.license = "
|
12
|
+
spec.homepage = "https://github.com/boltops-tools/s3-secure"
|
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 "rexml"
|
25
28
|
spec.add_dependency "text-table"
|
26
29
|
spec.add_dependency "thor"
|
27
30
|
spec.add_dependency "zeitwerk"
|