cookbooks/firewall/libraries/helpers_firewalld.rb
module FirewallCookbook
module Helpers
module Firewalld
include FirewallCookbook::Helpers
include Chef::Mixin::ShellOut
def firewalld_rules_filename
'/etc/sysconfig/firewalld-chef.rules'
end
def firewalld_rule!(cmd)
shell_out!(cmd, input: 'yes')
end
def firewalld_active?
cmd = shell_out('firewall-cmd', '--state')
cmd.stdout =~ /^running$/
end
def firewalld_default_zone?(z)
return false unless firewalld_active?
cmd = shell_out('firewall-cmd', '--get-default-zone')
cmd.stdout =~ /^#{z.to_s}$/
end
def firewalld_default_zone!(z)
raise 'firewalld not active' unless firewalld_active?
shell_out!('firewall-cmd', "--set-default-zone=#{z}")
end
def log_current_firewalld
shell_out!('firewall-cmd --direct --get-all-rules')
end
def firewalld_flush!
raise 'firewall not active' unless firewalld_active?
shell_out!('firewall-cmd', '--direct', '--remove-rules', 'ipv4', 'filter', 'INPUT')
shell_out!('firewall-cmd', '--direct', '--remove-rules', 'ipv4', 'filter', 'OUTPUT')
shell_out!('firewall-cmd', '--direct', '--permanent', '--remove-rules', 'ipv4', 'filter', 'INPUT')
shell_out!('firewall-cmd', '--direct', '--permanent', '--remove-rules', 'ipv4', 'filter', 'OUTPUT')
end
def firewalld_all_rules_permanent!
raise 'firewall not active' unless firewalld_active?
rules = shell_out!('firewall-cmd', '--direct', '--get-all-rules').stdout
perm_rules = shell_out!('firewall-cmd', '--direct', '--permanent', '--get-all-rules').stdout
rules == perm_rules
end
def firewalld_save!
raise 'firewall not active' unless firewalld_active?
shell_out!('firewall-cmd', '--direct', '--permanent', '--remove-rules', 'ipv4', 'filter', 'INPUT')
shell_out!('firewall-cmd', '--direct', '--permanent', '--remove-rules', 'ipv4', 'filter', 'OUTPUT')
shell_out!('firewall-cmd', '--direct', '--get-all-rules').stdout.lines do |line|
shell_out!("firewall-cmd --direct --permanent --add-rule #{line}")
end
end
def ip_versions(resource)
if ipv4_rule?(resource)
%w(ipv4)
elsif ipv6_rule?(resource)
%w(ipv6)
else # no source or destination address, add rules for both ipv4 and ipv6
%w(ipv4 ipv6)
end
end
CHAIN = { in: 'INPUT', out: 'OUTPUT', pre: 'PREROUTING', post: 'POSTROUTING' }.freeze unless defined? CHAIN # , nil => "FORWARD"}
TARGET = { allow: 'ACCEPT', reject: 'REJECT', deny: 'DROP', masquerade: 'MASQUERADE', redirect: 'REDIRECT', log: 'LOG --log-prefix \'iptables: \' --log-level 7' }.freeze unless defined? TARGET
def build_firewall_rule(new_resource, ip_version = 'ipv4')
return new_resource.raw.strip if new_resource.raw
type = new_resource.command
firewall_rule = if new_resource.direction
"#{ip_version} filter #{CHAIN[new_resource.direction.to_sym]} "
else
"#{ip_version} filter FORWARD "
end
firewall_rule << "#{new_resource.position} "
if [:pre, :post].include?(new_resource.direction)
firewall_rule << '-t nat '
end
# Firewalld order of prameters is important here see example output below:
# ipv4 filter INPUT 1 -s 1.2.3.4/32 -d 5.6.7.8/32 -i lo -p tcp -m tcp -m state --state NEW -m comment --comment "hello" -j DROP
firewall_rule << "-s #{ip_with_mask(new_resource, new_resource.source)} " if new_resource.source && new_resource.source != '0.0.0.0/0'
firewall_rule << "-d #{new_resource.destination} " if new_resource.destination
firewall_rule << "-i #{new_resource.interface} " if new_resource.interface
firewall_rule << "-o #{new_resource.dest_interface} " if new_resource.dest_interface
firewall_rule << "-p #{new_resource.protocol} " if new_resource.protocol && new_resource.protocol.to_s.to_sym != :none
firewall_rule << '-m tcp ' if new_resource.protocol && new_resource.protocol.to_s.to_sym == :tcp
# using multiport here allows us to simplify our greps and rule building
firewall_rule << "-m multiport --sports #{port_to_s(new_resource.source_port)} " if new_resource.source_port
firewall_rule << "-m multiport --dports #{port_to_s(dport_calc(new_resource))} " if dport_calc(new_resource)
firewall_rule << "-m state --state #{new_resource.stateful.is_a?(Array) ? new_resource.stateful.join(',').upcase : new_resource.stateful.to_s.upcase} " if new_resource.stateful
firewall_rule << "-m comment --comment '#{new_resource.description}' " if new_resource.include_comment
firewall_rule << "-j #{TARGET[type]} "
firewall_rule << "--to-ports #{new_resource.redirect_port} " if type == :redirect
firewall_rule.strip!
firewall_rule
end
end
end
end