integ/config/puppet-modules/puppet-firewall-1.8.2/centos/patches/0001-Add-support-for-random-fully-flag.patch
Steven Webster 5d51ff6dd7 Enable puppet-firewall parsing of --random-fully rules
A problem may occur if puppet attempts to inject a firewall rule
while the underlying iptables/ip6tables has existing rules which
use the --random-fully flag in the NAT table.

The issue occurs because puppet-firewall first makes a call to
iptables-save/ip6tables-save to parse the existing rules
(to determine if the rule already exists).  If it finds a rule
with --random-fully, it will immediately bail out.

The current version(s) of puppet-firewall in StarlingX are old
enough that they don't have parsing logic for the --random-fully
flag that was initially supported in iptables version 1.6.2+.

Now that StarlingX uses iptables 1.8.4, we must account for the
possibility that various components (ie. kubernetes) will make
use of --random-fully rules.

This feature has been implemented upstream in the following commits:

https://github.com/puppetlabs/puppetlabs-firewall/commits/

9a4bc6a81cf0cd4a56ba458fadac830a2c4df529
0ea2b74c0b4a451a37bae8c2ff105b72481ab485

The above commits have been ported back to:

CentOS: puppet-firewall-1.8.2
Debian: puppetlabs-firewall-1.12.0

Since StarlingX does not currently build it's own version
of puppet-firewall in either CentOS or Debian, this commit
also contains the infrastructure to do so.

Testing:

Note: Since the issue is intermittent on unlock, the functional
tests were performed with a custom runtime manifest that installed
a dummy iptables/ip6tables rule when an interface was modified.
At this time, it was guaranteed that there were rules with
the --random-fully flag present.

CentOS:

Package build: PASS
Present in iso: PASS
IPv4 functional test (iptables): PASS
IPv6 functional test (ip6tables): PASS

Debian:

Package build: PASS
Present in iso: PASS
IPv4 functional test (iptables): PASS
IPv6 functional test (ip6tables): PASS

Closes-Bug: #1971900

Signed-off-by: Steven Webster <steven.webster@windriver.com>
Change-Id: I7dbb9e1b99d95df0aa5a7db7aa22c3c314253788
2022-05-10 11:17:08 -04:00

226 lines
9.7 KiB
Diff

From e4db4b965cd00d295d2dac0802fef78d1d115c17 Mon Sep 17 00:00:00 2001
From: Steven Webster <steven.webster@windriver.com>
Date: Mon, 2 May 2022 13:07:49 -0400
Subject: [PATCH] Add support for random fully flag
Enable puppet-firewall parsing of --random-fully rules
A problem may occur if puppet attempts to inject a firewall rule
while the underlying iptables/ip6tables has existing rules which
use the --random-fully flag in the NAT table.
The issue occurs because puppet-firewall first makes a call to
iptables-save/ip6tables-save to parse the existing rules
(to determine if the rule already exists). If it finds a rule
with --random-fully, it will immediately bail out.
The current version(s) of puppet-firewall in StarlingX are old
enough that they don't have parsing logic for the --random-fully
flag that was initially supported in iptables version 1.6.2+.
Now that StarlingX uses iptables 1.8.4, we must account for the
possibility that various components (ie. kubernetes) will make
use of --random-fully rules.
This feature has been implemented upstream in the following commits:
https://github.com/puppetlabs/puppetlabs-firewall/commits/
9a4bc6a81cf0cd4a56ba458fadac830a2c4df529
0ea2b74c0b4a451a37bae8c2ff105b72481ab485
This commit ports back the above commits
Signed-off-by: Steven Webster <steven.webster@windriver.com>
---
lib/puppet/provider/firewall/ip6tables.rb | 9 +++++-
lib/puppet/provider/firewall/iptables.rb | 12 +++++++-
lib/puppet/type/firewall.rb | 10 +++++++
spec/acceptance/firewall_spec.rb | 32 ++++++++++++++++++++++
spec/fixtures/ip6tables/conversion_hash.rb | 7 +++++
5 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/lib/puppet/provider/firewall/ip6tables.rb b/lib/puppet/provider/firewall/ip6tables.rb
index c8b3f64..cdb981a 100644
--- a/lib/puppet/provider/firewall/ip6tables.rb
+++ b/lib/puppet/provider/firewall/ip6tables.rb
@@ -49,6 +49,11 @@ Puppet::Type.type(:firewall).provide :ip6tables, :parent => :iptables, :source =
mark_flag = '--set-xmark'
end
+ kernelversion = Facter.value('kernelversion')
+ if (kernelversion && Puppet::Util::Package.versioncmp(kernelversion, '3.13') >= 0) &&
+ (ip6tables_version && Puppet::Util::Package.versioncmp(ip6tables_version, '1.6.2') >= 0)
+ has_feature :random_fully
+ end
def initialize(*args)
ip6tables_version = Facter.value('ip6tables_version')
@@ -109,6 +114,7 @@ Puppet::Type.type(:firewall).provide :ip6tables, :parent => :iptables, :source =
:proto => "-p",
:queue_num => "--queue-num",
:queue_bypass => "--queue-bypass",
+ :random_fully => "--random-fully",
:rdest => "--rdest",
:reap => "--reap",
:recent => "-m recent",
@@ -168,6 +174,7 @@ Puppet::Type.type(:firewall).provide :ip6tables, :parent => :iptables, :source =
:islastfrag,
:isfirstfrag,
:log_uid,
+ :random_fully,
:rsource,
:rdest,
:reap,
@@ -244,7 +251,7 @@ Puppet::Type.type(:firewall).provide :ip6tables, :parent => :iptables, :source =
:ctstate, :icmp, :hop_limit, :limit, :burst, :length, :recent, :rseconds, :reap,
:rhitcount, :rttl, :rname, :mask, :rsource, :rdest, :ipset, :string, :string_algo,
:string_from, :string_to, :jump, :clamp_mss_to_pmtu, :gateway, :todest,
- :tosource, :toports, :checksum_fill, :log_level, :log_prefix, :log_uid, :reject, :set_mss, :set_dscp, :set_dscp_class, :mss, :queue_num, :queue_bypass,
+ :tosource, :toports, :checksum_fill, :log_level, :log_prefix, :log_uid, :random_fully, :reject, :set_mss, :set_dscp, :set_dscp_class, :mss, :queue_num, :queue_bypass,
:set_mark, :match_mark, :connlimit_above, :connlimit_mask, :connmark, :time_start, :time_stop, :month_days, :week_days, :date_start, :date_stop, :time_contiguous, :kernel_timezone,
:src_cc, :dst_cc, :name]
diff --git a/lib/puppet/provider/firewall/iptables.rb b/lib/puppet/provider/firewall/iptables.rb
index b05ba43..767bdc0 100644
--- a/lib/puppet/provider/firewall/iptables.rb
+++ b/lib/puppet/provider/firewall/iptables.rb
@@ -58,6 +58,12 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
mark_flag = '--set-xmark'
end
+ kernelversion = Facter.value('kernelversion')
+ if (kernelversion && Puppet::Util::Package.versioncmp(kernelversion, '3.13') >= 0) &&
+ (iptables_version && Puppet::Util::Package.versioncmp(iptables_version, '1.6.2') >= 0)
+ has_feature :random_fully
+ end
+
@protocol = "IPv4"
@resource_map = {
@@ -102,6 +108,7 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
:proto => "-p",
:queue_num => "--queue-num",
:queue_bypass => "--queue-bypass",
+ :random_fully => "--random-fully",
:random => "--random",
:rdest => "--rdest",
:reap => "--reap",
@@ -167,6 +174,7 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
:clamp_mss_to_pmtu,
:isfragment,
:log_uid,
+ :random_fully,
:random,
:rdest,
:reap,
@@ -288,7 +296,7 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
:string_from, :string_to, :jump, :goto, :clusterip_new, :clusterip_hashmode,
:clusterip_clustermac, :clusterip_total_nodes, :clusterip_local_node, :clusterip_hash_init, :queue_num, :queue_bypass,
:nflog_group, :nflog_prefix, :nflog_range, :nflog_threshold, :clamp_mss_to_pmtu, :gateway,
- :set_mss, :set_dscp, :set_dscp_class, :todest, :tosource, :toports, :to, :checksum_fill, :random, :log_prefix,
+ :set_mss, :set_dscp, :set_dscp_class, :todest, :tosource, :toports, :to, :checksum_fill, :random_fully, :random, :log_prefix,
:log_level, :log_uid, :reject, :set_mark, :match_mark, :mss, :connlimit_above, :connlimit_mask, :connmark, :time_start, :time_stop,
:month_days, :week_days, :date_start, :date_stop, :time_contiguous, :kernel_timezone,
:src_cc, :dst_cc, :name]
@@ -418,6 +426,8 @@ Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Fir
# only replace those -f that are not followed by an l to
# distinguish between -f and the '-f' inside of --tcp-flags.
values = values.sub(/\s-f(?!l)(?=.*--comment)/, ' -f true')
+ elsif bool == :random
+ values = values.sub(/#{resource_map[bool]}(\s|$)(?!"!")/, "#{resource_map[bool]} true")
else
# append `true` to booleans that are not already negated (followed by "!")
values = values.sub(/#{resource_map[bool]}(?! "!")/, "#{resource_map[bool]} true")
diff --git a/lib/puppet/type/firewall.rb b/lib/puppet/type/firewall.rb
index 6deab2b..1637688 100644
--- a/lib/puppet/type/firewall.rb
+++ b/lib/puppet/type/firewall.rb
@@ -67,6 +67,7 @@ Puppet::Type.newtype(:firewall) do
feature :string_matching, "String matching features"
feature :queue_num, "Which NFQUEUE to send packets to"
feature :queue_bypass, "If nothing is listening on queue_num, allow packets to bypass the queue"
+ feature :random_fully, "The ability to use --random-fully flag"
# provider specific features
feature :iptables, "The provider provides iptables features."
@@ -569,6 +570,15 @@ Puppet::Type.newtype(:firewall) do
EOS
end
+ newproperty(:random_fully, :required_features => :random_fully) do
+ desc <<-EOS
+ When using a jump value of "MASQUERADE", "DNAT", "REDIRECT", or "SNAT"
+ this boolean will enable randomized port mapping.
+ EOS
+
+ newvalues(:true, :false)
+ end
+
newproperty(:random, :required_features => :dnat) do
desc <<-EOS
When using a jump value of "MASQUERADE", "DNAT", "REDIRECT", or "SNAT"
diff --git a/spec/acceptance/firewall_spec.rb b/spec/acceptance/firewall_spec.rb
index 8eee85b..617ebe5 100644
--- a/spec/acceptance/firewall_spec.rb
+++ b/spec/acceptance/firewall_spec.rb
@@ -2416,5 +2416,37 @@ describe 'firewall basics', docker: true do
end
end
+ describe 'random-fully' do
+ supports_random_fully = if os[:family] == 'redhat' && os[:release].start_with?('8')
+ true
+ elsif os[:family] == 'debian' && os[:release].start_with?('10')
+ true
+ else
+ false
+ end
+
+ before(:all) do
+ pp = <<-EOS
+ firewall { '901 - set random-fully':
+ table => 'nat',
+ chain => 'POSTROUTING',
+ jump => 'MASQUERADE',
+ random_fully => true,
+ }
+ EOS
+ apply_manifest(pp, :catch_failures => true)
+ end
+
+ it 'adds random-fully rule', if: supports_random_fully do
+ shell('iptables-save') do |r|
+ expect(r.stdout).to match(%r{-A POSTROUTING -p tcp -m comment --comment "901 - set random-fully" -j MASQUERADE --random-fully})
+ end
+ end
+ it 'adds rule without random-fully', unless: supports_random_fully do
+ shell('iptables-save') do |r|
+ expect(r.stdout).to match(%r{-A POSTROUTING -p tcp -m comment --comment "901 - set random-fully" -j MASQUERADE})
+ end
+ end
+ end
end
diff --git a/spec/fixtures/ip6tables/conversion_hash.rb b/spec/fixtures/ip6tables/conversion_hash.rb
index 8174875..ad94ac4 100644
--- a/spec/fixtures/ip6tables/conversion_hash.rb
+++ b/spec/fixtures/ip6tables/conversion_hash.rb
@@ -33,6 +33,13 @@ ARGS_TO_HASH6 = {
:sport => ['547'],
:dport => ['546'],
},
+ 'random-fully' => {
+ line: '-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -j MASQUERADE --random-fully',
+ table: 'filter',
+ provider: 'ip6tables',
+ params: {
+ random_fully: 'true',
+ },
}
}
--
2.29.2