firewall: add IPv6 support

This patch adds support for ip6tables rules in TripleO, in a intuitive
and flexible fashion.

1) Default firewal rules 'source' parameter to undef.
   It was 0.0.0.0/0 before but now undef, so we don't need complex logic to
   support ipv6 rules. undef will create empty source, which is the same as
   0.0.0.0/0 or ::/0.

2) Automatically convert icmp rules to ipv6-icmp for ipv6 rules.

3) Automatically create IPv6 rules like it's for IPv4.

4) Only create rules that can be created, depending on
   source/destination ip version.

This patch should be backward compatible and adds a layer of security
for IPv6 deployments. If previous deployments were manually creating
Ipv6 rules, it's possible that this patch will override them. Our
framework is able to configure any rule, so it shouldn't be a problem
for upgrades.

Note: the code had to be partially rewritten because of Puppet3 vs
Puppet4.

Co-Authored-By: Ben Nemec <bnemec@redhat.com>
Co-Authored-By: Alex Schultz <aschultz@redhat.com>
Closes-Bug: #1654050
Change-Id: I98a00a9ae265d3e5854632e749cc8c3a1647298c
(cherry picked from commit 8c99073890)
This commit is contained in:
Emilien Macchi 2017-01-04 13:56:59 -05:00
parent 939e0375a1
commit f6d398a7da
2 changed files with 84 additions and 18 deletions

View File

@ -49,7 +49,7 @@
#
# [*source*]
# (optional) The source IP address associated to the rule.
# Defaults to '0.0.0.0/0'
# Defaults to undef
#
# [*iniface*]
# (optional) The network interface associated to the rule.
@ -74,7 +74,7 @@ define tripleo::firewall::rule (
$proto = 'tcp',
$action = 'accept',
$state = ['NEW'],
$source = '0.0.0.0/0',
$source = undef,
$iniface = undef,
$chain = 'INPUT',
$destination = undef,
@ -110,6 +110,16 @@ define tripleo::firewall::rule (
'destination' => $destination,
'jump' => $jump_real,
}
if $proto == 'icmp' {
$ipv6 = {
'provider' => 'ip6tables',
'proto' => 'ipv6-icmp',
}
} else {
$ipv6 = {
'provider' => 'ip6tables',
}
}
if $proto != 'gre' {
$state_rule = {
'state' => $state
@ -119,8 +129,10 @@ define tripleo::firewall::rule (
}
$rule = merge($basic, $state_rule, $extras)
validate_hash($rule)
$ipv4_rule = merge($basic, $state_rule, $extras)
$ipv6_rule = merge($basic, $state_rule, $ipv6, $extras)
validate_hash($ipv4_rule)
validate_hash($ipv6_rule)
# This conditional will ensure that TCP and UDP firewall rules have
# a port specified in the configuration when using INPUT or OUTPUT chains.
@ -131,6 +143,16 @@ define tripleo::firewall::rule (
if ($proto in ['tcp', 'udp']) and (! ($port or $dport or $sport) and ($chain != 'FORWARD')) {
fail("${title} firewall rule cannot be created. TCP or UDP rules for INPUT or OUTPUT need port or sport or dport.")
}
create_resources('firewall', { "${title}" => $rule })
if $source or $destination {
if (('.' in join(any2array($destination), ',')) or ('.' in join(any2array($source), ','))){
create_resources('firewall', { "${title} ipv4" => $ipv4_rule })
}
if ((':' in join(any2array($destination), ',')) or (':' in join(any2array($source), ','))){
create_resources('firewall', { "${title} ipv6" => $ipv6_rule })
}
} else {
create_resources('firewall', { "${title} ipv4" => $ipv4_rule })
create_resources('firewall', { "${title} ipv6" => $ipv6_rule })
}
}

View File

@ -34,35 +34,65 @@ describe 'tripleo::firewall' do
end
it 'configure basic pre firewall rules' do
is_expected.to contain_firewall('000 accept related established rules').with(
is_expected.to contain_firewall('000 accept related established rules ipv4').with(
:proto => 'all',
:state => ['RELATED', 'ESTABLISHED'],
:action => 'accept',
)
is_expected.to contain_firewall('001 accept all icmp').with(
is_expected.to contain_firewall('000 accept related established rules ipv6').with(
:proto => 'all',
:state => ['RELATED', 'ESTABLISHED'],
:action => 'accept',
:provider => 'ip6tables',
)
is_expected.to contain_firewall('001 accept all icmp ipv4').with(
:proto => 'icmp',
:action => 'accept',
:state => ['NEW'],
)
is_expected.to contain_firewall('002 accept all to lo interface').with(
is_expected.to contain_firewall('001 accept all icmp ipv6').with(
:proto => 'ipv6-icmp',
:action => 'accept',
:state => ['NEW'],
:provider => 'ip6tables',
)
is_expected.to contain_firewall('002 accept all to lo interface ipv4').with(
:proto => 'all',
:iniface => 'lo',
:action => 'accept',
:state => ['NEW'],
)
is_expected.to contain_firewall('003 accept ssh').with(
is_expected.to contain_firewall('002 accept all to lo interface ipv6').with(
:proto => 'all',
:iniface => 'lo',
:action => 'accept',
:state => ['NEW'],
:provider => 'ip6tables',
)
is_expected.to contain_firewall('003 accept ssh ipv4').with(
:dport => '22',
:proto => 'tcp',
:action => 'accept',
:state => ['NEW'],
)
is_expected.to contain_firewall('003 accept ssh ipv6').with(
:dport => '22',
:proto => 'tcp',
:action => 'accept',
:state => ['NEW'],
:provider => 'ip6tables',
)
end
it 'configure basic post firewall rules' do
is_expected.to contain_firewall('999 drop all').with(
is_expected.to contain_firewall('999 drop all ipv4').with(
:proto => 'all',
:action => 'drop',
:source => '0.0.0.0/0',
)
is_expected.to contain_firewall('999 drop all ipv6').with(
:proto => 'all',
:action => 'drop',
:provider => 'ip6tables',
)
end
end
@ -77,41 +107,55 @@ describe 'tripleo::firewall' do
'302 fwd custom cidr 1' => {'port' => 'all', 'chain' => 'FORWARD', 'destination' => '192.0.2.0/24'},
'303 add custom application 3' => {'dport' => '8081', 'proto' => 'tcp', 'action' => 'accept'},
'304 add custom application 4' => {'sport' => '1000', 'proto' => 'tcp', 'action' => 'accept'},
'305 add gre rule' => {'proto' => 'gre'}
'305 add gre rule' => {'proto' => 'gre'},
'306 add custom cidr 2' => {'port' => 'all', 'destination' => '::1/24'},
}
)
end
it 'configure custom firewall rules' do
is_expected.to contain_firewall('300 add custom application 1').with(
is_expected.to contain_firewall('300 add custom application 1 ipv4').with(
:port => '999',
:proto => 'udp',
:action => 'accept',
:state => ['NEW'],
)
is_expected.to contain_firewall('301 add custom application 2').with(
is_expected.to contain_firewall('301 add custom application 2 ipv4').with(
:port => '8081',
:proto => 'tcp',
:action => 'accept',
:state => ['NEW'],
)
is_expected.to contain_firewall('302 fwd custom cidr 1').with(
is_expected.to contain_firewall('302 fwd custom cidr 1 ipv4').with(
:chain => 'FORWARD',
:proto => 'tcp',
:destination => '192.0.2.0/24',
)
is_expected.to contain_firewall('303 add custom application 3').with(
is_expected.to_not contain_firewall('302 fwd custom cidr 1 ipv6')
is_expected.to contain_firewall('303 add custom application 3 ipv4').with(
:dport => '8081',
:proto => 'tcp',
:action => 'accept',
:state => ['NEW'],
)
is_expected.to contain_firewall('304 add custom application 4').with(
is_expected.to contain_firewall('304 add custom application 4 ipv4').with(
:sport => '1000',
:proto => 'tcp',
:action => 'accept',
:state => ['NEW'],
)
is_expected.to contain_firewall('305 add gre rule').without(:state)
is_expected.to contain_firewall('304 add custom application 4 ipv6').with(
:sport => '1000',
:proto => 'tcp',
:action => 'accept',
:state => ['NEW'],
)
is_expected.to contain_firewall('305 add gre rule ipv4').without(:state)
is_expected.to contain_firewall('306 add custom cidr 2 ipv6').with(
:proto => 'tcp',
:destination => '::1/24',
:action => 'accept',
:provider => 'ip6tables',
)
end
end