mirror of
https://github.com/inspec/inspec
synced 2024-11-22 20:53:11 +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
|
||||
"/usr/sbin/ipnat -l" => cmd.call("ipnat-l"),
|
||||
%{type "/usr/sbin/ipnat"} => empty.call,
|
||||
# ipfilter
|
||||
"/usr/sbin/ipfstat -io" => cmd.call("ipfstat-io"),
|
||||
%{type "/usr/sbin/ipfstat"} => empty.call,
|
||||
# apache_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"),
|
||||
|
|
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