inspec 0.20.1 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +45 -2
- data/docs/dsl_inspec.rst +2 -2
- data/docs/resources.rst +9 -9
- data/docs/ruby_usage.rst +145 -0
- data/inspec.gemspec +1 -0
- data/lib/bundles/inspec-compliance/cli.rb +15 -2
- data/lib/inspec/cli.rb +23 -10
- data/lib/inspec/dsl.rb +0 -52
- data/lib/inspec/objects/or_test.rb +1 -0
- data/lib/inspec/objects/test.rb +4 -4
- data/lib/inspec/profile.rb +76 -61
- data/lib/inspec/profile_context.rb +12 -11
- data/lib/inspec/rspec_json_formatter.rb +93 -40
- data/lib/inspec/rule.rb +7 -29
- data/lib/inspec/runner.rb +15 -4
- data/lib/inspec/runner_mock.rb +1 -1
- data/lib/inspec/runner_rspec.rb +26 -24
- data/lib/inspec/version.rb +1 -1
- data/lib/matchers/matchers.rb +3 -3
- data/lib/resources/auditd_rules.rb +2 -2
- data/lib/resources/host.rb +1 -1
- data/lib/resources/interface.rb +1 -1
- data/lib/resources/kernel_parameter.rb +1 -1
- data/lib/resources/mount.rb +2 -1
- data/lib/resources/mysql_session.rb +1 -1
- data/lib/resources/os_env.rb +2 -2
- data/lib/resources/passwd.rb +33 -93
- data/lib/resources/port.rb +47 -3
- data/lib/resources/processes.rb +3 -3
- data/lib/resources/service.rb +33 -1
- data/lib/resources/user.rb +15 -15
- data/lib/utils/base_cli.rb +1 -3
- data/lib/utils/filter.rb +30 -7
- data/test/cookbooks/os_prepare/recipes/_upstart_service_centos.rb +4 -0
- data/test/functional/helper.rb +1 -0
- data/test/functional/inheritance_test.rb +1 -1
- data/test/functional/inspec_compliance_test.rb +4 -3
- data/test/functional/inspec_exec_json_test.rb +122 -0
- data/test/functional/inspec_exec_test.rb +23 -117
- data/test/functional/{inspec_json_test.rb → inspec_json_profile_test.rb} +13 -15
- data/test/functional/inspec_test.rb +15 -2
- data/test/helper.rb +5 -1
- data/test/integration/default/auditd_rules_spec.rb +3 -3
- data/test/integration/default/kernel_parameter_spec.rb +6 -6
- data/test/integration/default/service_spec.rb +4 -0
- data/test/resource/command_test.rb +9 -9
- data/test/resource/dsl_test.rb +1 -1
- data/test/resource/file_test.rb +17 -17
- data/test/unit/control_test.rb +1 -1
- data/test/unit/mock/cmd/hpux-netstat-inet +10 -0
- data/test/unit/mock/cmd/hpux-netstat-inet6 +11 -0
- data/test/unit/mock/profiles/skippy-profile-os/controls/one.rb +1 -1
- data/test/unit/profile_context_test.rb +2 -2
- data/test/unit/profile_test.rb +11 -14
- data/test/unit/resources/passwd_test.rb +13 -14
- data/test/unit/resources/port_test.rb +14 -0
- data/test/unit/resources/processes_test.rb +3 -3
- data/test/unit/resources/service_test.rb +103 -39
- data/test/unit/utils/filter_table_test.rb +35 -3
- metadata +25 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 609dd579538c5f1f9a4f86acf691fee0270ad878
|
4
|
+
data.tar.gz: c4d6ae9ca27a55efca499a37ee70d71c50e2ff42
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29a47097ef98d5ddafc0c145bfff580ac74762538e3de8ef9d5730e210f0a76a478d084acf344f3668b946bee98c03102f8248d4d0632bcc12b5d94cf574b3e9
|
7
|
+
data.tar.gz: 65fb88edad1729f9968024c37e9466824d467f290c14f233ca87e70e1792d96cac3a37d9cd36ec2177ac0a64e7f0038225d38911183525e74c4ad23374f68472
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,46 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [0.
|
4
|
-
[Full Changelog](https://github.com/chef/inspec/compare/v0.20.
|
3
|
+
## [0.21.0](https://github.com/chef/inspec/tree/0.21.0) (2016-05-10)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.20.1...0.21.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- Support nested describe.one blocks [\#711](https://github.com/chef/inspec/issues/711)
|
9
|
+
- inspec exec format json backtrace [\#614](https://github.com/chef/inspec/issues/614)
|
10
|
+
- Improve error output for compliance plugin [\#544](https://github.com/chef/inspec/issues/544)
|
11
|
+
- Cryptic error output if authentication with Chef Compliance fails [\#489](https://github.com/chef/inspec/issues/489)
|
12
|
+
- How to access the impact of a test failure? [\#377](https://github.com/chef/inspec/issues/377)
|
13
|
+
- Optimize InSpec detect [\#300](https://github.com/chef/inspec/issues/300)
|
14
|
+
- document output and/or expected results [\#210](https://github.com/chef/inspec/issues/210)
|
15
|
+
- Remove redundant space when missing expectation [\#724](https://github.com/chef/inspec/pull/724) ([alexpop](https://github.com/alexpop))
|
16
|
+
- Provide service params [\#721](https://github.com/chef/inspec/pull/721) ([alexpop](https://github.com/alexpop))
|
17
|
+
- api: make processes return integers for pid/vsz/rss [\#717](https://github.com/chef/inspec/pull/717) ([arlimus](https://github.com/arlimus))
|
18
|
+
- Expose systemd service properties via .info [\#715](https://github.com/chef/inspec/pull/715) ([alexpop](https://github.com/alexpop))
|
19
|
+
- Use only strings in resource examples, docs and tests [\#708](https://github.com/chef/inspec/pull/708) ([alexpop](https://github.com/alexpop))
|
20
|
+
- use filtertable with passwd resource [\#699](https://github.com/chef/inspec/pull/699) ([arlimus](https://github.com/arlimus))
|
21
|
+
- show error if user is not logged in to compliance server [\#696](https://github.com/chef/inspec/pull/696) ([chris-rock](https://github.com/chris-rock))
|
22
|
+
- JSON formatter redesign [\#671](https://github.com/chef/inspec/pull/671) ([arlimus](https://github.com/arlimus))
|
23
|
+
|
24
|
+
**Fixed bugs:**
|
25
|
+
|
26
|
+
- bugfix: handle train errors in inspec execution [\#705](https://github.com/chef/inspec/pull/705) ([arlimus](https://github.com/arlimus))
|
27
|
+
|
28
|
+
**Closed issues:**
|
29
|
+
|
30
|
+
- How do I inherit a profile from another profile? [\#691](https://github.com/chef/inspec/issues/691)
|
31
|
+
- How do I download a profile from a compliance server? [\#690](https://github.com/chef/inspec/issues/690)
|
32
|
+
- inspec compliance login fails [\#689](https://github.com/chef/inspec/issues/689)
|
33
|
+
|
34
|
+
**Merged pull requests:**
|
35
|
+
|
36
|
+
- inspec detect learns human-readable output [\#720](https://github.com/chef/inspec/pull/720) ([chris-rock](https://github.com/chris-rock))
|
37
|
+
- Add documentation on how to use ruby [\#718](https://github.com/chef/inspec/pull/718) ([alexpop](https://github.com/alexpop))
|
38
|
+
- export \#tests\(\) from OrTest object [\#714](https://github.com/chef/inspec/pull/714) ([arlimus](https://github.com/arlimus))
|
39
|
+
- use strings instead of symbols [\#707](https://github.com/chef/inspec/pull/707) ([vjeffrey](https://github.com/vjeffrey))
|
40
|
+
- hpux support for basic port properties [\#706](https://github.com/chef/inspec/pull/706) ([Anirudh-Gupta](https://github.com/Anirudh-Gupta))
|
41
|
+
|
42
|
+
## [v0.20.1](https://github.com/chef/inspec/tree/v0.20.1) (2016-04-30)
|
43
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.20.0...v0.20.1)
|
5
44
|
|
6
45
|
**Implemented enhancements:**
|
7
46
|
|
@@ -11,6 +50,10 @@
|
|
11
50
|
|
12
51
|
- fix appveyor caching [\#700](https://github.com/chef/inspec/pull/700) ([arlimus](https://github.com/arlimus))
|
13
52
|
|
53
|
+
**Merged pull requests:**
|
54
|
+
|
55
|
+
- 0.20.1 [\#702](https://github.com/chef/inspec/pull/702) ([alexpop](https://github.com/alexpop))
|
56
|
+
|
14
57
|
## [v0.20.0](https://github.com/chef/inspec/tree/v0.20.0) (2016-04-29)
|
15
58
|
[Full Changelog](https://github.com/chef/inspec/compare/v0.19.3...v0.20.0)
|
16
59
|
|
data/docs/dsl_inspec.rst
CHANGED
@@ -117,7 +117,7 @@ The following test shows how to audit machines running |mysql| to ensure that pa
|
|
117
117
|
them to an attacker. Prevent this at all costs.
|
118
118
|
'
|
119
119
|
describe command('env') do
|
120
|
-
its(
|
120
|
+
its('stdout') { should_not match(/^MYSQL_PWD=/) }
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
@@ -232,7 +232,7 @@ The following example illustrates various ways to add tags and references to `co
|
|
232
232
|
.. |inspec resource| replace:: InSpec Resource
|
233
233
|
.. |chef compliance| replace:: Chef Compliance
|
234
234
|
.. |ruby| replace:: Ruby
|
235
|
-
.. |
|
235
|
+
.. |ssh| replace:: SSH
|
236
236
|
.. |windows| replace:: Microsoft Windows
|
237
237
|
.. |postgresql| replace:: PostgreSQL
|
238
238
|
.. |apache| replace:: Apache
|
data/docs/resources.rst
CHANGED
@@ -364,7 +364,7 @@ The following examples show how to use this InSpec audit resource.
|
|
364
364
|
|
365
365
|
# syntax for auditd >= 2.3
|
366
366
|
describe auditd_rules do
|
367
|
-
its(
|
367
|
+
its('lines') { should contain_match(%r{-w /etc/ssh/sshd_config/}) }
|
368
368
|
end
|
369
369
|
|
370
370
|
The syntax for recent auditd versions allows more precise tests, such as the following:
|
@@ -386,7 +386,7 @@ The syntax for recent auditd versions allows more precise tests, such as the fol
|
|
386
386
|
end
|
387
387
|
|
388
388
|
describe auditd_rules.key('sshd_config') do
|
389
|
-
its(
|
389
|
+
its('permissions') { should contain_match(/x/) }
|
390
390
|
end
|
391
391
|
|
392
392
|
Note that filters can be chained, for example:
|
@@ -2045,7 +2045,7 @@ The following examples show how to use this InSpec audit resource.
|
|
2045
2045
|
.. code-block:: ruby
|
2046
2046
|
|
2047
2047
|
describe kernel_parameter('net.ipv4.conf.all.forwarding') do
|
2048
|
-
its(
|
2048
|
+
its('value') { should eq 1 }
|
2049
2049
|
end
|
2050
2050
|
|
2051
2051
|
**Test if global forwarding is disabled for an IPv6 address**
|
@@ -2053,7 +2053,7 @@ The following examples show how to use this InSpec audit resource.
|
|
2053
2053
|
.. code-block:: ruby
|
2054
2054
|
|
2055
2055
|
describe kernel_parameter('net.ipv6.conf.all.forwarding') do
|
2056
|
-
its(
|
2056
|
+
its('value') { should eq 0 }
|
2057
2057
|
end
|
2058
2058
|
|
2059
2059
|
**Test if an IPv6 address accepts redirects**
|
@@ -2061,7 +2061,7 @@ The following examples show how to use this InSpec audit resource.
|
|
2061
2061
|
.. code-block:: ruby
|
2062
2062
|
|
2063
2063
|
describe kernel_parameter('net.ipv6.conf.interface.accept_redirects') do
|
2064
|
-
its(
|
2064
|
+
its('value') { should eq 'true' }
|
2065
2065
|
end
|
2066
2066
|
|
2067
2067
|
|
@@ -2417,7 +2417,7 @@ The following examples show how to use this InSpec audit resource.
|
|
2417
2417
|
|
2418
2418
|
sql = mysql_session('my_user','password')
|
2419
2419
|
describe sql.query('show databases like \'test\';') do
|
2420
|
-
its(
|
2420
|
+
its('stdout') { should_not match(/test/) }
|
2421
2421
|
end
|
2422
2422
|
|
2423
2423
|
|
@@ -3148,12 +3148,12 @@ A ``passwd`` |inspec resource| block declares one (or more) users and associated
|
|
3148
3148
|
.. code-block:: ruby
|
3149
3149
|
|
3150
3150
|
describe passwd do
|
3151
|
-
its(
|
3151
|
+
its('users') { should_not include 'forbidden_user' }
|
3152
3152
|
end
|
3153
3153
|
|
3154
3154
|
describe passwd.uid(0) do
|
3155
|
-
its(
|
3156
|
-
its(
|
3155
|
+
its('users') { should cmp 'root' }
|
3156
|
+
its('count') { should eq 1 }
|
3157
3157
|
end
|
3158
3158
|
|
3159
3159
|
where
|
data/docs/ruby_usage.rst
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
=====================================================
|
2
|
+
Using |ruby| in InSpec
|
3
|
+
=====================================================
|
4
|
+
|
5
|
+
The |inspec| DSL is a |ruby| based DSL for writing audit controls, which includes audit resources that you can invoke.
|
6
|
+
Core and custom resources are written as regular |ruby| classes which inherit from ``Inspec.resource``.
|
7
|
+
|
8
|
+
Assuming we have a |json| file like this on the node to be tested:
|
9
|
+
|
10
|
+
.. code-block:: json
|
11
|
+
|
12
|
+
{
|
13
|
+
"keys":[
|
14
|
+
{"username":"john", "key":"/opt/keys/johnd.key"},
|
15
|
+
{"username":"jane", "key":"/opt/keys/janed.key"},
|
16
|
+
{"username":"sunny ", "key":"/opt/keys/sunnym.key"}
|
17
|
+
]
|
18
|
+
}
|
19
|
+
|
20
|
+
The following example shows how you can use pure |ruby| code(variables, loops, conditionals, regular expressions, etc) to run a few tests against the above |json| file:
|
21
|
+
|
22
|
+
.. code-block:: ruby
|
23
|
+
|
24
|
+
control 'check-interns' do
|
25
|
+
# use the json inspec resource to get the file
|
26
|
+
json_obj = json('/opt/keys/interns.json')
|
27
|
+
describe json_obj do
|
28
|
+
its('keys') { should_not eq nil }
|
29
|
+
end
|
30
|
+
if json_obj['keys']
|
31
|
+
# loop over the keys array
|
32
|
+
json_obj['keys'].each do |intern|
|
33
|
+
username = intern['username'].strip
|
34
|
+
# check for white spaces chars in usernames
|
35
|
+
describe username do
|
36
|
+
it { should_not match(/\s/) }
|
37
|
+
end
|
38
|
+
# check key file owners and permissions
|
39
|
+
describe file(intern['key']) do
|
40
|
+
it { should be_owned_by username }
|
41
|
+
its('mode') { should eq 0600 }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
Execution
|
48
|
+
=====================================================
|
49
|
+
|
50
|
+
It's important to understand that |ruby| code used in custom resources and controls DSL is executed on the system that runs |inspec|. This allows |inspec| to work without |ruby| and rubygems being required on remote targets(servers or containers).
|
51
|
+
|
52
|
+
For example, using ```ls``` or ``system('ls')`` will result in the ``ls`` command being run locally and not on the target(remote) system.
|
53
|
+
In order to process the output of ``ls`` executed on the target system, use ``inspec.command('ls')`` or ``inspec.powershell('ls')``
|
54
|
+
|
55
|
+
Similarly, use ``inspec.file(PATH)`` to access files or directories from remote systems in your tests or custom resources.
|
56
|
+
|
57
|
+
Using rubygems
|
58
|
+
=====================================================
|
59
|
+
|
60
|
+
|ruby| gems are self-contained programs and libraries ...
|
61
|
+
|
62
|
+
|
63
|
+
Interactive Debugging with Pry
|
64
|
+
=====================================================
|
65
|
+
|
66
|
+
Here's a sample |inspec| control that users |ruby| variables to instantiate an |inspec| resource once and use the content in multipLe tests.
|
67
|
+
|
68
|
+
.. code-block:: ruby
|
69
|
+
|
70
|
+
control 'check-perl' do
|
71
|
+
impact 0.3
|
72
|
+
title 'Check perl compiled options and permissions'
|
73
|
+
perl_out = command('perl -V')
|
74
|
+
#require 'pry'; binding.pry;
|
75
|
+
describe perl_out do
|
76
|
+
its('exit_status') { should eq 0 }
|
77
|
+
its('stdout') { should match (/USE_64_BIT_ALL/) }
|
78
|
+
its('stdout') { should match (/useposix=true/) }
|
79
|
+
its('stdout') { should match (/-fstack-protector/) }
|
80
|
+
end
|
81
|
+
|
82
|
+
# extract an array of include directories
|
83
|
+
perl_inc = perl_out.stdout.partition('@INC:').last.strip.split("\n")
|
84
|
+
# ensure include directories are only writable by 'owner'
|
85
|
+
perl_inc.each do |path|
|
86
|
+
describe directory(path.strip) do
|
87
|
+
it { should_not be_writable.by('group') }
|
88
|
+
it { should_not be_writable.by('other') }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
An **advanced** but very useful |ruby| tip. In the previous example, I commented out the ``require 'pry'; binding.pry;`` line. If you remove the ``#`` prefix and run the control, the execution will stop at that line and give you a ``pry`` shell. Use that to troubleshoot, print variables, see methods available, etc. For the above example:
|
94
|
+
|
95
|
+
.. code-block:: ruby
|
96
|
+
|
97
|
+
[1] pry> perl_out.exit_status
|
98
|
+
=> 0
|
99
|
+
[2] pry> perl_out.stderr
|
100
|
+
=> ""
|
101
|
+
[3] pry> ls perl_out
|
102
|
+
Inspec::Plugins::Resource#methods: inspect
|
103
|
+
Inspec::Resources::Cmd#methods: command exist? exit_status result stderr stdout to_s
|
104
|
+
Inspec::Plugins::ResourceCommon#methods: resource_skipped skip_resource
|
105
|
+
Inspec::Resource::Registry::Command#methods: inspec
|
106
|
+
instance variables: @__backend_runner__ @__resource_name__ @command @result
|
107
|
+
[4] pry> perl_out.stdout.partition('@INC:').last.strip.split("\n")
|
108
|
+
=> ["/Library/Perl/5.18/darwin-thread-multi-2level",
|
109
|
+
" /Library/Perl/5.18",
|
110
|
+
...REDACTED...
|
111
|
+
[5] pry> exit # or abort
|
112
|
+
|
113
|
+
You can use ``pry`` inside both the controls DSL and resources.
|
114
|
+
Similarly, for dev and test, you can use ``inspec shell`` which is based on ``pry``, for example:
|
115
|
+
|
116
|
+
.. code-block:: ruby
|
117
|
+
|
118
|
+
$ inspec shell
|
119
|
+
Welcome to the interactive InSpec Shell
|
120
|
+
To find out how to use it, type: help
|
121
|
+
|
122
|
+
inspec> command('ls /home/gordon/git/inspec/docs').stdout
|
123
|
+
=> "ctl_inspec.rst\ndsl_inspec.rst\ndsl_resource.rst\n"
|
124
|
+
inspec> command('ls').stdout.split("\n")
|
125
|
+
=> ["ctl_inspec.rst", "dsl_inspec.rst", "dsl_resource.rst"]
|
126
|
+
|
127
|
+
inspec> help command
|
128
|
+
Name: command
|
129
|
+
|
130
|
+
Description:
|
131
|
+
Use the command InSpec audit resource to test an arbitrary command that is run on the system.
|
132
|
+
|
133
|
+
Example:
|
134
|
+
describe command('ls -al /') do
|
135
|
+
it { should exist }
|
136
|
+
its('stdout') { should match /bin/ }
|
137
|
+
its('stderr') { should eq '' }
|
138
|
+
its('exit_status') { should eq 0 }
|
139
|
+
end
|
140
|
+
|
141
|
+
.. |inspec| replace:: InSpec
|
142
|
+
.. |chef compliance| replace:: Chef Compliance
|
143
|
+
.. |ruby| replace:: Ruby
|
144
|
+
.. |csv| replace:: CSV
|
145
|
+
.. |json| replace:: JSON
|
data/inspec.gemspec
CHANGED
@@ -58,6 +58,8 @@ module Compliance
|
|
58
58
|
desc 'profiles', 'list all available profiles in Chef Compliance'
|
59
59
|
def profiles
|
60
60
|
config = Compliance::Configuration.new
|
61
|
+
return if !loggedin(config)
|
62
|
+
|
61
63
|
profiles = Compliance::API.profiles(config)
|
62
64
|
if !profiles.empty?
|
63
65
|
# iterate over profiles
|
@@ -73,6 +75,9 @@ module Compliance
|
|
73
75
|
desc 'exec PROFILE', 'executes a Chef Compliance profile'
|
74
76
|
exec_options
|
75
77
|
def exec(*tests)
|
78
|
+
config = Compliance::Configuration.new
|
79
|
+
return if !loggedin(config)
|
80
|
+
|
76
81
|
# iterate over tests and add compliance scheme
|
77
82
|
tests = tests.map { |t| 'compliance://' + t }
|
78
83
|
|
@@ -84,7 +89,10 @@ module Compliance
|
|
84
89
|
desc 'upload PATH', 'uploads a local profile to Chef Compliance'
|
85
90
|
option :overwrite, type: :boolean, default: false,
|
86
91
|
desc: 'Overwrite existing profile on Chef Compliance.'
|
87
|
-
def upload(path) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, PerceivedComplexity
|
92
|
+
def upload(path) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, PerceivedComplexity, Metrics/CyclomaticComplexity
|
93
|
+
config = Compliance::Configuration.new
|
94
|
+
return if !loggedin(config)
|
95
|
+
|
88
96
|
unless File.exist?(path)
|
89
97
|
puts "Directory #{path} does not exist."
|
90
98
|
exit 1
|
@@ -110,7 +118,6 @@ module Compliance
|
|
110
118
|
end
|
111
119
|
|
112
120
|
# determine user information
|
113
|
-
config = Compliance::Configuration.new
|
114
121
|
if config['token'].nil? || config['user'].nil?
|
115
122
|
error.call('Please login via `inspec compliance login`')
|
116
123
|
end
|
@@ -261,6 +268,12 @@ module Compliance
|
|
261
268
|
|
262
269
|
[success, msg]
|
263
270
|
end
|
271
|
+
|
272
|
+
def loggedin(config)
|
273
|
+
serverknown = !config['server'].nil?
|
274
|
+
puts 'You need to login first with `inspec compliance login`' if !serverknown
|
275
|
+
serverknown
|
276
|
+
end
|
264
277
|
end
|
265
278
|
|
266
279
|
# register the subcommand to Inspec CLI registry
|
data/lib/inspec/cli.rb
CHANGED
@@ -15,8 +15,6 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
15
15
|
desc: 'Show diagnostics (versions, configurations)'
|
16
16
|
|
17
17
|
desc 'json PATH', 'read all tests in PATH and generate a JSON summary'
|
18
|
-
option :id, type: :string,
|
19
|
-
desc: 'Attach a profile ID to all test results'
|
20
18
|
option :output, aliases: :o, type: :string,
|
21
19
|
desc: 'Save the created profile to a path'
|
22
20
|
option :controls, type: :array,
|
@@ -115,9 +113,19 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
115
113
|
|
116
114
|
desc 'detect', 'detect the target OS'
|
117
115
|
target_options
|
116
|
+
option :format, type: :string
|
118
117
|
def detect
|
119
|
-
|
120
|
-
|
118
|
+
o = opts.dup
|
119
|
+
o[:command] = 'os.params'
|
120
|
+
res = run_command(o)
|
121
|
+
if opts['format'] == 'json'
|
122
|
+
puts res.to_json
|
123
|
+
else
|
124
|
+
headline('Operating System Details')
|
125
|
+
%w{name family release arch}.each { |item|
|
126
|
+
puts "#{mark_text(item.to_s.capitalize + ':')} #{res[item.to_sym]}"
|
127
|
+
}
|
128
|
+
end
|
121
129
|
end
|
122
130
|
|
123
131
|
desc 'shell', 'open an interactive debugging shell'
|
@@ -129,25 +137,30 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
129
137
|
o = opts.dup
|
130
138
|
o[:logger] = Logger.new(STDOUT)
|
131
139
|
o[:logger].level = get_log_level(o.log_level)
|
132
|
-
|
133
140
|
if o[:command].nil?
|
134
141
|
runner = Inspec::Runner.new(o)
|
135
142
|
return Inspec::Shell.new(runner).start
|
136
143
|
else
|
137
|
-
|
138
|
-
runner = Inspec::Runner.new(opts)
|
139
|
-
res = runner.create_context.load(o[:command])
|
144
|
+
res = run_command(o)
|
140
145
|
jres = res.respond_to?(:to_json) ? res.to_json : JSON.dump(res)
|
141
146
|
puts jres
|
142
147
|
end
|
143
|
-
rescue RuntimeError => e
|
144
|
-
puts e.message
|
148
|
+
rescue RuntimeError, Train::UserError => e
|
149
|
+
$stderr.puts e.message
|
145
150
|
end
|
146
151
|
|
147
152
|
desc 'version', 'prints the version of this tool'
|
148
153
|
def version
|
149
154
|
puts Inspec::VERSION
|
150
155
|
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def run_command(opts)
|
160
|
+
opts[:test_collector] = 'mock'
|
161
|
+
runner = Inspec::Runner.new(opts)
|
162
|
+
runner.create_context.load(opts[:command])
|
163
|
+
end
|
151
164
|
end
|
152
165
|
|
153
166
|
# Load all plugins on startup
|
data/lib/inspec/dsl.rb
CHANGED
@@ -31,37 +31,6 @@ module Inspec::DSL
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
# Register a given rule with RSpec and
|
35
|
-
# let it run. This happens after everything
|
36
|
-
# else is merged in.
|
37
|
-
def self.execute_rule(r, profile_id)
|
38
|
-
checks = ::Inspec::Rule.prepare_checks(r)
|
39
|
-
fid = InspecBaseRule.full_id(r, profile_id)
|
40
|
-
checks.each do |m, a, b|
|
41
|
-
# check if the resource is skippable and skipped
|
42
|
-
cres = rule_from_check(m, a, b)
|
43
|
-
set_rspec_ids(cres, fid) if m == 'describe'
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# merge two rules completely; all defined
|
48
|
-
# fields from src will be overwritten in dst
|
49
|
-
def self.merge_rules(dst, src)
|
50
|
-
InspecBaseRule.merge dst, src
|
51
|
-
end
|
52
|
-
|
53
|
-
# Attach an ID attribute to the
|
54
|
-
# metadata of all examples
|
55
|
-
# TODO: remove this once IDs are in rspec-core
|
56
|
-
def self.set_rspec_ids(obj, id)
|
57
|
-
obj.examples.each {|ex|
|
58
|
-
ex.metadata[:id] = id
|
59
|
-
}
|
60
|
-
obj.children.each {|c|
|
61
|
-
set_rspec_ids(c, id)
|
62
|
-
}
|
63
|
-
end
|
64
|
-
|
65
34
|
def self.load_spec_files_for_profile(bind_context, opts, &block)
|
66
35
|
# get all spec files
|
67
36
|
target = get_reference_profile(opts[:profile_id], opts[:conf])
|
@@ -121,24 +90,3 @@ module Inspec::DSL
|
|
121
90
|
ctx
|
122
91
|
end
|
123
92
|
end
|
124
|
-
|
125
|
-
module Inspec::GlobalDSL
|
126
|
-
def __register_rule(r)
|
127
|
-
# make sure the profile id is attached to the rule
|
128
|
-
::Inspec::DSL.execute_rule(r, __profile_id)
|
129
|
-
end
|
130
|
-
|
131
|
-
def __unregister_rule(_id)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
module Inspec::DSLHelper
|
136
|
-
def self.bind_dsl(scope)
|
137
|
-
(class << scope; self; end).class_exec do
|
138
|
-
include Inspec::DSL
|
139
|
-
include Inspec::GlobalDSL
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
::Inspec::DSLHelper.bind_dsl(self)
|