mirror of
https://github.com/inspec/inspec
synced 2024-11-26 14:40:26 +00:00
CFINSPEC-66 : Add Ipfilter resource
Signed-off-by: Sonu Saha <sonu.saha@progress.com>
This commit is contained in:
parent
136a805c1e
commit
7c874e67df
5 changed files with 203 additions and 0 deletions
75
docs-chef-io/content/inspec/resources/ipfilter.md
Normal file
75
docs-chef-io/content/inspec/resources/ipfilter.md
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
+++
|
||||||
|
title = "ipfilter resource"
|
||||||
|
draft = false
|
||||||
|
gh_repo = "inspec"
|
||||||
|
platform = "bsd"
|
||||||
|
platform = "solaris"
|
||||||
|
|
||||||
|
[menu]
|
||||||
|
[menu.inspec]
|
||||||
|
title = "ipfilter"
|
||||||
|
identifier = "inspec/resources/os/ipfilter.md ipfilter resource"
|
||||||
|
parent = "inspec/resources/os"
|
||||||
|
+++
|
||||||
|
|
||||||
|
Use the `ipfilter` Chef InSpec audit resource to test rules that are defined for `ipfilter`. The `ipfstat` utility is used to report on packet filter statistics and filter list. `ipfstat -io` is used to view the active filtering rule set for the input and the output side of the kernel IP processing. The rule match is done against the output rules of `ipfstat -io`.
|
||||||
|
|
||||||
|
## Availability
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
This resource is distributed along with Chef InSpec itself. You can use it automatically.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
An `ipfilter` resource block declares tests for rules in IP tables:
|
||||||
|
|
||||||
|
describe ipfilter do
|
||||||
|
it { should have_rule("RULE") }
|
||||||
|
end
|
||||||
|
|
||||||
|
where
|
||||||
|
|
||||||
|
- `have_rule('RULE')` tests the active rule for ipfilter. This must match the entire line taken from `'ipfstat -io'`.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
The following examples show how to use this Chef InSpec audit resource.
|
||||||
|
|
||||||
|
### Test if there are no restrictions on loopback interface
|
||||||
|
|
||||||
|
describe ipfilter do
|
||||||
|
it { should have_rule("pass in quick on lo0 all") }
|
||||||
|
it { should have_rule("pass out quick on lo0 all") }
|
||||||
|
end
|
||||||
|
|
||||||
|
### Test if there are no restrictions on inside LAN interface named xl0 for private network
|
||||||
|
|
||||||
|
describe ipfilter do
|
||||||
|
it { should have_rule("pass in quick on xl0 all") }
|
||||||
|
it { should have_rule("pass out quick on xl0 all") }
|
||||||
|
end
|
||||||
|
|
||||||
|
### Test if there is a rule allowing FTP traffic on the public interface named dc0
|
||||||
|
|
||||||
|
describe iptables do
|
||||||
|
it { should have_rule("pass out quick on dc0 proto tcp from any to any port = ftp flags S/FSRPAU keep state") }
|
||||||
|
end
|
||||||
|
|
||||||
|
### Test if there is a rule allowing SSH on the public interface named dc0
|
||||||
|
|
||||||
|
describe iptables do
|
||||||
|
it { should have_rule("pass out quick on dc0 proto tcp from any to any port = ssh flags S/FSRPAU keep state") }
|
||||||
|
end
|
||||||
|
|
||||||
|
Note that the rule specification must exactly match what's in the output of `'ipfstat -io'`, which will depend on how you've built your rules.
|
||||||
|
|
||||||
|
## Matchers
|
||||||
|
|
||||||
|
For a full list of available matchers, please visit our [matchers page](/inspec/matchers/).
|
||||||
|
|
||||||
|
### have_rule
|
||||||
|
|
||||||
|
The `have_rule` matcher tests the named rule against the information in the output rule of `'ipftstat -io'`:
|
||||||
|
|
||||||
|
it { should have_rule("RULE") }
|
58
lib/inspec/resources/ipfilter.rb
Normal file
58
lib/inspec/resources/ipfilter.rb
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
require "inspec/resources/command"
|
||||||
|
module Inspec::Resources
|
||||||
|
class IpFilter < Inspec.resource(1)
|
||||||
|
name "ipfilter"
|
||||||
|
supports platform: "freebsd"
|
||||||
|
supports platform: "solaris"
|
||||||
|
desc "Use the ipfilter InSpec audit resource to test rules that are defined for ipfilter, which maintains the IP rule set"
|
||||||
|
example <<~EXAMPLE
|
||||||
|
describe ipfilter do
|
||||||
|
it { should have_rule("pass in quick on lo0 all") }
|
||||||
|
end
|
||||||
|
EXAMPLE
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
# checks if the instance is either bsd or solaris
|
||||||
|
return if inspec.os.bsd? || inspec.os.solaris?
|
||||||
|
|
||||||
|
# ensures, all calls are aborted for non-supported os
|
||||||
|
@ipfilter_cache = []
|
||||||
|
skip_resource "The `ipfilter` resource is not supported on your OS yet."
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_rule?(rule = nil)
|
||||||
|
# checks if the rule is part of the ruleset
|
||||||
|
retrieve_rules.any? { |line| line.casecmp(rule) == 0 }
|
||||||
|
end
|
||||||
|
|
||||||
|
def retrieve_rules
|
||||||
|
# this would be true if the OS family was not bsd/solaris when checked in initliaze
|
||||||
|
return @ipfilter_cache if defined?(@ipfilter_cache)
|
||||||
|
|
||||||
|
# construct ipfstat command to read all rules
|
||||||
|
bin = find_ipfstat_or_error
|
||||||
|
ipfstat_cmd = "#{bin} -io"
|
||||||
|
cmd = inspec.command(ipfstat_cmd)
|
||||||
|
|
||||||
|
# Return empty array when command is not executed successfully
|
||||||
|
# or there is no output since no rules are active
|
||||||
|
return [] if cmd.exit_status.to_i != 0 || cmd.stdout == ""
|
||||||
|
|
||||||
|
# split rules, returns array or rules
|
||||||
|
@iptables_cache = cmd.stdout.split("\n").map(&:strip)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
format("Ipfilter").strip
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def find_ipfstat_or_error
|
||||||
|
%w{/usr/sbin/ipfstat /sbin/ipfstat ipfstat}.each do |cmd|
|
||||||
|
return cmd if inspec.command(cmd).exist?
|
||||||
|
end
|
||||||
|
|
||||||
|
raise Inspec::Exceptions::ResourceFailed, "Could not find `ipfstat`"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
35
test/fixtures/cmd/ipfstat-io
vendored
Normal file
35
test/fixtures/cmd/ipfstat-io
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
pass out quick on lo0 all
|
||||||
|
pass out quick on xl0 all
|
||||||
|
pass out quick on dc0 proto tcp from any to any port = http flags S/FSRPAU keep state
|
||||||
|
pass out quick on dc0 proto tcp from any to any port = https flags S/FSRPAU keep state
|
||||||
|
pass out quick on dc0 proto tcp from any to any port = pop3 flags S/FSRPAU keep state
|
||||||
|
pass out quick on dc0 proto tcp from any to any port = smtp flags S/FSRPAU keep state
|
||||||
|
pass out quick on dc0 proto tcp from any to any port = time flags S/FSRPAU keep state
|
||||||
|
pass out quick on d0c0 proto tcp from any to any port = ftp flags S/FSRPAU keep state
|
||||||
|
pass out quick on dc0 proto tcp from any to any port = ssh flags S/FSRPAU keep state
|
||||||
|
pass out quick on dc0 inet proto icmp from any to any icmp-type echo keep state
|
||||||
|
block out log first quick on dc0 all
|
||||||
|
pass in quick on lo0 all
|
||||||
|
pass in quick on xl0 all
|
||||||
|
block in quick on dc0 inet from 192.168.0.0/16 to any
|
||||||
|
block in quick on dc0 inet from 172.16.0.0/12 to any
|
||||||
|
block in quick on dc0 inet from 10.0.0.0/8 to any
|
||||||
|
block in quick on dc0 inet from 127.0.0.0/8 to any
|
||||||
|
block in quick on dc0 inet from 0.0.0.0/8 to any
|
||||||
|
block in quick on dc0 inet from 169.254.0.0/16 to any
|
||||||
|
block in quick on dc0 inet from 192.0.2.0/24 to any
|
||||||
|
block in quick on dc0 inet from 204.152.64.0/23 to any
|
||||||
|
block in quick on dc0 inet from 224.0.0.0/3 to any
|
||||||
|
block in quick on dc0 from any to any with frag
|
||||||
|
block in quick on dc0 proto tcp from any to any with short
|
||||||
|
block in quick on dc0 inet from any to any with opt lsrr
|
||||||
|
block in quick on dc0 inet from any to any with opt ssrr
|
||||||
|
block in log first quick on dc0 proto tcp from any to any flags FPU/FSRPAU
|
||||||
|
block in quick on dc0 from any to any with ipopts
|
||||||
|
block in quick on dc0 inet proto icmp from any to any icmp-type echo
|
||||||
|
block in quick on dc0 proto tcp from any to any port = auth
|
||||||
|
block in log first quick on dc0 proto tcp/udp from any to any port = netbios-ns
|
||||||
|
block in log first quick on dc0 proto tcp/udp from any to any port = netbios-dgm
|
||||||
|
block in log first quick on dc0 proto tcp/udp from any to any port = netbios-ssn
|
||||||
|
block in log first quick on dc0 proto tcp/udp from any to any port = 81
|
||||||
|
block in log first quick on dc0 all
|
|
@ -372,6 +372,9 @@ class MockLoader
|
||||||
# ipnat
|
# ipnat
|
||||||
"/usr/sbin/ipnat -l" => cmd.call("ipnat-l"),
|
"/usr/sbin/ipnat -l" => cmd.call("ipnat-l"),
|
||||||
%{type "/usr/sbin/ipnat"} => empty.call,
|
%{type "/usr/sbin/ipnat"} => empty.call,
|
||||||
|
# ipfilter
|
||||||
|
"/usr/sbin/ipfstat -io" => cmd.call("ipfstat-io"),
|
||||||
|
%{type "/usr/sbin/ipfstat"} => empty.call,
|
||||||
# apache_conf
|
# apache_conf
|
||||||
"sh -c 'find /etc/apache2/ports.conf -type f -maxdepth 1'" => cmd.call("find-apache2-ports-conf"),
|
"sh -c 'find /etc/apache2/ports.conf -type f -maxdepth 1'" => cmd.call("find-apache2-ports-conf"),
|
||||||
"sh -c 'find /etc/httpd/conf.d/*.conf -type f -maxdepth 1'" => cmd.call("find-httpd-ssl-conf"),
|
"sh -c 'find /etc/httpd/conf.d/*.conf -type f -maxdepth 1'" => cmd.call("find-httpd-ssl-conf"),
|
||||||
|
|
32
test/unit/resources/ipfilter_test.rb
Normal file
32
test/unit/resources/ipfilter_test.rb
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
require "helper"
|
||||||
|
require "inspec/resource"
|
||||||
|
require "inspec/resources/ipfilter"
|
||||||
|
|
||||||
|
describe "Inspec::Resources::Ipfilter" do
|
||||||
|
# freebsd11
|
||||||
|
it "verify ipfilter on freebsd11" do
|
||||||
|
resource = MockLoader.new(:freebsd11).load_resource("ipfilter")
|
||||||
|
_(resource.has_rule?("pass out quick on lo0 all")).must_equal true
|
||||||
|
_(resource.has_rule?("pass in quick on lo0 all")).must_equal true
|
||||||
|
_(resource.has_rule?("block in quick on dc0 inet from 10.0.0.0/8 to any")).must_equal true
|
||||||
|
_(resource.has_rule?(nil)).must_equal false
|
||||||
|
end
|
||||||
|
|
||||||
|
# solaris11
|
||||||
|
it "verify ipfilter on solaris11" do
|
||||||
|
resource = MockLoader.new(:solaris11).load_resource("ipfilter")
|
||||||
|
_(resource.has_rule?("pass out quick on lo0 all")).must_equal true
|
||||||
|
_(resource.has_rule?("pass in quick on lo0 all")).must_equal true
|
||||||
|
_(resource.has_rule?("block in quick on dc0 inet from 10.0.0.0/8 to any")).must_equal true
|
||||||
|
_(resource.has_rule?(nil)).must_equal false
|
||||||
|
end
|
||||||
|
|
||||||
|
# undefined
|
||||||
|
it "verify ipfilter on unsupported os" do
|
||||||
|
resource = MockLoader.new(:undefined).load_resource("ipfilter")
|
||||||
|
_(resource.has_rule?("pass out quick on lo0 all")).must_equal false
|
||||||
|
_(resource.has_rule?("pass in quick on lo0 all")).must_equal false
|
||||||
|
_(resource.has_rule?("block in quick on dc0 inet from 10.0.0.0/8 to any")).must_equal false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in a new issue