]> review.fuel-infra Code Review - puppet-modules/puppetlabs-firewall.git/commitdiff
add iptables provider
authorJonathan Boyett <jonathan@failingservers.com>
Mon, 9 May 2011 23:22:32 +0000 (16:22 -0700)
committerJonathan Boyett <jonathan@failingservers.com>
Mon, 9 May 2011 23:22:32 +0000 (16:22 -0700)
lib/puppet/provider/firewall.rb [new file with mode: 0644]
lib/puppet/provider/firewall/iptables.rb [new file with mode: 0644]

diff --git a/lib/puppet/provider/firewall.rb b/lib/puppet/provider/firewall.rb
new file mode 100644 (file)
index 0000000..d946e6b
--- /dev/null
@@ -0,0 +1,47 @@
+class Puppet::Provider::Firewall < Puppet::Provider
+  
+  # Prefetch our rule list. This is ran once every time before any other
+  # action (besides initialization of each object).
+  def self.prefetch(resources)
+    debug("[prefetch(resources)]")
+    instances.each do |prov|
+      if resource = resources[prov.name] || resources[prov.name.downcase]
+        resource.provider = prov
+      end
+    end
+  end
+
+  # Look up the current status. This allows us to conventiently look up
+  # existing status with properties[:foo].
+  def properties
+    if @property_hash.empty?
+      @property_hash = query || {:ensure => :absent}
+      @property_hash[:ensure] = :absent if @property_hash.empty?
+    end
+    @property_hash.dup
+  end
+
+  # Pull the current state of the list from the full list.  We're
+  # getting some double entendre here....
+  def query
+    self.class.instances.each do |instance|
+      if instance.name == self.name or instance.name.downcase == self.name
+        return instance.properties
+      end
+    end
+    nil
+  end
+
+  # Executed if method is missing. In this case we are going to catch 
+  # unqualified property methods for dynamic property setting and getting.
+  def method_missing(meth, *args, &block)
+    if @property_hash.keys.include?(meth) then
+      return @property_hash[meth.to_sym]
+    elsif @property_hash.keys.include?(meth.to_s.chomp("=").to_sym) then
+      @property_hash[:needs_change] = true
+      return true
+    end
+
+    super
+  end
+end
diff --git a/lib/puppet/provider/firewall/iptables.rb b/lib/puppet/provider/firewall/iptables.rb
new file mode 100644 (file)
index 0000000..d8d2692
--- /dev/null
@@ -0,0 +1,156 @@
+require 'puppet/provider/firewall'
+
+Puppet::Type.type(:firewall).provide :iptables, :parent => Puppet::Provider::Firewall do
+  include Puppet::Util::Firewall
+  
+  @doc = "Iptables type provider"
+
+  commands :iptables => '/sbin/iptables'
+  commands :iptables_save => '/sbin/iptables-save'
+
+  defaultfor :operatingsystem => [:redhat, :debian, :ubuntu, :fedora, :suse, :centos, :sles, :oel, :ovm]
+  confine :operatingsystem => [:redhat, :debian, :ubuntu, :fedora, :suse, :centos, :sles, :oel, :ovm]
+
+  mk_resource_methods
+
+  @@resource_map = {
+    :burst => "--limit-burst",
+    :destination => "-d",
+    :dport => "-m multiport --dports",
+    :icmp => "-m icmp --icmp-type",
+    :iniface => "-i",
+    :jump => "-j",
+    :limit => "--limit",
+    :log_level => "--log-level",
+    :log_prefix => "--log-prefix",
+    :name => "-m comment --comment",
+    :outiface => "-o",
+    :proto => "-p",
+    :reject => "--reject-with",
+    :source => "-s",
+    :state => "-m state --state",
+    :sport => "-m multiport --sports",
+    :table => "-t",
+    :todest => "--to-destination",
+    :toports => "--to-ports",
+    :tosource => "--to-source",
+  }
+
+  @@resource_list = [:table, :source, :destination, :iniface, :outiface, :proto, :sport, :dport, :tosource, :todest,
+                     :reject, :log_level, :log_prefix, :name, :state, :icmp, :limit, :burst, :toports, :jump]
+
+
+  def insert
+    debug 'Inserting rule %s' % resource[:name]
+    iptables insert_args
+  end
+
+  def update
+    debug 'Updating rule %s' % resource[:name]
+    iptables update_args 
+  end
+
+  def delete
+    debug 'Deleting rule %s' % resource[:name]
+    iptables "-D", properties[:chain], properties[:rulenum]
+  end
+
+  def exists?
+    properties[:ensure] != :absent
+  end
+
+  # Flush the property hash once done.
+  def flush
+    debug("[flush]")
+    needs_change = @property_hash.delete(:needs_change)
+    if needs_change
+      notice("Properties changed - updating rule")
+      update
+    end
+    @property_hash.clear
+  end
+  
+  def self.instances
+    debug "[instances]"
+    table = nil
+    rules = []
+    iptables_save.lines do |line|
+      unless line =~ /^\#\s+|^\:\S+|^COMMIT/
+        if line =~ /^\*/
+          table = line.sub(/\*/, "").chomp!
+        else
+          if hash = rule_to_hash(line, table)
+            rules << new(hash)
+          end
+        end
+      end
+    end
+    rules
+  end
+
+  def self.rule_to_hash(line, table)
+    hash = {}
+    keys = []
+    values = line.dup
+
+    @@resource_list.reverse.each do |k|
+      if values.slice!(@@resource_map[k])
+        keys << k
+      end
+    end
+
+    # Manually remove chain
+    values.slice!('-A')
+    keys << :chain
+
+    keys.zip(values.scan(/"[^"]*"|\S+/).reverse) { |f, v| hash[f] = v.gsub(/"/, '') }
+    hash[:provider] = self.name.to_s
+    hash[:table] = table
+    hash[:ensure] = :present
+    hash
+  end
+
+  def insert_args
+    args = []
+    args << ["-I", resource[:chain], insert_order]
+    args << general_args
+    args
+  end
+
+  def update_args
+    args = []
+    args << ["-R", resource[:chain], properties[:rulenum]]
+    args << general_args
+    args
+  end
+
+  def general_args
+    debug "Current resource: %s" % resource.class
+    args = []
+    @@resource_list.each do |res|
+      if(resource.value(res))
+        args << @@resource_map[res].split(' ')
+        args << resource[res]
+      end
+    end
+    args
+  end
+
+  def insert_order
+    debug("[insert_order]")
+    rules = []
+    
+    # Find list of current rules based on chain
+    self.class.instances.each do |rule|
+      next unless rule.chain == resource[:chain]
+      rules << rule
+    end
+    
+    # No rules at all? Just bail now.
+    return 1 if rules.empty?
+
+    my_rule = resource[:name].to_s
+    rules << my_rule
+    rules.sort.index(my_rule) + 1
+  end
+end