Skip to content

Commit

Permalink
another refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
nilsver committed Nov 19, 2024
1 parent b857350 commit 02d9b5f
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 125 deletions.
8 changes: 4 additions & 4 deletions resources/attributes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@

default['firewall']['roles'] = {
'manager' => {
'home_zone' => {
'home' => {
'tcp_ports' => [
53, 443, 2056, 2057, 2058, 2181, 2888, 3888, 4443,
5432, 7946, 7980, 8080, 8081, 8083, 8084, 8300, 8301,
8302, 8400, 8500, 9000, 9001, 9092, 27017, 50505],
'udp_ports' => [123, 161, 162, 1812, 1813, 2055, 5353, 6343],
'protocols' => ['igmp'],
},
'public_zone' => {
'public' => {
'tcp_ports' => [53, 443, 2056, 2057, 2058, 8080, 8081, 8083, 8084, 9000, 9001],
'udp_ports' => [53, 161, 162, 123, 2055, 6343, 5353],
'protocols' => ['112'],
'rich_rules' => ['rule family="ipv4" source address="224.0.0.18" accept'],
},
},
'proxy' => {
'public_zone' => {
'public' => {
'tcp_ports' => [514, 2056, 2057, 2058, 7779],
'udp_ports' => [161, 162, 1812, 1813, 2055, 6343],
},
},
'ips' => {
'public_zone' => {
'public' => {
'udp_ports' => [161, 162],
},
},
Expand Down
106 changes: 24 additions & 82 deletions resources/libraries/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,96 +4,38 @@ module Helpers
require 'socket'
include ::Chef::Mixin::ShellOut

def fetch_existing_rules(zone)
ports = shell_out!("firewall-cmd --zone=#{zone} --list-ports").stdout.strip.split(/\s+/)
protos = shell_out!("firewall-cmd --zone=#{zone} --list-protocols").stdout.strip.split(/\s+/)
rich_rules = shell_out!("firewall-cmd --zone=#{zone} --list-rich-rules").stdout.strip.split(/\n/)
return ports, protos, rich_rules
end

def configure_firewalld_rules
if is_manager?
ports_home, protos_home, rich_rules_home = fetch_existing_rules('home')
apply_zone_rules(node['firewall']['roles']['manager']['home_zone'], 'home', ports_home, protos_home, rich_rules_home)

ports_pub, protos_pub, rich_rules_pub = fetch_existing_rules('public')
apply_zone_rules(node['firewall']['roles']['manager']['public_zone'], 'public', ports_pub, protos_pub, rich_rules_pub)
end
if is_proxy?
ports_pub, protos_pub, rich_rules_pub = fetch_existing_rules('public')
apply_zone_rules(node['firewall']['roles']['proxy']['public_zone'], 'public', ports_pub, protos_pub, rich_rules_pub)
end
if is_ips?
ports_pub, protos_pub, rich_rules_pub = fetch_existing_rules('public')
apply_zone_rules(node['firewall']['roles']['ips']['public_zone'], 'public', ports_pub, protos_pub, rich_rules_pub)
end
end

def apply_zone_rules(zone_rules, zone, existing_ports, existing_protocols, existing_rich_rules)
return if zone_rules.nil?
zone_rules['tcp_ports']&.each { |port| apply_rule(:port, port, zone, existing_ports, 'tcp') }
zone_rules['udp_ports']&.each { |port| apply_rule(:port, port, zone, existing_ports, 'udp') }
zone_rules['protocols']&.each { |protocol| apply_rule(:protocol, protocol, zone, existing_protocols) }
zone_rules['rich_rules']&.each { |rule| apply_rule(:rich_rule, rule, zone, existing_rich_rules) }
end

def apply_rule(type, value, zone, existing_items, protocol = nil)
value = "#{value}/#{protocol || 'tcp'}" if type == :port
unless existing_items.include?(value)
case type
when :port
firewall_rule "Allow port #{value} in #{zone} zone" do
port value
protocol protocol
zone zone
action :create
permanent true
end
when :protocol
firewall_rule "Allow protocol #{value} in #{zone} zone" do
protocols value
zone zone
action :create
permanent true
end
when :rich_rule
firewall_rule "Adding rich rule #{value} in #{zone} zone" do
rules value
zone zone
action :create
permanent true
end
def apply_rule(type, value, zone, protocol = nil)
case type
when :port
firewall_rule "Allow port #{value}/#{protocol} in #{zone} zone" do
port value
protocol protocol
zone zone
action :create
permanent true
not_if "firewall-cmd --permanent --zone=#{zone} --query-port=#{value}/#{protocol}"
end
end
end

def manage_kafka_rule_for_ips(ip, rich_rules)
unless rich_rules.include?(ip)
firewall_rule "Open Kafka port 9092 for manager ips" do
rules "rule family='ipv4' source address=#{ip} port port=9092 protocol=tcp accept"
zone 'public'
when :protocol
firewall_rule "Allow protocol #{value} in #{zone} zone" do
protocols value
zone zone
action :create
permanent true
not_if "firewall-cmd --permanent --zone=#{zone} --query-protocol=#{value}"
end
end
end

def remove_kafka_rule_for_ips(ip, rich_rules)
if rich_rules.include?(ip)
firewall_rule "Remove Kafka port 9092 for manager IPs" do
rules "rule family='ipv4' source address=#{ip} port port=9092 protocol=tcp accept"
zone 'public'
action :delete
when :rich_rule
firewall_rule "Adding rich rule #{value} in #{zone} zone" do
rules value
zone zone
action :create
permanent true
not_if "firewall-cmd --permanent --zone=#{zone} --query-rich-rule='#{value}'"
end
end
end

def reload!
shell_out!('firewall-cmd --reload')
end

def get_existing_ips_for_port(rich_rules)
def get_existing_ip_addresses_in_rules
rich_rules = shell_out!('firewall-cmd --zone=public --list-rich-rules').stdout
existing_ips = []
rich_rules.split("\n").each do |rule|
if rule.include?('port="9092"')
Expand Down Expand Up @@ -131,7 +73,7 @@ def is_ips?
node.role?('ips-sensor') || node.role?('ipscp-sensor')
end

def get_ip_of_manager_ips
def get_ip_of_manager_ips_nodes
sensors = search(:node, 'role:ips-sensor').sort
sensors.map { |s| { ipaddress: s['ipaddress'] } }
end
Expand Down
97 changes: 58 additions & 39 deletions resources/providers/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
action :add do
sync_ip = new_resource.sync_ip
ip_addr = new_resource.ip_addr
ip_address_ips = get_ip_of_manager_ips

service 'firewalld' do
action [:enable, :start]
end
ip_address_ips_nodes = get_ip_of_manager_ips_nodes

dnf_package 'firewalld' do
action :upgrade
Expand All @@ -23,57 +19,80 @@
notifies :restart, 'service[firewalld]', :delayed
end

# Add sync interface and subnet to home zone
if is_manager?
sync_interface = interface_for_ip(sync_ip)
sync_subnet = ip_to_subnet(sync_ip)
interfaces = shell_out!('firewall-cmd --zone=home --list-interfaces').stdout.strip.split
sources = shell_out!('firewall-cmd --zone=home --list-sources').stdout.strip.split

unless interfaces.include?(interface_for_ip(sync_ip))
firewall_rule 'Add sync interface to home' do
interface sync_interface
zone 'home'
action :create
permanent true
end
firewall_rule 'Add sync interface to home' do
interface sync_interface
zone 'home'
action :create
permanent true
not_if "firewall-cmd --zone=home --query-interface=#{sync_interface}"
end

unless sources.include?(ip_to_subnet(sync_ip))
firewall_rule 'Add sync subnet to home' do
sources sync_subnet
zone 'home'
action :create
permanent true
end
firewall_rule 'Add sync subnet to home' do
sources sync_subnet
zone 'home'
action :create
permanent true
not_if "firewall-cmd --zone=home --query-source=#{sync_subnet}"
end
end

configure_firewalld_rules
# Applying firewall ports, protocols, and rich rules based on zones
roles = {
'manager' => ['home', 'public'],
'proxy' => ['public'],
'ips' => ['public']
}
roles.each do |role, zones|
next unless send("is_#{role}?")
zones.each do |zone|
zone_rules = node['firewall']['roles'][role][zone]
next if zone_rules.nil?
zone_rules['tcp_ports']&.each { |port| apply_rule(:port, port, zone, 'tcp') }
zone_rules['udp_ports']&.each { |port| apply_rule(:port, port, zone, 'udp') }
zone_rules['protocols']&.each { |protocol| apply_rule(:protocol, protocol, zone) }
zone_rules['rich_rules']&.each { |rule| apply_rule(:rich_rule, rule, zone) }
end
end

# Managing port 9092 on the manager only for that specific IPS
if is_manager? && sync_ip != ip_addr
rich_rules = shell_out!('firewall-cmd --zone=public --list-rich-rules').stdout
existing_ips = get_existing_ips_for_port(rich_rules)
if ip_address_ips.empty?
existing_ips.each do |ip|
if rich_rules.match(/source address=\"#{ip}\".*port port=\"9092\".*protocol=\"tcp\"/)
manage_kafka_rule_for_ips(ip, rich_rules)
end
end
else
ips_to_remove = existing_ips - ip_address_ips.map { |ips| ips[:ipaddress] }
existing_addresses = get_existing_ip_addresses_in_rules
aux = ip_address_ips_nodes.empty? ? existing_addresses : ip_address_ips_nodes.map { |ips| ips[:ipaddress] }

unless ip_address_ips_nodes.empty?
ips_to_remove = existing_addresses - aux
ips_to_remove.each do |ip|
if rich_rules.match(/source address=\"#{ip}\".*port port=\"9092\".*protocol=\"tcp\"/)
remove_kafka_rule_for_ips(ip, rich_rules)
firewall_rule "Remove Kafka port 9092 for IP: #{ip}" do
rules "rule family='ipv4' source address=#{ip} port port=9092 protocol=tcp accept"
zone 'public'
action :delete
permanent true
only_if "firewall-cmd --permanent --zone=public --query-rich-rule='rule family=\"ipv4\" source address=\"#{ip}\" port port=\"9092\" protocol=\"tcp\" accept'"
end
end
ip_address_ips.each do |ip|
unless rich_rules.match(/source address=\"#{ip[:ipaddress]}\".*port port=\"9092\".*protocol=\"tcp\"/)
manage_kafka_rule_for_ips(ip[:ipaddress], rich_rules)
end
end

aux.each do |ip|
firewall_rule "Open Kafka port 9092 for IP: #{ip}" do
rules "rule family='ipv4' source address=#{ip} port port=9092 protocol=tcp accept"
zone 'public'
action :create
permanent true
not_if "firewall-cmd --permanent --zone=public --query-rich-rule='rule family=\"ipv4\" source address=\"#{ip}\" port port=\"9092\" protocol=\"tcp\" accept'"
end
end
end
reload!

service 'firewalld' do
service_name 'firewalld'
supports status: true, reload: true, restart: true, start: true, enable: true
action [:enable, :start, :reload]
end

Chef::Log.info('Firewall configuration has been applied.')
end
Expand Down

0 comments on commit 02d9b5f

Please sign in to comment.