]> git.openstreetmap.org Git - chef.git/commitdiff
Refactor firewall rules to simplify IPv4/IPv6 handling
authorTom Hughes <tom@compton.nu>
Thu, 9 Mar 2023 18:26:46 +0000 (18:26 +0000)
committerTom Hughes <tom@compton.nu>
Sat, 11 Mar 2023 14:30:59 +0000 (14:30 +0000)
13 files changed:
cookbooks/bind/recipes/default.rb
cookbooks/exim/recipes/default.rb
cookbooks/ftp/recipes/default.rb
cookbooks/geodns/recipes/default.rb
cookbooks/logstash/recipes/default.rb
cookbooks/munin/recipes/default.rb
cookbooks/networking/recipes/default.rb
cookbooks/networking/resources/firewall_rule.rb
cookbooks/openssh/recipes/default.rb
cookbooks/prometheus/resources/exporter.rb
cookbooks/rsyncd/recipes/default.rb
cookbooks/snmpd/recipes/default.rb
roles/lyonix.rb

index 6c596420de79e514c3ac0af10886f6d2b197c01f..10ab7ce0bba31b4f89e205b361e57bf6f3ca5fc3 100644 (file)
@@ -62,16 +62,14 @@ end
 
 firewall_rule "accept-dns-udp" do
   action :accept
-  source "net"
-  dest "fw"
-  proto "udp"
+  context :incoming
+  protocol :udp
   dest_ports "domain"
 end
 
 firewall_rule "accept-dns-tcp" do
   action :accept
-  source "net"
-  dest "fw"
-  proto "tcp"
+  context :incoming
+  protocol :tcp
   dest_ports "domain"
 end
index dbf90bdfb4554397df2cb54b0295214089da10d8..71309e6090e12c44c744665da2b1ec0d1c0b45d6 100644 (file)
@@ -229,56 +229,36 @@ prometheus_exporter "exim" do
 end
 
 if node[:exim][:smarthost_name]
-  node[:exim][:daemon_smtp_ports].each do |port|
-    firewall_rule "accept-inbound-smtp-#{port}" do
-      action :accept
-      source "net"
-      dest "fw"
-      proto "tcp"
-      dest_ports port
-      source_ports "1024-65535"
-    end
+  firewall_rule "accept-inbound-smtp" do
+    action :accept
+    context :incoming
+    protocol :tcp
+    dest_ports node[:exim][:daemon_smtp_ports]
+    source_ports "1024-65535"
   end
 else
-  smarthosts_inet = []
-  smarthosts_inet6 = []
+  smarthosts = []
 
   search(:node, "exim_smarthost_name:*?").each do |host|
-    smarthosts_inet |= host.ipaddresses(:role => :external, :family => :inet)
-    smarthosts_inet6 |= host.ipaddresses(:role => :external, :family => :inet6)
+    smarthosts |= host.ipaddresses(:role => :external)
   end
 
-  node[:exim][:daemon_smtp_ports].each do |port|
-    firewall_rule "accept-inbound-smtp-#{port}" do
-      action :accept
-      family :inet
-      source "net:#{smarthosts_inet.sort.join(',')}"
-      dest "fw"
-      proto "tcp"
-      dest_ports port
-      source_ports "1024-65535"
-      not_if { smarthosts_inet.empty? }
-    end
-
-    firewall_rule "accept-inbound-smtp-#{port}" do
-      action :accept
-      family :inet6
-      source "net:#{smarthosts_inet6.sort.join(',')}"
-      dest "fw"
-      proto "tcp"
-      dest_ports port
-      source_ports "1024-65535"
-      not_if { smarthosts_inet6.empty? }
-    end
+  firewall_rule "accept-inbound-smtp" do
+    action :accept
+    context :incoming
+    protocol :tcp
+    source smarthosts
+    dest_ports node[:exim][:daemon_smtp_ports]
+    source_ports "1024-65535"
+    not_if { smarthosts.empty? }
   end
 end
 
 if node[:exim][:smarthost_via]
   firewall_rule "deny-outbound-smtp" do
     action :reject
-    source "fw"
-    dest "net"
-    proto "tcp"
+    context :outgoing
+    protocol :tcp
     dest_ports "smtp"
   end
 end
index 14ab725a0e402495163c2c9bee4c0792fa78b00a..9cd534a0b98d7022f9c43a845ceebcdd4d7121c5 100644 (file)
@@ -45,9 +45,8 @@ end
 
 firewall_rule "accept-ftp-tcp" do
   action :accept
-  source "net"
-  dest "fw"
-  proto "tcp"
+  context :incoming
+  protocol :tcp
   dest_ports "ftp"
   helper "ftp"
 end
index b40a7643f9c7082e6d035861f97f70c248d7058b..a50b711411b461253de52123f894e3f3784bf230 100644 (file)
@@ -90,16 +90,14 @@ end
 
 firewall_rule "accept-dns-udp" do
   action :accept
-  source "net"
-  dest "fw"
-  proto "udp"
+  context :incoming
+  protocol :udp
   dest_ports "domain"
 end
 
 firewall_rule "accept-dns-tcp" do
   action :accept
-  source "net"
-  dest "fw"
-  proto "tcp"
+  context :incoming
+  protocol :tcp
   dest_ports "domain"
 end
index 56caa73129ff7a123c441107deaed3da3d595a5b..34f731af29734698f9c9dddc0a157a32ba54bb8b 100644 (file)
@@ -74,54 +74,26 @@ template "/etc/cron.daily/expire-logstash" do
   mode "755"
 end
 
-forwarders = search(:node, "recipes:logstash\\:\\:forwarder")
+forwarders = []
 
-forwarders.sort_by { |n| n[:fqdn] }.each do |forwarder|
-  forwarder.interfaces(:role => :external) do |interface|
-    firewall_rule "accept-lumberjack-#{forwarder}" do
-      action :accept
-      family interface[:family]
-      source "net:#{interface[:address]}"
-      dest "fw"
-      proto "tcp"
-      dest_ports "5043"
-      source_ports "1024-65535"
-    end
-
-    firewall_rule "accept-beats-#{forwarder}" do
-      action :accept
-      family interface[:family]
-      source "net:#{interface[:address]}"
-      dest "fw"
-      proto "tcp"
-      dest_ports "5044"
-      source_ports "1024-65535"
-    end
+search(:node, "recipes:logstash\\:\\:forwarder").each do |forwarder|
+  forwarder.interfaces(:role => :external).map do |interface|
+    forwarders << interface[:address]
   end
 end
 
-gateways = search(:node, "roles:gateway")
-
-gateways.sort_by { |n| n[:fqdn] }.each do |gateway|
-  gateway.interfaces(:role => :external) do |interface|
-    firewall_rule "accept-lumberjack-#{gateway}" do
-      action :accept
-      family interface[:family]
-      source "net:#{interface[:address]}"
-      dest "fw"
-      proto "tcp"
-      dest_ports "5043"
-      source_ports "1024-65535"
-    end
-
-    firewall_rule "accept-beats-#{gateway}" do
-      action :accept
-      family interface[:family]
-      source "net:#{interface[:address]}"
-      dest "fw"
-      proto "tcp"
-      dest_ports "5044"
-      source_ports "1024-65535"
-    end
+search(:node, "roles:gateway").each do |forwarder|
+  forwarder.interfaces(:role => :external).map do |interface|
+    forwarders << interface[:address]
   end
 end
+
+firewall_rule "accept-logstash" do
+  action :accept
+  context :incoming
+  protocol :tcp
+  source forwarders
+  dest_ports %w[5043 5044]
+  source_ports "1024-65535"
+  not_if { forwarders.empty? }
+end
index c1233f9b9203804a9aafa4fe5e3f24a947b4c468..0a2a344528159a0bb687300e6fa325170419f5ab 100644 (file)
@@ -24,22 +24,24 @@ service "munin-node" do
   supports :status => true, :restart => true, :reload => true
 end
 
-servers = search(:node, "recipes:munin\\:\\:server")
+servers = []
 
-servers.each do |server|
+search(:node, "recipes:munin\\:\\:server").each do |server|
   server.interfaces(:role => :external) do |interface|
-    firewall_rule "accept-munin-#{server}" do
-      action :accept
-      family interface[:family]
-      source "net:#{interface[:address]}"
-      dest "fw"
-      proto "tcp"
-      dest_ports "munin"
-      source_ports "1024-65535"
-    end
+    servers << interface[:address]
   end
 end
 
+firewall_rule "accept-munin" do
+  action :accept
+  context :incoming
+  protocol :tcp
+  source servers
+  dest_ports "munin"
+  source_ports "1024-65535"
+  not_if { servers.empty? }
+end
+
 template "/etc/munin/munin-node.conf" do
   source "munin-node.conf.erb"
   owner "root"
index 799871963e100279457774c0e37be78f83ab4d1f..f3371490069870b74f1d26fde1b8e053142f9919 100644 (file)
@@ -438,17 +438,11 @@ else
 end
 
 if node[:networking][:wireguard][:enabled]
-  wireguard_source = if node[:roles].include?("gateway")
-                       "net"
-                     else
-                       "osm"
-                     end
-
   firewall_rule "accept-wireguard" do
     action :accept
-    source wireguard_source
-    dest "fw"
-    proto "udp"
+    context :incoming
+    protocol :udp
+    source :osm unless node[:roles].include?("gateway")
     dest_ports "51820"
     source_ports "51820"
   end
@@ -456,9 +450,8 @@ end
 
 firewall_rule "accept-http" do
   action :accept
-  source "net"
-  dest "fw"
-  proto "tcp"
+  context :incoming
+  protocol :tcp
   dest_ports %w[http https]
   rate_limit node[:networking][:firewall][:http_rate_limit]
   connection_limit node[:networking][:firewall][:http_connection_limit]
index 6f429ac5dd537574921e4aa5573ce9febd701537..4cda0486bbbdcea894eaff7bbbe837fbcbe5c0e1 100644 (file)
@@ -17,6 +17,8 @@
 # limitations under the License.
 #
 
+require "ipaddr"
+
 resource_name :firewall_rule
 provides :firewall_rule
 
@@ -25,10 +27,10 @@ unified_mode true
 default_action :nothing
 
 property :rule, :kind_of => String, :name_property => true
-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 :context, :kind_of => Symbol, :required => true, :is => [:incoming, :outgoing]
+property :protocol, :kind_of => Symbol, :required => true, :is => [:udp, :tcp]
+property :source, :kind_of => [String, Symbol, Array]
+property :dest, :kind_of => [String, Symbol, Array]
 property :dest_ports, :kind_of => [String, Integer, Array]
 property :source_ports, :kind_of => [String, Integer, Array]
 property :rate_limit, :kind_of => String
@@ -38,64 +40,37 @@ property :helper, :kind_of => String
 property :compile_time, TrueClass, :default => true
 
 action :accept do
-  add_rule :accept
+  add_rule(:accept, "ip")
+  add_rule(:accept, "ip6")
 end
 
 action :drop do
-  add_rule :drop
+  add_rule(:drop, "ip")
+  add_rule(:drop, "ip6")
 end
 
 action :reject do
-  add_rule :reject
+  add_rule(:reject, "ip")
+  add_rule(:reject, "ip6")
 end
 
 action_class do
-  def add_rule(action)
-    if new_resource.family.nil?
-      add_nftables_rule(action, "inet")
-      add_nftables_rule(action, "inet6")
-    elsif new_resource.family.to_s == "inet"
-      add_nftables_rule(action, "inet")
-    elsif new_resource.family.to_s == "inet6"
-      add_nftables_rule(action, "inet6")
-    end
-  end
-
-  def add_nftables_rule(action, family)
+  def add_rule(action, ip)
     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
+    protocol = new_resource.protocol.to_s
 
-    if new_resource.dest == "osm"
-      rule << "#{ip} daddr @#{ip}-osm-addresses"
-    elsif new_resource.dest =~ /^net:(.*)$/
-      addresses = Regexp.last_match(1).split(",").join(", ")
+    source = addresses(new_resource.source, ip)
+    dest = addresses(new_resource.dest, ip)
 
-      rule << "#{ip} daddr { #{addresses} }"
-    end
+    return if new_resource.source && source.empty?
+    return if new_resource.dest && dest.empty?
 
-    rule << "ct state new" if new_resource.proto == "tcp"
+    rule << "#{protocol} sport #{format_ports(new_resource.source_ports)}"  if new_resource.source_ports
+    rule << "#{protocol} dport #{format_ports(new_resource.dest_ports)}" if new_resource.dest_ports
+    rule << "#{ip} saddr #{format_addresses(source, ip)}" if new_resource.source
+    rule << "#{ip} daddr #{format_addresses(dest, ip)}" if new_resource.dest
+    rule << "ct state new" if new_resource.protocol == :tcp
 
     if new_resource.connection_limit
       set = "connlimit-#{new_resource.rule}-#{ip}"
@@ -119,7 +94,7 @@ action_class do
       helper = "#{new_resource.rule}-#{new_resource.helper}"
 
       node.default[:networking][:firewall][:helpers] << {
-        :name => helper, :helper => new_resource.helper, :protocol => proto
+        :name => helper, :helper => new_resource.helper, :protocol => protocol
       }
 
       rule << "ct helper set #{helper}"
@@ -131,18 +106,32 @@ action_class do
             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(" ")
+    node.default[:networking][:firewall][new_resource.context] << rule.join(" ")
+  end
+
+  def addresses(addresses, ip)
+    if addresses.is_a?(Symbol)
+      addresses
+    else
+      Array(addresses).map do |address|
+        if ip == "ip" && IPAddr.new(address).ipv4?
+          address
+        elsif ip == "ip6" && IPAddr.new(address).ipv6?
+          address
+        end
+      end.compact
     end
   end
 
-  def nftables_source_ports
-    Array(new_resource.source_ports).map(&:to_s).join(",")
+  def format_ports(ports)
+    "{ #{Array(ports).map(&:to_s).join(', ')} }"
   end
 
-  def nftables_dest_ports
-    Array(new_resource.dest_ports).map(&:to_s).join(",")
+  def format_addresses(addresses, ip)
+    if addresses.is_a?(Symbol)
+      "@#{ip}-#{addresses}-addresses"
+    else
+      "{ #{Array(addresses).map(&:to_s).join(', ')} }"
+    end
   end
 end
index 6a299d22695dc7d9d2804e4fab876984a2e95a48..8b57aaaef75ef5e799b1ab08be8e6440cc811817 100644 (file)
@@ -84,8 +84,7 @@ end
 
 firewall_rule "accept-ssh" do
   action :accept
-  source "net"
-  dest "fw"
-  proto "tcp"
+  context :incoming
+  protocol :tcp
   dest_ports node[:openssh][:port]
 end
index 0e1d9d6e46a1be1ac8ffd8be33aa0cc836b58dcc..66dcd2b294ac354ee21f7415b19121576a9fb395 100644 (file)
@@ -78,9 +78,9 @@ action :create do
 
   firewall_rule "accept-prometheus-#{new_resource.exporter}" do
     action :accept
-    source "osm"
-    dest "fw"
-    proto "tcp"
+    context :incoming
+    protocol :tcp
+    source :osm
     dest_ports new_resource.port
     only_if { node[:prometheus][:mode] == "external" }
   end
index bcc0046e467a03521466432778e44490f28ed442..89ee459091705e5e057647b191921fe0beb393ad 100644 (file)
@@ -77,9 +77,8 @@ end
 
 firewall_rule "accept-rsync" do
   action :accept
-  source "net"
-  dest "fw"
-  proto "tcp"
+  context :incoming
+  protocol :tcp
   dest_ports "rsync"
   source_ports "1024-65535"
 end
index 6fc4a36aac8e7e401022c7c2b5a544c919afaa2c..f4a57fef2851d72d81ae9b8e456f3a5203378e6c 100644 (file)
@@ -37,50 +37,11 @@ service "snmpd" do
   supports :status => true, :restart => true
 end
 
-if node[:snmpd][:clients]
-  node[:snmpd][:clients].each do |address|
-    firewall_rule "accept-snmp" do
-      action :accept
-      family "inet"
-      source "net:#{address}"
-      dest "fw"
-      proto "udp"
-      dest_ports "snmp"
-      source_ports "1024-65535"
-    end
-  end
-else
-  firewall_rule "accept-snmp" do
-    action :accept
-    family "inet"
-    source "net"
-    dest "fw"
-    proto "udp"
-    dest_ports "snmp"
-    source_ports "1024-65535"
-  end
-end
-
-if node[:snmpd][:clients6]
-  node[:snmpd][:clients6].each do |address|
-    firewall_rule "accept-snmp" do
-      action :accept
-      family "inet6"
-      source "net:#{address}"
-      dest "fw"
-      proto "udp"
-      dest_ports "snmp"
-      source_ports "1024-65535"
-    end
-  end
-else
-  firewall_rule "accept-snmp" do
-    action :accept
-    family "inet6"
-    source "net"
-    dest "fw"
-    proto "udp"
-    dest_ports "snmp"
-    source_ports "1024-65535"
-  end
+firewall_rule "accept-snmp" do
+  action :accept
+  context :incoming
+  protocol :udp
+  source node[:snmpd][:clients] if node[:snmpd][:clients]
+  dest_ports "snmp"
+  source_ports "1024-65535"
 end
index b44835628a604878f925deac9b6b82ec066cd6a4..b37ccb05c1e6b8d4f583a1a4c48b8c432e7302e9 100644 (file)
@@ -5,8 +5,7 @@ default_attributes(
   :hosted_by => "LyonIX",
   :location => "Lyon, France",
   :snmpd => {
-    :clients => ["77.95.64.0/21"],
-    :clients6 => ["2a03:9180::/32", "2001:7f8:47::/48"],
+    :clients => ["77.95.64.0/21", "2a03:9180::/32", "2001:7f8:47::/48"],
     :community => "lyonix",
     :location => "LYON",
     :contact => "sysadm@rezopole.net"