Commit edb14d34 authored by m.pausch's avatar m.pausch
Browse files

syntax, typos, bugs, style

parent 9674e8c8
#
# Cookbook Name:: sys
# Cookbook:: sys
# Library:: Helpers::Nftables
#
# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
# Copyright:: 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
#
# Authors:
# Matthias Pausch (m.pausch@gsi.de)
......@@ -28,14 +28,6 @@ module Sys
require 'ipaddr'
include Chef::Mixin::ShellOut
def dport(new_resource)
new_resource.dest_port || new_resource.port
end
def sport(new_resource)
new_resource.source_port
end
def valid_ips?(ips)
Array(ips).inject(false) do |a, ip|
a || !!IPAddr.new(ip)
......@@ -55,16 +47,16 @@ module Sys
end
end
def port_to_s(p)
if p.is_a?(String)
p
elsif p && p.is_a?(Integer)
p.to_s
elsif p && p.is_a?(Array)
p_strings = p.map { |o| port_to_s(o) }
"{#{p_strings.sort.join(',')}}"
elsif p && p.is_a?(Range)
"#{p.first}-#{p.last}"
def port_to_s(port)
if port.is_a?(String)
port
elsif port && port.is_a?(Integer)
port.to_s
elsif port && port.is_a?(Array)
port_strings = port.map { |o| port_to_s(o) }
"{#{port_strings.sort.join(',')}}"
elsif port && port.is_a?(Range)
"#{port.first}-#{port.last}"
end
end
......@@ -73,33 +65,29 @@ module Sys
sorted_values = rules.values.sort.uniq
sorted_values.each do |sorted_value|
contents << "# position #{sorted_value}"
contents << rules.select { |_,v| v == sorted_value }.keys.join("\n")
contents << rules.select { |_, v| v == sorted_value }.keys.join("\n")
end
"#{contents.join("\n")}\n"
end
unless defined? CHAIN
CHAIN = {
in: 'input',
out: 'output',
pre: 'prerouting',
post: 'postrouting',
forward: 'forward',
}.freeze
end
unless defined? TARGET
TARGET = {
accept: 'accept',
allow: 'accept',
deny: 'drop',
drop: 'drop',
log: 'log prefix "nftables:" group 0',
masquerade: 'masquerade',
redirect: 'redirect',
reject: 'reject',
}.freeze
end
CHAIN ||= {
in: 'input',
out: 'output',
pre: 'prerouting',
post: 'postrouting',
forward: 'forward',
}.freeze
TARGET ||= {
accept: 'accept',
allow: 'accept',
deny: 'drop',
drop: 'drop',
log: 'log prefix "nftables:" group 0',
masquerade: 'masquerade',
redirect: 'redirect',
reject: 'reject',
}.freeze
def build_nftables_rule(rule_resource)
return rule_resource.raw.strip if rule_resource.raw
......@@ -118,7 +106,7 @@ module Sys
nftables_rule << CHAIN.fetch(rule_resource.direction.to_sym)
nftables_rule << ' '
nftables_rule << "iif #{rule_resource.interface} " if rule_resource.interface
nftables_rule << "oif #{rule_resource.outerface} " if rule_resource.dest_interface
nftables_rule << "oif #{rule_resource.outerface} " if rule_resource.outerface
if rule_resource.source
source_set = build_set_of_ips(rule_resource.source)
......@@ -136,12 +124,12 @@ module Sys
when :'ipv6-icmp', :icmpv6
nftables_rule << 'icmpv6 type { echo-request, nd-router-solicit, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } '
when :tcp, :udp
nftables_rule << "#{rule_resource.protocol} sport #{port_to_s(rule_resource.sport)} " if sport(rule_resource)
nftables_rule << "#{rule_resource.protocol} dport #{port_to_s(rule_resource.dport)} " if dport(rule_resource)
nftables_rule << "#{rule_resource.protocol} sport #{port_to_s(rule_resource.sport)} " if rule_resource.sport
nftables_rule << "#{rule_resource.protocol} dport #{port_to_s(rule_resource.dport)} " if rule_resource.dport
when :esp, :ah
nftables_rule << "#{ip_family} #{ip_family == :ip6 ? 'nexthdr' : 'protocol'} #{rule_resource.protocol} "
# nothing to do default :ipv6, :none
# nothing to do default :ipv6, :none
end
nftables_rule << "ct state #{Array(rule_resource.stateful).join(',').downcase} " if rule_resource.stateful
......@@ -152,39 +140,29 @@ module Sys
nftables_rule
end
def log_nftables
shell_out!('nft -n list ruleset')
rescue Mixlib::ShellOut::ShellCommandFailed
Chef::Log.info('log_nftables failed!')
rescue Mixlib::ShellOut::CommandTimeout
Chef::Log.info('log_nftables timed out!')
end
def default_ruleset(new_resource)
rules = {
'add table inet filter' => 1,
"add chain inet filter INPUT { type filter hook input priority 0 ; policy #{new_resource.input_policy}; }" => 2,
"add chain inet filter OUTPUT { type filter hook output priority 0 ; policy #{new_resource.output_policy}; }" => 2,
"add chain inet filter FOWARD { type filter hook forward priority 0 ; policy #{new_resource.forward_policy}; }" => 2,
"add chain inet filter input { type filter hook input priority 0 ; policy #{new_resource.input_policy}; }" => 2,
"add chain inet filter output { type filter hook output priority 0 ; policy #{new_resource.output_policy}; }" => 2,
"add chain inet filter forward { type filter hook forward priority 0 ; policy #{new_resource.forward_policy}; }" => 2,
}
if new_resource.table_ip_nat
rules['add table ip nat'] = 1
rules['add chain ip nat POSTROUTING { type nat hook postrouting priority 100 ;}'] = 2
rules['add chain ip nat PREROUTING { type nat hook prerouting priority -100 ;}'] = 2
rules['add chain ip nat postrouting { type nat hook postrouting priority 100 ;}'] = 2
rules['add chain ip nat prerouting { type nat hook prerouting priority -100 ;}'] = 2
end
if new_resource.table_ip6_nat
rules['add table ip6 nat'] = 1
rules['add chain ip6 nat POSTROUTING { type nat hook postrouting priority 100 ;}'] = 2
rules['add chain ip6 nat PREROUTING { type nat hook prerouting priority -100 ;}'] = 2
rules['add chain ip6 nat postrouting { type nat hook postrouting priority 100 ;}'] = 2
rules['add chain ip6 nat prerouting { type nat hook prerouting priority -100 ;}'] = 2
end
rules
end
def ensure_default_rules_exist(current_node, new_resource)
def ensure_default_rules_exist(new_resource)
input = new_resource.rules || {}
input.merge!(default_ruleset(current_node).to_h)
new_resource.rules(input)
input.merge!(default_ruleset(new_resource))
end
end
end
......
#
# Cookbook Name:: sys
# Cookbook:: sys
# Resource:: nftables
#
# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
# Copyright:: 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
#
# Authors:
# Matthias Pausch (m.pausch@gsi.de)
......@@ -25,7 +25,6 @@
if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION))
action_class do
include Sys::Helpers::Nftables
def lookup_or_create_service(name)
......@@ -51,30 +50,29 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
end
end
#unified_mode true
provides :nftables, os: 'linux', platform: %w(debian)
# unified_mode true
property :rules,
Hash
property :input_policy,
String,
equal_to: %w(drop accept),
default: 'accept'
String,
equal_to: %w(drop accept),
default: 'accept'
property :output_policy,
String,
equal_to: %w(drop accept),
default: 'accept'
String,
equal_to: %w(drop accept),
default: 'accept'
property :forward_policy,
String,
equal_to: %w(drop accept),
default: 'accept'
String,
equal_to: %w(drop accept),
default: 'accept'
property :table_ip_nat,
[true, false],
default: false
[true, false],
default: false
property :table_ip6_nat,
[true, false],
default: false
[true, false],
default: false
def whyrun_supported?
false
......@@ -91,14 +89,17 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
edit_resource('sys_nftables', new_resource.name) do
action :nothing
delayed_action :rebuild
forward_policy new_resource.forward_policy
output_policy new_resource.output_policy
input_policy new_resource.input_policy
table_ip_nat new_resource.table_ip_nat
table_ip6_nat new_resource.table_ip6_nat
end
end
end
action :rebuild do
ensure_default_rules_exist(node, new_resource)
# prints all the nftables rules
log_nftables
ensure_default_rules_exist(new_resource)
# this takes the commands in each hash entry and builds a rule file
nftables_file = lookup_or_create_rulesfile('/etc/nftables.conf')
......
#
# Cookbook Name:: sys
# Cookbook:: sys
# Resource:: nftables_rule
#
# Copyright 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
# Copyright:: 2022 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
#
# Authors:
# Matthias Pausch (m.pausch@gsi.de)
......@@ -35,6 +35,7 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
end
provides :nftables_rule
# unified_mode true
default_action :create
property :nftables_name,
......@@ -43,15 +44,15 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
property :command,
Symbol,
default: :allow,
equal_to: %i[
equal_to: %i(
accept allow deny drop log masquerade redirect reject
]
)
property :protocol,
[Integer, Symbol],
default: :tcp,
callbacks: { 'must be valid IP protocol specification' =>
lambda(p) do
%i[udp tcp icmp icmpv6 ipv6-icmp esp ah ipv6 none].include?(p) || (0..142).include?(p)
lambda do |p|
%i(udp tcp icmp icmpv6 ipv6-icmp esp ah ipv6 none).include?(p) || (0..142).include?(p)
end }
property :direction,
Symbol,
......@@ -70,11 +71,11 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
property :source,
[String, Array],
callbacks: {
'must be a valid ip address' => lambda(ips) do
'must be a valid ip address' => lambda do |ips|
Array(ips).inject(false) do |a, ip|
a || !!IPAddr.new(ip)
end
end
end,
}
property :sport,
[Integer, String, Array, Range]
......@@ -85,11 +86,11 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
property :destination,
[String, Array],
callbacks: {
'must be a valid ip address' => lambda(ips) do
'must be a valid ip address' => lambda do |ips|
Array(ips).inject(false) do |a, ip|
a || !!IPAddr.new(ip)
end
end
end,
}
property :outerface,
String
......@@ -124,7 +125,7 @@ if Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION
edit_resource!('sys_nftables', new_resource.nftables_name) do |fw_rule|
r = rules.dup || {}
r.merge!({
fwr => fw_rule.position
fwr => fw_rule.position,
})
rules(r)
delayed_action :rebuild
......
return unless Gem::Requirement.new('>= 12.15').satisfied_by?(Gem::Version.new(Chef::VERSION))
firewall 'default' do
nftables 'default' do
table_ip_nat true
table_ip6_nat true
input_policy 'drop'
end
firewall_rule 'allow loopback' do
nftables_rule 'allow loopback' do
interface 'lo'
protocol :none
command :allow
only_if { node['sys']['firewall']['allow_loopback'] }
end
firewall_rule 'allow icmp' do
nftables_rule 'allow icmp' do
protocol :icmp
command :allow
only_if { node['sys']['firewall']['allow_icmp'] }
end
firewall_rule 'allow world to ssh' do
port 22
only_if { node['sys']['firewall']['allow_ssh'] }
end
# allow established connections
firewall_rule 'established' do
nftables_rule 'established' do
position 40
stateful [:related, :established]
protocol :none # explicitly don't specify protocol
command :allow
only_if { node['sys']['firewall']['allow_established'] }
end
firewall_rule 'ssh22' do
port 22
command :allow
nftables_rule 'ssh22' do
dport 22
end
firewall_rule 'port array' do
port [2222, 2200]
nftables_rule 'port array' do
dport [2222, 2200]
command :allow
end
firewall_rule 'range' do
port 1000..1100
nftables_rule 'range' do
dport 1000..1100
command :allow
end
firewall_rule 'range-udp' do
port 60000..61000
nftables_rule 'range-udp' do
dport 60000..61000
protocol :udp
end
firewall_rule 'ping6' do
nftables_rule 'ping6' do
protocol :icmpv6
end
# other rules
firewall_rule 'temp1' do
port 1234
nftables_rule 'temp1' do
dport 1234
command :deny
end
firewall_rule 'temp2' do
port 1235
nftables_rule 'temp2' do
dport 1235
command :reject
end
firewall_rule 'addremove' do
port 1236
nftables_rule 'addremove' do
dport 1236
command :allow
end
firewall_rule 'addremove2' do
port 1236
nftables_rule 'addremove2' do
dport 1236
command :deny
end
firewall_rule 'protocolnum' do
nftables_rule 'protocolnum' do
protocol 112
command :allow
end
firewall_rule 'prepend' do
port 7788
nftables_rule 'prepend' do
dport 7788
position 5
end
firewall_rule "block single ip" do
nftables_rule "block single ip" do
source '192.168.99.99'
position 49
command :reject
end
firewall_rule 'block ip-range' do
nftables_rule 'block ip-range' do
source ['192.168.99.99', '192.168.100.100']
command :drop
end
firewall_rule "block single destination ip" do
nftables_rule "block single destination ip" do
destination '192.168.99.99'
position 49
command :reject
end
firewall_rule 'block destination ip-range' do
nftables_rule 'block destination ip-range' do
destination ['192.168.99.99', '192.168.100.100']
command :drop
end
firewall_rule 'ipv6-source' do
port 80
nftables_rule 'ipv6-source' do
dport 80
family :ip6
source '2001:db8::ff00:42:8329'
command :allow
end
firewall_rule 'array' do
port [1234, 5000..5100, '5678']
nftables_rule 'array' do
dport [1234, 5000..5100, '5678']
command :allow
end
firewall_rule 'RPC Port Range In' do
port 5000..5100
nftables_rule 'RPC Port Range In' do
dport 5000..5100
protocol :tcp
command :allow
direction :in
end
firewall_rule 'HTTP HTTPS' do
port [80, 443]
nftables_rule 'HTTP HTTPS' do
dport [80, 443]
protocol :tcp
direction :out
command :allow
end
firewall_rule 'port2433' do
nftables_rule 'port2433' do
description 'This should not be included'
include_comment false
source '127.0.0.0/8'
port 2433
dport 2433
direction :in
command :allow
end
firewall_rule 'esp' do
nftables_rule 'esp' do
protocol :esp
command :allow
end
firewall_rule 'ah' do
nftables_rule 'ah' do
protocol :ah
command :allow
end
firewall_rule 'esp-ipv6' do
nftables_rule 'esp-ipv6' do
source '::'
family :ip6
protocol :esp
command :allow
end
firewall_rule 'ah-ipv6' do
nftables_rule 'ah-ipv6' do
source '::'
family :ip6
protocol :ah
command :allow
end
firewall_rule 'redirect' do
nftables_rule 'redirect' do
direction :pre
port 5555
dport 5555
redirect_port 6666
command :redirect
end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment