rtkwlf / cookbook-simple-iptables

Simple Chef iptables cookbook
86 stars 63 forks source link

Wrapping simple_iptables_rule in LWRP #67

Open jperville opened 9 years ago

jperville commented 9 years ago

I attempted wrapping a simple_iptables_rule resource in my own LWRP (eg. to allow custom cookbooks to easily open ports on a restrictive firewall); the rules execute (I can see log messages when running with log_level :debug and I can even see my rules persisted in the node normal attributes) however my firewall rules never appear in /etc/iptable-rules (and even less in the running iptable rules).

Is there any reason why:

simple_iptables_rule 'system' do
  rule '-i eth2 -p tcp --dport 1337'
  jump 'ACCEPT'
end

would work while:

my_firewall_port '1337'

would not, assuming a my_firewall_port LWRP that could be implemented like this (please forgive eventual typos):

#resource
actions :whitelist
default_action :whitelist

attribute :port, kind_of: [String, Integer], name_attribute => true
attribute :proto, kind_of: String, equal_to: %w[tcp udp], default: 'tcp'
attribute :lan_ifname, kind_of: String, default: node['my-firewall']['lan-interface']
attribute :chain, kind_of: String, default: node['my-firewall']['iptables-chain']

#provider
#use_inline_resources # have tried both with and without -- with does not produce CHEF-3694 spam

action :whitelist do
  simple_iptables_rule new_resource.chain do
    rule "-i #{new_resource.lan_ifname} -p #{new_resource.proto} --dport #{new_resource.port}'
    jump 'ACCEPT'
  end
end

From browsing the code of the simple-iptables cookbooks, I found at least one place where the resource collection is scanned for instances of Chef::Resource::SimpleIptablesRules (and Policy). It may explain why wrapping with LWRP is broken, at least in the use_inline_resources case (if using that option then the SimpleIptableRules instances won't appear in the top-level resource collection at all). For the non use_inline_resources cases, I think it is because the /etc/iptable-rules template is already rendered when my LWRP is converged but I don't see any clean way to converge my LWRP early other than forcing it to run at compile time (which is a first but very ugly workaround).

As a workaround, I ended up implementing the LWRP with a chef 'definition' but I understand that this is a bit like hack (and the CHEF-3694 spam reminds it to me at every chef run).

Thank you very much in advance.

aspring commented 9 years ago

This is indeed due to the LWRP using its own resource collection versus the global resource collection. I have a workaround I just need to cleanup and get a PR for where I removed the scanning of the resource collection by the default recipe, and that was replaced by a making a few changes to the the simple_iptables LWRPs to correctly flush old entries (maintaining the smart cleanup), as well as a few changes to the notifications triggered in the default recipe to make sure the updating of the iptables and the like are handled as close to the end of the chef run as possible.

rtkrruvinskiy commented 9 years ago

@aspring Thanks for looking into this. I'm looking forward to the pull request!

jperville commented 9 years ago

Also looking forward to the PR to clean up my cookbooks, thank you @aspring.

aspring commented 9 years ago

Just to follow up, the implementation of this we were testing hit a single snag that we are trying to work around, though Im not sure if its possible with the current functionality we have.

Essentially using a set of notifications works very well, however in the implementation we have, if a chef run fails for any reason there is the possibility of writing an incomplete iptables config, that are subsequently brought live. This is due to the delayed notification resources getting rolled up at the end, which includes the resources that template/test/bring live the changes.