kernel_module resource: added blacklisting, enabled, disabled, docs and unit tests (#1798)

* Fix up methods, add command mock, do string matching in ruby instead of command

Fixes #1643
Fixes #1673

Signed-off-by: Aaron Lippold <lippold@gmail.com>
This commit is contained in:
Aaron Lippold 2017-07-05 05:41:44 -04:00 committed by Christoph Hartmann
parent 224935e9cf
commit cc7ed38d09
7 changed files with 275 additions and 23 deletions

View file

@ -4,20 +4,45 @@ title: About the kernel_module Resource
# kernel_module # kernel_module
Use the `kernel_module` InSpec audit resource to test kernel modules on Linux platforms. These parameters are located under `/lib/modules`. Any submodule may be tested using this resource. Use the `kernel_module` InSpec audit resource to test kernel modules on Linux
platforms. These parameters are located under `/lib/modules`. Any submodule may
be tested using this resource.
The `kernel_module` resource can also verify if a kernel module is `blacklisted`
or if a module is disabled via a fake install using the `bin_true` or `bin_false`
method.
## Syntax ## Syntax
A `kernel_module` resource block declares a module name, and then tests if that module is a loadable kernel module: A `kernel_module` resource block declares a module name, and then tests if that
module is a loadable kernel module, if it is enabled, disabled or if it is
blacklisted:
describe kernel_module('module_name') do describe kernel_module('video') do
it { should be_loaded } it { should be_loaded }
it { should_not be_disabled }
it { should_not be_blacklisted }
end
describe kernel_module('sstfb') do
it { should_not be_loaded }
it { should be_disabled }
end
describe kernel_module('floppy') do
it { should be_blacklisted }
end
describe kernel_module('dhcp') do
it { should_not be_loaded }
end end
where where
* `'module_name'` must specify a kernel module, such as `'bridge'` * `'module_name'` must specify a kernel module, such as `'bridge'`
* `{ should be_loaded }` tests if the module is a loadable kernel module * `{ should be_loaded }` tests if the module is a loadable kernel module
* `{ should be_blacklisted }` tests if the module is blacklisted or if the module is disabled via a fake install using /bin/false or /bin/true
* `{ should be_disabled }` tests if the module is disabled via a fake install using /bin/false or /bin/true
## Matchers ## Matchers
@ -59,9 +84,50 @@ The `version` matcher tests if the named module version is on the system:
The following examples show how to use this InSpec audit resource. The following examples show how to use this InSpec audit resource.
### Test if a module is loaded ### Test a modules 'version'
describe kernel_module('bridge') do describe kernel_module('bridge') do
it { should be_loaded } it { should be_loaded }
its(:version) { should cmp >= '2.2.2' } its(:version) { should cmp >= '2.2.2' }
end end
### Test if a module is loaded, not disabled and not blacklisted
describe kernel_module('video') do
it { should be_loaded }
it { should_not be_disabled }
it { should_not be_blacklisted }
end
### Check if a module is blacklisted
describe kernel_module('floppy') do
it { should be_blacklisted }
end
### Ensure a module is *not* blacklisted and it is loaded
describe kernel_module('video') do
it { should_not be_blacklisted }
it { should be_loaded }
end
### Ensure a module is disabled via 'bin_false'
describe kernel_module('sstfb') do
it { should_not be_loaded }
it { should be_disabled }
end
### Ensure a module is 'blacklisted'/'disabled' via 'bin_true'
describe kernel_module('nvidiafb') do
it { should_not be_loaded }
it { should be_blacklisted }
end
### Ensure a module is not loaded
describe kernel_module('dhcp') do
it { should_not be_loaded }
end

View file

@ -1,20 +1,44 @@
# encoding: utf-8 # encoding: utf-8
# author: Christoph Hartmann # author: Christoph Hartmann
# author: Dominik Richter # author: Dominik Richter
# author: Aaron Lippold
# author: Adam Leff
module Inspec::Resources module Inspec::Resources
class KernelModule < Inspec.resource(1) class KernelModule < Inspec.resource(1)
name 'kernel_module' name 'kernel_module'
desc 'Use the kernel_module InSpec audit resource to test kernel modules on Linux platforms. These parameters are located under /lib/modules. Any submodule may be tested using this resource.' desc 'Use the kernel_module InSpec audit resource to test kernel modules on
Linux platforms. These parameters are located under /lib/modules. Any submodule
may be tested using this resource.
The `kernel_module` resource can also verify if a kernel module is `blacklisted`
or if a module is disabled via a fake install using the `bin_true` or `bin_false`
method.'
example " example "
describe kernel_module('bridge') do
describe kernel_module('video') do
it { should be_loaded } it { should be_loaded }
it { should_not be_disabled }
it { should_not be_blacklisted }
end
describe kernel_module('sstfb') do
it { should_not be_loaded }
it { should be_disabled }
end
describe kernel_module('floppy') do
it { should be_blacklisted }
end
describe kernel_module('dhcp') do
it { should_not be_loaded }
end end
" "
def initialize(modulename = nil) def initialize(modulename = nil)
@module = modulename @module = modulename
# this resource is only supported on Linux # this resource is only supported on Linux
return skip_resource 'The `kernel_parameter` resource is not supported on your OS.' if !inspec.os.linux? return skip_resource 'The `kernel_parameter` resource is not supported on your OS.' if !inspec.os.linux?
end end
@ -36,19 +60,51 @@ module Inspec::Resources
!found.nil? !found.nil?
end end
def version def disabled?
if inspec.os.redhat? || inspec.os.name == 'fedora' !modprobe_output.match(%r{^install\s+#{@module}\s+/(s?)bin/(true|false)}).nil?
modinfo_cmd = "/sbin/modinfo -F version #{@module}"
else
modinfo_cmd = "modinfo -F version #{@module}"
end end
cmd = inspec.command(modinfo_cmd) def blacklisted?
!modprobe_output.match(/^blacklist\s+#{@module}/).nil? || disabled_via_bin_true? || disabled_via_bin_false?
end
def version
cmd = inspec.command("#{modinfo_cmd_for_os} -F version #{@module}")
cmd.exit_status.zero? ? cmd.stdout.delete("\n") : nil cmd.exit_status.zero? ? cmd.stdout.delete("\n") : nil
end end
def to_s def to_s
"Kernel Module #{@module}" "Kernel Module #{@module}"
end end
private
def modprobe_output
@modprobe_output ||= inspec.command("#{modprobe_cmd_for_os} --showconfig").stdout
end
def modinfo_cmd_for_os
if inspec.os.redhat? || inspec.os.name == 'fedora'
'/sbin/modinfo'
else
'modinfo'
end
end
def modprobe_cmd_for_os
if inspec.os.redhat? || inspec.os.name == 'fedora'
'/sbin/modprobe'
else
'modprobe'
end
end
def disabled_via_bin_true?
!modprobe_output.match(%r{^install\s+#{@module}\s+/(s?)bin/true}).nil?
end
def disabled_via_bin_false?
!modprobe_output.match(%r{^install\s+#{@module}\s+/(s?)bin/false}).nil?
end
end end
end end

View file

@ -335,6 +335,8 @@ class MockLoader
"docker inspect 71b5df59442b" => cmd.call('docker-inspec'), "docker inspect 71b5df59442b" => cmd.call('docker-inspec'),
# docker images # docker images
"83c36bfade9375ae1feb91023cd1f7409b786fd992ad4013bf0f2259d33d6406" => cmd.call('docker-images'), "83c36bfade9375ae1feb91023cd1f7409b786fd992ad4013bf0f2259d33d6406" => cmd.call('docker-images'),
# modprobe for kernel_module
"modprobe --showconfig" => cmd.call('modprobe-config'),
# get-process cmdlet for processes resource # get-process cmdlet for processes resource
'$Proc = Get-Process -IncludeUserName | Where-Object {$_.Path -ne $null } | Select-Object PriorityClass,Id,CPU,PM,VirtualMemorySize,NPM,SessionId,Responding,StartTime,TotalProcessorTime,UserName,Path | ConvertTo-Csv -NoTypeInformation;$Proc.Replace("""","").Replace("`r`n","`n")' => cmd.call('get-process_processes'), '$Proc = Get-Process -IncludeUserName | Where-Object {$_.Path -ne $null } | Select-Object PriorityClass,Id,CPU,PM,VirtualMemorySize,NPM,SessionId,Responding,StartTime,TotalProcessorTime,UserName,Path | ConvertTo-Csv -NoTypeInformation;$Proc.Replace("""","").Replace("`r`n","`n")' => cmd.call('get-process_processes'),
# host resource: check to see if netcat is installed # host resource: check to see if netcat is installed

View file

@ -9,13 +9,40 @@ if !os.linux?
return return
end end
# @todo add a disabled kernel module with /bin/true and /bin/false
# Test kernel modules on all linux systems # Test kernel modules on all linux systems
describe kernel_module('video') do describe kernel_module('video') do
it { should be_loaded } it { should be_loaded }
it { should_not be_disabled }
it { should_not be_blacklisted }
end
describe kernel_module('video') do
it { should_not be_blacklisted }
it { should be_enabled }
end
describe kernel_module('sstfb') do
it { should_not be_loaded }
it { should be_disabled }
it { should be_disabled_via_bin_false }
end
describe kernel_module('nvidiafb') do
it { should_not be_loaded }
it { should be_disabled }
it { should be_disabled_via_bin_true }
end
describe kernel_module('floppy') do
it { should be_blacklisted }
it { should_not be_enabled }
end end
describe kernel_module('bridge') do describe kernel_module('bridge') do
it { should_not be_loaded } it { should_not be_loaded }
it { should_not be_enabled }
end end
describe kernel_module('dhcp') do describe kernel_module('dhcp') do

View file

@ -1,2 +1,3 @@
Module Size Used by Module Size Used by
bridge 73728 1 br_netfilter bridge 73728 1 br_netfilter
video 24400 0

View file

@ -0,0 +1,3 @@
blacklist floppy
install nvidiafb /bin/true
install sstfb /sbin/false

View file

@ -6,23 +6,120 @@ require 'helper'
require 'inspec/resource' require 'inspec/resource'
describe 'Inspec::Resources::KernelModule' do describe 'Inspec::Resources::KernelModule' do
it 'verify kernel_module parsing' do
#kernel version
# 1
it 'Verify kernel_module version' do
resource = load_resource('kernel_module', 'dhcp')
_(resource.version).must_equal '3.2.2'
end
# loaded
# 2
it 'Verify kernel_module parsing `loaded` - true' do
resource = load_resource('kernel_module', 'bridge') resource = load_resource('kernel_module', 'bridge')
_(resource.loaded?).must_equal true _(resource.loaded?).must_equal true
end end
it 'verify kernel_module parsing' do # 3
it 'Verify kernel_module parsing `loaded` - false' do
resource = load_resource('kernel_module', 'bridges') resource = load_resource('kernel_module', 'bridges')
_(resource.loaded?).must_equal false _(resource.loaded?).must_equal false
end end
it 'verify kernel_module parsing' do #disabled
resource = load_resource('kernel_module', 'dhcp') # 4
it 'Verify kernel_module parsing `disabled` - true ' do
resource = load_resource('kernel_module', 'nvidiafb')
_(resource.disabled?).must_equal true
end
# 5
it 'Verify kernel_module parsing `disabled` - false' do
resource = load_resource('kernel_module', 'bridge')
_(resource.disabled?).must_equal false
end
#/bin/true
# 6
it 'Verify a kernel_module is disabled via /bin/true - true' do
resource = load_resource('kernel_module', 'nvidiafb')
_(resource.blacklisted?).must_equal true
end
# 7
it 'Verify a kernel_module is not disabled via /bin/true - false' do
resource = load_resource('kernel_module', 'ssftb')
_(resource.blacklisted?).must_equal false
end
# 8
#/bin/false
it 'Verify a kernel_module is disabled via /bin/false - true' do
resource = load_resource('kernel_module', 'sstfb')
_(resource.blacklisted?).must_equal true
end
# 9
it 'Verify a kernel_module is not disabled via /bin/false - true ' do
resource = load_resource('kernel_module', 'bridge')
_(resource.blacklisted?).must_equal false
end
# 10
# unlisted bin/true,/bin/false
it 'Verify an unlisted kernel_module is not disabled via /bin/true - false' do
resource = load_resource('kernel_module', 'fakemod')
_(resource.blacklisted?).must_equal false
end
# 11
it 'Verify an unlisted kernel_module is not disabled via /bin/false - false' do
resource = load_resource('kernel_module', 'fakemod')
_(resource.blacklisted?).must_equal false
end
# 12
#blacklisting
it 'Verify a kernel_module is blacklisted - true' do
resource = load_resource('kernel_module', 'floppy')
_(resource.blacklisted?).must_equal true
end
# 13
it 'Verify a kernel_module is not blacklisted - false' do
resource = load_resource('kernel_module', 'ssftb')
_(resource.blacklisted?).must_equal false
end
# 14
#unlisted moduled
it 'Verify an unlisted kernel_module is not `loaded` - false' do
resource = load_resource('kernel_module', 'not_a_module')
_(resource.loaded?).must_equal false _(resource.loaded?).must_equal false
end end
it 'verify kernel_module version' do # 15
resource = load_resource('kernel_module', 'dhcp') it 'Verify an unlisted kernel_module is not `disabled` - false' do
_(resource.version).must_equal '3.2.2' resource = load_resource('kernel_module', 'not_a_module')
_(resource.disabled?).must_equal false
end
# 16
it 'Verify an unlisted kernel_module is not blacklisted - false' do
resource = load_resource('kernel_module', 'not_a_module')
_(resource.blacklisted?).must_equal false
end
# 17
it 'Verify an unlisted kernel_module is not disabled_via_bin_true - false' do
resource = load_resource('kernel_module', 'not_a_module')
_(resource.blacklisted?).must_equal false
end
# 18
it 'Verify an unlisted kernel_module is not disabled_via_bin_false - false' do
resource = load_resource('kernel_module', 'not_a_module')
_(resource.blacklisted?).must_equal false
end end
end end