mirror of
https://github.com/inspec/inspec
synced 2024-11-10 15:14:23 +00:00
etc_fstab resource: test contents of the /etc/fstab file (#2064)
* Adding support for fstab Signed-off-by: dromazos <dromazmj@dukes.jmu.edu> * New Resource - etc_fstab Signed-off-by: dromazos <dromazmj@dukes.jmu.edu> * New Resource - etc_fstab Signed-off-by: dromazos <dromazmj@dukes.jmu.edu> * Modifications to new resource - etc_fstab Signed-off-by: dromazos <dromazmj@dukes.jmu.edu> * Modifications to new resource - etc_fstab Signed-off-by: dromazos <dromazmj@dukes.jmu.edu> * Modifications to new resource - etc_fstab Signed-off-by: dromazos <dromazmj@dukes.jmu.edu> * Modifications to docs of new resource etc_fstab Signed-off-by: dromazmj <dromazmj@dukes.jmu.edu> * Modifications to new resource etc_fstab Signed-off-by: dromazmj <dromazmj@dukes.jmu.edu>
This commit is contained in:
parent
a9d0d65c54
commit
70548ab754
8 changed files with 335 additions and 0 deletions
117
docs/resources/etc_fstab.md.erb
Normal file
117
docs/resources/etc_fstab.md.erb
Normal file
|
@ -0,0 +1,117 @@
|
|||
---
|
||||
title: About the etc_fstab Resource
|
||||
---
|
||||
|
||||
# etc_fstab
|
||||
|
||||
Use the `etc_fstab` InSpec audit resource to test information about all partitions and storage devices on a system.
|
||||
## Syntax
|
||||
|
||||
An etc_fstab rule specifies a device name, its mount point, its mount type, the options its mounted with,
|
||||
its dump options, and the order the files system should be checked.
|
||||
|
||||
## Syntax
|
||||
|
||||
Use the where clause to match a property to one or more rules in the fstab file.
|
||||
|
||||
describe etc_fstab.where { device_name == 'value' } do
|
||||
its('mount_point') { should cmp 'hostname' }
|
||||
its('file_system_type') { should cmp 'list' }
|
||||
its('mount_options') { should cmp 'list' }
|
||||
its('dump_options') { should cmp 'list' }
|
||||
its('file_system_options') { should cmp 'list' }
|
||||
end
|
||||
|
||||
Use the optional constructor parameter to give an alternative path to fstab file
|
||||
|
||||
describe etc_fstab(hosts_path).where { device_name == 'value' } do
|
||||
its('mount_point') { should cmp 'hostname' }
|
||||
its('file_system_type') { should cmp 'list' }
|
||||
its('mount_options') { should cmp 'list' }
|
||||
its('dump_options') { should cmp 'list' }
|
||||
its('file_system_options') { should cmp 'list ' }
|
||||
end
|
||||
|
||||
where
|
||||
|
||||
* `device_name` is the name associated with the device.
|
||||
* `mount_point` is the directory at which the filesystem is configured to be mounted.
|
||||
* `file_system_type` is the type of file system of the device or partition.
|
||||
* `mount_options` is the options for the device or partition.
|
||||
* `dump_options` is a number used by dump to decide if a file system should be backed up.
|
||||
* `file_system_options` is a number that specifies the order the file system should be checked.
|
||||
|
||||
## Property Examples and Return Types
|
||||
|
||||
### device_name
|
||||
|
||||
`device_name` returns a string array of device names mounted on the system.
|
||||
|
||||
describe etc_fstab.where { mount_point == '/mnt/sr0' } do
|
||||
its('device_name') { should cmp '/dev/sr0' }
|
||||
end
|
||||
|
||||
### mount_point
|
||||
|
||||
`mount_point` returns a string array of directorys at which filesystems are configured to be mounted.
|
||||
|
||||
describe etc_fstab.where { device_name == '/dev/sr0' } do
|
||||
its('mount_point') { should cmp '/mnt/sr0' }
|
||||
end
|
||||
|
||||
### file_system_type
|
||||
|
||||
`file_system_type` returns a String array of each partitions file system type.
|
||||
|
||||
describe etc_fstab.where { device_name == '/dev/sr0' } do
|
||||
its('file_system_type') { should cmp 'iso9660' }
|
||||
end
|
||||
|
||||
### mount_options
|
||||
|
||||
`mount_options` returns a two dimensional array of each partitions mount options.
|
||||
|
||||
describe etc_fstab.where { mount_point == '/' } do
|
||||
its('mount_options') { should eq [['defaults', 'x-systemd.device-timeout=0']] }
|
||||
end
|
||||
|
||||
### dump_options
|
||||
|
||||
`dump_options` returns a integer array of each partitions dump option.
|
||||
|
||||
describe etc_fstab.where { device_name == '/dev/sr0' } do
|
||||
its('dump_options') { should cmp 0 }
|
||||
end
|
||||
|
||||
### file_system_options
|
||||
|
||||
`file_system_options` returns a integer array of each partitions file system option.
|
||||
|
||||
describe etc_fstab.where { device_name == '/dev/sr0' } do
|
||||
its('file_system_options') { should cmp 0 }
|
||||
end
|
||||
|
||||
## Examples
|
||||
|
||||
The following examples show how to use this InSpec resource.
|
||||
|
||||
### Check all partitions that have type of 'nfs'.
|
||||
|
||||
nfs_systems = etc_fstab.nfs_file_systems
|
||||
nfs_systems.each do |partition|
|
||||
describe partition do
|
||||
its('mount_options') { should include 'nosuid' }
|
||||
end
|
||||
end
|
||||
|
||||
### Check the partition mounted at /home contains 'nosuid' in its mount_options.
|
||||
|
||||
describe etc_fstab do
|
||||
its('home_mount_options') { should include 'nosuid' }
|
||||
end
|
||||
|
||||
### Check if a partition is mounted at a point.
|
||||
|
||||
describe etc_fstab.where { mount_point == '/home' } do
|
||||
it { should be_configured }
|
||||
end
|
|
@ -89,6 +89,7 @@ require 'resources/directory'
|
|||
require 'resources/docker'
|
||||
require 'resources/docker_image'
|
||||
require 'resources/docker_container'
|
||||
require 'resources/etc_fstab'
|
||||
require 'resources/etc_group'
|
||||
require 'resources/etc_hosts'
|
||||
require 'resources/file'
|
||||
|
|
107
lib/resources/etc_fstab.rb
Normal file
107
lib/resources/etc_fstab.rb
Normal file
|
@ -0,0 +1,107 @@
|
|||
# encoding: utf-8
|
||||
# copyright:
|
||||
# author: Matthew Dromazos
|
||||
|
||||
require 'utils/parser'
|
||||
|
||||
class EtcFstab < Inspec.resource(1)
|
||||
name 'etc_fstab'
|
||||
desc 'Use the etc_fstab InSpec audit resource to check the configuration of the etc/fstab file.'
|
||||
example "
|
||||
removable_media = etc_fstab.removable_media_file_systems
|
||||
removable_media.each do |media|
|
||||
describe media do
|
||||
its ('mount_options') { should include 'nosuid' }
|
||||
end
|
||||
end
|
||||
|
||||
nfs_systems = etc_fstab.nfs_file_systems
|
||||
nfs_systems.each do |file_system|
|
||||
describe file_system do
|
||||
its ('mount_options') { should include 'nosuid' }
|
||||
its ('mount_options') { should include 'noexec' }
|
||||
its ('mount_options') { should include '\'sec=krb5:krb5i:krb5p\'' }
|
||||
end
|
||||
end
|
||||
|
||||
describe etc_fstab do
|
||||
its ('home_mount_options') { should include 'nosuid' }
|
||||
end
|
||||
"
|
||||
|
||||
attr_reader :params
|
||||
|
||||
include CommentParser
|
||||
|
||||
def initialize(fstab_path = nil)
|
||||
return skip_resource 'The `etc_fstab` resource is not supported on your OS.' unless inspec.os.linux?
|
||||
@conf_path = fstab_path || '/etc/fstab'
|
||||
@files_contents = {}
|
||||
@content = nil
|
||||
@params = nil
|
||||
read_content
|
||||
end
|
||||
|
||||
filter = FilterTable.create
|
||||
filter.add_accessor(:where)
|
||||
.add_accessor(:entries)
|
||||
.add(:device_name, field: 'device_name')
|
||||
.add(:mount_point, field: 'mount_point')
|
||||
.add(:file_system_type, field: 'file_system_type')
|
||||
.add(:mount_options, field: 'mount_options')
|
||||
.add(:dump_options, field: 'dump_options')
|
||||
.add(:file_system_options, field: 'file_system_options')
|
||||
.add(:configured?) { |x| x.entries.any? }
|
||||
|
||||
filter.connect(self, :params)
|
||||
|
||||
def nfs_file_systems
|
||||
where { file_system_type.match(/nfs/) }
|
||||
end
|
||||
|
||||
def home_mount_options
|
||||
return nil unless where { mount_point == '/home' }.configured?
|
||||
where { mount_point == '/home' }.entries[0].mount_options
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def read_content
|
||||
@content = ''
|
||||
@params = {}
|
||||
@content = read_file(@conf_path)
|
||||
@params = parse_conf(@content)
|
||||
end
|
||||
|
||||
def parse_conf(content)
|
||||
content.map do |line|
|
||||
data, = parse_comment_line(line, comment_char: '#', standalone_comments: false)
|
||||
parse_line(data) unless data == ''
|
||||
end.compact
|
||||
end
|
||||
|
||||
def parse_line(line)
|
||||
attributes = line.split
|
||||
{
|
||||
'device_name' => attributes[0],
|
||||
'mount_point' => attributes[1],
|
||||
'file_system_type' => attributes[2],
|
||||
'mount_options' => attributes[3].split(','),
|
||||
'dump_options' => attributes[4].to_i,
|
||||
'file_system_options' => attributes[5].to_i,
|
||||
}
|
||||
end
|
||||
|
||||
def read_file(conf_path = @conf_path)
|
||||
file = inspec.file(conf_path)
|
||||
if !file.file?
|
||||
return skip_resource "Can't find \"#{@conf_path}\""
|
||||
end
|
||||
|
||||
raw_conf = file.content
|
||||
if raw_conf.empty? && !file.empty?
|
||||
return skip_resource("File is empty or unable to read file at path:\"#{@conf_path}\"")
|
||||
end
|
||||
raw_conf.lines
|
||||
end
|
||||
end
|
|
@ -161,6 +161,9 @@ class MockLoader
|
|||
'/var/lib/postgresql/9.5/main' => mockfile.call('var.9.5.main'),
|
||||
'/etc/hosts' => mockfile.call('hosts'),
|
||||
'C:\windows\system32\drivers\etc\hosts' => mockfile.call('hosts'),
|
||||
'/etc/fstab' => mockfile.call('fstab'),
|
||||
'fstab_no_home' => mockfile.call('fstab_no_home'),
|
||||
'fstab_one_mount' => mockfile.call('fstab_one_mount'),
|
||||
'/etc/aide.conf' => mockfile.call('aide.conf'),
|
||||
'/var/lib/fake_rpmdb' => mockdir.call(true),
|
||||
'/var/lib/rpmdb_does_not_exist' => mockdir.call(false),
|
||||
|
|
19
test/unit/mock/files/fstab
Normal file
19
test/unit/mock/files/fstab
Normal file
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# /etc/fstab
|
||||
# Created by anaconda on Fri Jul 21 21:25:41 2017
|
||||
#
|
||||
# Accessible filesystems, by reference, are maintained under '/dev/disk'
|
||||
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
|
||||
#
|
||||
/dev/mapper/vg1-lv_root / xfs defaults,x-systemd.device-timeout=0 0 0
|
||||
UUID=ebffcd01-0695-4d4a-91a4-3a53c6f88d06 /boot xfs defaults,nodev,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_home /home xfs defaults,x-systemd.device-timeout=0,nodev,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_tmp /tmp xfs defaults,x-systemd.device-timeout=0,nodev,noexec,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_var /var xfs defaults,x-systemd.device-timeout=0,nodev,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_log /var/log xfs defaults,x-systemd.device-timeout=0,nodev,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_audit /var/log/audit xfs defaults,x-systemd.device-timeout=0,nodev,nosuid,nodev,noexec,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_swap swap swap defaults,x-systemd.device-timeout=0 0 0
|
||||
/dev/sr0 /mnt/sr0 iso9660 defaults,ro,noexec,noauto 0 0
|
||||
/dev/cdrom /mnt/cdrom iso9660 defaults,ro,noexec,noauto 0 0
|
||||
tmpfs /dev/shm tmpfs noexec,nosuid,nodev 0 0
|
||||
server:/usr/local/pub /pub nfs rsize=8192,wsize=8192,timeo=14,intr 0 0
|
18
test/unit/mock/files/fstab_no_home
Normal file
18
test/unit/mock/files/fstab_no_home
Normal file
|
@ -0,0 +1,18 @@
|
|||
#
|
||||
# /etc/fstab
|
||||
# Created by anaconda on Fri Jul 21 21:25:41 2017
|
||||
#
|
||||
# Accessible filesystems, by reference, are maintained under '/dev/disk'
|
||||
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
|
||||
#
|
||||
/dev/mapper/vg1-lv_root / xfs defaults,x-systemd.device-timeout=0 0 0
|
||||
UUID=ebffcd01-0695-4d4a-91a4-3a53c6f88d06 /boot xfs defaults,nodev,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_tmp /tmp xfs defaults,x-systemd.device-timeout=0,nodev,noexec,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_var /var xfs defaults,x-systemd.device-timeout=0,nodev,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_log /var/log xfs defaults,x-systemd.device-timeout=0,nodev,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_audit /var/log/audit xfs defaults,x-systemd.device-timeout=0,nodev,nosuid,nodev,noexec,nosuid 0 0
|
||||
/dev/mapper/vg1-lv_swap swap swap defaults,x-systemd.device-timeout=0 0 0
|
||||
/dev/sr0 /mnt/sr0 iso9660 defaults,ro,noexec,noauto 0 0
|
||||
/dev/cdrom /mnt/cdrom iso9660 defaults,ro,noexec,noauto 0 0
|
||||
tmpfs /dev/shm tmpfs noexec,nosuid,nodev 0 0
|
||||
server:/usr/local/pub /pub nfs rsize=8192,wsize=8192,timeo=14,intr 0 0
|
8
test/unit/mock/files/fstab_one_mount
Normal file
8
test/unit/mock/files/fstab_one_mount
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
# /etc/fstab
|
||||
# Created by anaconda on Fri Jul 21 21:25:41 2017
|
||||
#
|
||||
# Accessible filesystems, by reference, are maintained under '/dev/disk'
|
||||
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
|
||||
#
|
||||
/dev/mapper/vg1-lv_root / xfs defaults,x-systemd.device-timeout=0 0 0
|
62
test/unit/resources/etc_fstab_test.rb
Normal file
62
test/unit/resources/etc_fstab_test.rb
Normal file
|
@ -0,0 +1,62 @@
|
|||
# encoding: utf-8
|
||||
# author: Matthew Dromazos
|
||||
|
||||
require 'helper'
|
||||
require 'inspec/resource'
|
||||
|
||||
describe 'Inspec::Resources::Fstab' do
|
||||
let(:resource) { load_resource('etc_fstab') }
|
||||
it 'Verify etc_hosts filtering by `device_name`' do
|
||||
entries = resource.where { device_name == '/dev/mapper/vg1-lv_root' }
|
||||
_(entries.mount_point).must_equal ['/']
|
||||
_(entries.file_system_type).must_equal ['xfs']
|
||||
_(entries.mount_options).must_equal [['defaults', 'x-systemd.device-timeout=0']]
|
||||
_(entries.dump_options).must_equal [0]
|
||||
_(entries.file_system_options).must_equal [0]
|
||||
end
|
||||
|
||||
it 'Verify etc_hosts filtering by `mount_point`' do
|
||||
entries = resource.where { mount_point == '/' }
|
||||
_(entries.device_name).must_equal ['/dev/mapper/vg1-lv_root']
|
||||
_(entries.file_system_type).must_equal ['xfs']
|
||||
_(entries.mount_options).must_equal [['defaults', 'x-systemd.device-timeout=0']]
|
||||
_(entries.dump_options).must_equal [0]
|
||||
_(entries.file_system_options).must_equal [0]
|
||||
end
|
||||
|
||||
it 'Verify parsing an entry where mount_options is a single item' do
|
||||
resourceOneMount = load_resource('etc_fstab', 'fstab_one_mount')
|
||||
entries = resourceOneMount.where { file_system_options == 0 }
|
||||
_(entries.mount_options).must_equal [['defaults', 'x-systemd.device-timeout=0']]
|
||||
end
|
||||
|
||||
it 'Verify parsing an entry where mount_options is multiple items' do
|
||||
entries = resource.where { file_system_options == 0 }
|
||||
_(entries.mount_options).must_equal [['defaults', 'x-systemd.device-timeout=0'] , ['defaults', 'nodev', 'nosuid'], ['defaults', 'x-systemd.device-timeout=0', 'nodev', 'nosuid'], ['defaults', 'x-systemd.device-timeout=0', 'nodev', 'noexec', 'nosuid'],
|
||||
['defaults', 'x-systemd.device-timeout=0', 'nodev', 'nosuid'], ['defaults', 'x-systemd.device-timeout=0', 'nodev', 'nosuid'], ['defaults', 'x-systemd.device-timeout=0', 'nodev', 'nosuid', 'nodev', 'noexec', 'nosuid'], ['defaults', 'x-systemd.device-timeout=0'],
|
||||
['defaults', 'ro', 'noexec', 'noauto'], ['defaults', 'ro', 'noexec', 'noauto'], ['noexec', 'nosuid', 'nodev'], ['rsize=8192', 'wsize=8192', 'timeo=14', 'intr'] ]
|
||||
end
|
||||
|
||||
it 'verify home_mount_options returns something when /home is configured' do
|
||||
entries = resource.where { mount_point == '/home' }
|
||||
_(entries.configured?).must_equal true
|
||||
_(resource.home_mount_options).must_equal [ 'defaults', 'x-systemd.device-timeout=0', 'nodev', 'nosuid']
|
||||
end
|
||||
|
||||
it 'verify home_mount_options returns something when /home is not configured' do
|
||||
resourceNoHome = load_resource('etc_fstab', 'fstab_no_home')
|
||||
entries = resourceNoHome.where { mount_point == '/home' }
|
||||
_(entries.configured?).must_equal false
|
||||
_(resourceNoHome.home_mount_options).must_be_nil
|
||||
end
|
||||
|
||||
it 'verify etc_fstab can detect all nfs file systems' do
|
||||
entries = resource.nfs_file_systems
|
||||
_(entries.device_name).must_equal ['server:/usr/local/pub']
|
||||
_(entries.mount_point).must_equal ['/pub']
|
||||
_(entries.file_system_type).must_equal ['nfs']
|
||||
_(entries.mount_options).must_equal [['rsize=8192', 'wsize=8192', 'timeo=14', 'intr']]
|
||||
_(entries.dump_options).must_equal [0]
|
||||
_(entries.file_system_options).must_equal [0]
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue