cfn-nag 0.6.8 → 0.6.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ca27b8a27f49e0ab77d230cf271ba2d3e1174fd91fc089e510b920a3a718a3d
4
- data.tar.gz: 76c9c290e547543be8bf4251dcf8f28c6ae9b83802d8d15372ea8bec5c5d2a4a
3
+ metadata.gz: 3f9f1d1c26fcff5f16d5a7f08db72e28dc7f0d4494dfdd4290e9c4d2d1c73632
4
+ data.tar.gz: 61b1cd680139fdfcdfcead2f89a4d9df2bb829570f4dadc590930e366b83f0a6
5
5
  SHA512:
6
- metadata.gz: e2e2f2dfcdbccf5e92c5dca4ae55d0aaf9d1dd5be9ff82a2f11492130dee6ec612af999c8bca1383f777a1a205d4211f7434ee9d392bbe1612904bd51852509b
7
- data.tar.gz: 030f69e2d5e60547b234c6b984e0274e47df0fc9dfaa9fe432f0a90039bfbc483a5fea3cc57dd6762cb5de9d9c570d6651809a892b740fd97d0cc73ce7b93efb
6
+ metadata.gz: 30581a3a555205ea494ec63dfa059ceb2b04faed4bc20a36465e4c93afaa401c6fc1c5da10b87055df47858b0f43b7982485415ac2da0ceef0942e4a084be60b
7
+ data.tar.gz: 775886736eabe0a51107d69663305ced348a357958d073ec6d0393ea1ec940f5530c1ae0c18a59e893a2eeab4211ad6cee255d9bc7b4d57594f6bedb9d68c42e
@@ -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
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.8
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-10-01 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