Skip to content

Commit

Permalink
Provide a mechanism to flush un-managed rules
Browse files Browse the repository at this point in the history
This patchset adds a new parameter to the main class to activate a
mechanism that will invoke `systemctl reload nftables` during the
Puppet run if manual changes to the in-memory ruleset are detected.

To accomplish this, the systemd unit in charge of nftables is
configured to write a hash of the in-memory ruleset right after
starting/reloading. During the Puppet run, the hash of the current
rule set is compared to the one previously stored. If the hash differ
then `systemctl reload nftables` is executed to flush manual changes.

Fixes #113
  • Loading branch information
nbarrientos committed Dec 8, 2021
1 parent 9ea14bc commit abd95ac
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 3 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ Initially puppet deploys all configuration to
If and only if successful the configuration will be copied to
the real locations before the service is reloaded.

## Un-managed rules

Rules added manually by the administrator to the in-memory ruleset
will be left untouched. However, `nftables::allow_unmanaged_rules` can
be set to `false` to revert this behaviour and force a reload of the
ruleset during the Puppet run if non-managed changes are detected.

## Basic types

### nftables::config
Expand Down
4 changes: 4 additions & 0 deletions files/systemd/nft-hash-ruleset.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

umask 0377
/sbin/nft -s list ruleset | /usr/bin/sha1sum > $1
31 changes: 29 additions & 2 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,18 @@
# @param nat
# Add default tables and chains to process NAT traffic.
#
# @param allow_unmanaged_changes
# Allows to have in-memory rules that are not declared in Puppet
# code. Setting this to true activates a check that reloads nftables
# if the rules in memory have been modified outwith Puppet.
#
# @param nat_table_name
# The name of the 'nat' table.
#
# @param inmem_rules_hash_file
# The name of the file where the hash of the in-memory rules
# will be stored.
#
# @param sets
# Allows sourcing set definitions directly from Hiera.
#
Expand Down Expand Up @@ -99,10 +108,12 @@
Boolean $fwd_conntrack = false,
Boolean $inet_filter = true,
Boolean $nat = true,
Boolean $allow_unmanaged_rules = true,
Hash $rules = {},
Hash $sets = {},
String $log_prefix = '[nftables] %<chain>s %<comment>s',
String[1] $nat_table_name = 'nat',
Stdlib::Unixpath $inmem_rules_hash_file = '/var/cache/nft-memhash',
Variant[Boolean[false], String] $log_limit = '3/minute burst 5 packets',
Variant[Boolean[false], Pattern[/icmp(v6|x)? type .+|tcp reset/]] $reject_with = 'icmpx type port-unreachable',
Variant[Boolean[false], Enum['mask']] $firewalld_enable = 'mask',
Expand Down Expand Up @@ -164,10 +175,26 @@
restart => '/usr/bin/systemctl reload nftables',
}

systemd::dropin_file { 'puppet_nft.conf':
unless $allow_unmanaged_rules {
exec { 'Reload nftables if there are un-managed rules':
command => '/usr/bin/systemctl reload nftables',
refreshonly => false,
unless => "/usr/bin/test -s ${inmem_rules_hash_file} -a \"$(nft -s list ruleset | sha1sum)\" = \"$(cat ${inmem_rules_hash_file})\"",
require => Service['nftables'],
}
}

file { '/usr/local/sbin/nft-hash-ruleset.sh' :
ensure => file,
mode => '0755',
content => file('nftables/systemd/nft-hash-ruleset.sh'),
}
-> systemd::dropin_file { 'puppet_nft.conf':
ensure => present,
unit => 'nftables.service',
content => file('nftables/systemd/puppet_nft.conf'),
content => epp('nftables/systemd/puppet_nft.conf.epp', {
'hash_file' => $inmem_rules_hash_file,
}),
notify => Service['nftables'],
}

Expand Down
25 changes: 25 additions & 0 deletions spec/classes/nftables_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@
is_expected.to contain_systemd__dropin_file('puppet_nft.conf').with(
content: %r{^ExecReload=/sbin/nft -I /etc/nftables/puppet -f /etc/sysconfig/nftables.conf$}
)
is_expected.to contain_systemd__dropin_file('puppet_nft.conf').with(
content: %r{^ExecReload=/bin/bash /usr/local/sbin/nft-hash-ruleset.sh /var/cache/nft-memhash$}
)
is_expected.to contain_systemd__dropin_file('puppet_nft.conf').with(
content: %r{^ExecStartPost=/bin/bash /usr/local/sbin/nft-hash-ruleset.sh /var/cache/nft-memhash$}
)
}

it {
Expand All @@ -91,6 +97,8 @@
it { is_expected.to contain_class('nftables::rules::out::chrony') }
it { is_expected.not_to contain_class('nftables::rules::out::all') }
it { is_expected.not_to contain_nftables__rule('default_out-all') }
it { is_expected.not_to contain_exec('Reload nftables if there are un-managed rules') }
it { is_expected.to contain_file('/usr/local/sbin/nft-hash-ruleset.sh') }

context 'with out_all set true' do
let(:params) do
Expand Down Expand Up @@ -203,6 +211,23 @@
it { is_expected.to have_nftables__set_resource_count(0) }
end

context 'with not allowing un-managed changes' do
let(:params) do
{
'allow_unmanaged_rules' => false,
'inmem_rules_hash_file' => '/foo/bar',
}
end

it {
is_expected.to contain_exec('Reload nftables if there are un-managed rules').with(
command: '/usr/bin/systemctl reload nftables',
refreshonly: false,
unless: '/usr/bin/test -s /foo/bar -a "$(nft -s list ruleset | sha1sum)" = "$(cat /foo/bar)"'
)
}
end

context 'with with noflush_tables parameter' do
let(:params) do
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<%- |
Stdlib::Unixpath $hash_file,
|-%>
# Puppet Deployed
[Service]
ExecStart=
ExecStart=/sbin/nft -I /etc/nftables/puppet -f /etc/sysconfig/nftables.conf
ExecStartPost=/bin/bash /usr/local/sbin/nft-hash-ruleset.sh <%= $hash_file %>
ExecReload=
ExecReload=/sbin/nft -I /etc/nftables/puppet -f /etc/sysconfig/nftables.conf

ExecReload=/bin/bash /usr/local/sbin/nft-hash-ruleset.sh <%= $hash_file -%>

0 comments on commit abd95ac

Please sign in to comment.