Skip to content

Commit

Permalink
fix helper file and refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
nilsver committed Nov 14, 2024
1 parent 7792e08 commit b857350
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 71 deletions.
1 change: 0 additions & 1 deletion resources/attributes/default.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
default['firewalld']['user'] = 'firewall'

# Define roles with their respective firewall rules
default['firewall']['roles'] = {
'manager' => {
'home_zone' => {
Expand Down
184 changes: 117 additions & 67 deletions resources/libraries/helper.rb
Original file line number Diff line number Diff line change
@@ -1,89 +1,139 @@
# Cookbook:: firewall
# Provider:: config
module Firewall
module Helpers
require 'ipaddr'
require 'socket'
include ::Chef::Mixin::ShellOut

include Firewall::Helpers

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
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

dnf_package 'firewalld' do
action :upgrade
flush_cache [:before]
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)

template '/etc/firewalld.conf' do
source 'firewalld.conf.erb'
cookbook 'rb-firewall'
notifies :restart, 'service[firewalld]', :delayed
end
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

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
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

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
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
end
end
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
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'
action :create
permanent true
end
end
end
end

configure_firewalld_rules

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\"/)
remove_kafka_rule_for_ips(ip)
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
permanent true
end
end
else
ips_to_remove = existing_ips - ip_address_ips.map { |ips| ips[:ipaddress] }
ips_to_remove.each do |ip|
if rich_rules.match(/source address=\"#{ip}\".*port port=\"9092\".*protocol=\"tcp\"/)
remove_kafka_rule_for_ips(ip)
end

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

def get_existing_ips_for_port(rich_rules)
existing_ips = []
rich_rules.split("\n").each do |rule|
if rule.include?('port="9092"')
ip_match = rule.match(/source address="([^"]+)"/)
existing_ips << ip_match[1] if ip_match
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])
end
existing_ips
end

def interface_for_ip(ip_address)
return nil if ip_address.nil? || ip_address.empty?
interfaces = Socket.getifaddrs
interface = interfaces.find do |ifaddr|
ifaddr.addr.ipv4? && ifaddr.addr.ip_address == ip_address
end
interface.name
end

def ip_to_subnet(ip_address, prefix = 24)
ip = IPAddr.new(ip_address)
subnet = ip.mask(prefix)
"#{subnet}/#{prefix}"
end
end

reload!
def is_proxy?
node.role?('proxy-sensor')
end

Chef::Log.info('Firewall configuration has been applied.')
end
def is_manager?
node.role?('manager')
end

action :remove do
service 'firewalld' do
action [:disable, :stop]
end
def is_ips?
node.role?('ips-sensor') || node.role?('ipscp-sensor')
end

Chef::Log.info('Firewall configuration has been removed.')
def get_ip_of_manager_ips
sensors = search(:node, 'role:ips-sensor').sort
sensors.map { |s| { ipaddress: s['ipaddress'] } }
end
end
end
4 changes: 1 addition & 3 deletions resources/providers/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,10 @@
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\"/)
remove_kafka_rule_for_ips(ip, rich_rules)
manage_kafka_rule_for_ips(ip, rich_rules)
end
end
else
Expand All @@ -74,7 +73,6 @@
end
end
end

reload!

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

0 comments on commit b857350

Please sign in to comment.