Defining PF Macros In Multiple Anchor Files

Posted by Tres Mon, 25 Dec 2006 00:08:00 GMT

Splitting rules into multiple files allows you to easily organize rules, but the downside is that without a little scripting, you can’t really use macros effectively. Because of the way anchors work, you have to define macros in each file separately. This is a potential management overhead nightmare.

The #<–[MACROS]–> construct allows us to define all macros in a single file and distribute it to all anchor files. We keep all our macros in /usr/local/etc/pf_macros.conf. Just by putting #<–[MACROS]–> at the start of our ruleset, we can ensure that our single set of macros will be used in that file. That way, we can keep management overhead to a minimum. Here’s the ruby script that makes that possible:


#!/usr/bin/env ruby -w

# macros.rb 
# script which will push macro variables from one file into all anchors files and pf.conf
# this should be run with cfengine, so when files get pushed out, or changed, the 
# macros will automatically be defined.

# to allow this file to automatically push uniform macros to your pf anchors and pf.conf
# place a line like the following into the file you want to have macros pushed into
#<--[MACROS]-->
# this script will replace the entire line within which the <--[MACROS]--> element is used


require 'find'
require 'fileutils'
require 'date'

pf_base_conf_dir="/usr/local/etc"
timestamp = DateTime.now
pf_anchors_dir = "#{pf_base_conf_dir}/pf_anchors"
macro_defs_file = "#{pf_base_conf_dir}/pf_macros.conf"
pf_conf = "/etc/pf.conf"
backup_data_dir = "/tmp/"
backup_file = "data.#{timestamp}"
backup = "#{backup_data_dir}/#{backup_file}"

if File.exists?( "#{macro_defs_file}" ) 
    macro_definitions = IO.read("#{macro_defs_file}")
else
    macro_definitions = nil
end

#first take care of pf.conf

FileUtils.copy( pf_conf, backup )
File.open( backup, "r" ) do |file|
    new_file = File.open( pf_conf, "w" )
    file.each do |line|
        new_line = line.gsub( /^.*<--\[MACROS\]--\>.*$/, macro_definitions )
        new_file.write new_line
    end
    file.close
    FileUtils.rm( backup )
end

#then take care of the anchor files

Find.find(pf_anchors_dir) do |file_name| 
    Find.prune if file_name =~ /\.svn/
    if File.file?(file_name) 
        FileUtils.copy( file_name, backup )
        File.open(backup, "r") do |file|
            new_file = File.open( file_name, "w" )
            file.each do |line|
                newline = line.gsub(/^.*<--\[MACROS\]--\>.*$/, macro_definitions )
                new_file.write newline
            end
        file.close
        FileUtils.rm( backup )
        end 
    end
end

Posted in , , ,  | Tags ,

Comments are disabled