inspec 0.14.8 → 0.15.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/CHANGELOG.md +25 -2
- data/bin/inspec +3 -4
- data/examples/inheritance/README.md +19 -0
- data/examples/inheritance/controls/example.rb +11 -0
- data/examples/inheritance/inspec.yml +10 -0
- data/lib/bundles/inspec-compliance/cli.rb +1 -4
- data/lib/bundles/inspec-supermarket/cli.rb +1 -4
- data/lib/inspec/dsl.rb +48 -55
- data/lib/inspec/profile.rb +6 -2
- data/lib/inspec/profile_context.rb +21 -8
- data/lib/inspec/runner.rb +17 -12
- data/lib/inspec/runner_rspec.rb +1 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/resources/apache.rb +20 -18
- data/lib/resources/apache_conf.rb +92 -90
- data/lib/resources/apt.rb +92 -90
- data/lib/resources/audit_policy.rb +35 -33
- data/lib/resources/auditd_conf.rb +41 -39
- data/lib/resources/auditd_rules.rb +155 -153
- data/lib/resources/bond.rb +1 -1
- data/lib/resources/bridge.rb +97 -95
- data/lib/resources/command.rb +47 -45
- data/lib/resources/csv.rb +23 -21
- data/lib/resources/directory.rb +1 -1
- data/lib/resources/etc_group.rb +116 -114
- data/lib/resources/file.rb +1 -1
- data/lib/resources/gem.rb +39 -37
- data/lib/resources/group.rb +100 -98
- data/lib/resources/host.rb +103 -101
- data/lib/resources/inetd_conf.rb +42 -40
- data/lib/resources/ini.rb +15 -13
- data/lib/resources/interface.rb +106 -104
- data/lib/resources/iptables.rb +36 -34
- data/lib/resources/json.rb +64 -62
- data/lib/resources/kernel_module.rb +30 -28
- data/lib/resources/kernel_parameter.rb +44 -42
- data/lib/resources/limits_conf.rb +41 -39
- data/lib/resources/login_def.rb +38 -36
- data/lib/resources/mount.rb +43 -41
- data/lib/resources/mysql.rb +67 -65
- data/lib/resources/mysql_conf.rb +89 -87
- data/lib/resources/mysql_session.rb +46 -44
- data/lib/resources/npm.rb +35 -33
- data/lib/resources/ntp_conf.rb +44 -42
- data/lib/resources/oneget.rb +46 -44
- data/lib/resources/os.rb +22 -20
- data/lib/resources/os_env.rb +47 -45
- data/lib/resources/package.rb +213 -211
- data/lib/resources/parse_config.rb +59 -57
- data/lib/resources/passwd.rb +89 -87
- data/lib/resources/pip.rb +60 -58
- data/lib/resources/port.rb +352 -350
- data/lib/resources/postgres.rb +26 -24
- data/lib/resources/postgres_conf.rb +66 -64
- data/lib/resources/postgres_session.rb +47 -45
- data/lib/resources/processes.rb +56 -54
- data/lib/resources/registry_key.rb +150 -148
- data/lib/resources/script.rb +30 -28
- data/lib/resources/security_policy.rb +56 -54
- data/lib/resources/service.rb +638 -636
- data/lib/resources/shadow.rb +98 -96
- data/lib/resources/ssh_conf.rb +58 -56
- data/lib/resources/user.rb +363 -361
- data/lib/resources/windows_feature.rb +46 -44
- data/lib/resources/xinetd.rb +111 -109
- data/lib/resources/yaml.rb +16 -14
- data/lib/resources/yum.rb +107 -105
- data/lib/utils/base_cli.rb +18 -0
- data/test/helper.rb +2 -2
- data/test/unit/profile_context_test.rb +1 -1
- data/test/unit/resources/file_test.rb +1 -1
- data/test/unit/resources/mount_test.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ca71e169ffd037a7a61f99fc09188424a137168
|
4
|
+
data.tar.gz: 1aa83936f8b464a2044a7fae20cb14ddce1bdb87
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 774c8531d3bfdcab1c0a0587f670c09ab39099e89ff07a79e68c37bb3798e1a1a75e0b613c80a7bc7f8fb492c797ec26b04a12298a0493ddfd0d7784059cfb99
|
7
|
+
data.tar.gz: 4335e3fa250d9b6e3b54e25c82289fb3f232452ced7ad0d1a781349b2ae415d8b9533824c4ffda2f53340a96da0cea3720dd630637b59a6286511021672c3945
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,29 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [0.
|
4
|
-
[Full Changelog](https://github.com/chef/inspec/compare/v0.14.
|
3
|
+
## [0.15.0](https://github.com/chef/inspec/tree/0.15.0) (2016-03-09)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.14.8...0.15.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- add color output + make it the default [\#523](https://github.com/chef/inspec/pull/523) ([arlimus](https://github.com/arlimus))
|
9
|
+
- select controls to execute [\#522](https://github.com/chef/inspec/pull/522) ([arlimus](https://github.com/arlimus))
|
10
|
+
|
11
|
+
**Fixed bugs:**
|
12
|
+
|
13
|
+
- Rename internal File and OS resource classes [\#527](https://github.com/chef/inspec/pull/527) ([arlimus](https://github.com/arlimus))
|
14
|
+
- Placing all resources in the Inspec::Resources namespace [\#526](https://github.com/chef/inspec/pull/526) ([adamleff](https://github.com/adamleff))
|
15
|
+
- bugfix: inheritance of local profiles [\#524](https://github.com/chef/inspec/pull/524) ([arlimus](https://github.com/arlimus))
|
16
|
+
|
17
|
+
**Closed issues:**
|
18
|
+
|
19
|
+
- Colo\[u\]r those dots and Fs! [\#518](https://github.com/chef/inspec/issues/518)
|
20
|
+
|
21
|
+
**Merged pull requests:**
|
22
|
+
|
23
|
+
- 0.14.9 [\#525](https://github.com/chef/inspec/pull/525) ([arlimus](https://github.com/arlimus))
|
24
|
+
|
25
|
+
## [v0.14.8](https://github.com/chef/inspec/tree/v0.14.8) (2016-03-04)
|
26
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.14.7...v0.14.8)
|
5
27
|
|
6
28
|
**Closed issues:**
|
7
29
|
|
@@ -9,6 +31,7 @@
|
|
9
31
|
|
10
32
|
**Merged pull requests:**
|
11
33
|
|
34
|
+
- 0.14.8 [\#520](https://github.com/chef/inspec/pull/520) ([arlimus](https://github.com/arlimus))
|
12
35
|
- expose control impacts in json [\#519](https://github.com/chef/inspec/pull/519) ([arlimus](https://github.com/arlimus))
|
13
36
|
|
14
37
|
## [v0.14.7](https://github.com/chef/inspec/tree/v0.14.7) (2016-03-01)
|
data/bin/inspec
CHANGED
@@ -20,6 +20,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
20
20
|
desc: 'Attach a profile ID to all test results'
|
21
21
|
option :output, aliases: :o, type: :string,
|
22
22
|
desc: 'Save the created profile to a path'
|
23
|
+
profile_options
|
23
24
|
def json(target)
|
24
25
|
diagnose
|
25
26
|
o = opts.dup
|
@@ -42,6 +43,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
42
43
|
|
43
44
|
desc 'check PATH', 'verify all tests at the specified PATH'
|
44
45
|
option :format, type: :string
|
46
|
+
profile_options
|
45
47
|
def check(path) # rubocop:disable Metrics/AbcSize
|
46
48
|
diagnose
|
47
49
|
o = opts.dup
|
@@ -101,10 +103,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
101
103
|
end
|
102
104
|
|
103
105
|
desc 'exec PATHS', 'run all test files at the specified PATH.'
|
104
|
-
|
105
|
-
desc: 'Attach a profile ID to all test results'
|
106
|
-
target_options
|
107
|
-
option :format, type: :string
|
106
|
+
exec_options
|
108
107
|
def exec(*targets)
|
109
108
|
diagnose
|
110
109
|
run_tests(targets, opts)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Example InSpec Profile
|
2
|
+
|
3
|
+
This example shows the use of InSpec [profile](../../docs/profiles.rst) inheritance.
|
4
|
+
|
5
|
+
## Verify a profile
|
6
|
+
|
7
|
+
InSpec ships with built-in features to verify a profile structure.
|
8
|
+
|
9
|
+
```bash
|
10
|
+
$ inspec check examples/inheritance --profiles-path examples
|
11
|
+
```
|
12
|
+
|
13
|
+
## Execute a profile
|
14
|
+
|
15
|
+
To run a profile on a local machine use `inspec exec /path/to/profile`.
|
16
|
+
|
17
|
+
```bash
|
18
|
+
$ inspec exec examples/inheritance --profiles-path examples
|
19
|
+
```
|
@@ -0,0 +1,10 @@
|
|
1
|
+
name: inheritance
|
2
|
+
title: InSpec example inheritance
|
3
|
+
maintainer: Chef Software, Inc.
|
4
|
+
copyright: Chef Software, Inc.
|
5
|
+
copyright_email: support@chef.io
|
6
|
+
license: Apache 2 license
|
7
|
+
summary: Demonstrates the use of InSpec profile inheritance
|
8
|
+
version: 1.0.0
|
9
|
+
supports:
|
10
|
+
- os-family: linux
|
@@ -39,10 +39,7 @@ module Compliance
|
|
39
39
|
end
|
40
40
|
|
41
41
|
desc 'exec PROFILE', 'executes a Chef Compliance profile'
|
42
|
-
|
43
|
-
desc: 'Attach a profile ID to all test results'
|
44
|
-
target_options
|
45
|
-
option :format, type: :string
|
42
|
+
exec_options
|
46
43
|
def exec(*tests)
|
47
44
|
# iterate over tests and add compliance scheme
|
48
45
|
tests = tests.map { |t| 'compliance://' + t }
|
@@ -18,10 +18,7 @@ module Supermarket
|
|
18
18
|
end
|
19
19
|
|
20
20
|
desc 'exec PROFILE', 'execute a Supermarket profile'
|
21
|
-
|
22
|
-
desc: 'Attach a profile ID to all test results'
|
23
|
-
target_options
|
24
|
-
option :format, type: :string
|
21
|
+
exec_options
|
25
22
|
def exec(*tests)
|
26
23
|
# iterate over tests and add compliance scheme
|
27
24
|
tests = tests.map { |t| 'supermarket://' + t }
|
data/lib/inspec/dsl.rb
CHANGED
@@ -6,11 +6,13 @@
|
|
6
6
|
|
7
7
|
module Inspec::DSL
|
8
8
|
def require_controls(id, &block)
|
9
|
-
|
9
|
+
opts = { profile_id: id, include_all: false, backend: @backend, conf: @conf }
|
10
|
+
::Inspec::DSL.load_spec_files_for_profile(self, opts, &block)
|
10
11
|
end
|
11
12
|
|
12
13
|
def include_controls(id, &block)
|
13
|
-
|
14
|
+
opts = { profile_id: id, include_all: true, backend: @backend, conf: @conf }
|
15
|
+
::Inspec::DSL.load_spec_files_for_profile(self, opts, &block)
|
14
16
|
end
|
15
17
|
|
16
18
|
alias require_rules require_controls
|
@@ -60,72 +62,63 @@ module Inspec::DSL
|
|
60
62
|
}
|
61
63
|
end
|
62
64
|
|
63
|
-
def self.
|
64
|
-
|
65
|
-
|
65
|
+
def self.load_spec_files_for_profile(bind_context, opts, &block)
|
66
|
+
# get all spec files
|
67
|
+
target = get_reference_profile(opts[:profile_id], opts[:conf])
|
68
|
+
profile = Inspec::Profile.for_target(target, opts)
|
69
|
+
context = load_profile_context(opts[:profile_id], profile, opts)
|
66
70
|
|
67
|
-
|
68
|
-
|
69
|
-
|
71
|
+
# if we don't want all the rules, then just make 1 pass to get all rule_IDs
|
72
|
+
# that we want to keep from the original
|
73
|
+
filter_included_controls(context, opts, &block) if !opts[:include_all]
|
70
74
|
|
71
|
-
|
72
|
-
|
73
|
-
files = get_spec_files_for_profile profile_id
|
74
|
-
# load all rules from spec files
|
75
|
-
rule_registry = {}
|
76
|
-
# TODO: handling of only_ifs
|
77
|
-
only_ifs = []
|
78
|
-
files.each do |file|
|
79
|
-
load_spec_file_for_profile(profile_id, file, rule_registry, only_ifs)
|
80
|
-
end
|
75
|
+
# interpret the block and skip/modify as required
|
76
|
+
context.load(block) if block_given?
|
81
77
|
|
82
|
-
#
|
83
|
-
|
84
|
-
|
85
|
-
ctx = Inspec::ProfileContext.new(profile_id, block_registry, only_ifs)
|
86
|
-
ctx.instance_eval(&block)
|
78
|
+
# finally register all combined rules
|
79
|
+
context.rules.values.each do |control|
|
80
|
+
bind_context.register_control(control)
|
87
81
|
end
|
82
|
+
end
|
88
83
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
84
|
+
def self.filter_included_controls(context, opts, &block)
|
85
|
+
mock = Inspec::Backend.create({ backend: 'mock' })
|
86
|
+
include_ctx = Inspec::ProfileContext.new(opts[:profile_id], mock, opts[:conf])
|
87
|
+
include_ctx.load(block) if block_given?
|
88
|
+
# remove all rules that were not registered
|
89
|
+
context.rules.keys.each do |id|
|
90
|
+
unless include_ctx.rules[id]
|
91
|
+
context.rules[id] = nil
|
92
|
+
end
|
94
93
|
end
|
94
|
+
end
|
95
95
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
elsif r.nil?
|
103
|
-
rule_registry.delete(id)
|
104
|
-
else
|
105
|
-
merge_rules(org, r)
|
106
|
-
end
|
96
|
+
def self.get_reference_profile(id, opts)
|
97
|
+
profiles_path = opts['profiles_path'] ||
|
98
|
+
fail('You must supply a --profiles-path to inherit from other profiles.')
|
99
|
+
abs_path = File.expand_path(profiles_path.to_s)
|
100
|
+
unless File.directory? abs_path
|
101
|
+
fail("Cannot find profiles path #{abs_path}")
|
107
102
|
end
|
108
103
|
|
109
|
-
|
110
|
-
|
111
|
-
|
104
|
+
id_path = File.join(abs_path, id)
|
105
|
+
unless File.directory? id_path
|
106
|
+
fail("Cannot find referenced profile #{id} in #{id_path}")
|
112
107
|
end
|
108
|
+
|
109
|
+
id_path
|
113
110
|
end
|
114
111
|
|
115
|
-
def self.
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
if File.directory? libdir and !$LOAD_PATH.include?(libdir)
|
124
|
-
$LOAD_PATH.unshift(libdir)
|
125
|
-
end
|
126
|
-
files = Dir[File.join(path, 'spec', '*_spec.rb')]
|
112
|
+
def self.load_profile_context(id, profile, opts)
|
113
|
+
ctx = Inspec::ProfileContext.new(id, opts[:backend], opts[:conf])
|
114
|
+
profile.libraries.each do |path, content|
|
115
|
+
ctx.load(content.to_s, path, 1)
|
116
|
+
ctx.reload_dsl
|
117
|
+
end
|
118
|
+
profile.tests.each do |path, content|
|
119
|
+
ctx.load(content.to_s, path, 1)
|
127
120
|
end
|
128
|
-
|
121
|
+
ctx
|
129
122
|
end
|
130
123
|
end
|
131
124
|
|
data/lib/inspec/profile.rb
CHANGED
@@ -13,7 +13,7 @@ module Inspec
|
|
13
13
|
extend Forwardable
|
14
14
|
attr_reader :path
|
15
15
|
|
16
|
-
def self.
|
16
|
+
def self.resolve_target(target, opts)
|
17
17
|
# Fetchers retrieve file contents
|
18
18
|
opts[:target] = target
|
19
19
|
fetcher = Inspec::Fetcher.resolve(target)
|
@@ -27,7 +27,11 @@ module Inspec
|
|
27
27
|
fail("Don't understand inspec profile in #{target.inspect}, it "\
|
28
28
|
"doesn't look like a supported profile structure.")
|
29
29
|
end
|
30
|
-
|
30
|
+
reader
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.for_target(target, opts)
|
34
|
+
new(resolve_target(target, opts), opts)
|
31
35
|
end
|
32
36
|
|
33
37
|
attr_reader :source_reader
|
@@ -7,18 +7,18 @@ require 'inspec/dsl'
|
|
7
7
|
require 'securerandom'
|
8
8
|
|
9
9
|
module Inspec
|
10
|
-
class ProfileContext
|
11
|
-
attr_reader :rules
|
12
|
-
def initialize(profile_id, backend,
|
10
|
+
class ProfileContext # rubocop:disable Metrics/ClassLength
|
11
|
+
attr_reader :rules
|
12
|
+
def initialize(profile_id, backend, conf)
|
13
13
|
if backend.nil?
|
14
14
|
fail 'ProfileContext is initiated with a backend == nil. ' \
|
15
15
|
'This is a backend error which must be fixed upstream.'
|
16
16
|
end
|
17
17
|
|
18
18
|
@profile_id = profile_id
|
19
|
-
@rules = profile_registry
|
20
|
-
@only_ifs = only_ifs
|
21
19
|
@backend = backend
|
20
|
+
@conf = conf.dup
|
21
|
+
@rules = {}
|
22
22
|
|
23
23
|
reload_dsl
|
24
24
|
end
|
@@ -26,12 +26,16 @@ module Inspec
|
|
26
26
|
def reload_dsl
|
27
27
|
resources_dsl = Inspec::Resource.create_dsl(@backend)
|
28
28
|
ctx = create_context(resources_dsl, rule_context(resources_dsl))
|
29
|
-
@profile_context = ctx.new
|
29
|
+
@profile_context = ctx.new(@backend, @conf)
|
30
30
|
end
|
31
31
|
|
32
32
|
def load(content, source = nil, line = nil)
|
33
33
|
@current_load = { file: source }
|
34
|
-
|
34
|
+
if content.is_a? Proc
|
35
|
+
@profile_context.instance_eval(&content)
|
36
|
+
else
|
37
|
+
@profile_context.instance_eval(content, source || 'unknown', line || 1)
|
38
|
+
end
|
35
39
|
end
|
36
40
|
|
37
41
|
def unregister_rule(id)
|
@@ -93,6 +97,11 @@ module Inspec
|
|
93
97
|
include Inspec::DSL
|
94
98
|
include resources_dsl
|
95
99
|
|
100
|
+
def initialize(backend, conf) # rubocop:disable Lint/NestedMethodDefinition, Lint/DuplicateMethods
|
101
|
+
@backend = backend
|
102
|
+
@conf = conf
|
103
|
+
end
|
104
|
+
|
96
105
|
define_method :title do |arg|
|
97
106
|
profile_context_owner.set_header(:title, arg)
|
98
107
|
end
|
@@ -116,6 +125,10 @@ module Inspec
|
|
116
125
|
|
117
126
|
alias_method :rule, :control
|
118
127
|
|
128
|
+
define_method :register_control do |control|
|
129
|
+
profile_context_owner.register_rule(control) unless control.nil?
|
130
|
+
end
|
131
|
+
|
119
132
|
define_method :describe do |*args, &block|
|
120
133
|
loc = block_location(block, caller[0])
|
121
134
|
id = "(generated from #{loc} #{SecureRandom.hex})"
|
@@ -133,7 +146,7 @@ module Inspec
|
|
133
146
|
nil
|
134
147
|
end
|
135
148
|
|
136
|
-
|
149
|
+
define_method :skip_control do |id|
|
137
150
|
profile_context_owner.unregister_rule(id)
|
138
151
|
end
|
139
152
|
|
data/lib/inspec/runner.rb
CHANGED
@@ -46,6 +46,12 @@ module Inspec
|
|
46
46
|
@backend = Inspec::Backend.create(@conf)
|
47
47
|
end
|
48
48
|
|
49
|
+
def add_target(target, options = {})
|
50
|
+
profile = Inspec::Profile.for_target(target, options)
|
51
|
+
fail "Could not resolve #{target} to valid input." if profile.nil?
|
52
|
+
add_profile(profile, options)
|
53
|
+
end
|
54
|
+
|
49
55
|
def add_profile(profile, options = {})
|
50
56
|
return unless options[:ignore_supports] ||
|
51
57
|
profile.metadata.supports_transport?(@backend)
|
@@ -57,26 +63,20 @@ module Inspec
|
|
57
63
|
profile.tests.each do |ref, content|
|
58
64
|
r = profile.source_reader.target.abs_path(ref)
|
59
65
|
test = { ref: r, content: content }
|
60
|
-
add_content(test, libs)
|
66
|
+
add_content(test, libs, options)
|
61
67
|
end
|
62
68
|
end
|
63
69
|
|
64
|
-
def
|
65
|
-
|
66
|
-
fail "Could not resolve #{target} to valid input." if profile.nil?
|
67
|
-
add_profile(profile)
|
68
|
-
end
|
69
|
-
|
70
|
-
def create_context
|
71
|
-
Inspec::ProfileContext.new(@profile_id, @backend)
|
70
|
+
def create_context(options = {})
|
71
|
+
Inspec::ProfileContext.new(@profile_id, @backend, @conf.merge(options))
|
72
72
|
end
|
73
73
|
|
74
|
-
def add_content(test, libs)
|
74
|
+
def add_content(test, libs, options = {})
|
75
75
|
content = test[:content]
|
76
76
|
return if content.nil? || content.empty?
|
77
77
|
|
78
78
|
# load all libraries
|
79
|
-
ctx = create_context
|
79
|
+
ctx = create_context(options)
|
80
80
|
libs.each do |lib|
|
81
81
|
ctx.load(lib[:content].to_s, lib[:ref], lib[:line] || 1)
|
82
82
|
ctx.reload_dsl
|
@@ -86,7 +86,7 @@ module Inspec
|
|
86
86
|
ctx.load(content, test[:ref], test[:line] || 1)
|
87
87
|
|
88
88
|
# process the resulting rules
|
89
|
-
ctx.rules.each do |rule_id, rule|
|
89
|
+
filter_controls(ctx.rules, options[:controls]).each do |rule_id, rule|
|
90
90
|
register_rule(rule_id, rule)
|
91
91
|
end
|
92
92
|
end
|
@@ -96,6 +96,11 @@ module Inspec
|
|
96
96
|
|
97
97
|
private
|
98
98
|
|
99
|
+
def filter_controls(controls_map, include_list)
|
100
|
+
return controls_map if include_list.nil? || include_list.empty?
|
101
|
+
controls_map.select { |k, _| include_list.include?(k) }
|
102
|
+
end
|
103
|
+
|
99
104
|
def block_source_info(block)
|
100
105
|
return {} if block.nil? || !block.respond_to?(:source_location)
|
101
106
|
opts = {}
|