X-Git-Url: https://git.openstreetmap.org./chef.git/blobdiff_plain/8eee3f5c0467b78c1e3835246867dccc743b4f24..84b5aa673d3d29cbf124c93abaa4c6995b9c1ea5:/cookbooks/networking/resources/firewall_rule.rb diff --git a/cookbooks/networking/resources/firewall_rule.rb b/cookbooks/networking/resources/firewall_rule.rb index e92681ec7..6f429ac5d 100644 --- a/cookbooks/networking/resources/firewall_rule.rb +++ b/cookbooks/networking/resources/firewall_rule.rb @@ -20,6 +20,8 @@ resource_name :firewall_rule provides :firewall_rule +unified_mode true + default_action :nothing property :rule, :kind_of => String, :name_property => true @@ -27,11 +29,11 @@ property :family, :kind_of => [String, Symbol] property :source, :kind_of => String, :required => true property :dest, :kind_of => String, :required => true property :proto, :kind_of => String, :required => true -property :dest_ports, :kind_of => [String, Integer], :default => "-" -property :source_ports, :kind_of => [String, Integer], :default => "-" -property :rate_limit, :kind_of => String, :default => "-" -property :connection_limit, :kind_of => [String, Integer], :default => "-" -property :helper, :kind_of => String, :default => "-" +property :dest_ports, :kind_of => [String, Integer, Array] +property :source_ports, :kind_of => [String, Integer, Array] +property :rate_limit, :kind_of => String +property :connection_limit, :kind_of => [String, Integer] +property :helper, :kind_of => String property :compile_time, TrueClass, :default => true @@ -49,29 +51,98 @@ end action_class do def add_rule(action) - rule = { - :action => action.to_s.upcase, - :source => new_resource.source, - :dest => new_resource.dest, - :proto => new_resource.proto, - :dest_ports => new_resource.dest_ports.to_s, - :source_ports => new_resource.source_ports.to_s, - :rate_limit => new_resource.rate_limit, - :connection_limit => new_resource.connection_limit.to_s, - :helper => new_resource.helper - } - if new_resource.family.nil? - node.default[:networking][:firewall][:inet] << rule - node.default[:networking][:firewall][:inet6] << rule + add_nftables_rule(action, "inet") + add_nftables_rule(action, "inet6") elsif new_resource.family.to_s == "inet" - node.default[:networking][:firewall][:inet] << rule + add_nftables_rule(action, "inet") elsif new_resource.family.to_s == "inet6" - node.default[:networking][:firewall][:inet6] << rule - else - log "Unsupported network family" do - level :error - end + add_nftables_rule(action, "inet6") + end + end + + def add_nftables_rule(action, family) + rule = [] + + ip = case family + when "inet" then "ip" + when "inet6" then "ip6" + end + + proto = new_resource.proto + + if new_resource.source_ports + rule << "#{proto} sport { #{nftables_source_ports} }" + end + + if new_resource.dest_ports + rule << "#{proto} dport { #{nftables_dest_ports} }" + end + + if new_resource.source == "osm" + rule << "#{ip} saddr @#{ip}-osm-addresses" + elsif new_resource.source =~ /^net:(.*)$/ + addresses = Regexp.last_match(1).split(",").join(", ") + + rule << "#{ip} saddr { #{addresses} }" + end + + if new_resource.dest == "osm" + rule << "#{ip} daddr @#{ip}-osm-addresses" + elsif new_resource.dest =~ /^net:(.*)$/ + addresses = Regexp.last_match(1).split(",").join(", ") + + rule << "#{ip} daddr { #{addresses} }" + end + + rule << "ct state new" if new_resource.proto == "tcp" + + if new_resource.connection_limit + set = "connlimit-#{new_resource.rule}-#{ip}" + + node.default[:networking][:firewall][:sets] << set + + rule << "add @#{set} { #{ip} saddr ct count #{new_resource.connection_limit} }" + end + + if new_resource.rate_limit =~ %r{^s:(\d+)/sec:(\d+)$} + set = "ratelimit-#{new_resource.rule}-#{ip}" + rate = Regexp.last_match(1) + burst = Regexp.last_match(2) + + node.default[:networking][:firewall][:sets] << set + + rule << "update @#{set} { #{ip} saddr limit rate #{rate}/second burst #{burst} packets }" + end + + if new_resource.helper + helper = "#{new_resource.rule}-#{new_resource.helper}" + + node.default[:networking][:firewall][:helpers] << { + :name => helper, :helper => new_resource.helper, :protocol => proto + } + + rule << "ct helper set #{helper}" + end + + rule << case action + when :accept then "accept" + when :drop then "jump log-and-drop" + when :reject then "jump log-and-reject" + end + + if new_resource.source == "fw" + node.default[:networking][:firewall][:outgoing] << rule.join(" ") + elsif new_resource.dest == "fw" + node.default[:networking][:firewall][:incoming] << rule.join(" ") end end + + def nftables_source_ports + Array(new_resource.source_ports).map(&:to_s).join(",") + end + + def nftables_dest_ports + Array(new_resource.dest_ports).map(&:to_s).join(",") + end end