From: Jonathan Boyett Date: Mon, 9 May 2011 23:22:32 +0000 (-0700) Subject: add iptables provider X-Git-Tag: v0.0.1~75 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=53b752e83672f7f677b1e953a36e357f1ba4a00a;p=puppet-modules%2Fpuppetlabs-firewall.git add iptables provider --- diff --git a/lib/puppet/provider/firewall.rb b/lib/puppet/provider/firewall.rb new file mode 100644 index 0000000..d946e6b --- /dev/null +++ b/lib/puppet/provider/firewall.rb @@ -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 index 0000000..d8d2692 --- /dev/null +++ b/lib/puppet/provider/firewall/iptables.rb @@ -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