Skip to content

Raw rules not persisted with default config #233

Description

@chaim1221

👻 Brief Description

Using raw 'SOME_RULE' does not persist rules with Debian/Ubuntu. /etc/iptables/rules.v4 is created but it is not enforced. Setup fails kitchen test and I have to manually do iptables-restore (a hack in code does not work). I have tested this on both a KVM system (I thought it was libvirt) and a Docker system (I thought it was Docker) but I have tried putting the firewall recipe directives both before and after those installs, and those are common use cases anyway— they should not interfere with the managed firewall.

🥞 Cookbook version

depends 'firewall', '~>2.7.1'

👩‍🍳 Chef-Infra Version

16.10.17 (pinned for stability)

Version of chef-client in your environment.

🎩 Platform details

vagrant@virt-generic-debian10:~$ uname -a
Linux virt-generic-debian10 4.19.0-16-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64 GNU/Linux
vagrant@virt-generic-ubuntu2004:~$ uname -a
Linux virt-generic-ubuntu2004 5.4.0-74-generic #83-Ubuntu SMP Sat May 8 02:35:39 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Host is Ubuntu 21.04 running Kitchen and vagrant libvirt provider (because we use KVM in prod).

Steps To Reproduce

my_cookbook::firewall.rb

include_recipe "firewall"

ssh_port = node[:my_cookbook][:sshd][:port]
ssh_interface = node[:my_cookbook][:sshd][:interface]

common_rules = [
  '-P INPUT DROP',
  '-P FORWARD DROP',
  '-P OUTPUT ACCEPT',
  "-A INPUT -i lo -m comment --comment \"allow loopback\" -j ACCEPT",
  "-A INPUT -p icmp -m icmp --icmp-type any -j DROP",
  "-A INPUT -i #{ssh_interface} -p tcp -m tcp -m multiport --dports #{ssh_port} -m state --state NEW,ESTABLISHED -m comment --comment ssh -j ACCEPT",
  "-A OUTPUT -p tcp -m tcp -m multiport --dports #{ssh_port} -m state --state RELATED,ESTABLISHED -m comment --comment ssh -j ACCEPT",
  "-A OUTPUT -o lo -j ACCEPT",
]

service "ufw" do
  action :stop
end

service "ufw" do
  action :disable
end

firewall "default" do
  action :install
end

i = 1
common_rules.each do |rule|
  firewall_rule "common_rules" do
    raw      rule
    position i
  end
  i += 1
end

attributes::firewall.rb

default[:my_cookbook][:sshd][:port] = 22
default[:my_cookbook][:sshd][:interface] = 'eth0'

default['firewall']['ubuntu_iptables'] = true
default['firewall']['redhat7_iptables'] = true
default['firewall']['allow_loopback'] = true
default['firewall']['allow_icmp'] = false
default['firewall']['allow_ssh'] = false
default['firewall']['ipv6_enabled'] = false

integration::firewall_test.rb

common_rules = [
  '-P INPUT DROP',
  '-P FORWARD DROP',
  '-P OUTPUT ACCEPT',
  '-A INPUT -i lo -m comment --comment "allow loopback" -j ACCEPT',
  '-A INPUT -p icmp -m icmp --icmp-type any -j DROP',
  '-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 22 -m state --state NEW,ESTABLISHED -m comment --comment ssh -j ACCEPT',
  '-A OUTPUT -o lo -j ACCEPT',
]

unwanted_rules = [
  '-A INPUT -p tcp -m tcp -m multiport --dports 22 -m comment --comment "allow world to ssh" -j ACCEPT'
]

control 'any node' do
  describe iptables do
    common_rules.each do |expected|
      it { should have_rule(expected) }
    end
    unwanted_rules.each do |unwanted|
      it { should_not have_rule(unwanted) }
    end
  end

  describe service('ufw') do
    it { should_not be_enabled }
    it { should_not be_running }
  end

  describe service('netfilter-persistent') do
    it { should be_enabled }
    it { should be_running }
  end

  impact 1.0
  title 'any node firewall basic rules'
  desc 'iptables is not configured properly'
end

kvm.rb

%w{ qemu-kvm libvirt-daemon-system virtinst virt-manager virt-viewer bridge-utils cloud-image-utils libguestfs-tools ifupdown screen }.each do |pkg|
  package pkg do
    action :install
  end
end
# [snip - there's a lot more here I will add if necessary but trying to MVP here]

docker.rb

docker_service 'default' do
  action [ :create, :start ]
end

.kitchen.yml

---
driver:
  name: vagrant
  provider: libvirt
provisioner:
  name: chef_zero
  product_name: chef
  product_version: 16.10.17
  always_update_cookbooks: true
  chef_license: accept
verifier:
  name: inspec
platforms:
  - name: generic/debian10
  - name: generic/ubuntu2004
suites:
  - name: example
    run_list:
      - recipe[my_cookbook::kvm]
      - recipe[my_cookbook::docker]
      - recipe[my_cookbook::firewall]
    verifier:
      inspec_tests:
        - test/integration/firewall
    attributes:
      my_cookbook:
        sshd: 
          port: 22 # https://serverfault.com/a/746699/182753
          interface: eth0

🚓 Expected behavior

The firewall is configured with the expected rules and passes all tests.

➕ Actual behavior

Profile: tests from {:path=>"/home/celiyah/Code/my_cookbook/chef/test/integration/firewall"} (tests from {:path=>".home.celiyah.Code.my_cookbook.chef.test.integration.firewall"})
Version: (not specified)
Target:  ssh://vagrant@192.168.121.104:22

  ×  any node: any node firewall basic rules (5 failed)
     ×  Iptables is expected to have rule "-P INPUT DROP"
     expected Iptables to have rule "-P INPUT DROP"
     ✔  Iptables is expected to have rule "-P FORWARD DROP"
     ✔  Iptables is expected to have rule "-P OUTPUT ACCEPT"
     ×  Iptables is expected to have rule "-A INPUT -i lo -m comment --comment \"allow loopback\" -j ACCEPT"
     expected Iptables to have rule "-A INPUT -i lo -m comment --comment \"allow loopback\" -j ACCEPT"
     ×  Iptables is expected to have rule "-A INPUT -p icmp -m icmp --icmp-type any -j DROP"
     expected Iptables to have rule "-A INPUT -p icmp -m icmp --icmp-type any -j DROP"
     ×  Iptables is expected to have rule "-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 22 -m state --state NEW,ESTABLISHED -m comment --comment ssh -j ACCEPT"
     expected Iptables to have rule "-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 22 -m state --state NEW,ESTABLISHED -m comment --comment ssh -j ACCEPT"
     ×  Iptables is expected to have rule "-A OUTPUT -o lo -j ACCEPT"
     expected Iptables to have rule "-A OUTPUT -o lo -j ACCEPT"
     ✔  Iptables is expected not to have rule "-A INPUT -p tcp -m tcp -m multiport --dports 22 -m comment --comment \"allow world to ssh\" -j ACCEPT"
     ✔  Service ufw is expected not to be enabled
     ✔  Service ufw is expected not to be running
     ✔  Service netfilter-persistent is expected to be enabled
     ✔  Service netfilter-persistent is expected to be running


Profile Summary: 5 successful controls, 1 control failure, 0 controls skipped
Test Summary: 54 successful, 5 failures, 0 skipped

Add any other context about the problem here. e.g. related issues or existing pull requests.

You probably will notice I've contributed before :) not above submitting a PR but I do not understand what is happening here. UFW is disabled as expected. netfilter-persistent is enabled as expected. :onfire:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions