Serverspec
公式ドキュメントのiptablesセクション では、iptables があるルールを持っているか検証するために、have_rule マッチャーを使うべきと記載されています。
describe iptables do
it { should have_rule('-P INPUT ACCEPT') }
end
が、何故か fail する
例えば、iptables に 下記ルールを設定したとして
-A INPUT -m tcp -p tcp --dport 80 -j ACCEPT
serverspec では 下記のように書けば、pass するはず。
describe iptables do
it { should have_rule('-A INPUT -m tcp -p tcp --dport 80 -j ACCEPT') }
end
が、なぜか fail します。
serverspec / specinfra を読む
ドキュメントには詳しく書かれていないので、コードを読むことにします。
まずは serverspec。
RSpec::Matchers.define :have_rule do |rule|
match do |subject|
if subject.class.name == 'Serverspec::Type::Iptables' || subject.class.name == 'Serverspec::Type::Ip6tables'
subject.has_rule?(rule, @table, @chain)
else
subject.has_rule?(rule)
end
end
これだけではなぜfail しているのか不明なので、さらに specinfra を読みます。
class Specinfra::Command::Linux::Base::Iptables < Specinfra::Command::Base::Iptables
class << self
def check_has_rule(rule, table=nil, chain=nil)
cmd = "iptables"
cmd += " -t #{escape(table)}" if table
cmd += " -S"
cmd += " #{escape(chain)}" if chain
cmd += " | grep -- #{escape(rule)}"
cmd
end
end
end
見つけました。 iptables -S の結果を grep しているようです。
実際に、iptables -S すると、
$ iptables -S
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
...
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
という結果が得られます。
describe iptables do
it { should have_rule('-A INPUT -m tcp -p tcp --dport 80 -j ACCEPT') }
end
iptables -S の結果に対して評価してることが分かれば、なぜ上のspecがfailするのかは明らかで、"-m tcp -p tcp" の順序が逆だからということになります。
まとめ
serverspec の have_rule は "iptables -S" の結果を grep で評価してるよ、ということを覚えておくと役に立つかもしれません。