cfn-nag 0.6.4 → 0.6.9

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: fb0243f0a2f327d0408fe6524596d7bf9a0ce8214fb217e869a785983dc30b88
4
- data.tar.gz: e9bc6213a3beb72d785abb9e58908460771d36b2127d72d0dde421c4c22b5daa
3
+ metadata.gz: 3f9f1d1c26fcff5f16d5a7f08db72e28dc7f0d4494dfdd4290e9c4d2d1c73632
4
+ data.tar.gz: 61b1cd680139fdfcdfcead2f89a4d9df2bb829570f4dadc590930e366b83f0a6
5
5
  SHA512:
6
- metadata.gz: 99a21920685b6a2a6762060c18d7aeef9881a2527e78324f949582a03b4003adba0713c5421a2bd2040e94c78cb969b1230cd6cbf1e624b7e3056050385011c2
7
- data.tar.gz: 3ffb6ec0595927f615efa3e653083fc9efa4bd60db1a20f48591205a06c20ebc07efcf7e6c8330aef0eaee9508cadae34becbbf73c8b3d4ffab25d7491579cba
6
+ metadata.gz: 30581a3a555205ea494ec63dfa059ceb2b04faed4bc20a36465e4c93afaa401c6fc1c5da10b87055df47858b0f43b7982485415ac2da0ceef0942e4a084be60b
7
+ data.tar.gz: 775886736eabe0a51107d69663305ced348a357958d073ec6d0393ea1ec940f5530c1ae0c18a59e893a2eeab4211ad6cee255d9bc7b4d57594f6bedb9d68c42e
@@ -102,9 +102,14 @@ class CfnNag
102
102
  violations << fatal_violation(error)
103
103
  end
104
104
 
105
+ violations = prune_fatal_violations(violations) if @config.ignore_fatal
105
106
  audit_result(violations)
106
107
  end
107
108
 
109
+ def prune_fatal_violations(violations)
110
+ violations.reject { |violation| violation.type == Violation::FAILING_VIOLATION }
111
+ end
112
+
108
113
  def render_results(aggregate_results:,
109
114
  output_format:)
110
115
  results_renderer(output_format).new.render(aggregate_results)
@@ -9,6 +9,7 @@ class CfnNagConfig
9
9
  print_suppression: false,
10
10
  isolate_custom_rule_exceptions: false,
11
11
  fail_on_warnings: false,
12
+ ignore_fatal: false,
12
13
  rule_repository_definitions: [],
13
14
  rule_arguments: {})
14
15
  @rule_directory = rule_directory
@@ -24,6 +25,7 @@ class CfnNagConfig
24
25
  @fail_on_warnings = fail_on_warnings
25
26
  @rule_repositories = rule_repositories
26
27
  @rule_arguments = rule_arguments
28
+ @ignore_fatal = ignore_fatal
27
29
  end
28
30
  # rubocop:enable Metrics/ParameterLists
29
31
 
@@ -34,4 +36,5 @@ class CfnNagConfig
34
36
  attr_reader :blacklist_definition
35
37
  attr_reader :fail_on_warnings
36
38
  attr_reader :rule_repositories
39
+ attr_reader :ignore_fatal
37
40
  end
@@ -129,6 +129,7 @@ class CfnNagExecutor
129
129
  isolate_custom_rule_exceptions: opts[:isolate_custom_rule_exceptions],
130
130
  fail_on_warnings: opts[:fail_on_warnings],
131
131
  rule_repository_definitions: @rule_repository_definitions,
132
+ ignore_fatal: opts[:ignore_fatal],
132
133
  rule_arguments: merge_rule_arguments(opts)
133
134
  )
134
135
  end
@@ -100,6 +100,11 @@ class Options
100
100
  type: :string,
101
101
  required: false,
102
102
  default: nil
103
+ opt :ignore_fatal,
104
+ 'Ignore files with fatal violations. Useful for ignoring non-Cloudformation yaml/yml/json in a path',
105
+ type: :boolean,
106
+ required: false,
107
+ default: false
103
108
  end
104
109
  end
105
110
 
@@ -193,6 +198,12 @@ class Options
193
198
  type: :string,
194
199
  required: false,
195
200
  default: nil
201
+ opt :ignore_fatal,
202
+ 'Ignore files with fatal violations. Useful for ignoring non-Cloudformation yaml/yml/json in a path',
203
+ short: 'g',
204
+ type: :boolean,
205
+ required: false,
206
+ default: false
196
207
  end
197
208
  end
198
209
  # rubocop:enable Metrics/BlockLength
@@ -18,79 +18,80 @@ class EC2NetworkAclEntryOverlappingPortsRule < BaseRule
18
18
  end
19
19
 
20
20
  def audit_impl(cfn_model)
21
+ nacl_entries = cfn_model.resources_by_type('AWS::EC2::NetworkAclEntry')
22
+
23
+ # Select nacl entries that can be evaluated
24
+ nacl_entries.select! do |nacl_entry|
25
+ tcp_or_udp_protocol?(nacl_entry) && valid_ports?(nacl_entry)
26
+ end
27
+
21
28
  violating_nacl_entries = []
22
- cfn_model.resources_by_type('AWS::EC2::NetworkAcl').each do |nacl|
23
- violating_nacl_entries += violating_nacl_entries(nacl)
29
+
30
+ # Group entries by nacl id, ip type, and egress/ingress
31
+ grouped_nacl_entries = group_nacl_entries(nacl_entries)
32
+
33
+ grouped_nacl_entries.each do |grouping|
34
+ violating_nacl_entries += overlapping_port_entries(grouping)
24
35
  end
25
36
  violating_nacl_entries.map(&:logical_resource_id)
26
37
  end
27
38
 
28
39
  private
29
40
 
30
- def overlapping_port_entries(nacl_entries)
31
- unique_pairs(nacl_entries).select do |nacl_entry_pair|
32
- tcp_or_udp_protocol?(nacl_entry_pair[0], nacl_entry_pair[1]) && overlap?(nacl_entry_pair[0], nacl_entry_pair[1])
33
- end
41
+ def tcp_or_udp_protocol?(entry)
42
+ %w[6 17].include?(entry.protocol.to_s)
34
43
  end
35
44
 
36
- def tcp_or_udp_protocol?(entry1, entry2)
37
- %w[6 17].include?(entry1.protocol.to_s) && %w[6 17].include?(entry2.protocol.to_s)
45
+ def valid_ports?(entry)
46
+ !entry.portRange.nil? && valid_port_number?(entry.portRange['From']) && valid_port_number?(entry.portRange['To'])
38
47
  end
39
48
 
40
- def unique_pairs(arr)
41
- pairs_without_dupes = arr.product(arr).select { |pair| pair[0] != pair[1] }
42
- pairs_without_dupes.reduce(Set.new) { |set_of_sets, pair| set_of_sets << Set.new(pair) }.to_a.map(&:to_a)
49
+ def valid_port_number?(port)
50
+ port.is_a?(Numeric) || (port.is_a?(String) && port.to_i(10) != 0)
43
51
  end
44
52
 
45
- def overlap?(entry1, entry2)
46
- roverlap?(entry1, entry2) || loverlap?(entry1, entry2)
47
- end
53
+ def group_nacl_entries(nacl_entries)
54
+ grouped_nacl_entries = []
48
55
 
49
- def roverlap?(entry1, entry2)
50
- entry1.portRange['From'].between?(entry2.portRange['From'], entry2.portRange['To']) ||
51
- entry1.portRange['To'].between?(entry2.portRange['From'], entry2.portRange['To'])
52
- end
56
+ # Group by NaclID
57
+ nacl_entries.group_by(&:networkAclId).each_value do |entries|
58
+ # Split entries by ip type
59
+ ipv4_entries, ipv6_entries = entries.partition { |nacl_entry| nacl_entry.ipv6CidrBlock.nil? }
53
60
 
54
- def loverlap?(entry1, entry2)
55
- entry2.portRange['From'].between?(entry1.portRange['From'], entry1.portRange['To']) ||
56
- entry2.portRange['To'].between?(entry1.portRange['From'], entry1.portRange['To'])
57
- end
61
+ # Split entries by egress/ingress
62
+ egress4, ingress4 = ipv4_entries.partition { |nacl_entry| truthy?(nacl_entry.egress) }
63
+ egress6, ingress6 = ipv6_entries.partition { |nacl_entry| truthy?(nacl_entry.egress) }
58
64
 
59
- def egress_entries(nacl_entries)
60
- nacl_entries.select do |nacl_entry|
61
- truthy?(nacl_entry.egress)
65
+ grouped_nacl_entries << egress4
66
+ grouped_nacl_entries << ingress4
67
+ grouped_nacl_entries << egress6
68
+ grouped_nacl_entries << ingress6
62
69
  end
63
- end
64
70
 
65
- def ingress_entries(nacl_entries)
66
- nacl_entries.select do |nacl_entry|
67
- not_truthy?(nacl_entry.egress)
68
- end
71
+ grouped_nacl_entries
69
72
  end
70
73
 
71
- def ip6_entries(nacl_entries)
72
- nacl_entries.select do |nacl_entry|
73
- !nacl_entry.ipv6CidrBlock.nil?
74
- end
74
+ def overlapping_port_entries(nacl_entries)
75
+ unique_pairs(nacl_entries).select do |nacl_entry_pair|
76
+ overlap?(nacl_entry_pair[0], nacl_entry_pair[1])
77
+ end.flatten.uniq
75
78
  end
76
79
 
77
- def ip4_entries(nacl_entries)
78
- nacl_entries.select do |nacl_entry|
79
- nacl_entry.ipv6CidrBlock.nil?
80
- end
80
+ def unique_pairs(arr)
81
+ pairs_without_dupes = arr.product(arr).select { |pair| pair[0] != pair[1] }
82
+ pairs_without_dupes.reduce(Set.new) { |set_of_sets, pair| set_of_sets << Set.new(pair) }.to_a.map(&:to_a)
81
83
  end
82
84
 
83
- def violating_nacl_entries(nacl)
84
- violating_ip4_nacl_entries(nacl) || violating_ip6_nacl_entries(nacl)
85
+ def overlap?(entry1, entry2)
86
+ port_overlap?(entry1.portRange, entry2.portRange) || port_overlap?(entry2.portRange, entry1.portRange)
85
87
  end
86
88
 
87
- def violating_ip4_nacl_entries(nacl)
88
- overlapping_port_entries(egress_entries(ip4_entries(nacl.network_acl_entries))).flatten.uniq &&
89
- overlapping_port_entries(ingress_entries(ip4_entries(nacl.network_acl_entries))).flatten.uniq
89
+ def port_overlap?(port_range1, port_range2)
90
+ port_number(port_range1['From']).between?(port_number(port_range2['From']), port_number(port_range2['To'])) ||
91
+ port_number(port_range1['To']).between?(port_number(port_range2['From']), port_number(port_range2['To']))
90
92
  end
91
93
 
92
- def violating_ip6_nacl_entries(nacl)
93
- overlapping_port_entries(egress_entries(ip6_entries(nacl.network_acl_entries))).flatten.uniq &&
94
- overlapping_port_entries(ingress_entries(ip6_entries(nacl.network_acl_entries))).flatten.uniq
94
+ def port_number(port)
95
+ port.to_i
95
96
  end
96
97
  end
@@ -26,7 +26,10 @@ class SPCMRule < BaseRule
26
26
  policy_documents = SPCM.new.metric_impl(cfn_model)
27
27
  rescue StandardError => catch_all_exception
28
28
  puts "Experimental SPCM rule is failing. Please report #{catch_all_exception} with the violating template"
29
- policy_documents = {}
29
+ policy_documents = {
30
+ 'AWS::IAM::Policy' => {},
31
+ 'AWS::IAM::Role' => {}
32
+ }
30
33
  end
31
34
 
32
35
  threshold = spcm_threshold.nil? ? DEFAULT_THRESHOLD : spcm_threshold.to_i
@@ -6,7 +6,6 @@ require 'set'
6
6
  class ConditionMetric
7
7
  include Weights
8
8
 
9
- # rubocop:disable Metrics/AbcSize
10
9
  def metric(statement)
11
10
  return 0 if statement.condition.nil?
12
11
 
@@ -18,7 +17,6 @@ class ConditionMetric
18
17
  aggregate += values_with_policy_tags(statement.condition)
19
18
  aggregate
20
19
  end
21
- # rubocop:enable Metrics/AbcSize
22
20
 
23
21
  private
24
22
 
@@ -6,7 +6,6 @@ require 'cfn-nag/violation'
6
6
  class ColoredStdoutResults < StdoutResults
7
7
  private
8
8
 
9
- # rubocop:disable Metrics/AbcSize
10
9
  def message(message_type:,
11
10
  color:,
12
11
  message:,
@@ -24,7 +23,6 @@ class ColoredStdoutResults < StdoutResults
24
23
  puts colorize(color, '|') unless line_numbers.empty? && logical_resource_ids.nil?
25
24
  puts colorize(color, "| #{message}")
26
25
  end
27
- # rubocop:enable Metrics/AbcSize
28
26
 
29
27
  def color_code(color_symbol)
30
28
  case color_symbol
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cfn-nag
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Kascic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-02 00:00:00.000000000 Z
11
+ date: 2020-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 1.60.1
131
+ version: '1.76'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 1.60.1
138
+ version: '1.76'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: lightly
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -381,7 +381,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
381
381
  - !ruby/object:Gem::Version
382
382
  version: '0'
383
383
  requirements: []
384
- rubygems_version: 3.1.3
384
+ rubygems_version: 3.1.4
385
385
  signing_key:
386
386
  specification_version: 4
387
387
  summary: cfn-nag