Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit 484e786

Browse files
committed
Support for IPv6
-----> Starting Kitchen (v1.2.2.dev) -----> Verifying <ipv6-list-of-tables-centos-65>... Removing /tmp/busser/suites/serverspec Uploading /tmp/busser/suites/serverspec/list_of_tables_spec.rb (mode=0644) -----> Running serverspec test suite /opt/chef/embedded/bin/ruby -I/tmp/busser/suites/serverspec -S /opt/chef/embedded/bin/rspec /tmp/busser/suites/ serverspec/list_of_tables_spec.rb --color --format documentation iptables should have rule "-A INPUT -j simple_rule" should have rule "-A simple_rule -p tcp -m tcp --dport 80 -j ACCEPT" should have rule "-A INPUT -p tcp -m tcp --dport 81 -j ACCEPT" should have rule "-A FORWARD -p tcp -m tcp --dport 82 -j ACCEPT" should have rule "-A INPUT -m state --state NEW -j jump_with_rule" should have rule "-A jump_with_rule -p tcp -m tcp --dport 83 -j ACCEPT" should have rule "-A array_of_rules -p tcp -m tcp --dport 84 -j ACCEPT" should have rule "-A array_of_rules -p tcp -m tcp --dport 85 -j ACCEPT" should have rule "-A INPUT -j array_of_rules" should not have rule "*nat" should have rule "*mangle" should have rule "*filter" should not have rule "*raw" ip6tables should have rule "-A INPUT -j simple_rule" should have rule "-A simple_rule -p tcp -m tcp --dport 80 -j ACCEPT" should have rule "-A INPUT -p tcp -m tcp --dport 81 -j ACCEPT" should not have rule "-A FORWARD -p tcp -m tcp --dport 82 -j ACCEPT" should not have rule "-A INPUT -m state --state NEW -j jump_with_rule" should not have rule "-A jump_with_rule -p tcp -m tcp --dport 83 -j ACCEPT" should have rule "-A array_of_rules -p tcp -m tcp --dport 84 -j ACCEPT" should have rule "-A array_of_rules -p tcp -m tcp --dport 85 -j ACCEPT" should have rule "-A INPUT -j array_of_rules" should not have rule "*nat" should have rule "*mangle" should have rule "*filter" should not have rule "*raw" Finished in 0.23916 seconds 26 examples, 0 failures Finished verifying <ipv6-list-of-tables-centos-65> (0m1.63s). -----> Kitchen is finished. (0m2.37s)
1 parent 15aa483 commit 484e786

File tree

16 files changed

+404
-89
lines changed

16 files changed

+404
-89
lines changed

.kitchen.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ suites:
1414
run_list:
1515
- recipe[smoke]
1616
attributes:
17+
- name: ipv6_default
18+
run_list:
19+
- recipe[smoke::ipv6_default]
20+
attributes:
1721
- name: list_of_tables
1822
run_list:
1923
- recipe[smoke::tables]
2024
attributes:
25+
- name: ipv6_list_of_tables
26+
run_list:
27+
- recipe[smoke::ipv6_tables]
28+
attributes:

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,37 @@ COMMIT
220220
# Completed
221221
```
222222

223+
`IPv6` support
224+
--------------
225+
226+
To support IPv6, you will need to add `ipv6` the attribute like:
227+
default["simple_iptables"]["ip_versions"] = ["ipv4", "ipv6"]
228+
229+
When using `simple_iptables_policy` or `simple_iptables_rule` resources, you
230+
can enable the policy/rule for either `:ipv4`, `:ipv6` or `:both` using the
231+
`ip_version` parameter. For example:
232+
233+
simple_iptables_rule "management_interface" do
234+
direction "INPUT"
235+
chain_condition "-i eth1"
236+
rule [ "-p tcp --dport 80", "-p tcp --dport 443" ]
237+
jump "ACCEPT"
238+
ip_version :both
239+
end
240+
241+
will set the rule for both IPv4 and IPv6,
242+
243+
simple_iptables_rule "management_interface" do
244+
direction "INPUT"
245+
chain_condition "-i eth1"
246+
rule [ "-p tcp --dport 80", "-p tcp --dport 443" ]
247+
jump "ACCEPT"
248+
ip_version :ipv6
249+
end
250+
251+
will set it for IPv6 only. The default is to set the rule/policy for ipv4 only.
252+
253+
223254
Example
224255
=======
225256

attributes/default.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
default["simple_iptables"]["rules"] = {"filter" => [], "nat" => [], "mangle" => [], "raw" => []}
2-
default["simple_iptables"]["chains"] = {"filter" => [], "nat" => [], "mangle" => [], "raw" => []}
3-
default["simple_iptables"]["policy"] = {"filter" => {}, "nat" => {}, "mangle" => {}, "raw" => {}}
1+
default["simple_iptables"]["ipv4"]["rules"] = {"filter" => [], "nat" => [], "mangle" => [], "raw" => []}
2+
default["simple_iptables"]["ipv4"]["chains"] = {"filter" => [], "nat" => [], "mangle" => [], "raw" => []}
3+
default["simple_iptables"]["ipv4"]["policy"] = {"filter" => {}, "nat" => {}, "mangle" => {}, "raw" => {}}
4+
default["simple_iptables"]["ipv6"]["rules"] = {"filter" => [], "mangle" => [], "raw" => []}
5+
default["simple_iptables"]["ipv6"]["chains"] = {"filter" => [], "mangle" => [], "raw" => []}
6+
default["simple_iptables"]["ipv6"]["policy"] = {"filter" => {}, "mangle" => {}, "raw" => {}}
47

5-
default["simple_iptables"]["tables"] = %w(filter nat mangle raw)
8+
default["simple_iptables"]["ipv4"]["tables"] = %w(filter nat mangle raw)
9+
default["simple_iptables"]["ipv6"]["tables"] = %w(filter mangle raw)
10+
default["simple_iptables"]["ip_versions"] = ["ipv4"]

providers/policy.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
action :set do
2-
Chef::Log.debug("setting policy for #{new_resource.chain} to #{new_resource.policy}")
3-
node.set["simple_iptables"]["policy"][new_resource.table][new_resource.chain] = new_resource.policy
2+
if [:ipv4, :both].include?(new_resource.ip_version)
3+
handle_policy(new_resource, "ipv4")
4+
end
5+
if [:ipv6, :both].include?(new_resource.ip_version)
6+
handle_policy(new_resource, "ipv6")
7+
end
8+
end
9+
10+
def handle_policy(new_resource, ip_version)
11+
Chef::Log.debug("[#{ip_version}] setting policy for #{new_resource.chain} to #{new_resource.policy}")
12+
node.set["simple_iptables"][ip_version]["policy"][new_resource.table][new_resource.chain] = new_resource.policy
413
new_resource.updated_by_last_action(true)
514
end

providers/rule.rb

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,39 @@
11
require 'chef/mixin/shell_out'
22
include Chef::Mixin::ShellOut
33

4+
45
action :append do
6+
if [:ipv4, :both].include?(new_resource.ip_version)
7+
handle_rule(new_resource, "ipv4")
8+
end
9+
if [:ipv6, :both].include?(new_resource.ip_version)
10+
handle_rule(new_resource, "ipv6")
11+
end
12+
end
13+
14+
def handle_rule(new_resource, ip_version)
515
if new_resource.rule.kind_of?(String)
616
rules = [new_resource.rule]
717
else
818
rules = new_resource.rule
919
end
10-
11-
if not node["simple_iptables"]["chains"][new_resource.table].include?(new_resource.chain)
12-
node.set["simple_iptables"]["chains"][new_resource.table] = node["simple_iptables"]["chains"][new_resource.table].dup << new_resource.chain unless ["PREROUTING", "INPUT", "FORWARD", "OUTPUT", "POSTROUTING"].include?(new_resource.chain)
20+
if not node["simple_iptables"][ip_version]["chains"][new_resource.table].include?(new_resource.chain)
21+
node.set["simple_iptables"][ip_version]["chains"][new_resource.table] = node["simple_iptables"][ip_version]["chains"][new_resource.table].dup << new_resource.chain unless ["PREROUTING", "INPUT", "FORWARD", "OUTPUT", "POSTROUTING"].include?(new_resource.chain)
1322
unless new_resource.chain == new_resource.direction || new_resource.direction == :none
14-
node.set["simple_iptables"]["rules"][new_resource.table] << {:rule => "-A #{new_resource.direction} #{new_resource.chain_condition} --jump #{new_resource.chain}", :weight => new_resource.weight}
23+
node.set["simple_iptables"][ip_version]["rules"][new_resource.table] << {:rule => "-A #{new_resource.direction} #{new_resource.chain_condition} --jump #{new_resource.chain}", :weight => new_resource.weight}
1524
end
1625
end
1726

1827
# Then apply the rules to the node
1928
rules.each do |rule|
2029
new_rule = rule_string(new_resource, rule, false)
21-
if not node["simple_iptables"]["rules"][new_resource.table].include?({:rule => new_rule, :weight => new_resource.weight})
22-
node.set["simple_iptables"]["rules"][new_resource.table] << {:rule => new_rule, :weight => new_resource.weight}
23-
node.set["simple_iptables"]["rules"][new_resource.table].sort! {|a,b| a[:weight] <=> b[:weight]}
30+
if not node["simple_iptables"][ip_version]["rules"][new_resource.table].include?({:rule => new_rule, :weight => new_resource.weight})
31+
node.set["simple_iptables"][ip_version]["rules"][new_resource.table] << {:rule => new_rule, :weight => new_resource.weight}
32+
node.set["simple_iptables"][ip_version]["rules"][new_resource.table].sort! {|a,b| a[:weight] <=> b[:weight]}
2433
new_resource.updated_by_last_action(true)
25-
Chef::Log.debug("added rule '#{new_rule}'")
34+
Chef::Log.debug("[#{ip_version}] added rule '#{new_rule}'")
2635
else
27-
Chef::Log.debug("ignoring duplicate simple_iptables_rule '#{new_rule}'")
36+
Chef::Log.debug("[#{ip_version}] ignoring duplicate simple_iptables_rule '#{new_rule}'")
2837
end
2938
end
3039
end

recipes/default.rb

Lines changed: 112 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@
3636
# Before executing the simple_iptables_* resources, reset the
3737
# node attributes to their defaults. This gives "action :delete"
3838
# semantics for free by removing a resource from a recipe.
39-
node.set["simple_iptables"]["chains"] = {"filter" => [], "nat" => [], "mangle" => [], "raw" => []}
40-
node.set["simple_iptables"]["rules"] = {"filter" => [], "nat" => [], "mangle" => [], "raw" => []}
41-
node.set["simple_iptables"]["policy"] = {"filter" => {}, "nat" => {}, "mangle" => {}, "raw" => {}}
39+
node.set["simple_iptables"]["ipv4"]["chains"] = {"filter" => [], "nat" => [], "mangle" => [], "raw" => []}
40+
node.set["simple_iptables"]["ipv4"]["rules"] = {"filter" => [], "nat" => [], "mangle" => [], "raw" => []}
41+
node.set["simple_iptables"]["ipv4"]["policy"] = {"filter" => {}, "nat" => {}, "mangle" => {}, "raw" => {}}
4242

43+
node.set["simple_iptables"]["ipv6"]["chains"] = {"filter" => [], "mangle" => [], "raw" => []}
44+
node.set["simple_iptables"]["ipv6"]["rules"] = {"filter" => [], "mangle" => [], "raw" => []}
45+
node.set["simple_iptables"]["ipv6"]["policy"] = {"filter" => {}, "mangle" => {}, "raw" => {}}
4346
# Then run all the simple_iptables_* resources
4447
run_context.resource_collection.each do |resource|
4548
if resource.kind_of?(Chef::Resource::SimpleIptablesRule)
@@ -58,63 +61,126 @@
5861
case node['platform_family']
5962
when 'debian'
6063
iptable_rules = '/etc/iptables-rules'
64+
ip6table_rules = '/etc/ip6tables-rules'
6165
when 'rhel', 'fedora'
6266
iptable_rules = '/etc/sysconfig/iptables'
67+
ip6table_rules = '/etc/sysconfig/ip6tables'
6368
end
6469

65-
ruby_block "test-iptables" do
66-
block do
67-
cmd = Mixlib::ShellOut.new("iptables-restore --test < #{iptable_rules}",
68-
:user => "root")
69-
cmd.run_command
70-
if !Array(cmd.valid_exit_codes).include?(cmd.exitstatus)
71-
msg = <<-eos
72-
iptables-restore exited with code #{cmd.exitstatus} while testing new rules
73-
STDOUT:
74-
#{cmd.stdout}
75-
STDERR:
76-
#{cmd.stderr}
77-
eos
78-
match = cmd.stderr.match /line:?\s*(\d+)/
79-
if match
80-
line_no = match[1].to_i
81-
msg << "Line #{line_no}: #{IO.readlines(iptable_rules)[line_no-1]}"
70+
if node["simple_iptables"]["ip_versions"].include?("ipv4")
71+
ruby_block "test-iptables" do
72+
block do
73+
cmd = Mixlib::ShellOut.new("iptables-restore --test < #{iptable_rules}",
74+
:user => "root")
75+
cmd.run_command
76+
if !Array(cmd.valid_exit_codes).include?(cmd.exitstatus)
77+
msg = <<-eos
78+
iptables-restore exited with code #{cmd.exitstatus} while testing new rules
79+
STDOUT:
80+
#{cmd.stdout}
81+
STDERR:
82+
#{cmd.stderr}
83+
eos
84+
match = cmd.stderr.match /line:?\s*(\d+)/
85+
if match
86+
line_no = match[1].to_i
87+
msg << "Line #{line_no}: #{IO.readlines(iptable_rules)[line_no-1]}"
88+
end
89+
# Delete the file so that the next Chef run is forced to recreate it
90+
# and retest it. Otherwise, if the rules remain unchanged, the template
91+
# resource won't recreate the file, won't notify the test resource,
92+
# and the Chef run will be allowed to complete successfully despite
93+
# and invalid rule being present.
94+
File.delete(iptable_rules)
95+
raise msg
8296
end
83-
# Delete the file so that the next Chef run is forced to recreate it
84-
# and retest it. Otherwise, if the rules remain unchanged, the template
85-
# resource won't recreate the file, won't notify the test resource,
86-
# and the Chef run will be allowed to complete successfully despite
87-
# and invalid rule being present.
88-
File.delete(iptable_rules)
89-
raise msg
9097
end
98+
notifies :run, "execute[reload-iptables]"
99+
action :nothing
91100
end
92-
notifies :run, "execute[reload-iptables]"
93-
action :nothing
94-
end
95101

96-
execute "reload-iptables" do
97-
command "iptables-restore < #{iptable_rules}"
98-
user "root"
99-
action :nothing
102+
execute "reload-iptables" do
103+
command "iptables-restore < #{iptable_rules}"
104+
user "root"
105+
action :nothing
106+
end
107+
108+
template iptable_rules do
109+
source "iptables-rules.erb"
110+
cookbook "simple_iptables"
111+
notifies :create, "ruby_block[test-iptables]"
112+
action :create
113+
end
100114
end
101115

102-
template iptable_rules do
103-
source "iptables-rules.erb"
104-
cookbook "simple_iptables"
105-
notifies :create, "ruby_block[test-iptables]"
106-
action :create
116+
if node["simple_iptables"]["ip_versions"].include?("ipv6")
117+
ruby_block "test-ip6tables" do
118+
block do
119+
cmd = Mixlib::ShellOut.new("ip6tables-restore --test < #{ip6table_rules}",
120+
:user => "root")
121+
cmd.run_command
122+
if !Array(cmd.valid_exit_codes).include?(cmd.exitstatus)
123+
msg = <<-eos
124+
ip6tables-restore exited with code #{cmd.exitstatus} while testing new rules
125+
STDOUT:
126+
#{cmd.stdout}
127+
STDERR:
128+
#{cmd.stderr}
129+
eos
130+
match = cmd.stderr.match /line:?\s*(\d+)/
131+
if match
132+
line_no = match[1].to_i
133+
msg << "Line #{line_no}: #{IO.readlines(ip6table_rules)[line_no-1]}"
134+
end
135+
# Delete the file so that the next Chef run is forced to recreate it
136+
# and retest it. Otherwise, if the rules remain unchanged, the template
137+
# resource won't recreate the file, won't notify the test resource,
138+
# and the Chef run will be allowed to complete successfully despite
139+
# and invalid rule being present.
140+
File.delete(ip6table_rules)
141+
raise msg
142+
end
143+
end
144+
notifies :run, "execute[reload-ip6tables]"
145+
action :nothing
146+
end
147+
148+
execute "reload-ip6tables" do
149+
command "ip6tables-restore < #{ip6table_rules}"
150+
user "root"
151+
action :nothing
152+
end
153+
154+
template ip6table_rules do
155+
source "ip6tables-rules.erb"
156+
cookbook "simple_iptables"
157+
notifies :create, "ruby_block[test-ip6tables]"
158+
action :create
159+
end
107160
end
108161

109162
case node['platform_family']
110163
when 'debian'
111164

112-
# TODO: Generalize this for other platforms somehow
113-
file "/etc/network/if-up.d/iptables-rules" do
114-
owner "root"
115-
group "root"
116-
mode "0755"
117-
content "#!/bin/bash\niptables-restore < #{iptable_rules}\n"
118-
action :create
165+
if node["simple_iptables"]["ip_versions"].include?("ipv4")
166+
# TODO: Generalize this for other platforms somehow
167+
file "/etc/network/if-up.d/iptables-rules" do
168+
owner "root"
169+
group "root"
170+
mode "0755"
171+
content "#!/bin/bash\niptables-restore < #{iptable_rules}\n"
172+
action :create
173+
end
119174
end
175+
176+
if node["simple_iptables"]["ip_versions"].include?("ipv6")
177+
file "/etc/network/if-up.d/ip6tables-rules" do
178+
owner "root"
179+
group "root"
180+
mode "0755"
181+
content "#!/bin/bash\nip6tables-restore < #{ip6table_rules}\n"
182+
action :create
183+
end
184+
end
185+
120186
end

recipes/redhat.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,47 @@
33

44
simple_iptables_policy "INPUT" do
55
policy "ACCEPT"
6+
ip_version :ipv4
67
end
78

89
simple_iptables_rule "established" do
910
chain "INPUT"
1011
rule "-m conntrack --ctstate ESTABLISHED,RELATED"
1112
jump "ACCEPT"
1213
weight 1
14+
ip_version :ipv4
1315
end
1416

1517
simple_iptables_rule "icmp" do
1618
chain "INPUT"
1719
rule "--proto icmp"
1820
jump "ACCEPT"
1921
weight 2
22+
ip_version :ipv4
2023
end
2124

2225
simple_iptables_rule "loopback" do
2326
chain "INPUT"
2427
rule "--in-interface lo"
2528
jump "ACCEPT"
2629
weight 3
30+
ip_version :ipv4
2731
end
2832

2933
simple_iptables_rule "ssh" do
3034
chain "INPUT"
3135
rule "--proto tcp --dport 22 -m conntrack --ctstate NEW"
3236
jump "ACCEPT"
3337
weight 70
38+
ip_version :ipv4
3439
end
3540

3641
simple_iptables_rule "reject" do
3742
chain "INPUT"
3843
rule ""
3944
jump "REJECT --reject-with icmp-host-prohibited"
4045
weight 90
46+
ip_version :ipv4
4147
end
4248

4349
simple_iptables_rule "reject" do
@@ -46,4 +52,5 @@
4652
rule ""
4753
jump "REJECT --reject-with icmp-host-prohibited"
4854
weight 90
49-
end
55+
ip_version :ipv4
56+
end

resources/policy.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
attribute :chain, :name_attribute => true, :equal_to => ["INPUT", "FORWARD", "OUTPUT", "PREROUTING", "POSTROUTING"], :default => "INPUT"
44
attribute :table, :equal_to => ["filter", "nat", "mangle", "raw"], :default => "filter"
55
attribute :policy, :equal_to => ["ACCEPT", "DROP"], :required => true
6+
attribute :ip_version, :equal_to => [:ipv4, :ipv6, :both], :default => :ipv4
67

78

89
def initialize(*args)

resources/rule.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
attribute :direction, :equal_to => ["INPUT", "FORWARD", "OUTPUT", "PREROUTING", "POSTROUTING", :none], :default => "INPUT"
88
attribute :chain_condition, :kind_of => [String]
99
attribute :weight, :kind_of => Integer, :default => 50
10+
attribute :ip_version, :equal_to => [:ipv4, :ipv6, :both], :default => :ipv4
1011

1112
def initialize(*args)
1213
super

0 commit comments

Comments
 (0)