cfn-nag 0.3.67 → 0.3.68

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: ca2c6915b65ea17382453ae70f489848805320dcea810216e3830065242cf921
4
- data.tar.gz: 2ad82b8452806b72055b58a984edd30573df020e4ca7b97802c21e000235e4c6
3
+ metadata.gz: ffbdd25dd16e216af5280c00d56987c2236765b6e0467c3c35fc3167333802f0
4
+ data.tar.gz: 1a7d2fbeaca398861088d3f138ebd2b1bc89e03f85aa58af230353fed6790012
5
5
  SHA512:
6
- metadata.gz: aba6c9c12ede913365cb6dfd63aff3d517b8720e0c9f5e9f409757b5b9172ece6efa3d55613cad96070e9f753e4d80879fd876ed3d4468fc65497b9a1e2d7dc1
7
- data.tar.gz: 1442d1e3d10b86a85339970c7e95c711a8c0c61f486461b85f01a2b6d696ebb4fd850a57f6a0be5df17567431a452d00e080af9549b31e8d0e6ff472ed9f9f25
6
+ metadata.gz: 93235ea544b753874959e97ad5e72c776b40ce5687adbb3fcdf8f9f45390e9280e049f72d0974c9d8116883454f740270ec39deac382e3da20d24842e37886d4
7
+ data.tar.gz: ad62b96251d1a425007cae5cfdab6244880920489fc552136386cf7ebeed84187b5eeca21d3de19be2ff3365d553d6bb95eda268ff522e229f88ca01bf14713e
data/bin/cfn_nag CHANGED
@@ -8,7 +8,12 @@ require 'json'
8
8
  require 'rubygems/specification'
9
9
 
10
10
  opts = Trollop.options do
11
- usage '[options] <cloudformation template path ...>|<cloudformation template in STDIN>'
11
+ options_message = '[options] <cloudformation template path ...>|' \
12
+ '<cloudformation template in STDIN>'
13
+ custom_rule_exceptions_message = 'Isolate custom rule exceptions - ' \
14
+ 'just emit the exception without stack ' \
15
+ ' trace and keep chugging'
16
+ usage options_message
12
17
  version Gem::Specification.find_by_name('cfn-nag').version
13
18
 
14
19
  opt :debug,
@@ -42,7 +47,7 @@ opts = Trollop.options do
42
47
  required: false,
43
48
  default: nil
44
49
  opt :isolate_custom_rule_exceptions,
45
- 'Isolate custom rule exceptions - just emit the exception without stack trace and keep chugging',
50
+ custom_rule_exceptions_message,
46
51
  type: :boolean,
47
52
  required: false,
48
53
  default: false
@@ -60,12 +65,13 @@ unless opts[:parameter_values_path].nil?
60
65
  parameter_values_string = IO.read(opts[:parameter_values_path])
61
66
  end
62
67
 
63
- cfn_nag = CfnNag.new(profile_definition: profile_definition,
64
- rule_directory: opts[:rule_directory],
65
- allow_suppression: opts[:allow_suppression],
66
- print_suppression: opts[:print_suppression],
67
- isolate_custom_rule_exceptions:
68
- opts[:isolate_custom_rule_exceptions])
68
+ cfn_nag = CfnNag.new(
69
+ profile_definition: profile_definition,
70
+ rule_directory: opts[:rule_directory],
71
+ allow_suppression: opts[:allow_suppression],
72
+ print_suppression: opts[:print_suppression],
73
+ isolate_custom_rule_exceptions: opts[:isolate_custom_rule_exceptions]
74
+ )
69
75
 
70
76
  total_failure_count = 0
71
77
  until ARGF.closed? || ARGF.eof?
data/bin/cfn_nag_scan CHANGED
@@ -10,8 +10,20 @@ require 'rubygems/specification'
10
10
  opts = Trollop.options do
11
11
  version Gem::Specification.find_by_name('cfn-nag').version
12
12
 
13
+ input_path_message = 'CloudFormation template to nag on or directory of ' \
14
+ 'templates. Default is all *.json, *.yaml, *.yml ' \
15
+ 'and *.template recursively, but can be constrained ' \
16
+ 'by --template-pattern'
17
+
18
+ custom_rule_exceptions_message = 'Isolate custom rule exceptions - just ' \
19
+ 'emit the exception without stack trace ' \
20
+ 'and keep chugging'
21
+
22
+ template_pattern_message = 'Within the --input-path, match files to scan ' \
23
+ 'against this regular expression'
24
+
13
25
  opt :input_path,
14
- 'CloudFormation template to nag on or directory of templates. Default is all *.json, *.yaml, *.yml and *.template recursively, but can be constrained by --template-pattern',
26
+ input_path_message,
15
27
  type: :io,
16
28
  required: true
17
29
  opt :output_format,
@@ -49,12 +61,12 @@ opts = Trollop.options do
49
61
  required: false,
50
62
  default: false
51
63
  opt :isolate_custom_rule_exceptions,
52
- 'Isolate custom rule exceptions - just emit the exception without stack trace and keep chugging',
64
+ custom_rule_exceptions_message,
53
65
  type: :boolean,
54
66
  required: false,
55
67
  default: false
56
68
  opt :template_pattern,
57
- 'Within the --input-path, match files to scan against this regular expression',
69
+ template_pattern_message,
58
70
  type: :string,
59
71
  required: false,
60
72
  default: '..*\.json|..*\.yaml|..*\.yml|..*\.template'
@@ -72,14 +84,17 @@ unless opts[:profile_path].nil?
72
84
  profile_definition = IO.read(opts[:profile_path])
73
85
  end
74
86
 
75
- cfn_nag = CfnNag.new(profile_definition: profile_definition,
76
- rule_directory: opts[:rule_directory],
77
- allow_suppression: opts[:allow_suppression],
78
- print_suppression: opts[:print_suppression],
79
- isolate_custom_rule_exceptions: opts[:isolate_custom_rule_exceptions])
87
+ cfn_nag = CfnNag.new(
88
+ profile_definition: profile_definition,
89
+ rule_directory: opts[:rule_directory],
90
+ allow_suppression: opts[:allow_suppression],
91
+ print_suppression: opts[:print_suppression],
92
+ isolate_custom_rule_exceptions: opts[:isolate_custom_rule_exceptions]
93
+ )
80
94
 
81
95
  exit cfn_nag.audit_aggregate_across_files_and_render_results(
82
- input_path: opts[:input_path], output_format: opts[:output_format],
96
+ input_path: opts[:input_path],
97
+ output_format: opts[:output_format],
83
98
  parameter_values_path: opts[:parameter_values_path],
84
99
  template_pattern: opts[:template_pattern]
85
100
  )
@@ -66,19 +66,6 @@ class CfnNag
66
66
  aggregate_results
67
67
  end
68
68
 
69
- def audit_result(violations)
70
- {
71
- failure_count: Violation.count_failures(violations),
72
- violations: violations
73
- }
74
- end
75
-
76
- def fatal_violation(message)
77
- Violation.new(id: 'FATAL',
78
- type: Violation::FAILING_VIOLATION,
79
- message: message)
80
- end
81
-
82
69
  ##
83
70
  # Given cloudformation json/yml, run all the rules against it
84
71
  #
@@ -118,6 +105,19 @@ class CfnNag
118
105
 
119
106
  private
120
107
 
108
+ def audit_result(violations)
109
+ {
110
+ failure_count: Violation.count_failures(violations),
111
+ violations: violations
112
+ }
113
+ end
114
+
115
+ def fatal_violation(message)
116
+ Violation.new(id: 'FATAL',
117
+ type: Violation::FAILING_VIOLATION,
118
+ message: message)
119
+ end
120
+
121
121
  def filter_violations_by_profile(violations)
122
122
  profile = nil
123
123
  unless @profile_definition.nil?
@@ -78,9 +78,11 @@ class CustomRuleLoader
78
78
  def filter_rule_classes(cfn_model, violations)
79
79
  discover_rule_classes(@rule_directory).each do |rule_class|
80
80
  begin
81
- filtered_cfn_model = cfn_model_with_suppressed_resources_removed cfn_model: cfn_model,
82
- rule_id: rule_class.new.rule_id,
83
- allow_suppression: @allow_suppression
81
+ filtered_cfn_model = cfn_model_with_suppressed_resources_removed(
82
+ cfn_model: cfn_model,
83
+ rule_id: rule_class.new.rule_id,
84
+ allow_suppression: @allow_suppression
85
+ )
84
86
  audit_result = rule_class.new.audit(filtered_cfn_model)
85
87
  violations << audit_result unless audit_result.nil?
86
88
  rescue Exception => exception
@@ -122,7 +124,8 @@ class CustomRuleLoader
122
124
  logical_resource_id = mangled_metadata.first
123
125
  mangled_rules = mangled_metadata[1]
124
126
 
125
- STDERR.puts "#{logical_resource_id} has missing cfn_nag suppression rule id: #{mangled_rules}"
127
+ STDERR.puts "#{logical_resource_id} has missing cfn_nag suppression " \
128
+ "rule id: #{mangled_rules}"
126
129
  end
127
130
  end
128
131
 
@@ -132,7 +135,9 @@ class CustomRuleLoader
132
135
  rule_to_suppress['id'] == rule_id
133
136
  end
134
137
  if found_suppression_rule && @print_suppression
135
- STDERR.puts "Suppressing #{rule_id} on #{logical_resource_id} for reason: #{found_suppression_rule['reason']}"
138
+ message = "Suppressing #{rule_id} on #{logical_resource_id} for " \
139
+ "reason: #{found_suppression_rule['reason']}"
140
+ STDERR.puts message
136
141
  end
137
142
  !found_suppression_rule.nil?
138
143
  end
@@ -5,7 +5,8 @@ require_relative 'base'
5
5
 
6
6
  class LambdaPermissionInvokeFunctionActionRule < BaseRule
7
7
  def rule_text
8
- 'Lambda permission beside InvokeFunction might not be what you want? Not sure!?'
8
+ 'Lambda permission beside InvokeFunction might not be what you want? ' \
9
+ 'Not sure!?'
9
10
  end
10
11
 
11
12
  def rule_type
@@ -17,10 +18,11 @@ class LambdaPermissionInvokeFunctionActionRule < BaseRule
17
18
  end
18
19
 
19
20
  def audit_impl(cfn_model)
20
- violating_lambdas = cfn_model.resources_by_type('AWS::Lambda::Permission').select do |lambda_permission|
21
+ lambda_permissions = cfn_model.resources_by_type('AWS::Lambda::Permission')
22
+ violating_lambda_permissions = lambda_permissions.select do |lambda_permission|
21
23
  lambda_permission.action != 'lambda:InvokeFunction'
22
24
  end
23
25
 
24
- violating_lambdas.map(&:logical_resource_id)
26
+ violating_lambda_permissions.map(&:logical_resource_id)
25
27
  end
26
28
  end
@@ -18,10 +18,11 @@ class LambdaPermissionWildcardPrincipalRule < BaseRule
18
18
  end
19
19
 
20
20
  def audit_impl(cfn_model)
21
- violating_lambdas = cfn_model.resources_by_type('AWS::Lambda::Permission').select do |lambda_permission|
21
+ lambda_permissions = cfn_model.resources_by_type('AWS::Lambda::Permission')
22
+ violating_lambda_permissions = lambda_permissions.select do |lambda_permission|
22
23
  LambdaPrincipal.wildcard? lambda_permission.principal
23
24
  end
24
25
 
25
- violating_lambdas.map(&:logical_resource_id)
26
+ violating_lambda_permissions.map(&:logical_resource_id)
26
27
  end
27
28
  end
@@ -5,7 +5,8 @@ require_relative 'base'
5
5
 
6
6
  class RDSInstanceMasterUserPasswordRule < BaseRule
7
7
  def rule_text
8
- 'RDS instance master user password must be Ref to NoEcho Parameter. Default credentials are not recommended'
8
+ 'RDS instance master user password must be Ref to NoEcho Parameter. ' \
9
+ 'Default credentials are not recommended'
9
10
  end
10
11
 
11
12
  def rule_type
@@ -16,15 +17,18 @@ class RDSInstanceMasterUserPasswordRule < BaseRule
16
17
  'F23'
17
18
  end
18
19
 
19
- # one word of warning... if somebody applies parameter values via JSON.... this will compare that....
20
- # probably shouldn't be doing that though - if it's NoEcho there's a good reason
20
+ # one word of warning... if somebody applies parameter values via JSON....
21
+ # this will compare that....
22
+ # probably shouldn't be doing that though if it's NoEcho there's a good reason
21
23
  # bother checking synthesized_value? that would be the indicator.....
22
24
  def audit_impl(cfn_model)
23
- violating_rdsinstances = cfn_model.resources_by_type('AWS::RDS::DBInstance').select do |instance|
25
+ rds_dbinstances = cfn_model.resources_by_type('AWS::RDS::DBInstance')
26
+ violating_rdsinstances = rds_dbinstances.select do |instance|
24
27
  if instance.masterUserPassword.nil?
25
28
  false
26
29
  else
27
- !references_no_echo_parameter_without_default?(cfn_model, instance.masterUserPassword)
30
+ !no_echo_parameter_without_default?(cfn_model,
31
+ instance.masterUserPassword)
28
32
  end
29
33
  end
30
34
 
@@ -37,7 +41,7 @@ class RDSInstanceMasterUserPasswordRule < BaseRule
37
41
  string.to_s.casecmp('true').zero?
38
42
  end
39
43
 
40
- def references_no_echo_parameter_without_default?(cfn_model, master_user_password)
44
+ def no_echo_parameter_without_default?(cfn_model, master_user_password)
41
45
  # i feel like i've written this mess somewhere before
42
46
  if master_user_password.is_a? Hash
43
47
  if master_user_password.key? 'Ref'
@@ -6,7 +6,8 @@ require_relative 'base'
6
6
  # cfn_nag rules related to RDS Instance master username
7
7
  class RDSInstanceMasterUsernameRule < BaseRule
8
8
  def rule_text
9
- 'RDS instance master username must be Ref to NoEcho Parameter. Default credentials are not recommended'
9
+ 'RDS instance master username must be Ref to NoEcho Parameter. Default ' \
10
+ 'credentials are not recommended'
10
11
  end
11
12
 
12
13
  def rule_type
@@ -17,7 +17,9 @@ class RDSInstancePubliclyAccessibleRule < BaseRule
17
17
  end
18
18
 
19
19
  def audit_impl(cfn_model)
20
- violating_rdsinstances = cfn_model.resources_by_type('AWS::RDS::DBInstance').select do |instance|
20
+ rds_dbinstances = cfn_model.resources_by_type('AWS::RDS::DBInstance')
21
+
22
+ violating_rdsinstances = rds_dbinstances.select do |instance|
21
23
  instance.publiclyAccessible.nil? || instance.publiclyAccessible.to_s.casecmp('true').zero?
22
24
  end
23
25
 
@@ -17,12 +17,10 @@ class S3BucketPublicReadWriteAclRule < BaseRule
17
17
  end
18
18
 
19
19
  def audit_impl(cfn_model)
20
- logical_resource_ids = []
21
-
22
- cfn_model.resources_by_type('AWS::S3::Bucket').each do |bucket|
23
- logical_resource_ids << bucket.logical_resource_id if bucket.accessControl == 'PublicReadWrite'
20
+ violating_buckets = cfn_model.resources_by_type('AWS::S3::Bucket').select do |bucket|
21
+ bucket.accessControl == 'PublicReadWrite'
24
22
  end
25
23
 
26
- logical_resource_ids
24
+ violating_buckets.map(&:logical_resource_id)
27
25
  end
28
26
  end
@@ -20,21 +20,21 @@ class SecurityGroupEgressOpenToWorldRule < BaseRule
20
20
  end
21
21
 
22
22
  ##
23
- # This will behave slightly different than the legacy jq based rule which was targeted against inline ingress only
23
+ # This will behave slightly different than the legacy jq based rule which was
24
+ # targeted against inline ingress only
24
25
  def audit_impl(cfn_model)
25
- logical_resource_ids = []
26
- cfn_model.security_groups.each do |security_group|
26
+ violating_security_groups = cfn_model.security_groups.select do |security_group|
27
27
  violating_egresses = security_group.egresses.select do |egress|
28
28
  ip4_open?(egress) || ip6_open?(egress)
29
29
  end
30
30
 
31
- logical_resource_ids << security_group.logical_resource_id unless violating_egresses.empty?
31
+ !violating_egresses.empty?
32
32
  end
33
33
 
34
34
  violating_egresses = cfn_model.standalone_egress.select do |standalone_egress|
35
35
  ip4_open?(standalone_egress) || ip6_open?(standalone_egress)
36
36
  end
37
37
 
38
- logical_resource_ids + violating_egresses.map(&:logical_resource_id)
38
+ violating_security_groups.map(&:logical_resource_id) + violating_egresses.map(&:logical_resource_id)
39
39
  end
40
40
  end
@@ -17,21 +17,21 @@ class SecurityGroupEgressPortRangeRule < BaseRule
17
17
  end
18
18
 
19
19
  ##
20
- # This will behave slightly different than the legacy jq based rule which was targeted against inline ingress only
20
+ # This will behave slightly different than the legacy jq based rule which was
21
+ # targeted against inline ingress only
21
22
  def audit_impl(cfn_model)
22
- logical_resource_ids = []
23
- cfn_model.security_groups.each do |security_group|
23
+ violating_security_groups = cfn_model.security_groups.select do |security_group|
24
24
  violating_egresses = security_group.egresses.select do |egress|
25
25
  egress.fromPort != egress.toPort
26
26
  end
27
27
 
28
- logical_resource_ids << security_group.logical_resource_id unless violating_egresses.empty?
28
+ !violating_egresses.empty?
29
29
  end
30
30
 
31
31
  violating_egresses = cfn_model.standalone_egress.select do |standalone_egress|
32
32
  standalone_egress.fromPort != standalone_egress.toPort
33
33
  end
34
34
 
35
- logical_resource_ids + violating_egresses.map(&:logical_resource_id)
35
+ violating_security_groups.map(&:logical_resource_id) + violating_egresses.map(&:logical_resource_id)
36
36
  end
37
37
  end
@@ -20,21 +20,21 @@ class SecurityGroupIngressCidrNon32Rule < BaseRule
20
20
  end
21
21
 
22
22
  ##
23
- # This will behave slightly different than the legacy jq based rule which was targeted against inline ingress only
23
+ # This will behave slightly different than the legacy jq based rule which was
24
+ # targeted against inline ingress only
24
25
  def audit_impl(cfn_model)
25
- logical_resource_ids = []
26
- cfn_model.security_groups.each do |security_group|
26
+ violating_security_groups = cfn_model.security_groups.select do |security_group|
27
27
  violating_ingresses = security_group.ingresses.select do |ingress|
28
28
  ip4_cidr_range?(ingress) || ip6_cidr_range?(ingress)
29
29
  end
30
30
 
31
- logical_resource_ids << security_group.logical_resource_id unless violating_ingresses.empty?
31
+ !violating_ingresses.empty?
32
32
  end
33
33
 
34
34
  violating_ingresses = cfn_model.standalone_ingress.select do |standalone_ingress|
35
35
  ip4_cidr_range?(standalone_ingress) || ip6_cidr_range?(standalone_ingress)
36
36
  end
37
37
 
38
- logical_resource_ids + violating_ingresses.map(&:logical_resource_id)
38
+ violating_security_groups.map(&:logical_resource_id) + violating_ingresses.map(&:logical_resource_id)
39
39
  end
40
40
  end
@@ -8,7 +8,8 @@ class SecurityGroupIngressOpenToWorldRule < BaseRule
8
8
  include IpAddr
9
9
 
10
10
  def rule_text
11
- 'Security Groups found with cidr open to world on ingress. This should never be true on instance. Permissible on ELB'
11
+ 'Security Groups found with cidr open to world on ingress. This should ' \
12
+ 'never be true on instance. Permissible on ELB'
12
13
  end
13
14
 
14
15
  def rule_type
@@ -23,19 +24,18 @@ class SecurityGroupIngressOpenToWorldRule < BaseRule
23
24
  # This will behave slightly different than the legacy jq based rule
24
25
  # which was targeted against inline ingress only
25
26
  def audit_impl(cfn_model)
26
- logical_resource_ids = []
27
- cfn_model.security_groups.each do |security_group|
27
+ violating_security_groups = cfn_model.security_groups.select do |security_group|
28
28
  violating_ingresses = security_group.ingresses.select do |ingress|
29
29
  ip4_open?(ingress) || ip6_open?(ingress)
30
30
  end
31
31
 
32
- logical_resource_ids << security_group.logical_resource_id unless violating_ingresses.empty?
32
+ !violating_ingresses.empty?
33
33
  end
34
34
 
35
35
  violating_ingresses = cfn_model.standalone_ingress.select do |standalone_ingress|
36
36
  ip4_open?(standalone_ingress) || ip6_open?(standalone_ingress)
37
37
  end
38
38
 
39
- logical_resource_ids + violating_ingresses.map(&:logical_resource_id)
39
+ violating_security_groups.map(&:logical_resource_id) + violating_ingresses.map(&:logical_resource_id)
40
40
  end
41
41
  end
@@ -5,7 +5,8 @@ require_relative 'base'
5
5
 
6
6
  class SecurityGroupIngressPortRangeRule < BaseRule
7
7
  def rule_text
8
- 'Security Groups found ingress with port range instead of just a single port'
8
+ 'Security Groups found ingress with port range instead of just a single ' \
9
+ 'port'
9
10
  end
10
11
 
11
12
  def rule_type
@@ -17,21 +18,21 @@ class SecurityGroupIngressPortRangeRule < BaseRule
17
18
  end
18
19
 
19
20
  ##
20
- # This will behave slightly different than the legacy jq based rule which was targeted against inline ingress only
21
+ # This will behave slightly different than the legacy jq based rule which was
22
+ # targeted against inline ingress only
21
23
  def audit_impl(cfn_model)
22
- logical_resource_ids = []
23
- cfn_model.security_groups.each do |security_group|
24
+ violating_security_groups = cfn_model.security_groups.select do |security_group|
24
25
  violating_ingresses = security_group.ingresses.select do |ingress|
25
26
  ingress.fromPort != ingress.toPort
26
27
  end
27
28
 
28
- logical_resource_ids << security_group.logical_resource_id unless violating_ingresses.empty?
29
+ !violating_ingresses.empty?
29
30
  end
30
31
 
31
32
  violating_ingresses = cfn_model.standalone_ingress.select do |standalone_ingress|
32
33
  standalone_ingress.fromPort != standalone_ingress.toPort
33
34
  end
34
35
 
35
- logical_resource_ids + violating_ingresses.map(&:logical_resource_id)
36
+ violating_security_groups.map(&:logical_resource_id) + violating_ingresses.map(&:logical_resource_id)
36
37
  end
37
38
  end
@@ -5,7 +5,8 @@ require_relative 'base'
5
5
 
6
6
  class SecurityGroupMissingEgressRule < BaseRule
7
7
  def rule_text
8
- 'Missing egress rule means all traffic is allowed outbound. Make this explicit if it is desired configuration'
8
+ 'Missing egress rule means all traffic is allowed outbound. Make this ' \
9
+ 'explicit if it is desired configuration'
9
10
  end
10
11
 
11
12
  def rule_type
@@ -17,11 +18,10 @@ class SecurityGroupMissingEgressRule < BaseRule
17
18
  end
18
19
 
19
20
  def audit_impl(cfn_model)
20
- logical_resource_ids = []
21
- cfn_model.security_groups.each do |security_group|
22
- logical_resource_ids << security_group.logical_resource_id if security_group.egresses.empty?
21
+ violating_security_groups = cfn_model.security_groups.select do |security_group|
22
+ security_group.egresses.empty?
23
23
  end
24
24
 
25
- logical_resource_ids
25
+ violating_security_groups.map(&:logical_resource_id)
26
26
  end
27
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfn-nag
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.67
4
+ version: 0.3.68
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Kascic
@@ -193,7 +193,6 @@ files:
193
193
  - lib/cfn-nag/custom_rules/WafWebAclDefaultActionRule.rb
194
194
  - lib/cfn-nag/custom_rules/WorkspacesWorkspaceEncryptionRule.rb
195
195
  - lib/cfn-nag/custom_rules/base.rb
196
- - lib/cfn-nag/custom_rules/unencrypted_s3_put_allowed.rb
197
196
  - lib/cfn-nag/ip_addr.rb
198
197
  - lib/cfn-nag/jmes_path_discovery.rb
199
198
  - lib/cfn-nag/jmes_path_evaluator.rb
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # require 'cfn-nag/violation'
4
- # require 'model/action_parser'
5
- #
6
- # class UnencryptedS3PutObjectAllowedRule
7
- #
8
- # def rule_text
9
- # 'It appears that the S3 Bucket Policy allows s3:PutObject without server-side encryption'
10
- # end
11
- #
12
- # def rule_type
13
- # Violation::WARNING
14
- # end
15
- #
16
- # def rule_id
17
- # 'W1000'
18
- # end
19
- #
20
- # def audit(cfn_model)
21
- # logical_resource_ids = []
22
- # cfn_model.bucket_policies.each do |bucket_policy|
23
- # found_statement = bucket_policy.statements.find do |statement|
24
- # blocks_put_object_without_encryption(statement)
25
- # end
26
- # if found_statement.nil?
27
- # logical_resource_ids << bucket_policy.logical_resource_id
28
- # end
29
- # end
30
- #
31
- # if logical_resource_ids.size > 0
32
- # Violation.new(id: rule_id,
33
- # type: rule_type,
34
- # message: rule_text,
35
- # logical_resource_ids: logical_resource_ids)
36
- # else
37
- # nil
38
- # end
39
- # end
40
- #
41
- # private
42
- #
43
- # def blocks_put_object_without_encryption(statement)
44
- # encryption_condition = {
45
- # 'StringNotEquals' => {
46
- # 's3:x-amz-server-side-encryption' => 'AES256'
47
- # }
48
- # }
49
- #
50
- # # this isn't quite complete. parsing the Resource field can be tricky
51
- # # looking for a trailing wildcard will likely be right most of the time
52
- # # but there are a lot of string manipulations to confuse things so...
53
- # # just warn when we can't find at least the Deny+encryption - they may have an
54
- # # incomplete Deny (for encryption) and that will slip through
55
- # statement['Effect'] == 'Deny' and
56
- # ActionParser.new.include?(actual_action: statement['Action'], action_to_look_for: 's3:PutObject') and
57
- # S3BucketPolicy::condition_includes?(statement, encryption_condition) and
58
- # statement['Principal'] == '*'
59
- # end
60
- # end