Merge pull request #269 from chef/chris-rock/shell-help

Feature: Add shell `help resource` command
This commit is contained in:
Dominik Richter 2015-12-01 11:13:49 +01:00
commit 3d0a1b81d8
50 changed files with 409 additions and 106 deletions

View file

@ -7,9 +7,20 @@ module Inspec
class Resource class Resource
def self.name(name = nil) def self.name(name = nil)
return if name.nil? return if name.nil?
@name = name
Inspec::Plugins::Resource.__register(name, self) Inspec::Plugins::Resource.__register(name, self)
end end
def self.desc(description = nil)
return if description.nil?
Inspec::Resource.registry[@name].desc(description)
end
def self.example(example = nil)
return if example.nil?
Inspec::Resource.registry[@name].example(example)
end
def self.__register(name, obj) def self.__register(name, obj)
# rubocop:disable Lint/NestedMethodDefinition # rubocop:disable Lint/NestedMethodDefinition
cl = Class.new(obj) do cl = Class.new(obj) do
@ -23,6 +34,16 @@ module Inspec
super(*args) super(*args)
end end
def self.desc(description = nil)
return @description if description.nil?
@description = description
end
def self.example(example = nil)
return @example if example.nil?
@example = example
end
def inspec def inspec
@__backend_runner__ @__backend_runner__
end end

View file

@ -24,8 +24,8 @@ module Inspec
that = self that = self
# Add the help command # Add the help command
Pry::Commands.block_command 'usage', 'Show examples' do Pry::Commands.block_command 'help', 'Show examples' do |resource|
that.usage that.help(resource)
end end
# Add a help menu as the default intro # Add a help menu as the default intro
@ -38,15 +38,30 @@ module Inspec
"\033[1m#{x}\033[0m" "\033[1m#{x}\033[0m"
end end
def print_example(example)
# determine min whitespace that can be removed
min = nil
example.lines.each do |line|
if line.strip.length > 0 # ignore empty lines
line_whitespace = line.length - line.lstrip.length
min = line_whitespace if min.nil? || line_whitespace < min
end
end
# remove whitespace from each line
example.gsub(/\n\s{#{min}}/, "\n")
end
def intro def intro
puts 'Welcome to the interactive Inspec Shell' puts 'Welcome to the interactive InSpec Shell'
puts "To find out how to use it, type: #{mark 'usage'}" puts "To find out how to use it, type: #{mark 'help'}"
puts puts
end end
def usage def help(resource = nil)
ctx = @runner.backend if resource.nil?
puts <<EOF
ctx = @runner.backend
puts <<EOF
Welcome to the interactive Inspec Shell. Welcome to the interactive Inspec Shell.
@ -56,12 +71,45 @@ For example:
command('uname -a').stdout command('uname -a').stdout
file('/proc/cpuinfo').content file('/proc/cpuinfo').content
To show all available resources:
help resources
You are currently running on: You are currently running on:
OS family: #{mark ctx.os[:family] || 'unknown'} OS family: #{mark ctx.os[:family] || 'unknown'}
OS release: #{mark ctx.os[:release] || 'unknown'} OS release: #{mark ctx.os[:release] || 'unknown'}
EOF EOF
elsif resource == 'resources'
resources
else
if !Inspec::Resource.registry[resource].nil?
puts <<EOF
#{mark 'Name:'} #{resource}
#{mark 'Description:'}
#{Inspec::Resource.registry[resource].desc}
#{mark 'Example:'}
#{print_example(Inspec::Resource.registry[resource].example)}
#{mark 'Web Reference:'}
https://github.com/chef/inspec/blob/master/docs/resources.rst##{resource}
EOF
else
puts 'Only the following resources are available:'
resources
end
end
end
def resources
puts Inspec::Resource.registry.keys.join(' ')
end end
end end
end end

View file

@ -9,6 +9,12 @@ require 'utils/find_files'
class ApacheConf < Inspec.resource(1) class ApacheConf < Inspec.resource(1)
name 'apache_conf' name 'apache_conf'
desc 'Use the apache_conf InSpec audit resource to test the configuration settings for Apache. This file is typically located under /etc/apache2 on the Debian and Ubuntu platforms and under /etc/httpd on the Fedora, CentOS, Red Hat Enterprise Linux, and Arch Linux platforms. The configuration settings may vary significantly from platform to platform.'
example "
describe apache_conf do
its('setting_name') { should eq 'value' }
end
"
include FindFiles include FindFiles

View file

@ -30,6 +30,13 @@ require 'uri'
class AptRepository < Inspec.resource(1) class AptRepository < Inspec.resource(1)
name 'apt' name 'apt'
desc 'Use the apt InSpec audit resource to verify Apt repositories on the Debian and Ubuntu platforms, and also PPA repositories on the Ubuntu platform.'
example "
describe apt('nginx/stable') do
it { should exist }
it { should be_enabled }
end
"
def initialize(ppa_name) def initialize(ppa_name)
@deb_url = nil @deb_url = nil

View file

@ -23,15 +23,15 @@
# - "Failure" # - "Failure"
# #
# Further information is available at: https://msdn.microsoft.com/en-us/library/dd973859.aspx # Further information is available at: https://msdn.microsoft.com/en-us/library/dd973859.aspx
#
# Usage:
#
# describe audit_policy do
# its('Other Account Logon Events') { should_not eq 'No Auditing' }
# end
class AuditPolicy < Inspec.resource(1) class AuditPolicy < Inspec.resource(1)
name 'audit_policy' name 'audit_policy'
desc 'Use the audit_policy InSpec audit resource to test auditing policies on the Microsoft Windows platform. An auditing policy is a category of security-related events to be audited. Auditing is disabled by default and may be enabled for categories like account management, logon events, policy changes, process tracking, privilege use, system events, or object access. For each auditing category property that is enabled, the auditing level may be set to No Auditing, Not Specified, Success, Success and Failure, or Failure.'
example "
describe audit_policy do
its('parameter') { should eq 'value' }
end
"
def method_missing(method) def method_missing(method)
key = method.to_s key = method.to_s

View file

@ -6,15 +6,14 @@
require 'utils/simpleconfig' require 'utils/simpleconfig'
# Usage:
# describe audit_daemon_conf do
# its("space_left_action") { should eq "email" }
# its("action_mail_acct") { should eq "root" }
# its("admin_space_left_action") { should eq "halt" }
# end
class AuditDaemonConf < Inspec.resource(1) class AuditDaemonConf < Inspec.resource(1)
name 'auditd_conf' name 'auditd_conf'
desc "Use the auditd_conf InSpec audit resource to test the configuration settings for the audit daemon. This file is typically located under /etc/audit/auditd.conf' on UNIX and Linux platforms."
example "
describe auditd_conf do
its('space_left_action') { should eq 'email' }
end
"
def initialize(path = nil) def initialize(path = nil)
@conf_path = path || '/etc/audit/auditd.conf' @conf_path = path || '/etc/audit/auditd.conf'

View file

@ -4,16 +4,17 @@
# author: Dominik Richter # author: Dominik Richter
# license: All rights reserved # license: All rights reserved
# Usage:
# describe audit_daemon_rules do
# its("LIST_RULES") {should contain_match(/^exit,always arch=.* key=time-change syscall=adjtimex,settimeofday/) }
# its("LIST_RULES") {should contain_match(/^exit,always arch=.* key=time-change syscall=stime,settimeofday,adjtimex/) }
# its("LIST_RULES") {should contain_match(/^exit,always arch=.* key=time-change syscall=clock_settime/)}
# its("LIST_RULES") {should contain_match(/^exit,always watch=\/etc\/localtime perm=wa key=time-change/)}
# end
class AuditDaemonRules < Inspec.resource(1) class AuditDaemonRules < Inspec.resource(1)
name 'auditd_rules' name 'auditd_rules'
desc 'Use the auditd_rules InSpec audit resource to test the rules for logging that exist on the system. The audit.rules file is typically located under /etc/audit/ and contains the list of rules that define what is captured in log files.'
example "
describe auditd_rules do
its('LIST_RULES') {should contain_match(/^exit,always arch=.* key=time-change syscall=adjtimex,settimeofday/) }
its('LIST_RULES') {should contain_match(/^exit,always arch=.* key=time-change syscall=stime,settimeofday,adjtimex/) }
its('LIST_RULES') {should contain_match(/^exit,always arch=.* key=time-change syscall=clock_settime/)}
its('LIST_RULES') {should contain_match(/^exit,always watch=\/etc\/localtime perm=wa key=time-change/)}
end
"
def initialize def initialize
@content = inspec.command('/sbin/auditctl -l').stdout.chomp @content = inspec.command('/sbin/auditctl -l').stdout.chomp

View file

@ -4,15 +4,15 @@
require 'resources/file' require 'resources/file'
# Usage:
# describe bond('bond0') do
# it { should exist }
# it { should have_interface 'eth0' }
# end
module Inspec::Resources module Inspec::Resources
class Bond < File class Bond < File
name 'bond' name 'bond'
desc 'Use the bond InSpec audit resource to test a logical, bonded network interface (i.e. "two or more network interfaces aggregated into a single, logical network interface"). On Linux platforms, any value in the /proc/net/bonding directory may be tested.'
example "
describe bond('bond0') do
it { should exist }
end
"
def initialize(bond) def initialize(bond)
@bond = bond @bond = bond

View file

@ -10,6 +10,13 @@
class Bridge < Inspec.resource(1) class Bridge < Inspec.resource(1)
name 'bridge' name 'bridge'
desc 'Use the bridge InSpec audit resource to test basic network bridge properties, such as name, if an interface is defined, and the associations for any defined interface.'
example "
describe bridge 'br0' do
it { should exist }
it { should have_interface 'eth0' }
end
"
def initialize(bridge_name) def initialize(bridge_name)
@bridge_name = bridge_name @bridge_name = bridge_name

View file

@ -4,16 +4,18 @@
# author: Christoph Hartmann # author: Christoph Hartmann
# license: All rights reserved # license: All rights reserved
# Usage:
# describe command('ls -al /') do
# it { should exist }
# its(:stdout) { should match /bin/ }
# its(:stderr) { should match /No such file or directory/ }
# its(:exit_status) { should eq 0 }
# end
class Cmd < Inspec.resource(1) class Cmd < Inspec.resource(1)
name 'command' name 'command'
desc 'Use the command InSpec audit resource to test an arbitrary command that is run on the system.'
example "
describe command('ls -al /') do
it { should exist }
its(:stdout) { should match /bin/ }
its('stderr') { should eq '' }
its(:exit_status) { should eq 0 }
end
"
attr_reader :command attr_reader :command
def initialize(cmd) def initialize(cmd)

View file

@ -3,15 +3,16 @@
# author: Dominik Richter # author: Dominik Richter
# Parses a csv document # Parses a csv document
# Usage:
# describe csv('example.csv') do
# its('name') { should eq(['John', 'Alice']) }
# end
#
# This implementation was inspired by a blog post # This implementation was inspired by a blog post
# @see http://technicalpickles.com/posts/parsing-csv-with-ruby # @see http://technicalpickles.com/posts/parsing-csv-with-ruby
class CsvConfig < JsonConfig class CsvConfig < JsonConfig
name 'csv' name 'csv'
desc 'Use the csv InSpec audit resource to test configuration data in a CSV file.'
example "
describe csv('example.csv') do
its('name') { should eq(['John', 'Alice']) }
end
"
# override file load and parse hash from csv # override file load and parse hash from csv
def parse(content) def parse(content)

View file

@ -7,6 +7,12 @@ require 'resources/file'
module Inspec::Resources module Inspec::Resources
class Directory < File class Directory < File
name 'directory' name 'directory'
desc 'Use the directory InSpec audit resource to test if the file type is a directory. This is equivalent to using the file InSpec audit resource and the be_directory matcher, but provides a simpler and more direct way to test directories. All of the matchers available to file may be used with directory.'
example "
describe directory('path') do
it { should be_directory }
end
"
end end
def to_s def to_s

View file

@ -29,6 +29,14 @@ class EtcGroup < Inspec.resource(1)
include ContentParser include ContentParser
name 'etc_group' name 'etc_group'
desc 'Use the etc_group InSpec audit resource to test groups that are defined on Linux and UNIX platforms. The /etc/group file stores details about each group---group name, password, group identifier, along with a comma-separate list of users that belong to the group.'
example "
describe etc_group do
its('gids') { should_not contain_duplicates }
its('groups') { should include 'my_user' }
its('users') { should include 'my_user' }
end
"
attr_accessor :gid, :entries attr_accessor :gid, :entries
def initialize(path = nil) def initialize(path = nil)

View file

@ -7,6 +7,17 @@
module Inspec::Resources module Inspec::Resources
class File < Inspec.resource(1) class File < Inspec.resource(1)
name 'file' name 'file'
desc 'Use the file InSpec audit resource to test all system file types, including files, directories, symbolic links, named pipes, sockets, character devices, block devices, and doors.'
example "
describe file('path') do
it { should exist }
it { should be_file }
it { should be_readable }
it { should be_writable }
it { should be_owned_by 'root' }
its('mode') { should eq 0644 }
end
"
attr_reader :path attr_reader :path
def initialize(path) def initialize(path)

View file

@ -2,12 +2,14 @@
# author: Christoph Hartmann # author: Christoph Hartmann
# author: Dominik Richter # author: Dominik Richter
# Usage:
# describe gem('rubocop') do
# it { should be_installed }
# end
class GemPackage < Inspec.resource(1) class GemPackage < Inspec.resource(1)
name 'gem' name 'gem'
desc 'Use the gem InSpec audit resource to test if a global gem package is installed.'
example "
describe gem('rubocop') do
it { should be_installed }
end
"
def initialize(package_name) def initialize(package_name)
@package_name = package_name @package_name = package_name

View file

@ -15,6 +15,13 @@
class Group < Inspec.resource(1) class Group < Inspec.resource(1)
name 'group' name 'group'
desc 'Use the group InSpec audit resource to test groups on the system.'
example "
describe group('root') do
it { should exist }
its('gid') { should eq 0 }
end
"
def initialize(groupname, domain = nil) def initialize(groupname, domain = nil)
@group = groupname.downcase @group = groupname.downcase

View file

@ -26,6 +26,12 @@
class Host < Inspec.resource(1) class Host < Inspec.resource(1)
name 'host' name 'host'
desc 'Use the host InSpec audit resource to test the name used to refer to a specific host and its availability, including the Internet protocols and ports over which that host name should be available.'
example "
describe host('example.com') do
it { should be_reachable }
end
"
def initialize(hostname, params = {}) def initialize(hostname, params = {})
@hostname = hostname @hostname = hostname

View file

@ -6,16 +6,16 @@
require 'utils/simpleconfig' require 'utils/simpleconfig'
# Usage:
#
# describe inetd_conf do
# its('shell') { should eq nil }
# its('login') { should eq nil }
# its('exec') { should eq nil }
# end
class InetdConf < Inspec.resource(1) class InetdConf < Inspec.resource(1)
name 'inetd_conf' name 'inetd_conf'
desc 'Use the inetd_conf InSpec audit resource to test if a service is enabled in the inetd.conf file on Linux and UNIX platforms. inetd---the Internet service daemon---listens on dedicated ports, and then loads the appropriate program based on a request. The inetd.conf file is typically located at /etc/inetd.conf and contains a list of Internet services associated to the ports on which that service will listen. Only enabled services may handle a request; only services that are required by the system should be enabled.'
example "
describe inetd_conf do
its('shell') { should eq nil }
its('login') { should eq nil }
its('exec') { should eq nil }
end
"
def initialize(path = nil) def initialize(path = nil)
@conf_path = path || '/etc/inetd.conf' @conf_path = path || '/etc/inetd.conf'

View file

@ -4,14 +4,14 @@
require 'utils/simpleconfig' require 'utils/simpleconfig'
# Parses a ini file
# Usage:
# descibe ini do
# its("auth_protocol") { should eq "https" }
# end
class IniConfig < JsonConfig class IniConfig < JsonConfig
name 'ini' name 'ini'
desc 'Use the ini InSpec audit resource to test data in a INI file.'
example "
descibe ini do
its('auth_protocol') { should eq 'https' }
end
"
# override file load and parse hash with simple config # override file load and parse hash with simple config
def parse(content) def parse(content)
SimpleConfig.new(content).params SimpleConfig.new(content).params

View file

@ -2,18 +2,18 @@
# author: Christoph Hartmann # author: Christoph Hartmann
# author: Dominik Richter # author: Dominik Richter
# Usage:
# describe interface('eth0') do
# it { should exist }
# it { should be_up }
# its(:speed) { should eq 1000 }
# end
require 'utils/convert' require 'utils/convert'
class NetworkInterface < Inspec.resource(1) class NetworkInterface < Inspec.resource(1)
name 'interface' name 'interface'
desc 'Use the interface InSpec audit resource to test basic network adapter properties, such as name, status, state, address, and link speed (in MB/sec).'
example "
describe interface('eth0') do
it { should exist }
it { should be_up }
its(:speed) { should eq 1000 }
end
"
def initialize(iface) def initialize(iface)
@iface = iface @iface = iface

View file

@ -23,6 +23,12 @@
# @see https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html # @see https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html
class IpTables < Inspec.resource(1) class IpTables < Inspec.resource(1)
name 'iptables' name 'iptables'
desc 'Use the iptables InSpec audit resource to test rules that are defined in iptables, which maintains tables of IP packet filtering rules. There may be more than one table. Each table contains one (or more) chains (both built-in and custom). A chain is a list of rules that match packets. When the rule matches, the rule defines what target to assign to the packet.'
example "
describe iptables do
it { should have_rule('-P INPUT ACCEPT') }
end
"
def initialize(params = {}) def initialize(params = {})
@table = params[:table] || nil @table = params[:table] || nil

View file

@ -2,13 +2,14 @@
# author: Christoph Hartmann # author: Christoph Hartmann
# author: Dominik Richter # author: Dominik Richter
# Parses a json document
# Usage:
# describe json('policyfile.lock.json') do
# its('cookbook_locks.omnibus.version') { should eq('2.2.0') }
# end
class JsonConfig < Inspec.resource(1) class JsonConfig < Inspec.resource(1)
name 'json' name 'json'
desc 'Use the json InSpec audit resource to test data in a JSON file.'
example "
describe json('policyfile.lock.json') do
its('cookbook_locks.omnibus.version') { should eq('2.2.0') }
end
"
# make params readable # make params readable
attr_reader :params attr_reader :params

View file

@ -3,13 +3,14 @@
# author: Dominik Richter # author: Dominik Richter
# license: All rights reserved # license: All rights reserved
# Verifies if a kernel module is loaded
# Usage:
# describe kernel_module('bridge') do
# it { should be_loaded }
# end
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.'
example "
describe kernel_module('bridge') do
it { should be_loaded }
end
"
def initialize(modulename = nil) def initialize(modulename = nil)
@module = modulename @module = modulename

View file

@ -2,12 +2,14 @@
# author: Christoph Hartmann # author: Christoph Hartmann
# license: All rights reserved # license: All rights reserved
# Verifies if a kernel parameter is set
# describe kernel_parameter('net.ipv4.conf.all.forwarding') do
# its(:value) { should eq 0 }
# end
class KernelParameter < Inspec.resource(1) class KernelParameter < Inspec.resource(1)
name 'kernel_parameter' name 'kernel_parameter'
desc 'Use the kernel_parameter InSpec audit resource to test kernel parameters on Linux platforms.'
example "
describe kernel_parameter('net.ipv4.conf.all.forwarding') do
its(:value) { should eq 0 }
end
"
def initialize(parameter = nil) def initialize(parameter = nil)
@parameter = parameter @parameter = parameter

View file

@ -6,14 +6,14 @@
require 'utils/simpleconfig' require 'utils/simpleconfig'
# Usage:
#
# describe limits_conf do
# its('*') { should include ['hard','core','0'] }
# end
class LimitsConf < Inspec.resource(1) class LimitsConf < Inspec.resource(1)
name 'limits_conf' name 'limits_conf'
desc 'Use the limits_conf InSpec audit resource to test configuration settings in the /etc/security/limits.conf file. The limits.conf defines limits for processes (by user and/or group names) and helps ensure that the system on which those processes are running remains stable. Each process may be assigned a hard or soft limit.'
example "
describe limits_conf do
its('*') { should include ['hard','core','0'] }
end
"
def initialize(path = nil) def initialize(path = nil)
@conf_path = path || '/etc/security/limits.conf' @conf_path = path || '/etc/security/limits.conf'

View file

@ -20,6 +20,12 @@ require 'utils/simpleconfig'
class LoginDef < Inspec.resource(1) class LoginDef < Inspec.resource(1)
name 'login_defs' name 'login_defs'
desc 'Use the login_defs InSpec audit resource to test configuration settings in the /etc/login.defs file. The logins.defs file defines site-specific configuration for the shadow password suite on Linux and UNIX platforms, such as password expiration ranges, minimum/maximum values for automatic selection of user and group identifiers, or the method with which passwords are encrypted.'
example "
describe login_defs do
its('ENCRYPT_METHOD') { should eq 'SHA512' }
end
"
def initialize(path = nil) def initialize(path = nil)
@conf_path = path || '/etc/login.defs' @conf_path = path || '/etc/login.defs'

View file

@ -28,6 +28,12 @@ end
class MysqlConf < Inspec.resource(1) class MysqlConf < Inspec.resource(1)
name 'mysql_conf' name 'mysql_conf'
desc 'Use the mysql_conf InSpec audit resource to test the contents of the configuration file for MySQL, typically located at /etc/mysql/my.cnf or /etc/my.cnf.'
example "
describe mysql_conf('path') do
its('setting') { should eq 'value' }
end
"
include FindFiles include FindFiles

View file

@ -6,6 +6,13 @@
class MysqlSession < Inspec.resource(1) class MysqlSession < Inspec.resource(1)
name 'mysql_session' name 'mysql_session'
desc 'Use the mysql_session InSpec audit resource to test SQL commands run against a MySQL database.'
example "
sql = mysql_session('my_user','password')
describe sql.query('show databases like \'test\';') do
its(:stdout) { should_not match(/test/) }
end
"
def initialize(user = nil, pass = nil) def initialize(user = nil, pass = nil)
@user = user @user = user

View file

@ -2,12 +2,14 @@
# author: Christoph Hartmann # author: Christoph Hartmann
# author: Dominik Richter # author: Dominik Richter
# Usage:
# describe npm('bower') do
# it { should be_installed }
# end
class NpmPackage < Inspec.resource(1) class NpmPackage < Inspec.resource(1)
name 'npm' name 'npm'
desc 'Use the npm InSpec audit resource to test if a global npm package is installed. npm is the the package manager for Nodejs packages, such as bower and StatsD.'
example "
describe npm('bower') do
it { should be_installed }
end
"
def initialize(package_name) def initialize(package_name)
@package_name = package_name @package_name = package_name

View file

@ -6,15 +6,15 @@
require 'utils/simpleconfig' require 'utils/simpleconfig'
# Usage:
#
# describe ntp_conf do
# its('server') { should_not eq nil }
# its('restrict') { should include '-4 default kod notrap nomodify nopeer noquery'}
# end
class NtpConf < Inspec.resource(1) class NtpConf < Inspec.resource(1)
name 'ntp_conf' name 'ntp_conf'
desc 'Use the ntp_conf InSpec audit resource to test the synchronization settings defined in the ntp.conf file. This file is typically located at /etc/ntp.conf.'
example "
describe ntp_conf do
its('server') { should_not eq nil }
its('restrict') { should include '-4 default kod notrap nomodify nopeer noquery'}
end
"
def initialize(path = nil) def initialize(path = nil)
@conf_path = path || '/etc/ntp.conf' @conf_path = path || '/etc/ntp.conf'

View file

@ -11,6 +11,12 @@
# end # end
class OneGetPackage < Inspec.resource(1) class OneGetPackage < Inspec.resource(1)
name 'oneget' name 'oneget'
desc 'Use the oneget InSpec audit resource to test if the named package and/or package version is installed on the system. This resource uses OneGet, which is part of the Windows Management Framework 5.0 and Windows 10. This resource uses the Get-Package cmdlet to return all of the package names in the OneGet repository.'
example "
describe oneget('zoomit') do
it { should be_installed }
end
"
def initialize(package_name) def initialize(package_name)
@package_name = package_name @package_name = package_name

View file

@ -4,6 +4,12 @@
class OS < Inspec.resource(1) class OS < Inspec.resource(1)
name 'os' name 'os'
desc 'Use the os InSpec audit resource to test the platform on which the system is running.'
example "
describe os[:family] do
it { should eq 'redhat' }
end
"
# reuse helper methods from backend # reuse helper methods from backend
%w{redhat? debian? suse? bsd? solaris? linux? unix? windows?}.each do |os_family| %w{redhat? debian? suse? bsd? solaris? linux? unix? windows?}.each do |os_family|

View file

@ -15,6 +15,12 @@ require 'utils/simpleconfig'
class OsEnv < Inspec.resource(1) class OsEnv < Inspec.resource(1)
name 'os_env' name 'os_env'
desc 'Use the os_env InSpec audit resource to test the environment variables for the platform on which the system is running.'
example "
describe os_env('VARIABLE') do
its('matcher') { should eq 1 }
end
"
attr_reader :content attr_reader :content
def initialize(env = nil) def initialize(env = nil)

View file

@ -10,6 +10,13 @@
# end # end
class Package < Inspec.resource(1) class Package < Inspec.resource(1)
name 'package' name 'package'
desc 'Use the package InSpec audit resource to test if the named package and/or package version is installed on the system.'
example "
describe package('nginx') do
it { should be_installed }
its('version') { should eq 1.9.5 }
end
"
def initialize(package_name = nil) def initialize(package_name = nil)
@package_name = package_name @package_name = package_name

View file

@ -15,6 +15,14 @@
class PConfig < Inspec.resource(1) class PConfig < Inspec.resource(1)
name 'parse_config' name 'parse_config'
desc 'Use the parse_config InSpec audit resource to test arbitrary configuration files.'
example "
output = command('some-command').stdout
describe parse_config(output, { data_config_option: value } ) do
its('setting') { should eq 1 }
end
"
def initialize(content = nil, useropts = nil) def initialize(content = nil, useropts = nil)
@opts = {} @opts = {}
@ -63,6 +71,12 @@ end
class PConfigFile < PConfig class PConfigFile < PConfig
name 'parse_config_file' name 'parse_config_file'
desc 'Use the parse_config_file InSpec audit resource to test arbitrary configuration files. It works identiacal to parse_config. Instead of using a command output, this resource works with files.'
example "
describe parse_config_file('/path/to/file') do
its('setting') { should eq 1 }
end
"
def initialize(path, opts = nil) def initialize(path, opts = nil)
super(nil, opts) super(nil, opts)

View file

@ -29,6 +29,13 @@ require 'utils/parser'
class Passwd < Inspec.resource(1) class Passwd < Inspec.resource(1)
name 'passwd' name 'passwd'
desc 'Use the passwd InSpec audit resource to test the contents of /etc/passwd, which contains the following information for users that may log into the system and/or as users that own running processes.'
example "
describe passwd.uid(0) do
its('username') { should eq 'root' }
its('count') { should eq 1 }
end
"
include ContentParser include ContentParser

View file

@ -9,6 +9,12 @@
# #
class PipPackage < Inspec.resource(1) class PipPackage < Inspec.resource(1)
name 'pip' name 'pip'
desc 'Use the pip InSpec audit resource to test packages that are installed using the pip installer.'
example "
describe pip('Jinja2') do
it { should be_installed }
end
"
def initialize(package_name) def initialize(package_name)
@package_name = package_name @package_name = package_name

View file

@ -17,6 +17,13 @@
# TODO: improve handling of same port on multiple interfaces # TODO: improve handling of same port on multiple interfaces
class Port < Inspec.resource(1) class Port < Inspec.resource(1)
name 'port' name 'port'
desc "Use the port InSpec audit resource to test basic port properties, such as port, process, if it's listening."
example "
describe port(80) do
it { should be_listening }
its('protocol') {should eq 'tcp'}
end
"
def initialize(port) def initialize(port)
@port = port @port = port

View file

@ -10,6 +10,12 @@ require 'resources/postgres'
class PostgresConf < Inspec.resource(1) class PostgresConf < Inspec.resource(1)
name 'postgres_conf' name 'postgres_conf'
desc 'Use the postgres_conf InSpec audit resource to test the contents of the configuration file for PostgreSQL, typically located at /etc/postgresql/<version>/main/postgresql.conf or /var/lib/postgres/data/postgresql.conf, depending on the platform.'
example "
describe postgres_conf do
its('max_connections') { should eq '5' }
end
"
include FindFiles include FindFiles

View file

@ -25,6 +25,14 @@ end
class PostgresSession < Inspec.resource(1) class PostgresSession < Inspec.resource(1)
name 'postgres_session' name 'postgres_session'
desc 'Use the postgres_session InSpec audit resource to test SQL commands run against a PostgreSQL database.'
example "
sql = postgres_session('username', 'password')
describe sql.query('SELECT * FROM pg_shadow WHERE passwd IS NULL;') do
its('output') { should eq('') }
end
"
def initialize(user, pass) def initialize(user, pass)
@user = user || 'postgres' @user = user || 'postgres'

View file

@ -6,6 +6,12 @@
class Processes < Inspec.resource(1) class Processes < Inspec.resource(1)
name 'processes' name 'processes'
desc 'Use the processes InSpec audit resource to test properties for programs that are running on the system.'
example "
describe processes('mysqld') do
its('list.length') { should eq 1 }
end
"
attr_reader :list attr_reader :list
def initialize(grep) def initialize(grep)

View file

@ -12,6 +12,12 @@ require 'json'
class RegistryKey < Inspec.resource(1) class RegistryKey < Inspec.resource(1)
name 'registry_key' name 'registry_key'
desc 'Use the registry_key InSpec audit resource to test key values in the Microsoft Windows registry.'
example "
describe registry_key('path\to\key') do
its('name') { should eq 'value' }
end
"
attr_accessor :reg_key attr_accessor :reg_key

View file

@ -6,6 +6,16 @@
class Script < Cmd class Script < Cmd
name 'script' name 'script'
desc 'Use the script InSpec audit resource to test a Windows PowerShell script on the Microsoft Windows platform.'
example "
script = <<-EOH
# you powershell script
EOH
describe script(script) do
its('matcher') { should eq 'output' }
end
"
def initialize(script) def initialize(script)
case inspec.os[:family] case inspec.os[:family]

View file

@ -15,7 +15,12 @@
class SecurityPolicy < Inspec.resource(1) class SecurityPolicy < Inspec.resource(1)
name 'security_policy' name 'security_policy'
desc 'Use the security_policy InSpec audit resource to test security policies on the Microsoft Windows platform.'
example "
describe security_policy do
its('SeNetworkLogonRight') { should eq '*S-1-5-11' }
end
"
def initialize def initialize
@loaded = false @loaded = false
@policy = nil @policy = nil

View file

@ -21,6 +21,14 @@
# TODO: extend the logic to detect the running init system, independently of OS # TODO: extend the logic to detect the running init system, independently of OS
class Service < Inspec.resource(1) class Service < Inspec.resource(1)
name 'service' name 'service'
desc 'Use the service InSpec audit resource to test if the named service is installed, running and/or enabled.'
example "
describe service('service_name') do
it { should be_installed }
it { should be_enabled }
it { should be_running }
end
"
def initialize(service_name) def initialize(service_name)
@service_name = service_name @service_name = service_name

View file

@ -8,6 +8,12 @@ require 'utils/simpleconfig'
class SshConf < Inspec.resource(1) class SshConf < Inspec.resource(1)
name 'ssh_config' name 'ssh_config'
desc 'Use the sshd_config InSpec audit resource to test configuration data for the Open SSH daemon located at /etc/ssh/sshd_config on Linux and UNIX platforms. sshd---the Open SSH daemon---listens on dedicated ports, starts a daemon for each incoming connection, and then handles encryption, authentication, key exchanges, command executation, and data exchanges.'
example "
describe sshd_config do
its('Protocol') { should eq '2' }
end
"
def initialize(conf_path = nil, type = nil) def initialize(conf_path = nil, type = nil)
@conf_path = conf_path || '/etc/ssh/ssh_config' @conf_path = conf_path || '/etc/ssh/ssh_config'

View file

@ -40,7 +40,14 @@ require 'utils/convert'
class User < Inspec.resource(1) class User < Inspec.resource(1)
name 'user' name 'user'
desc 'Use the user InSpec audit resource to test user profiles, including the groups to which they belong, the frequency of required password changes, the directory paths to home and shell.'
example "
describe user('root') do
it { should exist }
its('uid') { should eq 1234 }
its('gid') { should eq 1234 }
end
"
def initialize(user) def initialize(user)
@user = user @user = user

View file

@ -29,6 +29,12 @@
# } # }
class WindowsFeature < Inspec.resource(1) class WindowsFeature < Inspec.resource(1)
name 'windows_feature' name 'windows_feature'
desc 'Use the windows_feature InSpec audit resource to test features on Microsoft Windows.'
example "
describe windows_feature('dhcp') do
it { should be_installed }
end
"
def initialize(feature) def initialize(feature)
@feature = feature @feature = feature

View file

@ -11,6 +11,12 @@ require 'yaml'
# end # end
class YamlConfig < JsonConfig class YamlConfig < JsonConfig
name 'yaml' name 'yaml'
desc 'Use the yaml InSpec audit resource to test configuration data in a YAML file.'
example "
describe yaml do
its('name') { should eq 'foo' }
end
"
# override file load and parse hash from yaml # override file load and parse hash from yaml
def parse(content) def parse(content)

View file

@ -32,6 +32,13 @@ require 'resources/file'
class Yum < Inspec.resource(1) class Yum < Inspec.resource(1)
name 'yum' name 'yum'
desc 'Use the yum InSpec audit resource to test packages in the Yum repository.'
example "
describe yum.repo('name') do
it { should exist }
it { should be_enabled }
end
"
# returns all repositories # returns all repositories
# works as following: # works as following: