Module: Belt::CLI::BucketSecurity

Included in:
SetupCommand
Defined in:
lib/belt/cli/bucket_security.rb

Instance Method Summary collapse

Instance Method Details

#audit_bucket_security(bucket) ⇒ Object



6
7
8
9
10
11
12
13
# File 'lib/belt/cli/bucket_security.rb', line 6

def audit_bucket_security(bucket)
  {
    versioning: check_versioning(bucket),
    encryption: check_encryption(bucket),
    public_access_block: check_public_access_block(bucket),
    tls_policy: check_tls_policy(bucket)
  }
end

#check_encryption(bucket) ⇒ Object



33
34
35
36
37
38
39
40
41
42
# File 'lib/belt/cli/bucket_security.rb', line 33

def check_encryption(bucket)
  output = safe_capture('aws', 's3api', 'get-bucket-encryption', '--bucket', bucket, '--output', 'json')
  return false unless output

  data = JSON.parse(output)
  rules = data.dig('ServerSideEncryptionConfiguration', 'Rules') || []
  rules.any? { |r| r.dig('ApplyServerSideEncryptionByDefault', 'SSEAlgorithm') }
rescue JSON::ParserError
  false
end

#check_public_access_block(bucket) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/belt/cli/bucket_security.rb', line 44

def check_public_access_block(bucket)
  output = safe_capture('aws', 's3api', 'get-public-access-block', '--bucket', bucket, '--output', 'json')
  return false unless output

  data = JSON.parse(output)
  config = data['PublicAccessBlockConfiguration'] || {}
  config['BlockPublicAcls'] && config['IgnorePublicAcls'] &&
    config['BlockPublicPolicy'] && config['RestrictPublicBuckets']
rescue JSON::ParserError
  false
end

#check_tls_policy(bucket) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/belt/cli/bucket_security.rb', line 56

def check_tls_policy(bucket)
  output = safe_capture('aws', 's3api', 'get-bucket-policy', '--bucket', bucket, '--output', 'json')
  return false unless output

  data = JSON.parse(output)
  policy = JSON.parse(data['Policy'])
  statements = policy['Statement'] || []
  statements.any? do |s|
    s['Effect'] == 'Deny' &&
      s.dig('Condition', 'Bool', 'aws:SecureTransport') == 'false'
  end
rescue JSON::ParserError, TypeError
  false
end

#check_versioning(bucket) ⇒ Object



23
24
25
26
27
28
29
30
31
# File 'lib/belt/cli/bucket_security.rb', line 23

def check_versioning(bucket)
  output = safe_capture('aws', 's3api', 'get-bucket-versioning', '--bucket', bucket, '--output', 'json')
  return false unless output

  data = JSON.parse(output)
  data['Status'] == 'Enabled'
rescue JSON::ParserError
  false
end

#harden_bucket(bucket, audit) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/belt/cli/bucket_security.rb', line 71

def harden_bucket(bucket, audit)
  unless audit[:versioning]
    enable_versioning(bucket)
    puts '  enable  versioning'
  end
  unless audit[:encryption]
    enable_encryption(bucket)
    puts '  enable  AES-256 encryption'
  end
  unless audit[:public_access_block]
    block_public_access(bucket)
    puts '  enable  public access block'
  end
  return if audit[:tls_policy]

  apply_tls_policy(bucket)
  puts '  enable  TLS-only bucket policy'
end


15
16
17
18
19
20
21
# File 'lib/belt/cli/bucket_security.rb', line 15

def print_security_audit(audit)
  puts "\nSecurity audit:"
  puts "  #{audit[:versioning] ? '' : ''} Versioning"
  puts "  #{audit[:encryption] ? '' : ''} Encryption (AES-256)"
  puts "  #{audit[:public_access_block] ? '' : ''} Public access block"
  puts "  #{audit[:tls_policy] ? '' : ''} TLS-only policy"
end