inspec 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +24 -2
- data/bin/inspec +5 -2
- data/lib/bundles/inspec-init.rb +8 -0
- data/lib/bundles/inspec-init/cli.rb +86 -0
- data/lib/bundles/inspec-init/templates/profile/README.md +3 -0
- data/lib/bundles/inspec-init/templates/profile/controls/example.rb +20 -0
- data/lib/bundles/inspec-init/templates/profile/inspec.yml +8 -0
- data/lib/bundles/inspec-init/templates/profile/libraries/.gitkeep +0 -0
- data/lib/inspec/targets/archive.rb +14 -24
- data/lib/inspec/targets/core.rb +37 -8
- data/lib/inspec/targets/dir.rb +115 -52
- data/lib/inspec/targets/folder.rb +14 -29
- data/lib/inspec/targets/tar.rb +11 -13
- data/lib/inspec/targets/zip.rb +7 -7
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/iptables.rb +11 -14
- data/lib/resources/service.rb +76 -12
- data/test/integration/cookbooks/os_prepare/recipes/default.rb +1 -0
- data/test/integration/cookbooks/os_prepare/recipes/iptables.rb +13 -0
- data/test/integration/test/integration/default/iptables_spec.rb +25 -0
- data/test/unit/mock/cmd/iptables-s +1 -1
- data/test/unit/resources/iptables_test.rb +5 -0
- data/test/unit/resources/service_test.rb +46 -4
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e3b076ffed41d9148eb98065a025a6acb6a9f70
|
4
|
+
data.tar.gz: eb36dc73cf37bc30a46949943ba7db582ed82417
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 09d87d6da242d31586af6d3e39e913223a141d6dbc39474c921636d3169a57bcf1b5029defc1d2f6a8f01c246fe3494846edfe9d00a27381f3aa13f8f335435a
|
7
|
+
data.tar.gz: d2806a4c8e637a1ec46cf3ed9ea5a40fc8dd32a6e3bb0de63f405d33f4de9a09d3f25faf36932d949b73c7d9ff1d11949e59963f6ab6116402890632facb0227
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,27 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [0.
|
4
|
-
[Full Changelog](https://github.com/chef/inspec/compare/v0.
|
3
|
+
## [0.12.0](https://github.com/chef/inspec/tree/0.12.0) (2016-02-15)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.11.0...0.12.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- add runlevel support for System V services [\#455](https://github.com/chef/inspec/pull/455) ([arlimus](https://github.com/arlimus))
|
9
|
+
- Add a init subcommand [\#454](https://github.com/chef/inspec/pull/454) ([chris-rock](https://github.com/chris-rock))
|
10
|
+
|
11
|
+
**Fixed bugs:**
|
12
|
+
|
13
|
+
- Windows 2008 isn't being detected. [\#346](https://github.com/chef/inspec/issues/346)
|
14
|
+
- Fix two minor logging and config bugs in CLI [\#452](https://github.com/chef/inspec/pull/452) ([srenatus](https://github.com/srenatus))
|
15
|
+
- bugfix: verify the target resolver before using it [\#449](https://github.com/chef/inspec/pull/449) ([arlimus](https://github.com/arlimus))
|
16
|
+
- Fix iptables on CentOS6 + more tests for iptables \(plus small code improvements\) [\#442](https://github.com/chef/inspec/pull/442) ([srenatus](https://github.com/srenatus))
|
17
|
+
|
18
|
+
**Merged pull requests:**
|
19
|
+
|
20
|
+
- rework target to resolver connection [\#447](https://github.com/chef/inspec/pull/447) ([arlimus](https://github.com/arlimus))
|
21
|
+
- separate directory resolver from target resolver [\#446](https://github.com/chef/inspec/pull/446) ([arlimus](https://github.com/arlimus))
|
22
|
+
|
23
|
+
## [v0.11.0](https://github.com/chef/inspec/tree/v0.11.0) (2016-02-10)
|
24
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.10.1...v0.11.0)
|
5
25
|
|
6
26
|
**Implemented enhancements:**
|
7
27
|
|
@@ -11,12 +31,14 @@
|
|
11
31
|
**Fixed bugs:**
|
12
32
|
|
13
33
|
- File stats are not always working properly [\#430](https://github.com/chef/inspec/issues/430)
|
34
|
+
- Inspec iptables should have\_rule tests not working [\#420](https://github.com/chef/inspec/issues/420)
|
14
35
|
- Integration test for apache config [\#406](https://github.com/chef/inspec/issues/406)
|
15
36
|
- rework auditd\_rules resource [\#312](https://github.com/chef/inspec/issues/312)
|
16
37
|
- resource/auditd\_rules: update rule list format [\#309](https://github.com/chef/inspec/issues/309)
|
17
38
|
|
18
39
|
**Merged pull requests:**
|
19
40
|
|
41
|
+
- 0.11.0 [\#443](https://github.com/chef/inspec/pull/443) ([arlimus](https://github.com/arlimus))
|
20
42
|
- Fix supermarket cli registration [\#441](https://github.com/chef/inspec/pull/441) ([chris-rock](https://github.com/chris-rock))
|
21
43
|
- update to winrm 1.6.1 command scheme [\#439](https://github.com/chef/inspec/pull/439) ([arlimus](https://github.com/arlimus))
|
22
44
|
- semantics: rename CLI plugins registry -\> commands [\#435](https://github.com/chef/inspec/pull/435) ([arlimus](https://github.com/arlimus))
|
data/bin/inspec
CHANGED
@@ -84,7 +84,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
84
84
|
def archive(path)
|
85
85
|
diagnose
|
86
86
|
|
87
|
-
o =
|
87
|
+
o = opts.dup
|
88
88
|
o[:logger] = Logger.new(STDOUT)
|
89
89
|
o[:logger].level = get_log_level(o.log_level)
|
90
90
|
|
@@ -129,8 +129,11 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
129
129
|
option :format, type: :string, default: Inspec::NoSummaryFormatter, hide: true
|
130
130
|
def shell_func
|
131
131
|
diagnose
|
132
|
+
o = opts.dup
|
133
|
+
o[:logger] = Logger.new(STDOUT)
|
134
|
+
o[:logger].level = get_log_level(o.log_level)
|
132
135
|
|
133
|
-
runner = Inspec::Runner.new(
|
136
|
+
runner = Inspec::Runner.new(o)
|
134
137
|
Inspec::Shell.new(runner).start
|
135
138
|
rescue RuntimeError => e
|
136
139
|
puts e.message
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Christoph Hartmann
|
3
|
+
|
4
|
+
module Init
|
5
|
+
class CLI < Inspec::BaseCLI
|
6
|
+
namespace 'init'
|
7
|
+
|
8
|
+
# read template directoy
|
9
|
+
template_dir = File.join(File.dirname(__FILE__), 'templates')
|
10
|
+
Dir.glob(File.join(template_dir, '*')) do |template|
|
11
|
+
relative = Pathname.new(template).relative_path_from(Pathname.new(template_dir))
|
12
|
+
|
13
|
+
# register command for the template
|
14
|
+
desc "#{relative} NAME", "Create a new #{relative}"
|
15
|
+
option :overwrite, type: :boolean, default: false,
|
16
|
+
desc: 'Overwrites existing directory'
|
17
|
+
define_method relative.to_s.to_sym do |name|
|
18
|
+
generator(relative.to_s, { name: name }, options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# 1. iterate over all files
|
25
|
+
# 2. read content in erb
|
26
|
+
# 3. write to target
|
27
|
+
def generator(type, attributes = {}, options = {}) # rubocop:disable Metrics/AbcSize
|
28
|
+
# path of this script
|
29
|
+
dir = File.dirname(__FILE__)
|
30
|
+
# look for template directory
|
31
|
+
base_dir = File.join(dir, 'templates', type)
|
32
|
+
# prepare glob for all subdirectories and files
|
33
|
+
template = File.join(base_dir, '**', '{*,.*}')
|
34
|
+
# generate target path
|
35
|
+
target = Pathname.new(Dir.pwd).join(attributes[:name])
|
36
|
+
puts "Create new #{type} at #{mark_text(target)}"
|
37
|
+
|
38
|
+
# check that the directory does not exist
|
39
|
+
if File.exist?(target) && !options['overwrite']
|
40
|
+
error "#{mark_text(target)} exists already, use --overwrite"
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
# ensure that target directory is available
|
45
|
+
FileUtils.mkdir_p(target)
|
46
|
+
|
47
|
+
# iterate over files and write to target path
|
48
|
+
Dir.glob(template) do |file|
|
49
|
+
relative = Pathname.new(file).relative_path_from(Pathname.new(base_dir))
|
50
|
+
destination = Pathname.new(target).join(relative)
|
51
|
+
if File.directory?(file)
|
52
|
+
li "Create directory #{mark_text(relative)}"
|
53
|
+
FileUtils.mkdir_p(destination)
|
54
|
+
elsif File.file?(file)
|
55
|
+
li "Create file #{mark_text(relative)}"
|
56
|
+
# read & render content
|
57
|
+
content = render(File.read(file), attributes)
|
58
|
+
# write file content
|
59
|
+
File.write(destination, content)
|
60
|
+
else
|
61
|
+
puts "Ignore #{file}, because its not an file or directoy"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# This is a render helper to bind hash values to a ERB template
|
67
|
+
def render(content, hash)
|
68
|
+
# create a new binding class
|
69
|
+
cls = Class.new do
|
70
|
+
hash.each do |key, value|
|
71
|
+
define_method key.to_sym do
|
72
|
+
value
|
73
|
+
end
|
74
|
+
end
|
75
|
+
# expose binding
|
76
|
+
define_method :bind do
|
77
|
+
binding
|
78
|
+
end
|
79
|
+
end
|
80
|
+
ERB.new(content).result(cls.new.bind)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# register the subcommand to Inspec CLI registry
|
85
|
+
Inspec::Plugins::CLI.add_subcommand(Init::CLI, 'init', 'init TEMPLATE ...', 'Scaffolds a new project', {})
|
86
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# copyright: 2015, The Authors
|
3
|
+
# license: All rights reserved
|
4
|
+
|
5
|
+
title 'sample section'
|
6
|
+
|
7
|
+
# you can also use plain tests
|
8
|
+
describe file('/tmp') do
|
9
|
+
it { should be_directory }
|
10
|
+
end
|
11
|
+
|
12
|
+
# you add controls here
|
13
|
+
control 'tmp-1.0' do # A unique ID for this control
|
14
|
+
impact 0.7 # The criticality, if this control fails.
|
15
|
+
title 'Create /tmp directory' # A human-readable title
|
16
|
+
desc 'An optional description...'
|
17
|
+
describe file('/tmp') do # The actual test
|
18
|
+
it { should be_directory }
|
19
|
+
end
|
20
|
+
end
|
File without changes
|
@@ -4,40 +4,30 @@
|
|
4
4
|
|
5
5
|
require 'rubygems/package'
|
6
6
|
require 'zlib'
|
7
|
+
require 'inspec/targets/dir'
|
7
8
|
|
8
9
|
module Inspec::Targets
|
9
|
-
class ArchiveHelper
|
10
|
-
|
11
|
-
|
10
|
+
class ArchiveHelper < DirsResolver
|
11
|
+
attr_reader :files
|
12
|
+
|
13
|
+
def initialize(target, _opts = {})
|
14
|
+
@target = target
|
15
|
+
files, @rootdir = structure(target)
|
12
16
|
|
13
17
|
# remove trailing slashes
|
14
18
|
files = files.collect { |f| f.chomp('/') }
|
15
19
|
|
16
20
|
# remove leading directory
|
17
|
-
|
18
|
-
|
21
|
+
root = Pathname(@rootdir)
|
22
|
+
@files = files.collect { |f|
|
23
|
+
Pathname(f).relative_path_from(root).to_s
|
19
24
|
}
|
20
|
-
|
21
|
-
helper = DirsHelper.get_handler(files)
|
22
|
-
if helper.nil?
|
23
|
-
fail "Don't know how to handle folder #{target}"
|
24
|
-
end
|
25
|
-
|
26
|
-
res = {
|
27
|
-
test: collect(helper, files, :get_filenames),
|
28
|
-
library: collect(helper, files, :get_libraries),
|
29
|
-
metadata: collect(helper, files, :get_metadata),
|
30
|
-
}.map { |as, list|
|
31
|
-
content(target, list, rootdir, base_folder: target, as: as)
|
32
|
-
}
|
33
|
-
|
34
|
-
res.flatten
|
35
25
|
end
|
36
26
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
27
|
+
def resolve(path, opts = {})
|
28
|
+
o = (opts || {})
|
29
|
+
o[:base_folder] = @target
|
30
|
+
content(@target, path, @rootdir, o)
|
41
31
|
end
|
42
32
|
end
|
43
33
|
end
|
data/lib/inspec/targets/core.rb
CHANGED
@@ -8,18 +8,47 @@ module Inspec
|
|
8
8
|
module Targets
|
9
9
|
extend Modulator
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
# Retrieve the resolver for a given target. Resolvers are any type of
|
12
|
+
# instance, that can take a target in the #resolve method, and turn
|
13
|
+
# it into raw InSpec code. It will actually retrieve all file's
|
14
|
+
# contents, including libraries and metadata.
|
15
|
+
#
|
16
|
+
# @param [any] target any target you are pointing to; typically a string
|
17
|
+
# @return [Inspec::Targets::*] the resolver handling this target
|
18
|
+
def self.find_resolver(target)
|
19
|
+
modules.values.find { |m| m.handles?(target) }
|
20
|
+
end
|
21
|
+
|
22
|
+
# Retrieve the target handler, i.e. the component that is going to handle
|
23
|
+
# all aspects of a given target. Unlike the resolver, this provides
|
24
|
+
# access to an object, that understands the target and is able to read
|
25
|
+
# all contents, while providing additional methods which InSpec itself
|
26
|
+
# does not care about (think: plugins).
|
27
|
+
#
|
28
|
+
# There is a special case, where you might be pointing to a URL containing
|
29
|
+
# a ZIP file which has a full InSpec Profile embedded. This will be
|
30
|
+
# resolved to a directory helper (Inspec::Targets::DirsResolver). This
|
31
|
+
# method will retrieve the right handler for this directory and provide it
|
32
|
+
# with full access all contents (i.e. the DirsResolver will be embedded).
|
33
|
+
#
|
34
|
+
# @param [any] target any target you are pointing to; typically a string
|
35
|
+
# @return [Inspec::Targets::*] the handler for this target
|
36
|
+
def self.find_handler(target)
|
37
|
+
resolver = find_resolver(target)
|
38
|
+
return resolver unless resolver.is_a?(Module) &&
|
39
|
+
resolver.ancestors.include?(DirsResolver)
|
40
|
+
resolver.from_target(target).handler
|
15
41
|
end
|
16
42
|
|
43
|
+
# Turn targets into actionable InSpec code, library-data and metadata.
|
44
|
+
#
|
45
|
+
# @param [any] targets any targets you are pointing to; typically strings
|
46
|
+
# @param [Hash] additional options for loading
|
47
|
+
# @return [Array] an array of resolved data, with :content, :ref, :type
|
17
48
|
def self.resolve(targets, opts = {})
|
18
49
|
Array(targets).map do |target|
|
19
|
-
handler =
|
20
|
-
|
21
|
-
fail "Don't know how to handle target: #{target}"
|
22
|
-
end
|
50
|
+
handler = find_resolver(target) ||
|
51
|
+
fail("Don't know how to handle target: #{target}")
|
23
52
|
handler.resolve(target, opts)
|
24
53
|
end.flatten
|
25
54
|
end
|
data/lib/inspec/targets/dir.rb
CHANGED
@@ -3,79 +3,142 @@
|
|
3
3
|
# author: Christoph Hartmann
|
4
4
|
|
5
5
|
module Inspec::Targets
|
6
|
+
# DirsHelper manages resolvers for directories. Wherever directories are,
|
7
|
+
# either a local folder, archive, or remote, this module provides all helpers
|
8
|
+
# than can resolve these.
|
9
|
+
#
|
10
|
+
# Resolvers provide these methods
|
11
|
+
# * handles?(paths) => true if the resolver is responsible for this target
|
12
|
+
# * get_filenames => Array[String] of files where tests/controls are found
|
13
|
+
# * get_metadata => String path with metadata information [optional]
|
14
|
+
# * get_libraries => Array[String] of library files [optional]
|
15
|
+
#
|
16
|
+
# Resolvers must register with this DirsHelper via #add_module .
|
6
17
|
module DirsHelper
|
7
|
-
|
8
|
-
# Previous versions used the `test` directory instead of the new `controls`
|
9
|
-
# directory. Usage of the test directory is deprecated and not recommended
|
10
|
-
# anymore. Support for `test` will be removed in InSpec 1.0
|
11
|
-
# TODO: remove `test` support for InSpec 1.0
|
12
|
-
class ProfileDir
|
13
|
-
def handles?(paths)
|
14
|
-
return true if paths.include?('inspec.yml')
|
15
|
-
(
|
16
|
-
!paths.grep(/^controls/).empty? ||
|
17
|
-
!paths.grep(/^test/).empty?
|
18
|
-
) && paths.include?('metadata.rb')
|
19
|
-
end
|
18
|
+
extend Modulator
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
20
|
+
def self.get_handler(paths)
|
21
|
+
modules.values.reverse.find { |x| x.handles?(paths) }
|
22
|
+
end
|
23
|
+
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
# Base class for all directory resolvers. I.e. any target helper that
|
26
|
+
# takes a directory/archive/... and ultimately calls DirsHelper to resolve it.
|
27
|
+
#
|
28
|
+
# These resolvers must implement the required methods of this class.
|
29
|
+
class DirsResolver
|
30
|
+
def files
|
31
|
+
fail NotImplementedError, "Directory resolver #{self.class} must implement #files"
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
return 'metadata.rb' if paths.include?('metadata.rb')
|
36
|
-
end
|
34
|
+
def resolve(_path)
|
35
|
+
fail NotImplementedError, "Directory resolver #{self.class} must implement #content"
|
37
36
|
end
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
def handler
|
39
|
+
DirsHelper.get_handler(files) ||
|
40
|
+
fail("Don't know how to handle #{self}")
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.from_target(target)
|
44
|
+
new(target)
|
45
|
+
end
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
def self.resolve(target, opts)
|
48
|
+
r = new(target, opts)
|
49
|
+
handler = r.handler
|
50
|
+
files = r.files
|
51
|
+
|
52
|
+
res = []
|
53
|
+
{
|
54
|
+
test: __collect(handler, :get_filenames, files),
|
55
|
+
library: __collect(handler, :get_libraries, files),
|
56
|
+
metadata: __collect(handler, :get_metadata, files),
|
57
|
+
}.each do |as, list|
|
58
|
+
Array(list).each { |path|
|
59
|
+
res.push(r.resolve(path, as: as))
|
60
|
+
}
|
48
61
|
end
|
62
|
+
|
63
|
+
return handler.resolve_contents(res) if handler.respond_to?(:resolve_contents)
|
64
|
+
res
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.__collect(handler, getter, files)
|
68
|
+
return [] unless handler.respond_to? getter
|
69
|
+
handler.method(getter).call(files)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# InSpec profile Loader
|
74
|
+
# Previous versions used the `test` directory instead of the new `controls`
|
75
|
+
# directory. Usage of the test directory is deprecated and not recommended
|
76
|
+
# anymore. Support for `test` will be removed in InSpec 1.0
|
77
|
+
# TODO: remove `test` support for InSpec 1.0
|
78
|
+
class ProfileDir
|
79
|
+
def handles?(paths)
|
80
|
+
return true if paths.include?('inspec.yml')
|
81
|
+
(
|
82
|
+
!paths.grep(/^controls/).empty? ||
|
83
|
+
!paths.grep(/^test/).empty?
|
84
|
+
) && paths.include?('metadata.rb')
|
49
85
|
end
|
50
86
|
|
51
|
-
|
52
|
-
|
53
|
-
|
87
|
+
def get_libraries(paths)
|
88
|
+
paths.find_all do |path|
|
89
|
+
path.start_with?('libraries') && path.end_with?('.rb')
|
54
90
|
end
|
91
|
+
end
|
55
92
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
93
|
+
def get_filenames(paths)
|
94
|
+
paths.find_all do |path|
|
95
|
+
path.start_with?('controls', 'test') && path.end_with?('.rb')
|
60
96
|
end
|
61
97
|
end
|
62
98
|
|
63
|
-
|
64
|
-
|
65
|
-
|
99
|
+
def get_metadata(paths)
|
100
|
+
return 'inspec.yml' if paths.include?('inspec.yml')
|
101
|
+
return 'metadata.rb' if paths.include?('metadata.rb')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
DirsHelper.add_module('inspec-profile', ProfileDir.new)
|
105
|
+
|
106
|
+
class ChefAuditDir
|
107
|
+
def handles?(paths)
|
108
|
+
paths.include?('recipes') and paths.include?('metadata.rb')
|
109
|
+
end
|
110
|
+
|
111
|
+
def get_filenames(paths)
|
112
|
+
paths.find_all do |x|
|
113
|
+
x.start_with? 'recipes/' and x.end_with? '.rb'
|
66
114
|
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
DirsHelper.add_module('chef-cookbook', ChefAuditDir.new)
|
118
|
+
|
119
|
+
class ServerspecDir
|
120
|
+
def handles?(paths)
|
121
|
+
paths.include?('spec')
|
122
|
+
end
|
67
123
|
|
68
|
-
|
69
|
-
|
124
|
+
def get_filenames(paths)
|
125
|
+
paths.find_all do |path|
|
126
|
+
path.start_with? 'spec' and path.end_with? '_spec.rb'
|
70
127
|
end
|
71
128
|
end
|
129
|
+
end
|
130
|
+
DirsHelper.add_module('serverspec-folder', ServerspecDir.new)
|
72
131
|
|
73
|
-
|
74
|
-
|
75
|
-
|
132
|
+
class FlatDir
|
133
|
+
def handles?(paths)
|
134
|
+
get_filenames(paths).empty? == false
|
135
|
+
end
|
76
136
|
|
77
|
-
def
|
78
|
-
|
137
|
+
def get_filenames(paths)
|
138
|
+
# TODO: eventually remove the metadata.rb exception here
|
139
|
+
# when we have fully phased out metadata.rb in 1.0
|
140
|
+
paths.find_all { |x| x.end_with?('.rb') && !x.include?('/') && x != 'metadata.rb' }
|
79
141
|
end
|
80
142
|
end
|
143
|
+
DirsHelper.add_module('flat-ruby-folder', FlatDir.new)
|
81
144
|
end
|
@@ -6,48 +6,33 @@ require 'inspec/targets/dir'
|
|
6
6
|
require 'inspec/targets/file'
|
7
7
|
|
8
8
|
module Inspec::Targets
|
9
|
-
class FolderHelper
|
10
|
-
def handles?(target)
|
9
|
+
class FolderHelper < DirsResolver
|
10
|
+
def self.handles?(target)
|
11
11
|
File.directory?(target)
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
attr_reader :files
|
15
|
+
|
16
|
+
def initialize(target, _opts = {})
|
17
|
+
@base_folder = target
|
15
18
|
# find all files in the folder
|
16
19
|
files = Dir[File.join(target, '**', '*')]
|
17
20
|
# remove the prefix
|
18
21
|
prefix = File.join(target, '')
|
19
|
-
files = files.map { |x| x.sub(prefix, '') }
|
20
|
-
|
21
|
-
|
22
|
-
if helper.nil?
|
23
|
-
fail "Don't know how to handle folder #{target}"
|
24
|
-
end
|
25
|
-
|
26
|
-
# get all test file contents
|
27
|
-
file_handler = Inspec::Targets.modules['file']
|
28
|
-
res = {
|
29
|
-
test: collect(helper, files, :get_filenames),
|
30
|
-
library: collect(helper, files, :get_libraries),
|
31
|
-
metadata: collect(helper, files, :get_metadata),
|
32
|
-
}.map { |as, list|
|
33
|
-
file_handler.resolve_all(list, base_folder: target, as: as)
|
34
|
-
}
|
22
|
+
@files = files.map { |x| x.sub(prefix, '') }
|
23
|
+
@file_handler = Inspec::Targets.modules['file']
|
24
|
+
end
|
35
25
|
|
36
|
-
|
37
|
-
|
26
|
+
def resolve(path, opts = {})
|
27
|
+
o = (opts || {})
|
28
|
+
o[:base_folder] = @base_folder
|
29
|
+
@file_handler.resolve(path, o)
|
38
30
|
end
|
39
31
|
|
40
32
|
def to_s
|
41
33
|
'Folder Loader'
|
42
34
|
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
def collect(helper, files, getter)
|
47
|
-
return [] unless helper.respond_to? getter
|
48
|
-
helper.method(getter).call(files)
|
49
|
-
end
|
50
35
|
end
|
51
36
|
|
52
|
-
Inspec::Targets.add_module('folder', FolderHelper
|
37
|
+
Inspec::Targets.add_module('folder', FolderHelper)
|
53
38
|
end
|
data/lib/inspec/targets/tar.rb
CHANGED
@@ -8,7 +8,7 @@ require 'inspec/targets/archive'
|
|
8
8
|
|
9
9
|
module Inspec::Targets
|
10
10
|
class TarHelper < ArchiveHelper
|
11
|
-
def handles?(target)
|
11
|
+
def self.handles?(target)
|
12
12
|
File.file?(target) && target.end_with?('.tar.gz', '.tgz')
|
13
13
|
end
|
14
14
|
|
@@ -30,22 +30,20 @@ module Inspec::Targets
|
|
30
30
|
[files, rootdir]
|
31
31
|
end
|
32
32
|
|
33
|
-
def content(input,
|
34
|
-
content =
|
33
|
+
def content(input, path, rootdir = nil, opts = {})
|
34
|
+
content = nil
|
35
35
|
Gem::Package::TarReader.new(Zlib::GzipReader.open(input)) do |tar|
|
36
36
|
tar.each do |entry|
|
37
37
|
if entry.directory?
|
38
38
|
# nothing to do
|
39
39
|
elsif entry.file?
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
content.push(h)
|
48
|
-
end
|
40
|
+
next unless path == entry.full_name.gsub(rootdir, '')
|
41
|
+
content = {
|
42
|
+
# NB if some file is empty, return empty-string, not nil
|
43
|
+
content: entry.read || '',
|
44
|
+
type: opts[:as] || :test,
|
45
|
+
ref: entry.full_name,
|
46
|
+
}
|
49
47
|
elsif entry.header.typeflag == '2'
|
50
48
|
# ignore symlinks for now
|
51
49
|
end
|
@@ -59,5 +57,5 @@ module Inspec::Targets
|
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
62
|
-
Inspec::Targets.add_module('tar', TarHelper
|
60
|
+
Inspec::Targets.add_module('tar', TarHelper)
|
63
61
|
end
|
data/lib/inspec/targets/zip.rb
CHANGED
@@ -8,22 +8,22 @@ require 'inspec/targets/archive'
|
|
8
8
|
|
9
9
|
module Inspec::Targets
|
10
10
|
class ZipHelper < ArchiveHelper
|
11
|
-
def handles?(target)
|
11
|
+
def self.handles?(target)
|
12
12
|
File.file?(target) and target.end_with?('.zip')
|
13
13
|
end
|
14
14
|
|
15
|
-
def content(input,
|
16
|
-
content =
|
15
|
+
def content(input, path, rootdir = nil, opts = {})
|
16
|
+
content = nil
|
17
17
|
::Zip::InputStream.open(input) do |io|
|
18
18
|
while (entry = io.get_next_entry)
|
19
|
-
next
|
20
|
-
|
19
|
+
next unless path == entry.name.gsub(rootdir, '')
|
20
|
+
content = {
|
21
21
|
# NB if some file is empty, return empty-string, not nil
|
22
22
|
content: io.read || '',
|
23
23
|
type: opts[:as] || :test,
|
24
24
|
ref: entry.name,
|
25
25
|
}
|
26
|
-
|
26
|
+
abort
|
27
27
|
end
|
28
28
|
end
|
29
29
|
content
|
@@ -51,5 +51,5 @@ module Inspec::Targets
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
Inspec::Targets.add_module('zip', ZipHelper
|
54
|
+
Inspec::Targets.add_module('zip', ZipHelper)
|
55
55
|
end
|
data/lib/inspec/version.rb
CHANGED
data/lib/resources/iptables.rb
CHANGED
@@ -31,8 +31,8 @@ class IpTables < Inspec.resource(1)
|
|
31
31
|
"
|
32
32
|
|
33
33
|
def initialize(params = {})
|
34
|
-
@table = params[:table]
|
35
|
-
@chain = params[:chain]
|
34
|
+
@table = params[:table]
|
35
|
+
@chain = params[:chain]
|
36
36
|
|
37
37
|
# we're done if we are on linux
|
38
38
|
return if inspec.os.linux?
|
@@ -43,29 +43,26 @@ class IpTables < Inspec.resource(1)
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def has_rule?(rule = nil, _table = nil, _chain = nil)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# for now, we expect an excact match
|
50
|
-
found = true if line.casecmp(rule) == 0
|
51
|
-
}
|
52
|
-
found
|
46
|
+
# checks if the rule is part of the ruleset
|
47
|
+
# for now, we expect an exact match
|
48
|
+
retrieve_rules.any? { |line| line.casecmp(rule) == 0 }
|
53
49
|
end
|
54
50
|
|
55
51
|
def retrieve_rules
|
56
52
|
return @iptables_cache if defined?(@iptables_cache)
|
57
53
|
|
58
54
|
# construct iptables command to read all rules
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
table_cmd = "-t #{@table}" if @table
|
56
|
+
iptables_cmd = format('iptables %s -S %s', table_cmd, @chain).strip
|
57
|
+
|
58
|
+
cmd = inspec.command(iptables_cmd)
|
62
59
|
return [] if cmd.exit_status.to_i != 0
|
63
60
|
|
64
61
|
# split rules, returns array or rules
|
65
|
-
@iptables_cache = cmd.stdout.
|
62
|
+
@iptables_cache = cmd.stdout.split("\n").map(&:strip)
|
66
63
|
end
|
67
64
|
|
68
65
|
def to_s
|
69
|
-
format('Iptables %s %s', @table
|
66
|
+
format('Iptables %s %s', @table && "table: #{@table}", @chain && "chain: #{@chain}").strip
|
70
67
|
end
|
71
68
|
end
|
data/lib/resources/service.rb
CHANGED
@@ -4,13 +4,59 @@
|
|
4
4
|
# author: Stephan Renatus
|
5
5
|
# license: All rights reserved
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
class Runlevels < Hash
|
8
|
+
attr_accessor :owner
|
9
|
+
|
10
|
+
def self.from_hash(owner, hash = {}, filter = nil)
|
11
|
+
res = Runlevels.new(owner)
|
12
|
+
filter = filter.first if filter.is_a?(Array) && filter.length <= 1
|
13
|
+
|
14
|
+
ks = case filter
|
15
|
+
when nil
|
16
|
+
hash.keys
|
17
|
+
when Regexp
|
18
|
+
hash.keys.find_all { |x| x.to_s =~ filter }
|
19
|
+
when Array
|
20
|
+
f = filter.map(&:to_s)
|
21
|
+
hash.keys.find_all { |x| f.include?(x.to_s) }
|
22
|
+
when Numeric
|
23
|
+
hash.keys.include?(filter) ? [filter] : []
|
24
|
+
else
|
25
|
+
hash.keys.find_all { |x| x == filter }
|
26
|
+
end
|
27
|
+
|
28
|
+
ks.each { |k| res[k] = hash[k] }
|
29
|
+
res
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(owner, default = false)
|
33
|
+
@owner = owner
|
34
|
+
super(default)
|
35
|
+
end
|
36
|
+
|
37
|
+
def filter(f)
|
38
|
+
Runlevels.from_hash(owner, self, f)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Check if all runlevels are enabled
|
42
|
+
#
|
43
|
+
# @return [boolean] true if all runlevels are enabled
|
44
|
+
def enabled?
|
45
|
+
values.all?
|
46
|
+
end
|
47
|
+
|
48
|
+
# Check if all runlevels are disabled
|
49
|
+
#
|
50
|
+
# @return [boolean] true if all runlevels are disabled
|
51
|
+
def disabled?
|
52
|
+
!values.any?
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
"#{owner} runlevels #{keys.join(', ')}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
14
60
|
# We detect the init system for each operating system, based on the operating
|
15
61
|
# system.
|
16
62
|
#
|
@@ -29,6 +75,10 @@ class Service < Inspec.resource(1)
|
|
29
75
|
it { should be_enabled }
|
30
76
|
it { should be_running }
|
31
77
|
end
|
78
|
+
|
79
|
+
describe service('service_name').runlevels(3, 5) do
|
80
|
+
it { should be_enabled }
|
81
|
+
end
|
32
82
|
"
|
33
83
|
|
34
84
|
attr_reader :service_ctl
|
@@ -98,7 +148,7 @@ class Service < Inspec.resource(1)
|
|
98
148
|
@cache ||= @service_mgmt.info(@service_name)
|
99
149
|
end
|
100
150
|
|
101
|
-
# verifies the service is enabled
|
151
|
+
# verifies if the service is enabled
|
102
152
|
def enabled?(_level = nil)
|
103
153
|
return false if info.nil?
|
104
154
|
info[:enabled]
|
@@ -116,6 +166,12 @@ class Service < Inspec.resource(1)
|
|
116
166
|
info[:running]
|
117
167
|
end
|
118
168
|
|
169
|
+
# get all runlevels that are available and their configuration
|
170
|
+
def runlevels(*args)
|
171
|
+
return Runlevels.new(self) if info.nil? or info[:runlevels].nil?
|
172
|
+
Runlevels.from_hash(self, info[:runlevels], args)
|
173
|
+
end
|
174
|
+
|
119
175
|
def to_s
|
120
176
|
"Service #{@service_name}"
|
121
177
|
end
|
@@ -275,6 +331,8 @@ class Upstart < ServiceManager
|
|
275
331
|
end
|
276
332
|
|
277
333
|
class SysV < ServiceManager
|
334
|
+
RUNLEVELS = { 0=>false, 1=>false, 2=>false, 3=>false, 4=>false, 5=>false, 6=>false }.freeze
|
335
|
+
|
278
336
|
def initialize(service_name, service_ctl = nil)
|
279
337
|
@service_ctl ||= 'service'
|
280
338
|
super
|
@@ -296,10 +354,15 @@ class SysV < ServiceManager
|
|
296
354
|
# on rhel via: 'chkconfig --list', is not installed by default
|
297
355
|
# bash: for i in `find /etc/rc*.d -name S*`; do basename $i | sed -r 's/^S[0-9]+//'; done | sort | uniq
|
298
356
|
enabled_services_cmd = inspec.command('find /etc/rc*.d -name S*')
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
357
|
+
service_line = %r{rc(?<runlevel>[0-6])\.d/S[^/]*?#{Regexp.escape service_name}$}
|
358
|
+
all_services = enabled_services_cmd.stdout.split("\n").map { |line|
|
359
|
+
service_line.match(line)
|
360
|
+
}.compact
|
361
|
+
enabled = !all_services.empty?
|
362
|
+
|
363
|
+
# Determine a list of runlevels which this service is activated for
|
364
|
+
runlevels = RUNLEVELS.dup
|
365
|
+
all_services.each { |x| runlevels[x[:runlevel].to_i] = true }
|
303
366
|
|
304
367
|
# check if service is really running
|
305
368
|
# service throws an exit code if the service is not installed or
|
@@ -313,6 +376,7 @@ class SysV < ServiceManager
|
|
313
376
|
installed: true,
|
314
377
|
running: running,
|
315
378
|
enabled: enabled,
|
379
|
+
runlevels: runlevels,
|
316
380
|
type: 'sysv',
|
317
381
|
}
|
318
382
|
end
|
@@ -11,6 +11,7 @@ include_recipe('os_prepare::mount')
|
|
11
11
|
include_recipe('os_prepare::service')
|
12
12
|
include_recipe('os_prepare::package')
|
13
13
|
include_recipe('os_prepare::registry_key')
|
14
|
+
include_recipe('os_prepare::iptables')
|
14
15
|
|
15
16
|
# configure repos, eg. nginx
|
16
17
|
include_recipe('os_prepare::apt')
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Stephan Renatus
|
3
|
+
|
4
|
+
case node['platform']
|
5
|
+
when 'ubuntu', 'rhel', 'centos', 'fedora'
|
6
|
+
execute 'iptables -A INPUT -i eth0 -p tcp -m tcp '\
|
7
|
+
'--dport 80 -m state --state NEW -m comment '\
|
8
|
+
'--comment "http on 80" -j ACCEPT'
|
9
|
+
execute 'iptables -N derby-cognos-web'
|
10
|
+
execute 'iptables -A INPUT -j derby-cognos-web'
|
11
|
+
execute 'iptables -A derby-cognos-web -p tcp -m tcp --dport 80 '\
|
12
|
+
'-m comment --comment "derby-cognos-web" -j ACCEPT'
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
case os[:family]
|
4
|
+
when 'ubuntu', 'fedora'
|
5
|
+
describe iptables do
|
6
|
+
it { should have_rule('-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m comment --comment "http on 80" -j ACCEPT') }
|
7
|
+
it { should_not have_rule('-A INPUT -i eth1 -p tcp -m tcp --dport 80 -j ACCEPT') }
|
8
|
+
|
9
|
+
# single-word comments have their quotes dropped
|
10
|
+
it { should have_rule('-A derby-cognos-web -p tcp -m tcp --dport 80 -m comment --comment derby-cognos-web -j ACCEPT') }
|
11
|
+
end
|
12
|
+
when 'rhel', 'centos'
|
13
|
+
describe iptables do
|
14
|
+
it { should have_rule('-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m comment --comment "http on 80" -j ACCEPT') }
|
15
|
+
it { should_not have_rule('-A INPUT -i eth1 -p tcp -m tcp --dport 80 -j ACCEPT') }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe iptables do
|
19
|
+
it { should have_rule('-A derby-cognos-web -p tcp -m tcp --dport 80 -m comment --comment "derby-cognos-web" -j ACCEPT') }
|
20
|
+
end if os[:release] == 6
|
21
|
+
|
22
|
+
describe iptables do
|
23
|
+
it { should have_rule('-A derby-cognos-web -p tcp -m tcp --dport 80 -m comment --comment derby-cognos-web -j ACCEPT') }
|
24
|
+
end if os[:release] == 7
|
25
|
+
end
|
@@ -3,4 +3,4 @@
|
|
3
3
|
-P OUTPUT ACCEPT
|
4
4
|
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
5
5
|
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -m state --state NEW -j ACCEPT
|
6
|
-
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -j ACCEPT
|
6
|
+
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m comment --comment "http like its 1990" -j ACCEPT
|
@@ -14,6 +14,11 @@ describe 'Inspec::Resources::Iptables' do
|
|
14
14
|
_(resource.has_rule?('-P OUTPUT DROP')).must_equal false
|
15
15
|
end
|
16
16
|
|
17
|
+
it 'verify iptables with comments on ubuntu' do
|
18
|
+
resource = MockLoader.new(:ubuntu1404).load_resource('iptables')
|
19
|
+
_(resource.has_rule?('-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m comment --comment "http like its 1990" -j ACCEPT')).must_equal true
|
20
|
+
end
|
21
|
+
|
17
22
|
it 'verify iptables on windows' do
|
18
23
|
resource = MockLoader.new(:windows).load_resource('iptables')
|
19
24
|
_(resource.has_rule?('-P OUTPUT ACCEPT')).must_equal false
|
@@ -6,6 +6,7 @@ require 'helper'
|
|
6
6
|
require 'inspec/resource'
|
7
7
|
|
8
8
|
describe 'Inspec::Resources::Service' do
|
9
|
+
let(:runlevels) { {0=>false, 1=>false, 2=>true, 3=>true, 4=>true, 5=>true, 6=>false} }
|
9
10
|
|
10
11
|
# windows
|
11
12
|
it 'verify service parsing' do
|
@@ -58,7 +59,7 @@ describe 'Inspec::Resources::Service' do
|
|
58
59
|
# centos 6 with sysv
|
59
60
|
it 'verify centos 6 package parsing' do
|
60
61
|
resource = MockLoader.new(:centos6).load_resource('service', 'sshd')
|
61
|
-
srv = { name: 'sshd', description: nil, installed: true, running: true, enabled: true, type: 'sysv' }
|
62
|
+
srv = { name: 'sshd', description: nil, installed: true, running: true, enabled: true, runlevels: runlevels, type: 'sysv' }
|
62
63
|
_(resource.info).must_equal srv
|
63
64
|
_(resource.installed?).must_equal true
|
64
65
|
_(resource.enabled?).must_equal true
|
@@ -67,7 +68,7 @@ describe 'Inspec::Resources::Service' do
|
|
67
68
|
|
68
69
|
it 'verify centos 6 package parsing with default sysv_service' do
|
69
70
|
resource = MockLoader.new(:centos6).load_resource('sysv_service', 'sshd')
|
70
|
-
srv = { name: 'sshd', description: nil, installed: true, running: true, enabled: true, type: 'sysv' }
|
71
|
+
srv = { name: 'sshd', description: nil, installed: true, running: true, enabled: true, runlevels: runlevels, type: 'sysv' }
|
71
72
|
_(resource.info).must_equal srv
|
72
73
|
_(resource.installed?).must_equal true
|
73
74
|
_(resource.enabled?).must_equal true
|
@@ -125,7 +126,7 @@ describe 'Inspec::Resources::Service' do
|
|
125
126
|
# debian 7 with systemv
|
126
127
|
it 'verify debian 7 package parsing' do
|
127
128
|
resource = MockLoader.new(:debian7).load_resource('service', 'sshd')
|
128
|
-
srv = { name: 'sshd', description: nil, installed: true, running: true, enabled: true, type: 'sysv' }
|
129
|
+
srv = { name: 'sshd', description: nil, installed: true, running: true, enabled: true, runlevels: runlevels, type: 'sysv' }
|
129
130
|
_(resource.info).must_equal srv
|
130
131
|
_(resource.installed?).must_equal true
|
131
132
|
_(resource.enabled?).must_equal true
|
@@ -173,7 +174,7 @@ describe 'Inspec::Resources::Service' do
|
|
173
174
|
# wrlinux
|
174
175
|
it 'verify wrlinux package parsing' do
|
175
176
|
resource = MockLoader.new(:wrlinux).load_resource('service', 'sshd')
|
176
|
-
srv = { name: 'sshd', description: nil, installed: true, running: true, enabled: true, type: 'sysv' }
|
177
|
+
srv = { name: 'sshd', description: nil, installed: true, running: true, enabled: true, runlevels: runlevels, type: 'sysv' }
|
177
178
|
_(resource.info).must_equal srv
|
178
179
|
_(resource.installed?).must_equal true
|
179
180
|
_(resource.enabled?).must_equal true
|
@@ -187,4 +188,45 @@ describe 'Inspec::Resources::Service' do
|
|
187
188
|
_(resource.installed?).must_equal false
|
188
189
|
_(resource.info).must_equal nil
|
189
190
|
end
|
191
|
+
|
192
|
+
# runlevel detection
|
193
|
+
describe 'runlevels on centos 6 (system V)' do
|
194
|
+
let(:service) { MockLoader.new(:centos6).load_resource('service', 'sshd') }
|
195
|
+
|
196
|
+
it 'grabs all runlevels' do
|
197
|
+
service.runlevels.keys.must_equal [0, 1, 2, 3, 4, 5, 6]
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'grabs runlevels via filter nil' do
|
201
|
+
service.runlevels(nil).keys.must_equal [0, 1, 2, 3, 4, 5, 6]
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'grabs runlevels by number' do
|
205
|
+
service.runlevels(3).keys.must_equal [3]
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'grabs runlevels by multiple numbers' do
|
209
|
+
service.runlevels(3, 4, 8).keys.must_equal [3, 4]
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'grabs runlevels via regex' do
|
213
|
+
service.runlevels(/[5-9]/).keys.must_equal [5, 6]
|
214
|
+
end
|
215
|
+
|
216
|
+
it 'checks enabled true if all services are enabled' do
|
217
|
+
service.runlevels(2, 4).enabled?.must_equal true
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'checks enabled false if some services are not enabled' do
|
221
|
+
service.runlevels(1, 4).enabled?.must_equal false
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'checks disabled true if all services are disabled' do
|
225
|
+
service.runlevels(0, 1).disabled?.must_equal true
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'checks disabled false if some services are not disabled' do
|
229
|
+
service.runlevels(0, 4).enabled?.must_equal false
|
230
|
+
end
|
231
|
+
end
|
190
232
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Richter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: r-train
|
@@ -223,6 +223,12 @@ files:
|
|
223
223
|
- lib/bundles/inspec-compliance/cli.rb
|
224
224
|
- lib/bundles/inspec-compliance/configuration.rb
|
225
225
|
- lib/bundles/inspec-compliance/target.rb
|
226
|
+
- lib/bundles/inspec-init.rb
|
227
|
+
- lib/bundles/inspec-init/cli.rb
|
228
|
+
- lib/bundles/inspec-init/templates/profile/README.md
|
229
|
+
- lib/bundles/inspec-init/templates/profile/controls/example.rb
|
230
|
+
- lib/bundles/inspec-init/templates/profile/inspec.yml
|
231
|
+
- lib/bundles/inspec-init/templates/profile/libraries/.gitkeep
|
226
232
|
- lib/bundles/inspec-supermarket/README.md
|
227
233
|
- lib/bundles/inspec-supermarket/api.rb
|
228
234
|
- lib/bundles/inspec-supermarket/cli.rb
|
@@ -339,6 +345,7 @@ files:
|
|
339
345
|
- test/integration/cookbooks/os_prepare/recipes/auditctl.rb
|
340
346
|
- test/integration/cookbooks/os_prepare/recipes/default.rb
|
341
347
|
- test/integration/cookbooks/os_prepare/recipes/file.rb
|
348
|
+
- test/integration/cookbooks/os_prepare/recipes/iptables.rb
|
342
349
|
- test/integration/cookbooks/os_prepare/recipes/json_yaml_csv_ini.rb
|
343
350
|
- test/integration/cookbooks/os_prepare/recipes/mount.rb
|
344
351
|
- test/integration/cookbooks/os_prepare/recipes/package.rb
|
@@ -356,6 +363,7 @@ files:
|
|
356
363
|
- test/integration/test/integration/default/file_spec.rb
|
357
364
|
- test/integration/test/integration/default/group_spec.rb
|
358
365
|
- test/integration/test/integration/default/ini_spec.rb
|
366
|
+
- test/integration/test/integration/default/iptables_spec.rb
|
359
367
|
- test/integration/test/integration/default/json_spec.rb
|
360
368
|
- test/integration/test/integration/default/kernel_module_spec.rb
|
361
369
|
- test/integration/test/integration/default/kernel_parameter_spec.rb
|
@@ -570,6 +578,7 @@ test_files:
|
|
570
578
|
- test/integration/cookbooks/os_prepare/recipes/auditctl.rb
|
571
579
|
- test/integration/cookbooks/os_prepare/recipes/default.rb
|
572
580
|
- test/integration/cookbooks/os_prepare/recipes/file.rb
|
581
|
+
- test/integration/cookbooks/os_prepare/recipes/iptables.rb
|
573
582
|
- test/integration/cookbooks/os_prepare/recipes/json_yaml_csv_ini.rb
|
574
583
|
- test/integration/cookbooks/os_prepare/recipes/mount.rb
|
575
584
|
- test/integration/cookbooks/os_prepare/recipes/package.rb
|
@@ -587,6 +596,7 @@ test_files:
|
|
587
596
|
- test/integration/test/integration/default/file_spec.rb
|
588
597
|
- test/integration/test/integration/default/group_spec.rb
|
589
598
|
- test/integration/test/integration/default/ini_spec.rb
|
599
|
+
- test/integration/test/integration/default/iptables_spec.rb
|
590
600
|
- test/integration/test/integration/default/json_spec.rb
|
591
601
|
- test/integration/test/integration/default/kernel_module_spec.rb
|
592
602
|
- test/integration/test/integration/default/kernel_parameter_spec.rb
|