From 708b39cf03bf862240cf47b41e76622fe8cf69d1 Mon Sep 17 00:00:00 2001 From: Matthias Pausch Date: Tue, 15 Feb 2022 22:29:28 +0100 Subject: [PATCH 1/9] Add resources and recipes for configuring firewall rules. This is an alternative implementation of https://github.com/sous-chefs/firewall The accumulator pattern is used, to collect firewall_rule resources across various recipes, which are then combined by the firewall resource into a single configuration file. The firewall_rule resources are converted to nftables-rules by the library sys_helpers_firewall. The firewall_rule resources are supposed to be largely compatible with those of the firewall cookbook from the sous-chefs. --- .gitlab-ci.yml | 1 + .kitchen.yml | 8 + Berksfile | 4 + CHANGELOG.md | 9 + attributes/firewall.rb | 23 +++ documents/firewall.md | 81 ++++++++ libraries/sys_helpers_firewall.rb | 175 ++++++++++++++++++ metadata.rb | 2 +- recipes/firewall.rb | 58 ++++++ recipes/nftables.rb | 30 +-- resources/firewall.rb | 123 ++++++++++++ resources/firewall_rule.rb | 110 +++++++++++ .../cookbooks/firewall-test/metadata.rb | 4 + .../firewall-test/recipes/default.rb | 135 ++++++++++++++ .../sys_firewall/serverspec/Gemfile | 10 + .../serverspec/localhost/firewall_spec.rb | 66 +++++++ .../sys_firewall/serverspec/spec_helper.rb | 3 + test/unit/recipes/firewall_spec.rb | 54 ++++++ 18 files changed, 866 insertions(+), 30 deletions(-) create mode 100644 attributes/firewall.rb create mode 100644 documents/firewall.md create mode 100644 libraries/sys_helpers_firewall.rb create mode 100644 recipes/firewall.rb create mode 100644 resources/firewall.rb create mode 100644 resources/firewall_rule.rb create mode 100644 test/fixtures/cookbooks/firewall-test/metadata.rb create mode 100644 test/fixtures/cookbooks/firewall-test/recipes/default.rb create mode 100644 test/integration/sys_firewall/serverspec/Gemfile create mode 100644 test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb create mode 100644 test/integration/sys_firewall/serverspec/spec_helper.rb create mode 100644 test/unit/recipes/firewall_spec.rb diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 81c7a25..ce937bb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,6 +42,7 @@ kitchen: - banner - chef - ferm + - firewall - linuxlogo - mail - nsswitch diff --git a/.kitchen.yml b/.kitchen.yml index 8bf9f7d..39c1cf2 100644 --- a/.kitchen.yml +++ b/.kitchen.yml @@ -169,6 +169,14 @@ suites: - 'policy ACCEPT;' FORWARD: - 'policy DROP;' + - name: sys_firewall + run_list: + - recipe[firewall-test::default] + attributes: + sys: + firewall: + manage: true + disable: false - name: sys_linuxlogo run_list: - recipe[sys::linuxlogo] diff --git a/Berksfile b/Berksfile index c521dfd..7346c95 100644 --- a/Berksfile +++ b/Berksfile @@ -8,3 +8,7 @@ cookbook 'fixtures', path: 'test/unit/fixtures', group: :chefspec # avoid https://github.com/sous-chefs/line/issues/92 # by pulling directly from github: cookbook 'line', github: 'sous-chefs/line', tag: "v0.6.3" + +group :integration do + cookbook 'firewall-test', path: 'test/fixtures/cookbooks/firewall-test' +end diff --git a/CHANGELOG.md b/CHANGELOG.md index 39cd221..496bf24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased +## [1.64.0] +### Added +- New recipe [`sys::firewall`](recipes/firewall.rb) +- New resource [`firewall`](resources/firewall_rule.rb) +- New resource [`firewall_rule`](resources/firewall_rule.rb) +- New attributes for configuring [`firewall`](attributes/firewall.rb) +- [`Documentation`](documents/firewall.md) +- Tests + ### Changed - Updated [documentation for `sys::pam`](documents/pam.md) - Send chef-client output to logfile in systemd-timer mode (!39) diff --git a/attributes/firewall.rb b/attributes/firewall.rb new file mode 100644 index 0000000..326db51 --- /dev/null +++ b/attributes/firewall.rb @@ -0,0 +1,23 @@ +default['sys']['firewall']['manage'] = false +default['sys']['firewall']['disable'] = true +default['sys']['firewall']['allow_ssh'] = true +default['sys']['firewall']['allow_loopback'] = true +default['sys']['firewall']['allow_icmp'] = true +default['sys']['firewall']['allow_established'] = true +default['sys']['firewall']['defaults']['policy'] = { + 'input' => 'drop', + 'forward' => 'drop', + 'output' => 'accept', +} +default['sys']['firewall']['defaults']['ruleset'] = { + 'add table inet filter' => 1, + 'add table ip6 nat' => 1, + 'add table ip nat' => 1, + "add chain inet filter INPUT { type filter hook input priority 0 ; policy #{node['sys']['firewall']['defaults']['policy']['input']}; }" => 2, + "add chain inet filter OUTPUT { type filter hook output priority 0 ; policy #{node['sys']['firewall']['defaults']['policy']['output']}; }" => 2, + "add chain inet filter FOWARD { type filter hook forward priority 0 ; policy #{node['sys']['firewall']['defaults']['policy']['forward']}; }" => 2, + 'add chain ip nat POSTROUTING { type nat hook postrouting priority 100 ;}' => 2, + 'add chain ip nat PREROUTING { type nat hook prerouting priority -100 ;}' => 2, + 'add chain ip6 nat POSTROUTING { type nat hook postrouting priority 100 ;}' => 2, + 'add chain ip6 nat PREROUTING { type nat hook prerouting priority -100 ;}' => 2, +} diff --git a/documents/firewall.md b/documents/firewall.md new file mode 100644 index 0000000..d479816 --- /dev/null +++ b/documents/firewall.md @@ -0,0 +1,81 @@ +Use the firewall recipe to configure nftables. + +↪ `attributes/firewall.rb` +↪ `recipes/firewall.rb` +↪ `resources/firewall.rb` +↪ `resources/firewall_rule.rb` +↪ `libraries/sys_helpers_firewall.rb` +↪ `documents/firewall.rb` +↪ `test/unit/recipies/firewall_spec.rb` + +# Examples + +## Disable nftables + +Use attributes in `node['sys']['firewall']`, e.g. to switch off nftables: + + node['sys']['firewall']['manage'] = true # To manage nftables at all + node['sys']['firewall']['disable'] = true # To disable nftables + +## Default rules + +If you want to use `sys::firewall`, just include the recipe and set +`node['sys']['firewall']['manage'] = true`. Adjust the follwing +self-explaining attributes to your needs. They all default to true: + +↪ `node['sys']['firewall']['allow_established']` +↪ `node['sys']['firewall']['allow_icmp']` +↪ `node['sys']['firewall']['allow_loopback']` +↪ `node['sys']['firewall']['allow_ssh']` + +This will give you the following default rules: + + table inet filter { + chain INPUT { + type filter hook input priority 0; policy drop; + iif "lo" accept comment "allow loopback" + icmp type echo-request accept comment "allow icmp" + tcp dport ssh accept comment "allow world to ssh" + ct state established,related accept comment "established" + } + + chain OUTPUT { + type filter hook output priority 0; policy accept; + } + + chain FOWARD { + type filter hook forward priority 0; policy drop; + } + } + table ip6 nat { + chain POSTROUTING { + type nat hook postrouting priority 100; policy accept; + } + + chain PREROUTING { + type nat hook prerouting priority -100; policy accept; + } + } + table ip nat { + chain POSTROUTING { + type nat hook postrouting priority 100; policy accept; + } + + chain PREROUTING { + type nat hook prerouting priority -100; policy accept; + } + } + + +## Using `sys::firewall` from other recipes + +Depend on the `sys`-cookbook in the `metadata.rb` and include +`sys::firewall` in the runlist. If access via ports `443` and `80` +should be possible, write a resource like this: + + firewall_rule 'allow http(s)` do + port [80,443] + end + +For further examples see the recipe +[sys::firewall](recipes/firewall.rb) and the recipe [firewall-test::default](test/fixtures/cookbooks/firewall-test/recipes/default.rb). diff --git a/libraries/sys_helpers_firewall.rb b/libraries/sys_helpers_firewall.rb new file mode 100644 index 0000000..bf9f907 --- /dev/null +++ b/libraries/sys_helpers_firewall.rb @@ -0,0 +1,175 @@ +# +# Author:: Matthias Pausch () +# Cookbook Name:: sys +# Library:: Helpers::Firewall +# +# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +# +# Authors: +# Matthias Pausch (m.pausch@gsi.de) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This code is an adjustment of https://github.com/sous-chefs/firewall +# + +module Sys + module Helpers + module Firewall + require 'ipaddr' + include Chef::Mixin::ShellOut + + def dport(new_resource) + new_resource.dest_port || new_resource.port + end + + def sport(new_resource) + new_resource.source_port + end + + def valid_ips?(ips) + Array(ips).inject(false) do |a, ip| + a || !!IPAddr.new(ip) + end + end + + def port_to_s(p) + if p.is_a?(String) + p + elsif p && p.is_a?(Integer) + p.to_s + elsif p && p.is_a?(Array) + p_strings = p.map { |o| port_to_s(o) } + "{#{p_strings.sort.join(',')}}" + elsif p && p.is_a?(Range) + "#{p.first}-#{p.last}" + end + end + + def disabled? + node['sys']['firewall']['disable'] + end + + def managed? + node['sys']['firewall']['manage'] + end + + def build_rule_file(rules) + contents = [] + sorted_values = rules.values.sort.uniq + sorted_values.each do |sorted_value| + contents << "# position #{sorted_value}" + contents << rules.select { |_,v| v == sorted_value }.keys.join("\n") + end + "#{contents.join("\n")}\n" + end + + unless defined? CHAIN + CHAIN = { + in: 'INPUT', + out: 'OUTPUT', + pre: 'PREROUTING', + post: 'POSTROUTING', + forward: 'FORWARD', + }.freeze + end + + unless defined? TARGET + TARGET = { + accept: 'accept', + allow: 'accept', + deny: 'drop', + drop: 'drop', + log: 'log prefix "nftables:" group 0', + masquerade: 'masquerade', + redirect: 'redirect', + reject: 'reject', + }.freeze + end + + def build_firewall_rule(rule_resource) + return rule_resource.raw.strip if rule_resource.raw + + ip_family = rule_resource.family + table = if [:pre, :post].include?(rule_resource.direction) + 'nat' + else + 'filter' + end + firewall_rule = if table == 'nat' + "add rule #{ip_family} #{table} " + else + "add rule inet #{table} " + end + firewall_rule << CHAIN.fetch(rule_resource.direction.to_sym) + firewall_rule << ' ' + firewall_rule << "iif #{rule_resource.interface} " if rule_resource.interface + firewall_rule << "oif #{rule_resource.dest_interface} " if rule_resource.dest_interface + + if rule_resource.source + source_ips = Array(rule_resource.source).map { |ip| IPAddr.new(ip) } + source_ips.delete(IPAddr.new('0.0.0.0/0')) + source_ips.delete(IPAddr.new('::/128')) + # Only works on buster and newer. In older debian-versions + # there is no prefix-method for IPv4-addresses. + addrs = source_ips.map { |ip| "#{ip}/#{ip.prefix}" } + if addrs.length == 1 + firewall_rule << "#{ip_family} saddr #{addrs.first} " + elsif addrs.length > 1 + firewall_rule << "#{ip_family} saddr {#{addrs.join(',')}} " + end + end + firewall_rule << "#{ip_family} daddr #{rule_resource.destination} " if rule_resource.destination + + case rule_resource.protocol + when :icmp + firewall_rule << 'icmp type echo-request ' + when :'ipv6-icmp', :icmpv6 + firewall_rule << 'icmpv6 type { echo-request, nd-router-solicit, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } ' + when :tcp, :udp + firewall_rule << "#{rule_resource.protocol} sport #{port_to_s(sport(rule_resource))} " if sport(rule_resource) + firewall_rule << "#{rule_resource.protocol} dport #{port_to_s(dport(rule_resource))} " if dport(rule_resource) + when :esp, :ah + firewall_rule << "#{ip_family} #{ip_family == :ip6 ? 'nexthdr' : 'protocol'} #{rule_resource.protocol} " + + # nothing to do default :ipv6, :none + end + + firewall_rule << "ct state #{Array(rule_resource.stateful).join(',').downcase} " if rule_resource.stateful + firewall_rule << "#{TARGET[rule_resource.command.to_sym]} " + firewall_rule << " to #{rule_resource.redirect_port} " if rule_resource.command == :redirect + firewall_rule << "comment \"#{rule_resource.description}\" " if rule_resource.include_comment + firewall_rule.strip! + firewall_rule + end + + def log_nftables + shell_out!('nft -n list ruleset') + rescue Mixlib::ShellOut::ShellCommandFailed + Chef::Log.info('log_nftables failed!') + rescue Mixlib::ShellOut::CommandTimeout + Chef::Log.info('log_nftables timed out!') + end + + def default_ruleset(current_node) + current_node['sys']['firewall']['defaults']['ruleset'].to_h + end + + def ensure_default_rules_exist(current_node, new_resource) + input = new_resource.rules || {} + input.merge!(default_ruleset(current_node).to_h) + new_resource.rules(input) + end + end + end +end diff --git a/metadata.rb b/metadata.rb index b773606..2fe692a 100644 --- a/metadata.rb +++ b/metadata.rb @@ -16,4 +16,4 @@ supports 'debian' depends 'line', '< 1.0' depends 'chef-vault' -version '1.63.1' +version '1.64.0' diff --git a/recipes/firewall.rb b/recipes/firewall.rb new file mode 100644 index 0000000..c22b215 --- /dev/null +++ b/recipes/firewall.rb @@ -0,0 +1,58 @@ +# +# Author:: Matthias Pausch () +# Cookbook Name:: sys +# Recipe:: firewall +# +# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +# +# Authors: +# Matthias Pausch (m.pausch@gsi.de) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This code is an adjustment of https://github.com/sous-chefs/firewall +# + +if node['sys']['firewall']['manage'] + fw_action = node['sys']['firewall']['disable'] ? :disable : :install + firewall 'default' do + action fw_action + end + + firewall_rule 'allow loopback' do + interface 'lo' + protocol :none + command :allow + only_if { node['sys']['firewall']['allow_loopback'] } + end + + firewall_rule 'allow icmp' do + protocol :icmp + command :allow + only_if { node['sys']['firewall']['allow_icmp'] } + end + + firewall_rule 'allow world to ssh' do + port 22 + source '0.0.0.0/0' + only_if { node['sys']['firewall']['allow_ssh'] } + end + + # allow established connections + firewall_rule 'established' do + stateful [:related, :established] + protocol :none # explicitly don't specify protocol + command :allow + only_if { node['sys']['firewall']['allow_established'] } + end +end diff --git a/recipes/nftables.rb b/recipes/nftables.rb index bb5d279..bffa081 100644 --- a/recipes/nftables.rb +++ b/recipes/nftables.rb @@ -9,34 +9,6 @@ unless node['sys']['nftables'].empty? if node['debian'] && node['debian']['codename'] && node['debian']['codename'].eql?('stretch') - package 'nftables' do - action :upgrade - end - - # Future version will not include the init-script, cf. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=804648 - file '/etc/init.d/nftables' do - action :delete - end - - nftables_serviceaction = :enable - nftables_action = :start - - unless node['sys']['nftables']['active'] - nftables_serviceaction = :disable - nftables_action = :stop - end - - template '/etc/nftables.conf' do - source 'etc_nftables.conf.erb' - mode '0644' - owner 'root' - group 'adm' - notifies :reload, 'service[nftables]', :immediately - end - - service 'nftables' do - supports :reload => true, :restart => true - action [ nftables_action, nftables_serviceaction ] - end + end end diff --git a/resources/firewall.rb b/resources/firewall.rb new file mode 100644 index 0000000..608a1a1 --- /dev/null +++ b/resources/firewall.rb @@ -0,0 +1,123 @@ +# +# Author:: Matthias Pausch () +# Cookbook Name:: sys +# Resource:: firewall +# +# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +# +# Authors: +# Matthias Pausch (m.pausch@gsi.de) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This code is an adjustment of https://github.com/sous-chefs/firewall +# + +if Gem::Requirement.new('>= 12.5').satisfied_by?(Gem::Version.new(Chef::VERSION)) + + action_class do + + include Sys::Helpers::Firewall + + def lookup_or_create_service(name) + begin + nftables_service = Chef.run_context.resource_collection.find(service: name) + rescue + nftables_service = service name do + action :nothing + end + end + nftables_service + end + + def lookup_or_create_rulesfile(name) + begin + nftables_file = Chef.run_context.resource_collection.find(file: name) + rescue + nftables_file = file name do + action :nothing + end + end + nftables_file + end + end + + #unified_mode true + + provides :firewall, os: 'linux', platform: %w(debian) + + property :rules, Hash + + def whyrun_supported? + false + end + + action :install do + return unless managed? + + # Ensure the package is installed + nft_pkg = package 'nftables' do + action :nothing + end + nft_pkg.run_action(:install) + + with_run_context :root do + edit_resource('sys_firewall', new_resource.name) do + action :nothing + delayed_action :rebuild + end + end + end + + action :rebuild do + return if !managed? + + ensure_default_rules_exist(node, new_resource) + # prints all the firewall rules + log_nftables + + # this takes the commands in each hash entry and builds a rule file + nftables_file = lookup_or_create_rulesfile('/etc/nftables.conf') + nftables_file.content "#!/usr/sbin/nft -f\nflush ruleset\n#{build_rule_file(new_resource.rules)}" + nftables_file.run_action(:create) + if disabled? + new_resource.run_action(:disable) + return + end + + nftables_service = lookup_or_create_service('nftables') + nftables_service.run_action(:enable) + + if nftables_file.updated_by_last_action? + nftables_service.run_action(:restart) + else + nftables_service.run_action(:start) + end + new_resource.updated_by_last_action(true) if nftables_service.updated_by_last_action? + end + + action :restart do + nftables_service = lookup_or_create_service('nftables') + nftables_service.run_action(:restart) + new_resource.updated_by_last_action(true) + end + + action :disable do + return unless managed? + nftables_service = lookup_or_create_service('nftables') + %i(disable stop).each do |a| + nftables_service.run_action(a) + new_resource.updated_by_last_action(true) if nftables_service.updated_by_last_action? + end + end +end diff --git a/resources/firewall_rule.rb b/resources/firewall_rule.rb new file mode 100644 index 0000000..add7135 --- /dev/null +++ b/resources/firewall_rule.rb @@ -0,0 +1,110 @@ +# +# Author:: Matthias Pausch () +# Cookbook Name:: sys +# Resource:: firewall_rule +# +# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +# +# Authors: +# Matthias Pausch (m.pausch@gsi.de) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This code is an adjustment of https://github.com/sous-chefs/firewall +# + +if Gem::Requirement.new('>= 12.5').satisfied_by?(Gem::Version.new(Chef::VERSION)) + require 'ipaddr' + action_class do + include Sys::Helpers::Firewall + + def return_early?(new_resource) + !new_resource.notify_firewall || + !(new_resource.action.include?(:create) && + !new_resource.should_skip?(:create)) || + !managed? + end + end + + provides :firewall_rule + default_action :create + + property :firewall_name, String, default: 'default' + + property :command, Symbol, default: :allow, equal_to: %i[ + accept allow deny drop log masquerade redirect reject + ] + + property :protocol, [Integer, Symbol], default: :tcp, + callbacks: { 'must be either :tcp, :udp, :icmp, :\'ipv6-icmp\', :icmpv6, :none, or a valid IP protocol number' => + ->(p) do + %i[udp tcp icmp icmpv6 ipv6-icmp esp ah ipv6 none].include?(p) || (0..142).include?(p) + end } + property :direction, Symbol, equal_to: [:in, :out, :pre, :post, :forward], default: :in + property :logging, Symbol, equal_to: [:connections, :packets] + # nftables handles ip6 and ip simultaneously. Except for directions + # :pre and :post, where where either :ip6 or :ip must be specified. + # callback should prevent from mixing that up. + property :family, Symbol, equal_to: [:ip6, :ip], default: :ip + property :source, [String, Array], callbacks: { + 'must be a valid ip address' => ->(ips) do + Array(ips).inject(false) do |a, ip| + a || !!IPAddr.new(ip) + end + end + } + property :source_port, [Integer, String, Array, Range] # source port + property :interface, String + + # I would rather call them sport and dport, without alternatives. + # However, firewall rules should be kept compatible with future + # releases of the firewall cookbook from the sous-chefs. + property :port, [Integer, String, Array, Range] # shorthand for dest_port + property :destination, [String, Array], callbacks: { + 'must be a valid ip address' => ->(ips) do + Array(ips).inject(false) do |a, ip| + a || !!IPAddr.new(ip) + end + end + } + property :dest_port, [Integer, String, Array, Range] + property :dest_interface, String + + property :position, Integer, default: 50 + property :stateful, [Symbol, Array] + property :redirect_port, Integer + property :description, String, name_property: true + property :include_comment, [true, false], default: true + + # for when you just want to pass a raw rule + property :raw, String + + # do you want this rule to notify the firewall to recalculate + # (and potentially reapply) the firewall_rule(s) it finds? + property :notify_firewall, [true, false], default: true + + action :create do + return if return_early?(new_resource) + + with_run_context :root do + edit_resource('sys_firewall', new_resource.firewall_name) do |fw_rule| + r = rules.dup || {} + r.merge!({ + build_firewall_rule(fw_rule) => fw_rule.position + }) + rules(r) + delayed_action :rebuild + end + end + end +end diff --git a/test/fixtures/cookbooks/firewall-test/metadata.rb b/test/fixtures/cookbooks/firewall-test/metadata.rb new file mode 100644 index 0000000..e40dc58 --- /dev/null +++ b/test/fixtures/cookbooks/firewall-test/metadata.rb @@ -0,0 +1,4 @@ +name 'firewall-test' +version '0.0.0' + +depends 'sys' diff --git a/test/fixtures/cookbooks/firewall-test/recipes/default.rb b/test/fixtures/cookbooks/firewall-test/recipes/default.rb new file mode 100644 index 0000000..f9187fe --- /dev/null +++ b/test/fixtures/cookbooks/firewall-test/recipes/default.rb @@ -0,0 +1,135 @@ +include_recipe 'sys::firewall' + +firewall_rule 'ssh22' do + port 22 + command :allow +end + +firewall_rule 'port array' do + port [2222, 2200] + command :allow +end + +firewall_rule 'range' do + port 1000..1100 + command :allow +end + +firewall_rule 'range-udp' do + port 60000..61000 + protocol :udp +end + +firewall_rule 'ping6' do + protocol :icmpv6 +end + +# other rules +firewall_rule 'temp1' do + port 1234 + command :deny +end + +firewall_rule 'temp2' do + port 1235 + command :reject +end + +firewall_rule 'addremove' do + port 1236 + command :allow +end + +firewall_rule 'addremove2' do + port 1236 + command :deny +end + +firewall_rule 'protocolnum' do + protocol 112 + command :allow +end + +firewall_rule 'prepend' do + port 7788 + position 5 +end + +firewall_rule "block single ip" do + source '192.168.99.99' + position 49 + command :reject +end + +firewall_rule 'block ip-range' do + source ['192.168.99.99', '192.168.100.100'] + command :drop +end + +firewall_rule 'ipv6-source' do + port 80 + family :ip6 + source '2001:db8::ff00:42:8329' + command :allow +end + +firewall_rule 'array' do + port [1234, 5000..5100, '5678'] + command :allow + +end + +firewall_rule 'RPC Port Range In' do + port 5000..5100 + protocol :tcp + command :allow + direction :in + +end + +firewall_rule 'HTTP HTTPS' do + port [80, 443] + protocol :tcp + direction :out + command :allow +end + +firewall_rule 'port2433' do + description 'This should not be included' + include_comment false + source '127.0.0.0/8' + port 2433 + direction :in + command :allow +end + +firewall_rule 'esp' do + protocol :esp + command :allow +end + +firewall_rule 'ah' do + protocol :ah + command :allow +end + +firewall_rule 'esp-ipv6' do + source '::' + family :ip6 + protocol :esp + command :allow +end + +firewall_rule 'ah-ipv6' do + source '::' + family :ip6 + protocol :ah + command :allow +end + +firewall_rule 'redirect' do + direction :pre + port 5555 + redirect_port 6666 + command :redirect +end diff --git a/test/integration/sys_firewall/serverspec/Gemfile b/test/integration/sys_firewall/serverspec/Gemfile new file mode 100644 index 0000000..3794d9d --- /dev/null +++ b/test/integration/sys_firewall/serverspec/Gemfile @@ -0,0 +1,10 @@ +source 'http://rubygems.org' + +group :jessie do + # net-ssh >= 5 requires ruby 2.2 and + # net-telnet >= 0.2 requires ruby 2.3 + if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.2.0') + gem 'net-ssh', '< 5' + gem 'net-telnet', '< 0.2' + end +end diff --git a/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb b/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb new file mode 100644 index 0000000..a5a65f6 --- /dev/null +++ b/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb @@ -0,0 +1,66 @@ +# +# Cookbook Name:: sys +# Integration tests for sys::firewall +# +# Copyright 2022-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +# +# Authors: +# Matthias Pausch (m.pausch@gsi.de) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +require 'spec_helper' +expected_rules = [ + /^table inet filter {$/, + /\s+type filter hook output priority.*/, + /\s+type filter hook forward priority.*/, + /\s+type filter hook input priority 0; policy drop;/, + /\s+tcp dport 7788 accept.*/, + /\s+ip saddr 192.168.99.99 reject.*/, + /\s+ip saddr { 192.168.99.99, 192.168.100.100 } drop.*/, + /\s+iif "lo" accept comment "allow loopback"/, + /\s+icmp type echo-request accept.*$/, + /\s+tcp dport 22 accept.*$/, + /\s+udp dport 60000-61000 accept.*$/, + /\s+ct state established,related accept.*$/, + /\s+icmpv6 type { echo-request, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept.*$/, + /\s+tcp dport 22 accept.*$/, + /\s+tcp dport { 2200, 2222 } accept.*$/, + /\s+tcp dport 1234 drop.*$/, + /\s+tcp dport 1235 reject.*$/, + /\s+tcp dport 1236 drop.*$/, + /\s+ip6 saddr 2001:db8::ff00:42:8329 tcp dport 80 accept.*$/, + /\s+tcp dport 1000-1100 accept.*$/, + /\s+tcp dport { 1234, 5000-5100, 5678 } accept.*$/, + /\s+tcp dport 5000-5100 accept.*$/, + %r{\s+ip saddr 127.0.0.0/8 tcp dport 2433 accept.*$}, + /\s+ip protocol esp accept.*$/, + /\s+ip protocol ah accept.*$/, + /\s+ip6 nexthdr esp accept.*$/, + /\s+ip6 nexthdr ah accept.*$/, +] + +describe command('nft -nn list ruleset') do + expected_rules.each do |r| + its(:stdout) { should match(r) } + end +end + +describe package('nftables') do + it { should be_installed } +end + +describe service('nftables') do + it { should be_enabled } + it { should be_running } +end diff --git a/test/integration/sys_firewall/serverspec/spec_helper.rb b/test/integration/sys_firewall/serverspec/spec_helper.rb new file mode 100644 index 0000000..37af1b4 --- /dev/null +++ b/test/integration/sys_firewall/serverspec/spec_helper.rb @@ -0,0 +1,3 @@ +require 'serverspec' + +set :backend, :exec diff --git a/test/unit/recipes/firewall_spec.rb b/test/unit/recipes/firewall_spec.rb new file mode 100644 index 0000000..1b1ed06 --- /dev/null +++ b/test/unit/recipes/firewall_spec.rb @@ -0,0 +1,54 @@ +describe 'sys::firewall' do + let(:chef_run) { ChefSpec::SoloRunner.new } + + context 'node.sys.ferm.table is empty' do + before do + chef_run.converge(described_recipe) + end + + it 'does nothing' do + expect(chef_run.run_context.resource_collection).to be_empty + end + end + + context 'with some rules' do + before do + chef_run.node.default[:sys][:ferm][:rules][:ip][:filter][:OUTPUT] = [ + 'policy ACCEPT;', + 'mod state state (ESTABLISHED RELATED) ACCEPT;' + ] + chef_run.converge(described_recipe) + end + + it 'upgrades package nftables' do + expect(chef_run).to install_package('nftables') + end + + it 'manages /etc/nftables.conf' do + expect(chef_run).to create_template('/etc/nftables.conf').with_mode('0644').with_owner('root').with_group('adm') + template = chef_run.template('/etc/nftables.conf') + expect(template).to notify('service[nftables]').to(:reload).immediately + end + + it 'enables and starts service "nftables"' do + expect(chef_run).to enable_service('nftables') + expect(chef_run).to start_service('nftables') + end + end + + context "with node['sys']['firewall']['active'] == false" do + before do + chef_run.node.default[:sys][:ferm][:rules][:ip][:filter][:OUTPUT] = [ + 'policy ACCEPT;', + 'mod state state (ESTABLISHED RELATED) ACCEPT;' + ] + chef_run.node.default['sys']['firewall']['active'] = false + chef_run.converge(described_recipe) + end + + it 'disables and stops service "nftables"' do + expect(chef_run).to disable_service('nftables') + expect(chef_run).to stop_service('nftables') + end + end +end -- GitLab From dece52ddf8640e2f977a96654ab8ecb95cb882dd Mon Sep 17 00:00:00 2001 From: Matthias Pausch Date: Fri, 25 Feb 2022 11:26:53 +0100 Subject: [PATCH 2/9] Fix version requirement for chef-client --- recipes/firewall.rb | 58 ++++++++++++++++++++------------------ resources/firewall.rb | 2 +- resources/firewall_rule.rb | 2 +- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/recipes/firewall.rb b/recipes/firewall.rb index c22b215..a43499f 100644 --- a/recipes/firewall.rb +++ b/recipes/firewall.rb @@ -23,36 +23,38 @@ # This code is an adjustment of https://github.com/sous-chefs/firewall # -if node['sys']['firewall']['manage'] - fw_action = node['sys']['firewall']['disable'] ? :disable : :install - firewall 'default' do - action fw_action - end - firewall_rule 'allow loopback' do - interface 'lo' - protocol :none - command :allow - only_if { node['sys']['firewall']['allow_loopback'] } - end +return unless node['sys']['firewall']['manage'] +return unless Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION)) - firewall_rule 'allow icmp' do - protocol :icmp - command :allow - only_if { node['sys']['firewall']['allow_icmp'] } - end +fw_action = node['sys']['firewall']['disable'] ? :disable : :install +firewall 'default' do + action fw_action +end + +firewall_rule 'allow loopback' do + interface 'lo' + protocol :none + command :allow + only_if { node['sys']['firewall']['allow_loopback'] } +end - firewall_rule 'allow world to ssh' do - port 22 - source '0.0.0.0/0' - only_if { node['sys']['firewall']['allow_ssh'] } - end +firewall_rule 'allow icmp' do + protocol :icmp + command :allow + only_if { node['sys']['firewall']['allow_icmp'] } +end + +firewall_rule 'allow world to ssh' do + port 22 + source '0.0.0.0/0' + only_if { node['sys']['firewall']['allow_ssh'] } +end - # allow established connections - firewall_rule 'established' do - stateful [:related, :established] - protocol :none # explicitly don't specify protocol - command :allow - only_if { node['sys']['firewall']['allow_established'] } - end +# allow established connections +firewall_rule 'established' do + stateful [:related, :established] + protocol :none # explicitly don't specify protocol + command :allow + only_if { node['sys']['firewall']['allow_established'] } end diff --git a/resources/firewall.rb b/resources/firewall.rb index 608a1a1..24d69b2 100644 --- a/resources/firewall.rb +++ b/resources/firewall.rb @@ -23,7 +23,7 @@ # This code is an adjustment of https://github.com/sous-chefs/firewall # -if Gem::Requirement.new('>= 12.5').satisfied_by?(Gem::Version.new(Chef::VERSION)) +if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION)) action_class do diff --git a/resources/firewall_rule.rb b/resources/firewall_rule.rb index add7135..1324e38 100644 --- a/resources/firewall_rule.rb +++ b/resources/firewall_rule.rb @@ -23,7 +23,7 @@ # This code is an adjustment of https://github.com/sous-chefs/firewall # -if Gem::Requirement.new('>= 12.5').satisfied_by?(Gem::Version.new(Chef::VERSION)) +if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION)) require 'ipaddr' action_class do include Sys::Helpers::Firewall -- GitLab From b7309e9ff7bf596c079eb28323c6c83c5d031474 Mon Sep 17 00:00:00 2001 From: Matthias Pausch Date: Fri, 25 Feb 2022 12:12:37 +0100 Subject: [PATCH 3/9] Skip firewall-test::default on Chef::VERSION < 12.15 --- test/fixtures/cookbooks/firewall-test/recipes/default.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/fixtures/cookbooks/firewall-test/recipes/default.rb b/test/fixtures/cookbooks/firewall-test/recipes/default.rb index f9187fe..3777935 100644 --- a/test/fixtures/cookbooks/firewall-test/recipes/default.rb +++ b/test/fixtures/cookbooks/firewall-test/recipes/default.rb @@ -1,3 +1,5 @@ +return unless Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION)) + include_recipe 'sys::firewall' firewall_rule 'ssh22' do -- GitLab From 45f53d73c647c6699e20918dcc77aef1edb11117 Mon Sep 17 00:00:00 2001 From: Matthias Pausch Date: Fri, 25 Feb 2022 12:33:42 +0100 Subject: [PATCH 4/9] Consequently, nftables should not be running --- .../serverspec/localhost/firewall_spec.rb | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb b/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb index a5a65f6..e9deb33 100644 --- a/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb +++ b/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb @@ -50,17 +50,30 @@ expected_rules = [ /\s+ip6 nexthdr ah accept.*$/, ] -describe command('nft -nn list ruleset') do - expected_rules.each do |r| - its(:stdout) { should match(r) } +if os[:release].to_i >= 10 + + describe command('nft -nn list ruleset') do + expected_rules.each do |r| + its(:stdout) { should match(r) } + end end -end -describe package('nftables') do - it { should be_installed } -end + describe package('nftables') do + it { should be_installed } + end -describe service('nftables') do - it { should be_enabled } - it { should be_running } + describe service('nftables') do + it { should be_enabled } + it { should be_running } + end + +else + describe package('nftables') do + it { should_not be_installed } + end + + describe service('nftables') do + it { should_not be_enabled } + it { should_not be_running } + end end -- GitLab From e71c7a03642bbd87480bfc4b27dfdc16c61f87d8 Mon Sep 17 00:00:00 2001 From: Christopher Huhn Date: Mon, 28 Feb 2022 14:04:12 +0000 Subject: [PATCH 5/9] Polish the documentation --- documents/firewall.md | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/documents/firewall.md b/documents/firewall.md index d479816..820533e 100644 --- a/documents/firewall.md +++ b/documents/firewall.md @@ -1,3 +1,5 @@ +# `sys::firewall` + Use the firewall recipe to configure nftables. ↪ `attributes/firewall.rb` @@ -8,20 +10,21 @@ Use the firewall recipe to configure nftables. ↪ `documents/firewall.rb` ↪ `test/unit/recipies/firewall_spec.rb` -# Examples +## Basic Usage -## Disable nftables +The `sys::firewall` recipe **does nothing unless explicitly activated** by setting `node['sys']['firewall']['manage']` to `true`. -Use attributes in `node['sys']['firewall']`, e.g. to switch off nftables: +### Disable nftables - node['sys']['firewall']['manage'] = true # To manage nftables at all - node['sys']['firewall']['disable'] = true # To disable nftables +`node['sys']['firewall']['disable']` will turn off *nftables*: + ```ruby +node['sys']['firewall']['manage'] = true # To manage nftables at all +node['sys']['firewall']['disable'] = true # To disable nftables +``` -## Default rules +### Default rules -If you want to use `sys::firewall`, just include the recipe and set -`node['sys']['firewall']['manage'] = true`. Adjust the follwing -self-explaining attributes to your needs. They all default to true: +When `sys::firewall` is activated and *nftables* is not disabled, the default rules are applied via the following self-explaining attributes, all of which default to true. Adjust to your needs: ↪ `node['sys']['firewall']['allow_established']` ↪ `node['sys']['firewall']['allow_icmp']` @@ -73,9 +76,11 @@ Depend on the `sys`-cookbook in the `metadata.rb` and include `sys::firewall` in the runlist. If access via ports `443` and `80` should be possible, write a resource like this: - firewall_rule 'allow http(s)` do - port [80,443] - end +```ruby +firewall_rule 'allow http(s)` do + port [80,443] +end +``` For further examples see the recipe [sys::firewall](recipes/firewall.rb) and the recipe [firewall-test::default](test/fixtures/cookbooks/firewall-test/recipes/default.rb). -- GitLab From e3424a2455eb983a094fa934889f1ae3c5b60758 Mon Sep 17 00:00:00 2001 From: Matthias Pausch Date: Thu, 10 Mar 2022 10:20:59 +0100 Subject: [PATCH 6/9] Do not configure the firewall if firewall resource is not defined --- resources/firewall_rule.rb | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/resources/firewall_rule.rb b/resources/firewall_rule.rb index 1324e38..f9a5cec 100644 --- a/resources/firewall_rule.rb +++ b/resources/firewall_rule.rb @@ -97,13 +97,17 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION return if return_early?(new_resource) with_run_context :root do - edit_resource('sys_firewall', new_resource.firewall_name) do |fw_rule| - r = rules.dup || {} - r.merge!({ - build_firewall_rule(fw_rule) => fw_rule.position - }) - rules(r) - delayed_action :rebuild + begin + edit_resource!('sys_firewall', new_resource.firewall_name) do |fw_rule| + r = rules.dup || {} + r.merge!({ + build_firewall_rule(fw_rule) => fw_rule.position + }) + rules(r) + delayed_action :rebuild + end + rescue Chef::Exceptions::ResourceNotFound + Chef::Log.warn "Resource firewall['#{new_resource.firewall_name}'] not found in resource collection. Not configuring firewall." end end end -- GitLab From eb992ff4076e549e9d05e44968e987cb599591f0 Mon Sep 17 00:00:00 2001 From: Christopher Huhn Date: Fri, 25 Mar 2022 12:33:21 +0100 Subject: [PATCH 7/9] Add a comment and emit a warning --- recipes/nftables.rb | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/recipes/nftables.rb b/recipes/nftables.rb index bffa081..25007b8 100644 --- a/recipes/nftables.rb +++ b/recipes/nftables.rb @@ -2,13 +2,25 @@ # Cookbook Name:: sys # Recipe:: nftables # -# Copyright 2014, HPC Team +# Copyright 2014-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +# +# Authors: +# Matthias Pausch +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # -unless node['sys']['nftables'].empty? - - if node['debian'] && node['debian']['codename'] && node['debian']['codename'].eql?('stretch') +# this recipe has been superseded by sys::firewall +return unless node['sys']['nftables'] - - end -end +Chef::Log.warn('The sys::nftables recipe has been removed. Use sys::firewall instead') -- GitLab From 2d3c73cef267cb29def2df98c5de2ac9e1c33fd8 Mon Sep 17 00:00:00 2001 From: Christopher Huhn Date: Fri, 25 Mar 2022 12:34:18 +0100 Subject: [PATCH 8/9] Cleanup file headers --- libraries/sys_helpers_firewall.rb | 1 - recipes/firewall.rb | 2 -- resources/firewall.rb | 1 - resources/firewall_rule.rb | 1 - .../serverspec/localhost/firewall_spec.rb | 4 +++- test/unit/recipes/firewall_spec.rb | 22 +++++++++++++++++++ 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/libraries/sys_helpers_firewall.rb b/libraries/sys_helpers_firewall.rb index bf9f907..4f49519 100644 --- a/libraries/sys_helpers_firewall.rb +++ b/libraries/sys_helpers_firewall.rb @@ -1,5 +1,4 @@ # -# Author:: Matthias Pausch () # Cookbook Name:: sys # Library:: Helpers::Firewall # diff --git a/recipes/firewall.rb b/recipes/firewall.rb index a43499f..ac197f3 100644 --- a/recipes/firewall.rb +++ b/recipes/firewall.rb @@ -1,5 +1,4 @@ # -# Author:: Matthias Pausch () # Cookbook Name:: sys # Recipe:: firewall # @@ -23,7 +22,6 @@ # This code is an adjustment of https://github.com/sous-chefs/firewall # - return unless node['sys']['firewall']['manage'] return unless Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION)) diff --git a/resources/firewall.rb b/resources/firewall.rb index 24d69b2..d379613 100644 --- a/resources/firewall.rb +++ b/resources/firewall.rb @@ -1,5 +1,4 @@ # -# Author:: Matthias Pausch () # Cookbook Name:: sys # Resource:: firewall # diff --git a/resources/firewall_rule.rb b/resources/firewall_rule.rb index f9a5cec..21a56c2 100644 --- a/resources/firewall_rule.rb +++ b/resources/firewall_rule.rb @@ -1,5 +1,4 @@ # -# Author:: Matthias Pausch () # Cookbook Name:: sys # Resource:: firewall_rule # diff --git a/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb b/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb index e9deb33..75f8773 100644 --- a/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb +++ b/test/integration/sys_firewall/serverspec/localhost/firewall_spec.rb @@ -2,7 +2,7 @@ # Cookbook Name:: sys # Integration tests for sys::firewall # -# Copyright 2022-2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH # # Authors: # Matthias Pausch (m.pausch@gsi.de) @@ -19,7 +19,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # + require 'spec_helper' + expected_rules = [ /^table inet filter {$/, /\s+type filter hook output priority.*/, diff --git a/test/unit/recipes/firewall_spec.rb b/test/unit/recipes/firewall_spec.rb index 1b1ed06..f03b42c 100644 --- a/test/unit/recipes/firewall_spec.rb +++ b/test/unit/recipes/firewall_spec.rb @@ -1,3 +1,25 @@ +# +# Cookbook Name:: sys +# Unit tests for sys::firewall +# +# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH +# +# Authors: +# Matthias Pausch +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + describe 'sys::firewall' do let(:chef_run) { ChefSpec::SoloRunner.new } -- GitLab From 4fc03c0c996a94fbdd8e02de7c5c056fb98c7730 Mon Sep 17 00:00:00 2001 From: Matthias Pausch Date: Fri, 25 Mar 2022 12:43:51 +0100 Subject: [PATCH 9/9] According to foodcritic this is not necessary anymore --- resources/firewall.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/resources/firewall.rb b/resources/firewall.rb index d379613..b748717 100644 --- a/resources/firewall.rb +++ b/resources/firewall.rb @@ -102,13 +102,11 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION else nftables_service.run_action(:start) end - new_resource.updated_by_last_action(true) if nftables_service.updated_by_last_action? end action :restart do nftables_service = lookup_or_create_service('nftables') nftables_service.run_action(:restart) - new_resource.updated_by_last_action(true) end action :disable do @@ -116,7 +114,6 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION nftables_service = lookup_or_create_service('nftables') %i(disable stop).each do |a| nftables_service.run_action(a) - new_resource.updated_by_last_action(true) if nftables_service.updated_by_last_action? end end end -- GitLab