]> review.fuel-infra Code Review - puppet-modules/puppetlabs-firewall.git/commitdiff
add support for removing unmanaged firewall rules
authorPatrick Hemmer <patrick.hemmer@gmail.com>
Tue, 17 Dec 2013 22:00:18 +0000 (17:00 -0500)
committerHunter Haugen <hunter@puppetlabs.com>
Tue, 28 Jan 2014 23:04:29 +0000 (15:04 -0800)
lib/puppet/type/firewallchain.rb

index 75ffa4e732a3f71f472bf43510c385d025b10655..35cb9ed80f2a73310efbebfa59995a5200a81325 100644 (file)
@@ -105,6 +105,46 @@ Puppet::Type.newtype(:firewallchain) do
     end
   end
 
+  newparam(:purge, :boolean => true) do
+    desc <<-EOS
+      Purge unmanaged firewall rules in this chain
+    EOS
+    defaultto :false
+  end
+
+  newparam(:ignore) do
+    desc <<-EOS
+      Regex to perform on firewall rules to exempt unmanaged rules from purging (when enabled).
+      This is matched against the output of `iptables-save`.
+
+      This can be a single regex, or an array of them.
+      To support flags, use the ruby inline flag mechanism.
+      Meaning a regex such as
+        /foo/i
+      can be written as
+        '(?i)foo' or '(?i:foo)'
+
+      Full example:
+      firewallchain { 'INPUT:filter:IPv4':
+        purge => true,
+        ignore => [
+          '-j fail2ban-ssh', # ignore the fail2ban jump rule
+          '--comment "[^"]*(?i:ignore)[^"]*"', # ignore any rules with "ignore" (case insensitive) in the comment in the rule
+        ],
+      }
+    EOS
+
+    validate do |value|
+      unless value.is_a?(Array) or value.is_a?(String) or value == false
+        self.devfail "Ignore must be a string or an Array"
+      end
+    end
+    munge do |patterns| # convert into an array of {Regex}es
+      patterns = [patterns] if patterns.is_a?(String)
+      patterns.map{|p| Regexp.new(p)}
+    end
+  end
+
   # Classes would be a better abstraction, pending:
   # http://projects.puppetlabs.com/issues/19001
   autorequire(:package) do
@@ -148,4 +188,34 @@ Puppet::Type.newtype(:firewallchain) do
       self.fail 'The "nat" table is not intended for filtering, the use of DROP is therefore inhibited'
     end
   end
+
+  def generate
+    return [] unless self.purge?
+
+    self[:name].match(Nameformat)
+    chain = $1
+    table = $2
+    protocol = $3
+
+    provider = case protocol
+               when 'IPv4'
+                 :iptables
+               when 'IPv6'
+                 :ip6tables
+               end
+
+    # gather a list of all rules present on the system
+    rules_resources = Puppet::Type.type(:firewall).instances
+
+    # Keep only rules in this chain
+    rules_resources.keep_if {|res| res[:provider] == provider and res.provider.properties[:table].to_s == table and res.provider.properties[:chain] == chain}
+
+    # Remove rules which match our ignore filter
+    rules_resources.delete_if {|res| self[:ignore].find_index{|f| res.provider.properties[:line].match(f)}} if self[:ignore]
+
+    # We mark all remaining rules for deletion, and then let the catalog override us on rules which should be present
+    rules_resources.each {|res| res[:ensure] = :absent}
+
+    rules_resources
+  end
 end