diff --git a/cookbooks/fb_iptables/README.md b/cookbooks/fb_iptables/README.md index 17273d7..a61db94 100644 --- a/cookbooks/fb_iptables/README.md +++ b/cookbooks/fb_iptables/README.md @@ -121,19 +121,19 @@ translated to key-value pairs in the config file. The keys will automatically be upper-cased and prefixed with `IPTABLES_` or `IP6TABLES_` as necessary. For example: -``` +```ruby node.default['fb_iptables']['sysconfig']['modules'] = 'nat' ``` would translate to: -``` +```bash IPTABLES_MODULES="nat" ``` and: -``` +```bash IP6TABLES_MODULES="nat" ``` @@ -144,4 +144,7 @@ if you need to trigger on rules reloading. ### Unsupported features The `nat` and `security` tables are not currently supported. +However, you can call `FB::Iptables.enable_nat(node)` to safely initialize +the `nat` structures for use. + User defined table are not supported. diff --git a/cookbooks/fb_iptables/files/default/fb_iptables_reload.sh b/cookbooks/fb_iptables/files/default/fb_iptables_reload.sh new file mode 100755 index 0000000..e4aa8e7 --- /dev/null +++ b/cookbooks/fb_iptables/files/default/fb_iptables_reload.sh @@ -0,0 +1,144 @@ +#!/bin/bash +# shellcheck disable=SC2086,SC2018,SC2019,SC1090,SC2064,SC2124,SC2181,SC2002,SC2153,SC2046,SC2173,SC2230 +# +# Copyright (c) 2016-present, Facebook, Inc. +# All rights reserved. +# +# 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. +# + +# Simple script for chef to call to +# dump and reload custom chain rules + +set -u + +CONFIG='/etc/fb_iptables.conf' +TMPDIR=$(mktemp -d /tmp/fb_iptables.XXXXXXXXXXXX) +trap "rm -rf $TMPDIR &>/dev/null" exit INT TERM KILL + +help_print() { + echo "$0 [4|6] " + exit; +} + +exit_error() { + msg="$@" + echo "ERROR: $msg" + exit 1 +} + +# Walk dynamic changes for a table and dump them to temp files in, if they exist +dump_dynamic_chains() { + local table="$1" + local dynamic_chains="$2" + local outfile + local chain_regex + echo -n " - Stashing dynamic chains on $table: " + for chain in $dynamic_chains; do + echo -n "$chain " + "${IPTABLES_CMD}" -t "$table" -S | grep -q "\-N $chain" + if [ $? -ne 0 ]; then + echo '(no chain yet, nothing to stash) ' + continue + fi + outfile=$TMPDIR/${table}_${chain}_rules + chain_regex="\-A $chain " + out=$("${IPTABLES_CMD}" -t "$table" -S) + if [ $? -ne 0 ]; then + exit_error "Failed to stash $chain on $table" + fi + if [ -n "$out" ]; then + echo "$out" | grep "$chain_regex" > "$outfile" + fi + done + echo 'done.' +} + +# Restore any registered chains we found and backed up +restore_dynamic_chains() { + local table="$1" + local dynamic_chains="$2" + + echo -n " - Restoring dynamic chains on $table: " + for chain in $dynamic_chains; do + echo -n "$chain " + local rules_file=$TMPDIR/${table}_${chain}_rules + if [ ! -r $rules_file ]; then + echo '(no chain to restore) ' + continue + fi + + ${IPTABLES_CMD} -t $table -F $chain + while read -r rule + do + ${IPTABLES_CMD} -t $table $rule + done < "$rules_file" + done + echo 'done.' +} + +reload_static_chains() { + local table="$1" + + # NOTE: You cannot use '-t' here ... ip6tables-* choke on it... you must + # specify --table= + echo " - Reloading $table" + cat "${CONFIG_DIR}/${IPTABLES_RULES_FILE}" | ${IPTABLES_CMD}-restore --table=$table +} + +reload() { + for table in $TABLES; do + # iptables-restore triggers loading modules, even with empty + # rules. Let's avoid that (t28313270). + echo "Reloading $table..." + cap_table=$(echo $table | tr 'a-z' 'A-Z') + static_chains=$(eval echo \$STATIC_${cap_table}_CHAINS) + if [ -z "$static_chains" ] && ! grep -q $table /proc/net/ip*_tables_names; then + continue + fi + dynamic_chains=$(eval echo \$${cap_table}_CHAINS) + dump_dynamic_chains $table "$dynamic_chains" + reload_static_chains $table + restore_dynamic_chains $table "$dynamic_chains" + done +} + +[ -r "$CONFIG" ] && . $CONFIG + +# Poor mans help print +if [ "$1" == "help" ]; then + help_print +fi + +# v4 or v6 +IPTABLES_CMD=ip6tables +IPTABLES_RULES_FILE="$RULES6_FILE" +if [ "$1" == "4" ]; then + IPTABLES_CMD=iptables + IPTABLES_RULES_FILE="$RULES_FILE" +fi +ACTION="$2" + +if [ ! -x $(which "${IPTABLES_CMD}") ]; then + echo "ERROR: No ${IPTABLES_CMD} in path bro ..." + exit 1 +fi + +case "$ACTION" in + reload) + reload + ;; + *) + help_print + ;; +esac diff --git a/cookbooks/fb_iptables/libraries/default.rb b/cookbooks/fb_iptables/libraries/default.rb index 90a80c0..838716c 100644 --- a/cookbooks/fb_iptables/libraries/default.rb +++ b/cookbooks/fb_iptables/libraries/default.rb @@ -24,14 +24,44 @@ module Iptables TABLES_AND_CHAINS = { 'mangle' => %w{PREROUTING INPUT OUTPUT FORWARD POSTROUTING}, 'filter' => %w{INPUT OUTPUT FORWARD}, - 'raw' => %w{PREROUTING OUTPUT}, + 'raw' => %w{PREROUTING OUTPUT}, } # rubocop:enable Style/MutableConstant + # Facebook, like others does not have NAT in their kernels. However many + # people do, so provide an easy way to initialize the various structures + # with NAT entries. + # + # Note this is idempotent - you can call it many times, it will not + # overwrite user rules + def self.enable_nat(node) + TABLES_AND_CHAINS['nat'] ||= %w{PREROUTING INPUT OUTPUT POSTROUTING} + + # normally this would be auto-vivified, but since we want to check + # fb_iptables.nat.$chain below, this has to exist + unless node['fb_iptables']['nat'] + node.default['fb_iptables']['nat'] = {} + end + + TABLES_AND_CHAINS['nat'].each do |chain| + next if node['fb_iptables']['nat'][chain] + + node.default['fb_iptables']['nat'][chain] = { + 'policy' => 'ACCEPT', + 'rules' => {}, + } + end + + unless node['fb_iptables']['dynamic_chains']['nat'] + node.default['fb_iptables']['dynamic_chains']['nat'] = {} + end + end + # Is the given rule valid for the give ip version def self.rule_supports_ip_version?(rule, version) return true unless rule['ip'] return true if rule['ip'] == version + rule['ip'].is_a?(Array) && rule['ip'].include?(version) end diff --git a/cookbooks/fb_iptables/metadata.rb b/cookbooks/fb_iptables/metadata.rb index 6fd5f08..b040a28 100644 --- a/cookbooks/fb_iptables/metadata.rb +++ b/cookbooks/fb_iptables/metadata.rb @@ -5,7 +5,6 @@ license 'Apache-2.0' description 'Installs/Configures iptables' source_url 'https://github.com/facebook/chef-cookbooks/' -long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '0.1.0' supports 'centos' depends 'fb_helpers' diff --git a/cookbooks/fb_iptables/recipes/default.rb b/cookbooks/fb_iptables/recipes/default.rb index ac5a9a9..fb97aa3 100644 --- a/cookbooks/fb_iptables/recipes/default.rb +++ b/cookbooks/fb_iptables/recipes/default.rb @@ -77,18 +77,19 @@ owner 'root' group 'root' mode '0644' + variables( + :iptables_config_dir => iptables_config_dir, + :iptables_rules_file => iptables_rule_file, + :ip6tables_rules_file => ip6tables_rule_file, + ) end -template '/usr/sbin/fb_iptables_reload' do - source 'fb_iptables_reload.erb' +# DO NOT MAKE THIS A TEMPLATE! USE THE CONFIG FILE TEMPLATED ABOVE!! +cookbook_file '/usr/sbin/fb_iptables_reload' do + source 'fb_iptables_reload.sh' owner 'root' group 'root' mode '0755' - variables( - :iptables_config_dir => iptables_config_dir, - :iptables_rules => iptables_rule_file, - :ip6tables_rules => ip6tables_rule_file, - ) end template "#{iptables_config_dir}/iptables-config" do @@ -112,11 +113,7 @@ # moving from "no rules" to any rules; otherwise we still verify # every time). if FB::Iptables.iptables_active?(4) - Mixlib::ShellOut.new( - # SCALE: backported - # https://github.com/facebook/chef-cookbooks/pull/56 - "/sbin/iptables-restore --test #{path}", - ).run_command.exitstatus.zero? + shell_out("/sbin/iptables-restore --test #{path}").exitstatus.zero? else true end @@ -141,11 +138,7 @@ verify do |path| # See comment ip iptables_rules if FB::Iptables.iptables_active?(6) - Mixlib::ShellOut.new( - # SCALE: backported - # https://github.com/facebook/chef-cookbooks/pull/56 - "/sbin/ip6tables-restore --test #{path}", - ).run_command.exitstatus.zero? + shell_out("/sbin/ip6tables-restore --test #{path}").exitstatus.zero? else true end diff --git a/cookbooks/fb_iptables/recipes/packages.rb b/cookbooks/fb_iptables/recipes/packages.rb index ce7e060..b1532d5 100644 --- a/cookbooks/fb_iptables/recipes/packages.rb +++ b/cookbooks/fb_iptables/recipes/packages.rb @@ -19,10 +19,12 @@ # limitations under the License. # -packages = ['iptables'] -if node.centos6? - packages << 'iptables-ipv6' -elsif node.ubuntu? +if (node.centos? && !(node.centos7? || node.centos8?)) || node.fedora? + packages = ['iptables-legacy'] +else + packages = ['iptables'] +end +if node.ubuntu? packages << 'iptables-persistent' else packages << 'iptables-services' diff --git a/cookbooks/fb_iptables/spec/default_spec.rb b/cookbooks/fb_iptables/spec/default_spec.rb new file mode 100644 index 0000000..6f49b0e --- /dev/null +++ b/cookbooks/fb_iptables/spec/default_spec.rb @@ -0,0 +1,160 @@ +# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2 +# +# Copyright (c) 2016-present, Facebook, Inc. +# All rights reserved. +# +# 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/spec_helper' +require_relative '../libraries/default' + +describe FB::Iptables do + let(:void_rule) { {} } + let(:v4_rule) { { 'ip' => 4 } } + let(:v6_rule) { { 'ip' => [6] } } + let(:v46_rule) { { 'ip' => [4, 6] } } + + describe '#rule_supports_ip_version?' do + it 'defaults to [4,6]' do + expect(FB::Iptables.rule_supports_ip_version?(void_rule, 4)).to be true + expect(FB::Iptables.rule_supports_ip_version?(void_rule, 4)).to be true + end + it 'supports Integer' do + expect(FB::Iptables.rule_supports_ip_version?(v4_rule, 4)).to be true + expect(FB::Iptables.rule_supports_ip_version?(v4_rule, 6)).to be false + end + it 'supports Array' do + expect(FB::Iptables.rule_supports_ip_version?(v6_rule, 4)).to be false + expect(FB::Iptables.rule_supports_ip_version?(v6_rule, 6)).to be true + expect(FB::Iptables.rule_supports_ip_version?(v46_rule, 4)).to be true + expect(FB::Iptables.rule_supports_ip_version?(v46_rule, 6)).to be true + end + end +end + +recipe 'fb_iptables::default', :unsupported => [:mac_os_x] do |tc| + let(:chef_run) do + tc.chef_run + end + + it 'FB::Iptables::TemplateHelpers::each_table yields |table,chains|' do + chef_run.converge(described_recipe) do |node| + node.default['fb_iptables']['filter']['only'] = 4 + end + FB::Iptables.each_table(4, chef_run.node) do |table_name, chains| + expect(FB::Iptables::TABLES_AND_CHAINS.keys.include?(table_name)). + to be true + x = chef_run.node['fb_iptables'][table_name].to_hash + x.delete('only') + expect(chains).to eq(x) + end + FB::Iptables.each_table(6, chef_run.node) do |table_name, _chains| + expect(table_name).not_to eq('filter') + end + end + + it 'creates a default /etc/sysconfig/ip[6]tables' do + chef_run.converge(described_recipe) + expect(chef_run).to render_file('/etc/sysconfig/iptables'). + with_content(tc.fixture('iptables_min')) + expect(chef_run).to render_file('/etc/sysconfig/ip6tables'). + with_content(tc.fixture('iptables_min')) + end + + it 'change default policies' do + chef_run.converge(described_recipe) do |node| + FB::Iptables::TABLES_AND_CHAINS.each do |t, chains| + chains.each do |c| + node.default['fb_iptables'][t][c]['policy'] = 'DROP' + end + end + end + expect(chef_run).to render_file('/etc/sysconfig/iptables'). + with_content(tc.fixture('iptables_drop')) + expect(chef_run).to render_file('/etc/sysconfig/ip6tables'). + with_content(tc.fixture('iptables_drop')) + end + + it 'complex ruleset' do + chef_run.converge(described_recipe) do |node| + { + 'test_1' => { + 'rule' => '-p udp -j REJECT', + }, + 'test_2' => { + 'ip' => 4, + 'rules' => [ + '-p udp -s 192.168.0.1 -j DROP', + '-p udp -s 192.168.0.2 -j DROP', + ], + }, + 'test_3' => { + 'ip' => [6], + 'rule' => '-p udp -s 2a03:2880:2130:cf05:face:b00c::3 -j DROP', + }, + }.each do |name, rule| + node.default['fb_iptables']['filter']['INPUT']['rules'][name] = + rule + end + end + expect(chef_run).to render_file('/etc/sysconfig/iptables'). + with_content(tc.fixture('iptables_complex')) + expect(chef_run).to render_file('/etc/sysconfig/ip6tables'). + with_content(tc.fixture('ip6tables_complex')) + end + + it 'multiple chain with ruleset' do + chef_run.converge(described_recipe) do |node| + { + 'test_1' => { + 'rule' => '-p udp -j REJECT', + }, + 'test_2' => { + 'ip' => 4, + 'rules' => [ + '-p udp -s 192.168.0.1 -j DROP', + '-p udp -s 192.168.0.2 -j DROP', + ], + }, + 'test_3' => { + 'rule' => '-p tcp --dport 3306 -j LOG_DB', + }, + }.each do |name, rule| + node.default['fb_iptables']['filter']['INPUT']['rules'][name] = + rule + end + { + 'test_4' => { + 'ip' => 4, + 'rules' => [ + '-p tcp -j REJECT --reject-with tcp-reset', + ], + }, + 'test_5' => { + 'ip' => 6, + 'rules' => [ + '-j LOG --log-prefix db-packet-dropped: --log-level 4', + ], + }, + }.each do |name, rule| + node.default['fb_iptables']['filter']['LOG_DB']['rules'][name] = + rule + end + end + expect(chef_run).to render_file('/etc/sysconfig/iptables'). + with_content(tc.fixture('iptables_multi_chain')) + expect(chef_run).to render_file('/etc/sysconfig/ip6tables'). + with_content(tc.fixture('ip6tables_multi_chain')) + end +end diff --git a/cookbooks/fb_iptables/spec/fixtures/default/ip6tables_complex b/cookbooks/fb_iptables/spec/fixtures/default/ip6tables_complex new file mode 100644 index 0000000..08c36d1 --- /dev/null +++ b/cookbooks/fb_iptables/spec/fixtures/default/ip6tables_complex @@ -0,0 +1,25 @@ +### This file generated by Chef. Changes will be overwritten. +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT + +*filter +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +# test_1 +-A INPUT -p udp -j REJECT +# test_3 +-A INPUT -p udp -s 2a03:2880:2130:cf05:face:b00c::3 -j DROP +COMMIT + +*raw +:PREROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT + +#Completed diff --git a/cookbooks/fb_iptables/spec/fixtures/default/ip6tables_multi_chain b/cookbooks/fb_iptables/spec/fixtures/default/ip6tables_multi_chain new file mode 100644 index 0000000..edf7392 --- /dev/null +++ b/cookbooks/fb_iptables/spec/fixtures/default/ip6tables_multi_chain @@ -0,0 +1,28 @@ +### This file generated by Chef. Changes will be overwritten. +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT + +*filter +-N LOG_DB +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +# test_1 +-A INPUT -p udp -j REJECT +# test_3 +-A INPUT -p tcp --dport 3306 -j LOG_DB +# test_5 +-A LOG_DB -j LOG --log-prefix db-packet-dropped: --log-level 4 +COMMIT + +*raw +:PREROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT + +#Completed diff --git a/cookbooks/fb_iptables/spec/fixtures/default/iptables_complex b/cookbooks/fb_iptables/spec/fixtures/default/iptables_complex new file mode 100644 index 0000000..ff70ff2 --- /dev/null +++ b/cookbooks/fb_iptables/spec/fixtures/default/iptables_complex @@ -0,0 +1,26 @@ +### This file generated by Chef. Changes will be overwritten. +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT + +*filter +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +# test_1 +-A INPUT -p udp -j REJECT +# test_2 +-A INPUT -p udp -s 192.168.0.1 -j DROP +-A INPUT -p udp -s 192.168.0.2 -j DROP +COMMIT + +*raw +:PREROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT + +#Completed diff --git a/cookbooks/fb_iptables/spec/fixtures/default/iptables_drop b/cookbooks/fb_iptables/spec/fixtures/default/iptables_drop new file mode 100644 index 0000000..02baf18 --- /dev/null +++ b/cookbooks/fb_iptables/spec/fixtures/default/iptables_drop @@ -0,0 +1,21 @@ +### This file generated by Chef. Changes will be overwritten. +*mangle +:PREROUTING DROP [0:0] +:INPUT DROP [0:0] +:OUTPUT DROP [0:0] +:FORWARD DROP [0:0] +:POSTROUTING DROP [0:0] +COMMIT + +*filter +:INPUT DROP [0:0] +:OUTPUT DROP [0:0] +:FORWARD DROP [0:0] +COMMIT + +*raw +:PREROUTING DROP [0:0] +:OUTPUT DROP [0:0] +COMMIT + +#Completed diff --git a/cookbooks/fb_iptables/spec/fixtures/default/iptables_min b/cookbooks/fb_iptables/spec/fixtures/default/iptables_min new file mode 100644 index 0000000..8906641 --- /dev/null +++ b/cookbooks/fb_iptables/spec/fixtures/default/iptables_min @@ -0,0 +1,21 @@ +### This file generated by Chef. Changes will be overwritten. +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT + +*filter +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +COMMIT + +*raw +:PREROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT + +#Completed diff --git a/cookbooks/fb_iptables/spec/fixtures/default/iptables_multi_chain b/cookbooks/fb_iptables/spec/fixtures/default/iptables_multi_chain new file mode 100644 index 0000000..4b16791 --- /dev/null +++ b/cookbooks/fb_iptables/spec/fixtures/default/iptables_multi_chain @@ -0,0 +1,31 @@ +### This file generated by Chef. Changes will be overwritten. +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT + +*filter +-N LOG_DB +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +# test_1 +-A INPUT -p udp -j REJECT +# test_2 +-A INPUT -p udp -s 192.168.0.1 -j DROP +-A INPUT -p udp -s 192.168.0.2 -j DROP +# test_3 +-A INPUT -p tcp --dport 3306 -j LOG_DB +# test_4 +-A LOG_DB -p tcp -j REJECT --reject-with tcp-reset +COMMIT + +*raw +:PREROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT + +#Completed diff --git a/cookbooks/fb_iptables/templates/default/fb_iptables.conf.erb b/cookbooks/fb_iptables/templates/default/fb_iptables.conf.erb index bdb6823..fe4b837 100644 --- a/cookbooks/fb_iptables/templates/default/fb_iptables.conf.erb +++ b/cookbooks/fb_iptables/templates/default/fb_iptables.conf.erb @@ -1,6 +1,9 @@ <% node['fb_iptables']['dynamic_chains'].to_hash.each do |table, chains| %> <%= table.tr('a-z', 'A-Z') %>_CHAINS="<%= chains.keys.join(' ') %>" <% end %> +CONFIG_DIR="<%= @iptables_config_dir %>" +RULES_FILE="<%= @iptables_rules_file %>" +RULES6_FILE="<%= @ip6tables_rules_file %>" TABLES="<%= FB::Iptables::TABLES_AND_CHAINS.keys.join(' ') %>" <% FB::Iptables::TABLES_AND_CHAINS.each do |table, chains| diff --git a/cookbooks/fb_iptables/templates/default/iptables.erb b/cookbooks/fb_iptables/templates/default/iptables.erb index 5ca2823..5326c35 100644 --- a/cookbooks/fb_iptables/templates/default/iptables.erb +++ b/cookbooks/fb_iptables/templates/default/iptables.erb @@ -1,33 +1,55 @@ ### This file generated by Chef. Changes will be overwritten. <% FB::Iptables.each_table(@ip, node) do |table, chains| %> *<%= table %> +<%# + Each dynamic chain needs to be created. We won't touch them, but + they need to be created. +%> <% node['fb_iptables']['dynamic_chains'][table].keys.each do |chain| %> -N <%= chain %> <% end %> +<%# + Any chains the user wants that aren't in the default set also need to be + created. +%> +<% user_chains = chains.keys - FB::Iptables::TABLES_AND_CHAINS[table] %> +<% user_chains.each do |chain| %> +-N <%= chain %> +<% end %> +<%# + Any chains that have a default policy, set it. Note that user chains + don't get default policies +%> <% chains.each do |name, chain| %> -<% dynamic_chains = FB::Iptables.get_dynamic_chains(table, name, node) %> -:<%= name %> <%= chain['policy'] %> [0:0] -<% chain['rules'].each do |rule_name, rule| %> -<% if FB::Iptables.rule_supports_ip_version?(rule, @ip) %> -# <%= rule_name %> -<% if rule['rules'] %> -<% rule['rules'].each do |line| %> --A <%= name %> <%= line %> -<% end %> -<% end %> -<% if rule['rule'] %> --A <%= name %> <%= rule['rule'] %> +<% if chain['policy'] %> +:<%= name %> <%= chain['policy'] %> [0:0] +<% end %> +<% end %> +<%# + Now that all the chains have been created, go ahead and populate the rules + for them +%> +<% chains.each do |name, chain| %> +<% chain['rules'].each do |rule_name, rule| %> +<% if FB::Iptables.rule_supports_ip_version?(rule, @ip) %> +# <%= rule_name %> +<% if rule['rules'] %> +<% rule['rules'].each do |line| %> +-A <%= name %> <%= line %> <% end %> <% end %> +<% if rule['rule'] %> +-A <%= name %> <%= rule['rule'] %> +<% end %> <% end %> -<% - unless dynamic_chains - next - end - dynamic_chains.each do |dynamic_chain_name| %> +<% end %> +<% # If any dynamic chains should be jumped to from this chain, add them %> +<% dynamic_chains = FB::Iptables.get_dynamic_chains(table, name, node) %> +<% next unless dynamic_chains %> +<% dynamic_chains.each do |dynamic_chain_name| %> -A <%= name %> -j <%= dynamic_chain_name %> -<% end%> -<% end %> +<% end%> +<% end %> COMMIT <% end %>