Skip to content

Commit

Permalink
Fix rule parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
2fa committed Apr 5, 2024
1 parent 6620ad2 commit 9e84433
Show file tree
Hide file tree
Showing 2 changed files with 343 additions and 3 deletions.
9 changes: 6 additions & 3 deletions lib/puppet/provider/firewall/firewall.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Puppet::Provider::Firewall::Firewall
# Regex used to retrieve table name
$table_name_regex = %r{^\*(nat|mangle|filter|raw|rawpost|broute|security)}
# Regex used to retrieve Rules
$rules_regex = %r{(-A.*)\n}
$rules_regex = %r{^(-A.*)\n}
# Base command
$base_command = {
'IPv4' => 'iptables -t',
Expand Down Expand Up @@ -471,6 +471,9 @@ def self.get_rules(context, basic, protocols = ['IPv4', 'IPv6'])
iptables_list.scan($table_regex).each do |table|
table_name = table[0].scan($table_name_regex)[0][0]
table[0].scan($rules_regex).each do |rule|
# iptables-save escapes ' symbol in it's output for some reason which leads to an incorrect command
# We need to manually replace \' to '
rule[0].gsub!("\\'","'")

Check failure on line 476 in lib/puppet/provider/firewall/firewall.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Layout/SpaceAfterComma: Space missing after comma. (https://rubystyle.guide#spaces-operators)

Check failure on line 476 in lib/puppet/provider/firewall/firewall.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Layout/SpaceAfterComma: Space missing after comma. (https://rubystyle.guide#spaces-operators)
raw_rules = if basic
Puppet::Provider::Firewall::Firewall.rule_to_name(context, rule[0], table_name, protocol)
else
Expand All @@ -494,7 +497,7 @@ def self.rule_to_name(_context, rule, table_name, protocol)
rule_hash[:table] = table_name
rule_hash[:protocol] = protocol

name_regex = Regexp.new("#{$resource_map[:name]}\\s(?:\"([^\"]*)|([^\"\\s]*))")
name_regex = Regexp.new("#{$resource_map[:name]}\\s+(?:\"(.+?(?<!\\\\))\"|([^\"\\s]+)\\b)(?:\\s|$)")
name_value = rule.scan(name_regex)[0]
# Combine the returned values and remove and trailing or leading whitespace
rule_hash[:name] = [name_value[0], name_value[1]].join(' ').strip if name_value
Expand Down Expand Up @@ -532,7 +535,7 @@ def self.rule_to_hash(_context, rule, table_name, protocol)
# When only a single word comment is returned no quotes are given, so we must check for this as well
# First find if flag is present, add a space to ensure accuracy with the more simplistic flags; i.e. `-i`
if rule.match(Regexp.new("#{value}\\s"))
value_regex = Regexp.new("(?:(!\\s))?#{value}\\s(?:\"([^\"]*)|([^\"\\s]*))")
value_regex = Regexp.new("(?:(!\\s))?#{value}\\s+(?:\"(.+?(?<!\\\\))\"|([^\"\\s]+)\\b)(?:\\s|$)")
key_value = rule.scan(value_regex)[0]
# Combine the returned values and remove and trailing or leading whitespace
key_value[1] = [key_value[0], key_value[1], key_value[2]].join
Expand Down
337 changes: 337 additions & 0 deletions spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,337 @@
# frozen_string_literal: true

require 'spec_helper'
require 'puppet/resource_api'

ensure_module_defined('Puppet::Provider::Firewall')
require 'puppet/provider/firewall/firewall'

RSpec.describe Puppet::Provider::Firewall::Firewall do
describe 'iptables-save output parsing' do
subject(:provider) { described_class.new }

let(:type) { Puppet::Type.type('firewall') }
let(:context) { Puppet::ResourceApi::BaseContext.new(type.type_definition.definition) }

describe 'get(_context)' do
let(:iptables) do
'
# Generated by iptables-save v1.8.4 on Thu Aug 10 10:15:14 2023
*filter
:INPUT ACCEPT [62:3308]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [39:3092]
:TEST_ONE - [0:0]
:TEST-ANOTHER - [0:0]
COMMIT
-A TEST_ONE -p tcp -m comment --comment "001 custom chain test rule"
-A INPUT -p tcp -m comment --comment "002 \"double-quotes\" test rule"
-A INPUT -p tcp -m comment --comment "007 \'single-quotes\' test rule"
-A TEST-ANOTHER -p tcp -m comment --comment "003 test -A in chain name"
-A TEST_ONE -p tcp -m comment --comment "foreign rule test"
# Completed on Thu Aug 10 10:15:14 2023
# Generated by iptables-save v1.8.4 on Thu Aug 10 10:15:14 2023
*raw
:PREROUTING ACCEPT [13222:23455532]
:OUTPUT ACCEPT [12523:852730]
COMMIT
-A OUTPUT -p tcp -m comment --comment "004 test raw table rule"
# Completed on Thu Aug 10 10:15:14 2023
'
end
let(:ip6tables) do
'
# Generated by ip6tables-save v1.8.4 on Thu Aug 10 10:21:55 2023
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [13:824]
:TEST_TWO - [0:0]
COMMIT
-A OUTPUT -p tcp -m comment --comment "005 test ipv6 rule"
# Completed on Thu Aug 10 10:21:55 2023
*raw
:PREROUTING ACCEPT [13222:23455532]
:OUTPUT ACCEPT [12523:852730]
COMMIT
-A TEST_TWO -p tcp -m comment --comment "006 test ipv6 rule in different table"
# Completed on Thu Aug 10 10:21:55 2023
'
end
let(:returned_data) do
[{chain: "TEST_ONE",

Check failure on line 62 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Layout/SpaceInsideHashLiteralBraces: Space inside { missing. (https://rubystyle.guide#spaces-braces)

Check failure on line 62 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)

Check failure on line 62 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Layout/SpaceInsideHashLiteralBraces: Space inside { missing. (https://rubystyle.guide#spaces-braces)

Check failure on line 62 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)
checksum_fill: false,
clamp_mss_to_pmtu: false,
clusterip_new: false,
ensure: "present",

Check failure on line 66 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)

Check failure on line 66 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)
ipvs: false,
isfirstfrag: false,
isfragment: false,
ishasmorefrags: false,
islastfrag: false,
kernel_timezone: false,
line: "-A TEST_ONE -p tcp -m comment --comment \"001 custom chain test rule\"",

Check failure on line 73 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)

Check failure on line 73 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)
log_ip_options: false,
log_tcp_options: false,
log_tcp_sequence: false,
log_uid: false,
name: "001 custom chain test rule",

Check failure on line 78 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)

Check failure on line 78 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)
notrack: false,
physdev_is_bridged: false,
physdev_is_in: false,
physdev_is_out: false,
proto: "tcp",

Check failure on line 83 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)

Check failure on line 83 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)
protocol: "IPv4",

Check failure on line 84 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)

Check failure on line 84 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)
queue_bypass: false,
random: false,
random_fully: false,
rdest: false,
reap: false,
rsource: false,
rttl: false,
socket: false,
table: "filter",

Check failure on line 93 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)

Check failure on line 93 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. (https://rubystyle.guide#consistent-string-literals)
time_contiguous: false},

Check failure on line 94 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 7.24, Ruby Ver: 2.7)

Layout/SpaceInsideHashLiteralBraces: Space inside } missing. (https://rubystyle.guide#spaces-braces)

Check failure on line 94 in spec/unit/puppet/provider/firewall/firewall_output_parsing_spec.rb

View workflow job for this annotation

GitHub Actions / Spec / Spec tests (Puppet: ~> 8.0, Ruby Ver: 3.2)

Layout/SpaceInsideHashLiteralBraces: Space inside } missing. (https://rubystyle.guide#spaces-braces)
{chain: "INPUT",
checksum_fill: false,
clamp_mss_to_pmtu: false,
clusterip_new: false,
ensure: "present",
ipvs: false,
isfirstfrag: false,
isfragment: false,
ishasmorefrags: false,
islastfrag: false,
kernel_timezone: false,
line: "-A INPUT -p tcp -m comment --comment \"002 \\\"double-quotes\\\" test rule\"",
log_ip_options: false,
log_tcp_options: false,
log_tcp_sequence: false,
log_uid: false,
name: "002 \\\"double-quotes\\\" test rule",
notrack: false,
physdev_is_bridged: false,
physdev_is_in: false,
physdev_is_out: false,
proto: "tcp",
protocol: "IPv4",
queue_bypass: false,
random: false,
random_fully: false,
rdest: false,
reap: false,
rsource: false,
rttl: false,
socket: false,
table: "filter",
time_contiguous: false},
{chain: "INPUT",
checksum_fill: false,
clamp_mss_to_pmtu: false,
clusterip_new: false,
ensure: "present",
ipvs: false,
isfirstfrag: false,
isfragment: false,
ishasmorefrags: false,
islastfrag: false,
kernel_timezone: false,
line: "-A INPUT -p tcp -m comment --comment \"007 'single-quotes' test rule\"",
log_ip_options: false,
log_tcp_options: false,
log_tcp_sequence: false,
log_uid: false,
name: "007 'single-quotes' test rule",
notrack: false,
physdev_is_bridged: false,
physdev_is_in: false,
physdev_is_out: false,
proto: "tcp",
protocol: "IPv4",
queue_bypass: false,
random: false,
random_fully: false,
rdest: false,
reap: false,
rsource: false,
rttl: false,
socket: false,
table: "filter",
time_contiguous: false},
{chain: "TEST-ANOTHER",
checksum_fill: false,
clamp_mss_to_pmtu: false,
clusterip_new: false,
ensure: "present",
ipvs: false,
isfirstfrag: false,
isfragment: false,
ishasmorefrags: false,
islastfrag: false,
kernel_timezone: false,
line: "-A TEST-ANOTHER -p tcp -m comment --comment \"003 test -A in chain name\"",
log_ip_options: false,
log_tcp_options: false,
log_tcp_sequence: false,
log_uid: false,
name: "003 test -A in chain name",
notrack: false,
physdev_is_bridged: false,
physdev_is_in: false,
physdev_is_out: false,
proto: "tcp",
protocol: "IPv4",
queue_bypass: false,
random: false,
random_fully: false,
rdest: false,
reap: false,
rsource: false,
rttl: false,
socket: false,
table: "filter",
time_contiguous: false},
{chain: "TEST_ONE",
checksum_fill: false,
clamp_mss_to_pmtu: false,
clusterip_new: false,
ensure: "present",
ipvs: false,
isfirstfrag: false,
isfragment: false,
ishasmorefrags: false,
islastfrag: false,
kernel_timezone: false,
line: "-A TEST_ONE -p tcp -m comment --comment \"foreign rule test\"",
log_ip_options: false,
log_tcp_options: false,
log_tcp_sequence: false,
log_uid: false,
name: "9005 foreign rule test",
notrack: false,
physdev_is_bridged: false,
physdev_is_in: false,
physdev_is_out: false,
proto: "tcp",
protocol: "IPv4",
queue_bypass: false,
random: false,
random_fully: false,
rdest: false,
reap: false,
rsource: false,
rttl: false,
socket: false,
table: "filter",
time_contiguous: false},
{chain: "OUTPUT",
checksum_fill: false,
clamp_mss_to_pmtu: false,
clusterip_new: false,
ensure: "present",
ipvs: false,
isfirstfrag: false,
isfragment: false,
ishasmorefrags: false,
islastfrag: false,
kernel_timezone: false,
line: "-A OUTPUT -p tcp -m comment --comment \"004 test raw table rule\"",
log_ip_options: false,
log_tcp_options: false,
log_tcp_sequence: false,
log_uid: false,
name: "004 test raw table rule",
notrack: false,
physdev_is_bridged: false,
physdev_is_in: false,
physdev_is_out: false,
proto: "tcp",
protocol: "IPv4",
queue_bypass: false,
random: false,
random_fully: false,
rdest: false,
reap: false,
rsource: false,
rttl: false,
socket: false,
table: "raw",
time_contiguous: false},
{chain: "OUTPUT",
checksum_fill: false,
clamp_mss_to_pmtu: false,
clusterip_new: false,
ensure: "present",
ipvs: false,
isfirstfrag: false,
isfragment: false,
ishasmorefrags: false,
islastfrag: false,
kernel_timezone: false,
line: "-A OUTPUT -p tcp -m comment --comment \"005 test ipv6 rule\"",
log_ip_options: false,
log_tcp_options: false,
log_tcp_sequence: false,
log_uid: false,
name: "005 test ipv6 rule",
notrack: false,
physdev_is_bridged: false,
physdev_is_in: false,
physdev_is_out: false,
proto: "tcp",
protocol: "IPv6",
queue_bypass: false,
random: false,
random_fully: false,
rdest: false,
reap: false,
rsource: false,
rttl: false,
socket: false,
table: "filter",
time_contiguous: false},
{chain: "TEST_TWO",
checksum_fill: false,
clamp_mss_to_pmtu: false,
clusterip_new: false,
ensure: "present",
ipvs: false,
isfirstfrag: false,
isfragment: false,
ishasmorefrags: false,
islastfrag: false,
kernel_timezone: false,
line: "-A TEST_TWO -p tcp -m comment --comment \"006 test ipv6 rule in different table\"",
log_ip_options: false,
log_tcp_options: false,
log_tcp_sequence: false,
log_uid: false,
name: "006 test ipv6 rule in different table",
notrack: false,
physdev_is_bridged: false,
physdev_is_in: false,
physdev_is_out: false,
proto: "tcp",
protocol: "IPv6",
queue_bypass: false,
random: false,
random_fully: false,
rdest: false,
reap: false,
rsource: false,
rttl: false,
socket: false,
table: "raw",
time_contiguous: false}
]
end

it 'processes the resource' do
allow(Puppet::Util::Execution).to receive(:execute).with('iptables-save').and_return(iptables)
allow(Puppet::Util::Execution).to receive(:execute).with('ip6tables-save').and_return(ip6tables)

expect(provider.get(context)).to eq(returned_data)
end
end
end
end

0 comments on commit 9e84433

Please sign in to comment.