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