1,410 changes: 714 additions & 696 deletions REFERENCE.md

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions lib/puppet/provider/firewall/ip6tables.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
has_feature :log_ip_options
has_feature :mark
has_feature :mss
has_feature :nflog_group
has_feature :nflog_prefix
has_feature :nflog_range
has_feature :nflog_threshold
has_feature :tcp_flags
has_feature :pkttype
has_feature :ishasmorefrags
Expand Down Expand Up @@ -125,6 +129,10 @@ def self.iptables_save(*args)
name: '-m comment --comment',
mac_source: ['-m mac --mac-source', '--mac-source'],
mss: '-m tcpmss --mss',
nflog_group: '--nflog-group',
nflog_prefix: '--nflog-prefix',
nflog_range: '--nflog-range',
nflog_threshold: '--nflog-threshold',
outiface: '-o',
pkttype: '-m pkttype --pkt-type',
port: '-m multiport --ports',
Expand Down Expand Up @@ -156,6 +164,7 @@ def self.iptables_save(*args)
stat_probability: '--probability',
state: '-m state --state',
string: '-m string --string',
string_hex: '-m string --hex-string',
string_algo: '--algo',
string_from: '--from',
string_to: '--to',
Expand Down Expand Up @@ -194,6 +203,7 @@ def self.iptables_save(*args)
bytecode: '-m bpf --bytecode',
zone: '--zone',
helper: '--helper',
notrack: '--notrack',
}

# These are known booleans that do not take a value, but we want to munge
Expand All @@ -220,6 +230,7 @@ def self.iptables_save(*args)
:time_contiguous,
:kernel_timezone,
:queue_bypass,
:notrack,
]

# Properties that use "-m <ipt module name>" (with the potential to have multiple
Expand Down Expand Up @@ -290,12 +301,12 @@ def self.iptables_save(*args)
:ctstate, :ctproto, :ctorigsrc, :ctorigdst, :ctreplsrc, :ctrepldst,
:ctorigsrcport, :ctorigdstport, :ctreplsrcport, :ctrepldstport, :ctstatus, :ctexpire, :ctdir,
: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,
:rhitcount, :rttl, :rname, :mask, :rsource, :rdest, :ipset, :string, :string_hex, :string_algo,
:string_from, :string_to, :jump, :nflog_group, :nflog_prefix, :nflog_range, :nflog_threshold, :clamp_mss_to_pmtu, :gateway, :todest,
:tosource, :toports, :checksum_fill, :log_level, :log_prefix, :log_uid, :log_tcp_sequence, :log_tcp_options, :log_ip_options,
: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, :hashlimit_upto, :hashlimit_above, :hashlimit_name, :hashlimit_burst,
:hashlimit_mode, :hashlimit_srcmask, :hashlimit_dstmask, :hashlimit_htable_size,
:hashlimit_htable_max, :hashlimit_htable_expire, :hashlimit_htable_gcinterval, :bytecode, :zone, :helper, :rpfilter, :name]
:hashlimit_htable_max, :hashlimit_htable_expire, :hashlimit_htable_gcinterval, :bytecode, :zone, :helper, :rpfilter, :name, :notrack]
end
7 changes: 5 additions & 2 deletions lib/puppet/provider/firewall/iptables.rb
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@
zone: '--zone',
helper: '--helper',
cgroup: '-m cgroup --cgroup',
notrack: '--notrack',
}

# These are known booleans that do not take a value, but we want to munge
Expand Down Expand Up @@ -231,6 +232,7 @@
:clusterip_new,
:queue_bypass,
:ipvs,
:notrack,
]

# Properties that use "-m <ipt module name>" (with the potential to have multiple
Expand Down Expand Up @@ -346,8 +348,7 @@ def munge_resource_map_from_resource(resource_map_original, compare)
:month_days, :week_days, :date_start, :date_stop, :time_contiguous, :kernel_timezone,
:src_cc, :dst_cc, :hashlimit_upto, :hashlimit_above, :hashlimit_name, :hashlimit_burst,
:hashlimit_mode, :hashlimit_srcmask, :hashlimit_dstmask, :hashlimit_htable_size,
:hashlimit_htable_max, :hashlimit_htable_expire, :hashlimit_htable_gcinterval, :bytecode, :ipvs, :zone, :helper, :cgroup,
:rpfilter, :name
:hashlimit_htable_max, :hashlimit_htable_expire, :hashlimit_htable_gcinterval, :bytecode, :ipvs, :zone, :helper, :cgroup, :rpfilter, :name, :notrack
]

def insert
Expand Down Expand Up @@ -449,6 +450,8 @@ def self.rule_to_hash(line, table, counter)
# --tcp-flags takes two values; we cheat by adding " around it
# so it behaves like --comment
values = values.gsub(%r{(!\s+)?--tcp-flags (\S*) (\S*)}, '--tcp-flags "\1\2 \3"')
# --hex-string output is in quotes, need to move ! inside quotes
values = values.gsub(%r{(!\s+)?--hex-string "(\S*?)"}, '--hex-string "\1\2"')
# --match-set can have multiple values with weird iptables format
if values =~ %r{-m set (!\s+)?--match-set}
values = values.gsub(%r{(!\s+)?--match-set (\S*) (\S*)}, '--match-set \1\2 \3')
Expand Down
18 changes: 18 additions & 0 deletions lib/puppet/type/firewall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2073,6 +2073,9 @@ def should_to_s(value)
String matching feature. Matches the package against the hex pattern
given as an argument.
PUPPETCODE
munge do |value|
_value = value.delete(' ')
end
end

newproperty(:string_algo, required_features: :string_matching) do
Expand Down Expand Up @@ -2240,6 +2243,15 @@ def should_to_s(value)
PUPPETCODE
end

newproperty(:notrack, required_features: :ct_target) do
# use this parameter with latest version of iptables
desc <<-PUPPETCODE
Invoke the disable connection tracking for this packet.
This parameter can be used with iptables version >= 1.8.3
PUPPETCODE
newvalues(:true, :false)
end

autorequire(:firewallchain) do
reqs = []
protocol = nil
Expand Down Expand Up @@ -2464,6 +2476,12 @@ def should_to_s(value)
end
end

if value(:notrack)
unless value(:jump).to_s == 'CT'
raise 'Parameter notrack requires jump => CT'
end
end

if value(:jump).to_s == 'CT'
unless value(:table).to_s =~ %r{raw}
raise 'Parameter jump => CT only applies to table => raw'
Expand Down
7 changes: 4 additions & 3 deletions metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "puppetlabs-firewall",
"version": "2.4.0",
"version": "2.5.0",
"author": "puppetlabs",
"summary": "Manages Firewalls such as iptables",
"license": "Apache-2.0",
Expand Down Expand Up @@ -67,7 +67,8 @@
"operatingsystemrelease": [
"14.04",
"16.04",
"18.04"
"18.04",
"20.04"
]
}
],
Expand All @@ -78,6 +79,6 @@
}
],
"template-url": "https://github.com/puppetlabs/pdk-templates#master",
"template-ref": "1.17.0-0-gd3a4319",
"template-ref": "heads/master-0-g88b05c7",
"pdk-version": "1.17.0"
}
14 changes: 10 additions & 4 deletions provision.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,21 @@ vagrant:
travis_deb:
provisioner: docker
images: ['litmusimage/debian:8', 'litmusimage/debian:9'] # 'litmusimage/debian10' removed due to failures present only on Docker
travis_ub:
travis_ub_5:
provisioner: docker
images: ['litmusimage/ubuntu:14.04', 'litmusimage/ubuntu:16.04', 'litmusimage/ubuntu:18.04']
travis_ub_6:
provisioner: docker
images: ['litmusimage/ubuntu:14.04', 'litmusimage/ubuntu:16.04', 'litmusimage/ubuntu:18.04', 'litmusimage/ubuntu:20.04']
travis_el6:
provisioner: docker
images: []
travis_el7:
provisioner: docker
images: ['litmusimage/centos:7']
release_checks:
provisioner: vmpooler
images: ['redhat-5-x86_64', 'redhat-6-x86_64', 'redhat-7-x86_64', 'redhat-8-x86_64', 'centos-5-x86_64', 'centos-6-x86_64', 'centos-7-x86_64', 'centos-8-x86_64', 'oracle-6-x86_64', 'scientific-6-x86_64', 'scientific-7-x86_64', 'debian-8-x86_64', 'debian-9-x86_64', 'debian-10-x86_64', 'sles-11-x86_64', 'sles-12-x86_64', 'sles-15-x86_64', 'ubuntu-1404-x86_64', 'ubuntu-1604-x86_64', 'ubuntu-1804-x86_64']
release_checks_5:
provisioner: abs
images: ['redhat-5-x86_64', 'redhat-6-x86_64', 'redhat-7-x86_64', 'redhat-8-x86_64', 'centos-5-x86_64', 'centos-6-x86_64', 'centos-7-x86_64', 'centos-8-x86_64', 'oracle-6-x86_64', 'scientific-6-x86_64', 'scientific-7-x86_64', 'debian-8-x86_64', 'debian-9-x86_64', 'debian-10-x86_64', 'sles-12-x86_64', 'sles-15-x86_64', 'ubuntu-1404-x86_64', 'ubuntu-1604-x86_64', 'ubuntu-1804-x86_64']
release_checks_6:
provisioner: abs
images: ['redhat-5-x86_64', 'redhat-6-x86_64', 'redhat-7-x86_64', 'redhat-8-x86_64', 'centos-5-x86_64', 'centos-6-x86_64', 'centos-7-x86_64', 'centos-8-x86_64', 'oracle-6-x86_64', 'scientific-6-x86_64', 'scientific-7-x86_64', 'debian-8-x86_64', 'debian-9-x86_64', 'debian-10-x86_64', 'sles-12-x86_64', 'sles-15-x86_64', 'ubuntu-1404-x86_64', 'ubuntu-1604-x86_64', 'ubuntu-1804-x86_64', 'ubuntu-2004-x86_64']
15 changes: 15 additions & 0 deletions spec/acceptance/firewall_attributes_happy_path_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@

describe 'attributes test' do
before(:all) do
notrack_manifest = "jump => 'CT', notrack => true"
notrack_manifest = "jump => 'NOTRACK'" if os[:family] == 'redhat' && [5, 6].include?(os[:release].to_i)

pp = <<-PUPPETCODE
class { '::firewall': }
firewall { '004 - log_level and log_prefix':
Expand Down Expand Up @@ -347,6 +350,13 @@ class { '::firewall': }
chain => 'OUTPUT',
table => 'mangle',
}
firewall { '004 do not track UDP connections to port 53':
chain => 'PREROUTING',
table => 'raw',
proto => 'udp',
dport => 53,
#{notrack_manifest}
}
PUPPETCODE
idempotent_apply(pp)
end
Expand Down Expand Up @@ -487,5 +497,10 @@ class { '::firewall': }
it 'jump is set' do
expect(result.stdout).to match(%r{-A INPUT -p tcp -m comment --comment "567 - jump" -j TEST})
end
it 'notrack is set' do
notrack_rule = '-A PREROUTING -p udp -m multiport --dports 53 -m comment --comment "004 do not track UDP connections to port 53" -j CT --notrack'
notrack_rule = '-A PREROUTING -p udp -m multiport --dports 53 -m comment --comment "004 do not track UDP connections to port 53" -j NOTRACK' if os[:family] == 'redhat' && [5, 6].include?(os[:release].to_i)
expect(result.stdout).to match(%r{#{notrack_rule}})
end
end
end
12 changes: 12 additions & 0 deletions spec/acceptance/firewall_attributes_ipv6_happy_path_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,15 @@ class { '::firewall': }
proto => all,
provider => 'ip6tables',
}
firewall { '812 - hex_string':
chain => 'INPUT',
proto => 'tcp',
string_hex => '|f4 6d 04 25 b2 02 00 0a|',
string_algo => 'kmp',
string_to => '65535',
action => accept,
provider => 'ip6tables',
}
PUPPETCODE
idempotent_apply(pp)
end
Expand Down Expand Up @@ -365,5 +374,8 @@ class { '::firewall': }
expect(result.stdout).to match(regex)
end
end
it 'checks hex_string value' do
expect(result.stdout).to match(%r{-A INPUT -p tcp -m string --hex-string "|f46d0425b202000a|" --algo kmp --to 65535 -m comment --comment "812 - hex_string" -j ACCEPT})
end
end
end
19 changes: 19 additions & 0 deletions spec/fixtures/ip6tables/conversion_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@
dport: ['546'],
},
},
'hexstring_matching_1' => {
line: '-A INPUT -m string --hex-string "|0000FF0001|" --algo bm',
table: 'filter',
params: {
string_hex: '|0000FF0001|',
string_algo: 'bm',
},
}
}.freeze

# This hash is for testing converting a hash to an argument line.
Expand Down Expand Up @@ -114,4 +122,15 @@
},
args: ['-t', :filter, '-p', :tcp, '-m', 'hl', '--hl-eq', 255, '-m', 'comment', '--comment', '100 hop limit'],
},
'nflog' => {
params: {
name: '100 nflog',
jump: 'NFLOG',
nflog_group: '1',
nflog_prefix: 'myprefix',
provider: 'ip6tables',
table: 'filter',
},
args: ['-t', :filter, '-p', :tcp, '-j', 'NFLOG', '--nflog-group', 1, '--nflog-prefix', 'myprefix', '-m', 'comment', '--comment', '100 nflog'],
},
}.freeze
11 changes: 11 additions & 0 deletions spec/fixtures/iptables/conversion_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,17 @@
cgroup: '0x100001',
},
},
'notrack' => {
line: '-A PREROUTING -p udp -m multiport --dports 53 -m comment --comment "004 do not track UDP connections to port 53" -j CT --notrack',
table: 'raw',
params: {
chain: 'PREROUTING',
proto: 'udp',
dport: ['53'],
jump: 'CT',
notrack: true
}
},
}.freeze

# This hash is for testing converting a hash to an argument line.
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
# set to strictest setting for testing
# by default Puppet runs at warning level
Puppet.settings[:strict] = :warning
Puppet.settings[:strict_variables] = true
end
c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT']
c.after(:suite) do
Expand Down
80 changes: 3 additions & 77 deletions spec/spec_helper_acceptance.rb
Original file line number Diff line number Diff line change
@@ -1,80 +1,6 @@
require 'serverspec'
# frozen_string_literal: true

require 'puppet_litmus'
require 'spec_helper_acceptance_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_acceptance_local.rb'))
include PuppetLitmus

if ENV['TARGET_HOST'].nil? || ENV['TARGET_HOST'] == 'localhost'
puts 'Running tests against this machine !'
if Gem.win_platform?
set :backend, :cmd
else
set :backend, :exec
end
else
# load inventory
inventory_hash = inventory_hash_from_inventory_file
node_config = config_from_node(inventory_hash, ENV['TARGET_HOST'])

if target_in_group(inventory_hash, ENV['TARGET_HOST'], 'docker_nodes')
host = ENV['TARGET_HOST']
set :backend, :docker
set :docker_container, host
elsif target_in_group(inventory_hash, ENV['TARGET_HOST'], 'ssh_nodes')
set :backend, :ssh
options = Net::SSH::Config.for(host)
options[:user] = node_config.dig('ssh', 'user') unless node_config.dig('ssh', 'user').nil?
options[:port] = node_config.dig('ssh', 'port') unless node_config.dig('ssh', 'port').nil?
options[:keys] = node_config.dig('ssh', 'private-key') unless node_config.dig('ssh', 'private-key').nil?
options[:password] = node_config.dig('ssh', 'password') unless node_config.dig('ssh', 'password').nil?
# Support both net-ssh 4 and 5.
# rubocop:disable Metrics/BlockNesting
options[:verify_host_key] = if node_config.dig('ssh', 'host-key-check').nil?
# Fall back to SSH behavior. This variable will only be set in net-ssh 5.3+.
if @strict_host_key_checking.nil? || @strict_host_key_checking
Net::SSH::Verifiers::Always.new
else
# SSH's behavior with StrictHostKeyChecking=no: adds new keys to known_hosts.
# If known_hosts points to /dev/null, then equivalent to :never where it
# accepts any key beacuse they're all new.
Net::SSH::Verifiers::AcceptNewOrLocalTunnel.new
end
elsif node_config.dig('ssh', 'host-key-check')
if defined?(Net::SSH::Verifiers::Always)
Net::SSH::Verifiers::Always.new
else
Net::SSH::Verifiers::Secure.new
end
elsif defined?(Net::SSH::Verifiers::Never)
Net::SSH::Verifiers::Never.new
else
Net::SSH::Verifiers::Null.new
end

host = if ENV['TARGET_HOST'].include?(':')
ENV['TARGET_HOST'].split(':').first
else
ENV['TARGET_HOST']
end
set :host, options[:host_name] || host
set :ssh_options, options
set :request_pty, true
elsif target_in_group(inventory_hash, ENV['TARGET_HOST'], 'winrm_nodes')
require 'winrm'

set :backend, :winrm
set :os, family: 'windows'
user = node_config.dig('winrm', 'user') unless node_config.dig('winrm', 'user').nil?
pass = node_config.dig('winrm', 'password') unless node_config.dig('winrm', 'password').nil?
endpoint = "http://#{ENV['TARGET_HOST']}:5985/wsman"

opts = {
user: user,
password: pass,
endpoint: endpoint,
operation_timeout: 300,
}

winrm = WinRM::Connection.new opts
Specinfra.configuration.winrm = winrm
end
end
PuppetLitmus.configure!
31 changes: 31 additions & 0 deletions spec/spec_helper_acceptance_local.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
require 'singleton'

class LitmusHelper
include Singleton
include PuppetLitmus
end

def iptables_flush_all_tables
['filter', 'nat', 'mangle', 'raw'].each do |t|
expect(run_shell("iptables -t #{t} -F").stderr).to eq('')
Expand Down Expand Up @@ -31,3 +38,27 @@ def update_profile_file
run_shell("sed -i '/mesg n/c\\test -t 0 && mesg n || true' ~/.profile")
run_shell("sed -i '/mesg n || true/c\\test -t 0 && mesg n || true' ~/.profile")
end

RSpec.configure do |c|
c.before :suite do
if os[:family] == 'debian' && os[:release].to_i == 10
pp = <<-PUPPETCODE
package { 'net-tools':
ensure => 'latest',
}
package { 'iptables':
ensure => 'latest',
}
PUPPETCODE
LitmusHelper.instance.apply_manifest(pp)
LitmusHelper.instance.run_shell('update-alternatives --set iptables /usr/sbin/iptables-legacy', expect_failures: true)
LitmusHelper.instance.run_shell('update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy', expect_failures: true)
end
pp = <<-PUPPETCODE
package { 'conntrack-tools':
ensure => 'latest',
}
PUPPETCODE
LitmusHelper.instance.apply_manifest(pp)
end
end