inspec 1.22.0 → 1.23.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 +22 -1
- data/Gemfile +1 -0
- data/README.md +5 -5
- data/Rakefile +1 -1
- data/docs/migration.md +67 -6
- data/docs/profiles.md +39 -0
- data/docs/resources/yaml.md.erb +15 -1
- data/examples/meta-profile/README.md +1 -1
- data/lib/bundles/inspec-habitat/profile.rb +16 -23
- data/lib/inspec/backend.rb +22 -16
- data/lib/inspec/cli.rb +7 -0
- data/lib/inspec/completions/fish.sh.erb +34 -0
- data/lib/inspec/env_printer.rb +9 -1
- data/lib/inspec/profile.rb +6 -1
- data/lib/inspec/rspec_json_formatter.rb +25 -15
- data/lib/inspec/runtime_profile.rb +26 -0
- data/lib/inspec/shell.rb +2 -2
- data/lib/inspec/version.rb +1 -1
- data/lib/matchers/matchers.rb +3 -3
- data/lib/resources/passwd.rb +4 -4
- data/lib/resources/xinetd.rb +1 -1
- data/lib/resources/yaml.rb +10 -2
- data/lib/source_readers/flat.rb +2 -1
- data/lib/source_readers/inspec.rb +13 -5
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e8390da8233b1e2b9fe3386b5487a3b947858be
|
4
|
+
data.tar.gz: 6603d92295c8e8826a9035a4ac71ab6c5ffcc2e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c13174864bb854dd39cdc7bba7140476e6dedb16db12cb55dbd9c98b435a672740737603c6d8d79b1fca704c4a9a2c080f6399112b6eb1d1b5804cf8822f775
|
7
|
+
data.tar.gz: 3e69e3df1a2d04bc9d13e123a0a7957fa57b0e5307d83d6220fd1bd384155dba4cb7d2341578e71a5c9c9fa4363ba1fbbe31ea31568a8f7f99b1e01f4c8a4420
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [1.23.0](https://github.com/chef/inspec/tree/1.23.0) (2017-05-04)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v1.22.0...1.23.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- Warn when using --sudo locally [\#1690](https://github.com/chef/inspec/issues/1690)
|
9
|
+
- Error and exit when using --sudo locally [\#1741](https://github.com/chef/inspec/pull/1741) ([adamleff](https://github.com/adamleff))
|
10
|
+
|
11
|
+
**Fixed bugs:**
|
12
|
+
|
13
|
+
- xinetd.rb `read\_content': undefined method `empty?' for nil:NilClass [\#1729](https://github.com/chef/inspec/issues/1729)
|
14
|
+
- Make the --no-color flag work for inspec exec [\#1749](https://github.com/chef/inspec/pull/1749) ([adamleff](https://github.com/adamleff))
|
15
|
+
- Fix xinetd resource failing when file cannot be read [\#1746](https://github.com/chef/inspec/pull/1746) ([adamleff](https://github.com/adamleff))
|
16
|
+
- Habitat profile bug fixes and improvements [\#1735](https://github.com/chef/inspec/pull/1735) ([rhass](https://github.com/rhass))
|
17
|
+
|
18
|
+
**Merged pull requests:**
|
19
|
+
|
20
|
+
- rake: lint before test [\#1755](https://github.com/chef/inspec/pull/1755) ([arlimus](https://github.com/arlimus))
|
21
|
+
- rename old deprecations that were meant for 1.0 [\#1737](https://github.com/chef/inspec/pull/1737) ([arlimus](https://github.com/arlimus))
|
22
|
+
- add `inspec.profile.file\(...\)` for profile files [\#1720](https://github.com/chef/inspec/pull/1720) ([arlimus](https://github.com/arlimus))
|
23
|
+
|
3
24
|
## [v1.22.0](https://github.com/chef/inspec/tree/v1.22.0) (2017-04-27)
|
4
25
|
[Full Changelog](https://github.com/chef/inspec/compare/v1.21.0...v1.22.0)
|
5
26
|
|
@@ -2453,4 +2474,4 @@
|
|
2453
2474
|
|
2454
2475
|
|
2455
2476
|
|
2456
|
-
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
2477
|
+
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -18,7 +18,7 @@ describe inetd_conf do
|
|
18
18
|
end
|
19
19
|
```
|
20
20
|
|
21
|
-
InSpec makes it easy to run your tests wherever you need. More options are found in our [CLI docs](
|
21
|
+
InSpec makes it easy to run your tests wherever you need. More options are found in our [CLI docs](https://www.inspec.io/docs/reference/cli/).
|
22
22
|
|
23
23
|
```bash
|
24
24
|
# run test locally
|
@@ -300,17 +300,17 @@ Windows | 2012+
|
|
300
300
|
|
301
301
|
Documentation
|
302
302
|
|
303
|
-
*
|
304
|
-
*
|
303
|
+
* https://www.inspec.io/docs/
|
304
|
+
* https://www.inspec.io/docs/reference/resources/
|
305
305
|
* https://github.com/chef/inspec/tree/master/docs
|
306
306
|
|
307
307
|
Tutorials/Blogs/Podcasts:
|
308
308
|
|
309
|
-
*
|
309
|
+
* https://www.inspec.io/tutorials/
|
310
310
|
|
311
311
|
Relationship to other tools (RSpec, Serverspec):
|
312
312
|
|
313
|
-
*
|
313
|
+
* https://www.inspec.io/docs/reference/inspec_and_friends/
|
314
314
|
|
315
315
|
## Share your Profiles
|
316
316
|
|
data/Rakefile
CHANGED
data/docs/migration.md
CHANGED
@@ -16,14 +16,75 @@ InSpec is a framework that allows you to run infrastructure testing as well as c
|
|
16
16
|
|
17
17
|
The following resources are available in InSpec:
|
18
18
|
|
19
|
-
|
19
|
+
| Serverspec | InSpec |
|
20
|
+
|:------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------:|
|
21
|
+
| [`bond`](http://serverspec.org/resource_types.html#bond) | [`bond`](https://www.inspec.io/docs/reference/resources/bond/) |
|
22
|
+
| [`bridge`](http://serverspec.org/resource_types.html#bridge) | [`bridge`](https://www.inspec.io/docs/reference/resources/bridge/) |
|
23
|
+
| [`command`](http://serverspec.org/resource_types.html#command) | [`command`](https://www.inspec.io/docs/reference/resources/command/) |
|
24
|
+
| [`cron`](http://serverspec.org/resource_types.html#cron) | [`crontab`](https://www.inspec.io/docs/reference/resources/crontab/) |
|
25
|
+
| [`docker_container`](http://serverspec.org/resource_types.html#docker_container) | [`docker_container`](https://www.inspec.io/docs/reference/resources/docker_container/) |
|
26
|
+
| [`docker_image`](http://serverspec.org/resource_types.html#docker_image) | [`docker_image`](https://www.inspec.io/docs/reference/resources/docker_image/) |
|
27
|
+
| [`file`](http://serverspec.org/resource_types.html#file) | [`file`](https://www.inspec.io/docs/reference/resources/file/) |
|
28
|
+
| [`group`](http://serverspec.org/resource_types.html#group) | [`group`](https://www.inspec.io/docs/reference/resources/group/) |
|
29
|
+
| [`host`](http://serverspec.org/resource_types.html#host) | [`host`](https://www.inspec.io/docs/reference/resources/host/) |
|
30
|
+
| [`interface`](http://serverspec.org/resource_types.html#interface) | [`interface`](https://www.inspec.io/docs/reference/resources/interface/) |
|
31
|
+
| [`iis_website`](http://serverspec.org/resource_types.html#iis_website) | [`iis_website`](https://www.inspec.io/docs/reference/resources/iis_website/) |
|
32
|
+
| [`iis_app_pool`](http://serverspec.org/resource_types.html#iis_app_pool) | [`iis_website`](https://www.inspec.io/docs/reference/resources/iis_website/) |
|
33
|
+
| [`iptables`](http://serverspec.org/resource_types.html#iptables) | [`iptables`](https://www.inspec.io/docs/reference/resources/iptables/) |
|
34
|
+
| [`kernel_module`](http://serverspec.org/resource_types.html#kernel_module) | [`kernel_module`](https://www.inspec.io/docs/reference/resources/kernel_module/) |
|
35
|
+
| [`linux_kernel_parameter`](http://serverspec.org/resource_types.html#linux_kernel_parameter) | [`kernel_parameter`](https://www.inspec.io/docs/reference/resources/kernel_parameter/) |
|
36
|
+
| [`mysql_config`](http://serverspec.org/resource_types.html#mysql_config) | [`mysql_conf`](https://www.inspec.io/docs/reference/resources/mysql_conf/) |
|
37
|
+
| [`package`](http://serverspec.org/resource_types.html#package) | [`package`](https://www.inspec.io/docs/reference/resources/package/) |
|
38
|
+
| [`port`](http://serverspec.org/resource_types.html#port) | [`port`](https://www.inspec.io/docs/reference/resources/port/) |
|
39
|
+
| [`ppa`](http://serverspec.org/resource_types.html#ppa) | [`apt`](https://www.inspec.io/docs/reference/resources/apt/) |
|
40
|
+
| [`process`](http://serverspec.org/resource_types.html#process) | [`processes`](https://www.inspec.io/docs/reference/resources/processes/) |
|
41
|
+
| [`service`](http://serverspec.org/resource_types.html#service) | [`service`](https://www.inspec.io/docs/reference/resources/service/) |
|
42
|
+
| [`user`](http://serverspec.org/resource_types.html#user) | [`user`](https://www.inspec.io/docs/reference/resources/user/) |
|
43
|
+
| [`windows_feature`](http://serverspec.org/resource_types.html#windows_feature) | [`windows_feature`](https://www.inspec.io/docs/reference/resources/windows_feature/) |
|
44
|
+
| [`windows_registry_key`](http://serverspec.org/resource_types.html#windows_registry_key) | [`registry_key`](https://www.inspec.io/docs/reference/resources/registry_key/) |
|
45
|
+
| [`x509_certificate`](http://serverspec.org/resource_types.html#x509_certificate) | [`x509_certificate`](https://www.inspec.io/docs/reference/resources/x509_certificate/) |
|
46
|
+
| [`yumrepo`](http://serverspec.org/resource_types.html#yumrepo) | [`yum`](https://www.inspec.io/docs/reference/resources/yum/) |
|
47
|
+
| [`zfs`](http://serverspec.org/resource_types.html#zfs) | [`zfs_pool`](https://www.inspec.io/docs/reference/resources/zfs_pool/) |
|
20
48
|
|
21
49
|
Some Serverspec resources are not available yet. We implement those resources based on user feedback. If you need a resource that is not available in InSpec, please open an [Github issue](https://github.com/chef/inspec/issues). The list of resources that are not available in InSpec:
|
22
50
|
|
23
|
-
`cgroup
|
24
|
-
|
25
|
-
|
26
|
-
|
51
|
+
* [`cgroup`](http://serverspec.org/resource_types.html#cgroup)
|
52
|
+
* [`default_gateway`](http://serverspec.org/resource_types.html#default_gateway)
|
53
|
+
* [`ip6tables`](http://serverspec.org/resource_types.html#ip6tables)
|
54
|
+
* [`ipfilter`](http://serverspec.org/resource_types.html#ipfilter)
|
55
|
+
* [`ipnat`](http://serverspec.org/resource_types.html#ipnat)
|
56
|
+
* [`linux_audit_system`](http://serverspec.org/resource_types.html#linux_audit_system)
|
57
|
+
* [`lxc`](http://serverspec.org/resource_types.html#lxc)
|
58
|
+
* [`mail_alias`](http://serverspec.org/resource_types.html#mail_alias)
|
59
|
+
* [`php_config`](http://serverspec.org/resource_types.html#php_config)
|
60
|
+
* [`routing_table`](http://serverspec.org/resource_types.html#routing_table)
|
61
|
+
* [`selinux`](http://serverspec.org/resource_types.html#selinux)
|
62
|
+
* [`selinux_module`](http://serverspec.org/resource_types.html#selinux_module)
|
63
|
+
* [`x509_private_key`](http://serverspec.org/resource_types.html#x509_private_key)
|
64
|
+
|
65
|
+
In addition InSpec provides additional [resources](https://www.inspec.io/docs/reference/resources/) that are not available in Serverspec:
|
66
|
+
|
67
|
+
* [`apache_conf`](https://www.inspec.io/docs/reference/resources/apache_conf/)
|
68
|
+
* [`apt`](https://www.inspec.io/docs/reference/resources/apt/)
|
69
|
+
* [`audit_policy`](https://www.inspec.io/docs/reference/resources/audit_policy/)
|
70
|
+
* [`auditd_conf`](https://www.inspec.io/docs/reference/resources/auditd_conf/)
|
71
|
+
* [`bash`](https://www.inspec.io/docs/reference/resources/bash/)
|
72
|
+
* [`csv`](https://www.inspec.io/docs/reference/resources/csv/)
|
73
|
+
* [`etc_shadow`](https://www.inspec.io/docs/reference/resources/etc_shadow/)
|
74
|
+
* [`gem`](https://www.inspec.io/docs/reference/resources/gem/)
|
75
|
+
* [`grub_conf`](https://www.inspec.io/docs/reference/resources/grub_conf/)
|
76
|
+
* [`inetd_conf`](https://www.inspec.io/docs/reference/resources/inetd_conf/)
|
77
|
+
* [`ini`](https://www.inspec.io/docs/reference/resources/ini/)
|
78
|
+
* [`json`](https://www.inspec.io/docs/reference/resources/json/)
|
79
|
+
* [`npm`](https://www.inspec.io/docs/reference/resources/npm/)
|
80
|
+
* [`ntp_conf`](https://www.inspec.io/docs/reference/resources/ntp_conf/)
|
81
|
+
* [`oneget`](https://www.inspec.io/docs/reference/resources/oneget/)
|
82
|
+
* [`pip`](https://www.inspec.io/docs/reference/resources/pip/)
|
83
|
+
* [`powershell`](https://www.inspec.io/docs/reference/resources/powershell/)
|
84
|
+
* [`security_policy`](https://www.inspec.io/docs/reference/resources/security_policy/)
|
85
|
+
* [`ssh_config`](https://www.inspec.io/docs/reference/resources/ssh_config/)
|
86
|
+
* [`sshd_config`](https://www.inspec.io/docs/reference/resources/sshd_config/)
|
87
|
+
* [`sys_info`](https://www.inspec.io/docs/reference/resources/sys_info/)
|
27
88
|
|
28
89
|
## How do I migrate my Serverspec tests to InSpec
|
29
90
|
|
@@ -53,7 +114,7 @@ kitchen verify package-install-centos-72
|
|
53
114
|
-----> Starting Kitchen (v1.14.2)
|
54
115
|
-----> Verifying <package-install-centos-72>...
|
55
116
|
Detected alternative framework tests for `inspec`
|
56
|
-
Loaded
|
117
|
+
Loaded
|
57
118
|
|
58
119
|
Target: ssh://vagrant@127.0.0.1:2200
|
59
120
|
|
data/docs/profiles.md
CHANGED
@@ -17,6 +17,8 @@ A profile should have the following structure::
|
|
17
17
|
│ └── control_etc.rb
|
18
18
|
├── libraries
|
19
19
|
│ └── extension.rb
|
20
|
+
|── files
|
21
|
+
│ └── extras.conf
|
20
22
|
└── inspec.yml
|
21
23
|
|
22
24
|
where:
|
@@ -24,6 +26,7 @@ where:
|
|
24
26
|
* `inspec.yml` includes the profile description (required)
|
25
27
|
* `controls` is the directory in which all tests are located (required)
|
26
28
|
* `libraries` is the directory in which all InSpec resource extensions are located (optional)
|
29
|
+
* `files` is the directory with additional files that a profile can access (optional)
|
27
30
|
* `README.md` should be used to explain the profile, its scope, and usage
|
28
31
|
|
29
32
|
See a complete example profile in the InSpec open source repository: https://github.com/chef/inspec/tree/master/examples/profile
|
@@ -301,3 +304,39 @@ The following command runs the tests and applies the secrets specified in `profi
|
|
301
304
|
$ inspec exec examples/profile-attribute --attrs examples/profile-attribute.yml
|
302
305
|
|
303
306
|
See the full example in the InSpec open source repository: https://github.com/chef/inspec/tree/master/examples/profile-attribute
|
307
|
+
|
308
|
+
# Profile files
|
309
|
+
|
310
|
+
An InSpec profile may contain additional files that can be accessed during tests. This covers use-cases where e.g. a list of ports is provided to be tested.
|
311
|
+
|
312
|
+
To access these files, they must be stored in the `files` directory at the root of a profile. They are accessed by their name relative to this folder with `inspec.profile.file(...)`.
|
313
|
+
|
314
|
+
Here is an example for reading and testing a list of ports. The folder structure is:
|
315
|
+
|
316
|
+
examples/profile
|
317
|
+
├── controls
|
318
|
+
│ ├── example.rb
|
319
|
+
|── files
|
320
|
+
│ └── services.yml
|
321
|
+
└── inspec.yml
|
322
|
+
|
323
|
+
With `services.yml` containing:
|
324
|
+
|
325
|
+
- service_name: httpd-alpha
|
326
|
+
port: 80
|
327
|
+
- service_name: httpd-beta
|
328
|
+
port: 8080
|
329
|
+
|
330
|
+
The tests in `example.rb` can now access this file:
|
331
|
+
|
332
|
+
my_services = yaml(content: inspec.profile.file('services.yml')).params
|
333
|
+
|
334
|
+
my_services.each do |s|
|
335
|
+
describe service(s['name']) do
|
336
|
+
it { should be_running }
|
337
|
+
end
|
338
|
+
|
339
|
+
describe port(s['port']) do
|
340
|
+
it { should be_listening }
|
341
|
+
end
|
342
|
+
end
|
data/docs/resources/yaml.md.erb
CHANGED
@@ -17,7 +17,7 @@ A `yaml` resource block declares the configuration data to be tested. Assume the
|
|
17
17
|
|
18
18
|
This file can be queried using:
|
19
19
|
|
20
|
-
describe yaml do
|
20
|
+
describe yaml('filename.yml') do
|
21
21
|
its('name') { should eq 'foo' }
|
22
22
|
its(['array', 1]) { should eq 'one' }
|
23
23
|
end
|
@@ -27,6 +27,20 @@ where
|
|
27
27
|
* `name` is a configuration setting in a Yaml file
|
28
28
|
* `should eq 'foo'` tests a value of `name` as read from a Yaml file versus the value declared in the test
|
29
29
|
|
30
|
+
Like the `json` resource, the `yaml` resource can read a file, run a command, or accept content inline:
|
31
|
+
|
32
|
+
describe yaml('config.yaml') do
|
33
|
+
its(['driver', 'name']) { should eq 'vagrant' }
|
34
|
+
end
|
35
|
+
|
36
|
+
describe yaml({ command: 'retrieve_data.py --yaml' }) do
|
37
|
+
its('state') { should eq 'open' }
|
38
|
+
end
|
39
|
+
|
40
|
+
describe yaml({ content: \"key1: value1\nkey2: value2\" }) do
|
41
|
+
its('key2') { should cmp 'value2' }
|
42
|
+
end
|
43
|
+
|
30
44
|
|
31
45
|
## Matchers
|
32
46
|
|
@@ -34,4 +34,4 @@ include_controls 'linux'
|
|
34
34
|
include_controls 'windows-patch-benchmark'
|
35
35
|
```
|
36
36
|
|
37
|
-
Further details are described in our [InSpec Docs](
|
37
|
+
Further details are described in our [InSpec Docs](https://www.inspec.io/docs/reference/profiles/)
|
@@ -213,7 +213,7 @@ module Habitat
|
|
213
213
|
# TODO: Would love to use Mixlib::ShellOut here, but it doesn't
|
214
214
|
# seem to preserve the STDIN tty, and docker gets angry.
|
215
215
|
Dir.chdir(work_dir) do
|
216
|
-
unless system(env, 'hab
|
216
|
+
unless system(env, 'hab pkg build .')
|
217
217
|
exit_with_error('Unable to build the Habitat artifact.')
|
218
218
|
end
|
219
219
|
end
|
@@ -299,33 +299,29 @@ module Habitat
|
|
299
299
|
pkg_name=#{package_name}
|
300
300
|
pkg_version=#{profile.version}
|
301
301
|
pkg_origin=#{habitat_origin}
|
302
|
-
|
303
|
-
pkg_deps=(chef/inspec)
|
304
|
-
pkg_build_deps=()
|
302
|
+
pkg_deps=(chef/inspec core/ruby core/hab)
|
305
303
|
pkg_svc_user=root
|
306
304
|
EOL
|
307
305
|
|
308
306
|
plan += "pkg_license='#{profile.metadata.params[:license]}'\n\n" if profile.metadata.params[:license]
|
309
307
|
|
310
308
|
plan += <<-EOL
|
311
|
-
do_download() {
|
312
|
-
return 0
|
313
|
-
}
|
314
|
-
|
315
|
-
do_verify() {
|
316
|
-
return 0
|
317
|
-
}
|
318
|
-
|
319
|
-
do_unpack() {
|
320
|
-
return 0
|
321
|
-
}
|
322
309
|
|
323
310
|
do_build() {
|
324
311
|
cp -vr $PLAN_CONTEXT/../src/* $HAB_CACHE_SRC_PATH/$pkg_dirname
|
325
312
|
}
|
326
313
|
|
327
314
|
do_install() {
|
328
|
-
|
315
|
+
local profile_contents
|
316
|
+
local excludes
|
317
|
+
profile_contents=($(ls))
|
318
|
+
excludes=(habitat results *.hart)
|
319
|
+
|
320
|
+
for item in ${excludes[@]}; do
|
321
|
+
profile_contents=(${profile_contents[@]/$item/})
|
322
|
+
done
|
323
|
+
|
324
|
+
cp -r ${profile_contents[@]} ${pkg_prefix}/dist/
|
329
325
|
}
|
330
326
|
EOL
|
331
327
|
|
@@ -336,15 +332,13 @@ do_install() {
|
|
336
332
|
<<-EOL
|
337
333
|
#!/bin/sh
|
338
334
|
|
339
|
-
export PATH=${PATH}:$(hab pkg path core/ruby)/bin
|
340
|
-
|
341
335
|
# InSpec will try to create a .cache directory in the user's home directory
|
342
336
|
# so this needs to be someplace writeable by the hab user
|
343
337
|
export HOME={{pkg.svc_var_path}}
|
344
338
|
|
345
|
-
PROFILE_IDENT="
|
339
|
+
PROFILE_IDENT="{{pkg.origin}}/{{pkg.name}}"
|
346
340
|
RESULTS_DIR="{{pkg.svc_var_path}}/inspec_results"
|
347
|
-
RESULTS_FILE="${RESULTS_DIR}
|
341
|
+
RESULTS_FILE="${RESULTS_DIR}/{{pkg.name}}.json"
|
348
342
|
ERROR_FILE="{{pkg.svc_var_path}}/inspec.err"
|
349
343
|
|
350
344
|
# Create a directory for inspec formatter output
|
@@ -352,10 +346,9 @@ mkdir -p {{pkg.svc_var_path}}/inspec_results
|
|
352
346
|
|
353
347
|
while true; do
|
354
348
|
echo "Executing InSpec for ${PROFILE_IDENT}"
|
355
|
-
hab pkg exec chef/inspec inspec exec
|
356
|
-
RC=$?
|
349
|
+
hab pkg exec chef/inspec inspec exec {{pkg.path}}/dist --format=json > ${RESULTS_FILE} 2>${ERROR_FILE}
|
357
350
|
|
358
|
-
if [
|
351
|
+
if [ $? -eq 0 ]; then
|
359
352
|
echo "InSpec run completed successfully."
|
360
353
|
elsif [ -s ${ERROR_FILE} ]
|
361
354
|
echo "InSpec run did NOT complete successfully. Error:"
|
data/lib/inspec/backend.rb
CHANGED
@@ -8,6 +8,27 @@ require 'train'
|
|
8
8
|
|
9
9
|
module Inspec
|
10
10
|
module Backend
|
11
|
+
module Base
|
12
|
+
attr_accessor :profile
|
13
|
+
|
14
|
+
# Provide a shorthand to retrieve the inspec version from within a profile
|
15
|
+
#
|
16
|
+
# @return [String] inspec version
|
17
|
+
def version
|
18
|
+
Inspec::VERSION
|
19
|
+
end
|
20
|
+
|
21
|
+
# Ruby internal for printing a nice name for this class
|
22
|
+
def to_s
|
23
|
+
'Inspec::Backend::Class'
|
24
|
+
end
|
25
|
+
|
26
|
+
# Ruby internal for pretty-printing a summary for this class
|
27
|
+
def inspect
|
28
|
+
"Inspec::Backend::Class @transport=#{backend.class}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
11
32
|
# Create the transport backend with aggregated resources.
|
12
33
|
#
|
13
34
|
# @param [Hash] config for the transport backend
|
@@ -26,22 +47,7 @@ module Inspec
|
|
26
47
|
end
|
27
48
|
|
28
49
|
cls = Class.new do
|
29
|
-
|
30
|
-
def to_s
|
31
|
-
'Inspec::Backend::Class'
|
32
|
-
end
|
33
|
-
|
34
|
-
# Ruby internal for pretty-printing a summary for this class
|
35
|
-
def inspect
|
36
|
-
"Inspec::Backend::Class @transport=#{backend.class}"
|
37
|
-
end
|
38
|
-
|
39
|
-
# Provide a shorthand to retrieve the inspec version from within a profile
|
40
|
-
#
|
41
|
-
# @return [String] inspec version
|
42
|
-
def version
|
43
|
-
Inspec::VERSION
|
44
|
-
end
|
50
|
+
include Base
|
45
51
|
|
46
52
|
define_method :backend do
|
47
53
|
connection
|
data/lib/inspec/cli.rb
CHANGED
@@ -155,6 +155,13 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
155
155
|
configure_logger(opts)
|
156
156
|
o = opts.dup
|
157
157
|
|
158
|
+
# print error if user passed --sudo but with no --target
|
159
|
+
if opts[:sudo] && opts[:target].nil?
|
160
|
+
Inspec::Log.error('--sudo is only valid when running against a remote host using --target')
|
161
|
+
Inspec::Log.error('To run InSpec locally with elevated privileges, run `sudo inspec exec ...`')
|
162
|
+
exit 1
|
163
|
+
end
|
164
|
+
|
158
165
|
# run tests
|
159
166
|
run_tests(targets, o)
|
160
167
|
rescue StandardError => e
|
@@ -0,0 +1,34 @@
|
|
1
|
+
function __fish_inspec_no_command --description 'Test if inspec has yet to be given the main command'
|
2
|
+
set -l cmd (commandline -opc)
|
3
|
+
test (count $cmd) -eq 1
|
4
|
+
end
|
5
|
+
|
6
|
+
function __fish_inspec_using_command
|
7
|
+
set -l cmd (commandline -opc)
|
8
|
+
set -q cmd[2]; and test "$argv[1]" = $cmd[2]
|
9
|
+
end
|
10
|
+
|
11
|
+
function __fish_inspec_using_command_and_no_subcommand
|
12
|
+
set -l cmd (commandline -opc)
|
13
|
+
test (count $cmd) -eq 2; and test "$argv[1]" = "$cmd[2]"
|
14
|
+
end
|
15
|
+
|
16
|
+
function __fish_inspec_using_subcommand --argument-names cmd_main cmd_sub
|
17
|
+
set -l cmd (commandline -opc)
|
18
|
+
set -q cmd[3]; and test "$cmd_main" = $cmd[2] -a "$cmd_sub" = $cmd[3]
|
19
|
+
end
|
20
|
+
|
21
|
+
<% top_level_commands_with_descriptions.each do |command_and_description| %>
|
22
|
+
<% command, description = command_and_description.split(':') %>
|
23
|
+
<% description.gsub!(/\\/, '') %>
|
24
|
+
# <%= command %> commands
|
25
|
+
complete -c inspec -f -n '__fish_inspec_no_command' -a <%= command %> -d "<%= description %>"
|
26
|
+
# <%= command %> help
|
27
|
+
complete -c inspec -f -n '__fish_inspec_using_command help' -a <%= command %> -d "<%= description %>"
|
28
|
+
|
29
|
+
<% (subcommands_with_commands_and_descriptions[command] || []).each do |command_and_description| %>
|
30
|
+
<% subcommand, description = command_and_description.split(':') %>
|
31
|
+
<% description.gsub!(/\\/, '') %>
|
32
|
+
complete -c inspec -f -n '__fish_inspec_using_command_and_no_subcommand <%= command %>' -a <%= subcommand %> -d "<%= description %>"
|
33
|
+
<% end %>
|
34
|
+
<% end %>
|
data/lib/inspec/env_printer.rb
CHANGED
@@ -5,6 +5,14 @@ require 'shellwords'
|
|
5
5
|
|
6
6
|
module Inspec
|
7
7
|
class EnvPrinter
|
8
|
+
attr_reader :shell
|
9
|
+
|
10
|
+
EVAL_COMMANDS = {
|
11
|
+
'bash' => 'eval \"$(inspec env bash)\"',
|
12
|
+
'fish' => 'inspec env fish > ~/.config/fish/completions/inspec.fish',
|
13
|
+
'zsh' => 'eval \"$(inspec env zsh)\"',
|
14
|
+
}.freeze
|
15
|
+
|
8
16
|
def initialize(command_class, shell = nil)
|
9
17
|
if !shell
|
10
18
|
@detected = true
|
@@ -56,7 +64,7 @@ module Inspec
|
|
56
64
|
puts <<EOF
|
57
65
|
# To use this, eval it in your shell
|
58
66
|
#
|
59
|
-
#
|
67
|
+
# #{EVAL_COMMANDS[shell]}
|
60
68
|
#
|
61
69
|
#
|
62
70
|
EOF
|
data/lib/inspec/profile.rb
CHANGED
@@ -13,6 +13,7 @@ require 'inspec/backend'
|
|
13
13
|
require 'inspec/rule'
|
14
14
|
require 'inspec/log'
|
15
15
|
require 'inspec/profile_context'
|
16
|
+
require 'inspec/runtime_profile'
|
16
17
|
require 'inspec/dependencies/cache'
|
17
18
|
require 'inspec/dependencies/lockfile'
|
18
19
|
require 'inspec/dependencies/dependency_set'
|
@@ -82,6 +83,7 @@ module Inspec
|
|
82
83
|
|
83
84
|
# rubocop:disable Metrics/AbcSize
|
84
85
|
def initialize(source_reader, options = {})
|
86
|
+
@source_reader = source_reader
|
85
87
|
@target = options[:target]
|
86
88
|
@logger = options[:logger] || Logger.new(nil)
|
87
89
|
@locked_dependencies = options[:dependencies]
|
@@ -91,10 +93,13 @@ module Inspec
|
|
91
93
|
@cache = options[:cache] || Cache.new
|
92
94
|
@backend = options[:backend] || Inspec::Backend.create(options.select { |k, _| k != 'target' })
|
93
95
|
@attr_values = options[:attributes]
|
94
|
-
@source_reader = source_reader
|
95
96
|
@tests_collected = false
|
96
97
|
@libraries_loaded = false
|
97
98
|
Metadata.finalize(@source_reader.metadata, @profile_id, options)
|
99
|
+
|
100
|
+
@runtime_profile = RuntimeProfile.new(self)
|
101
|
+
@backend.profile = @runtime_profile
|
102
|
+
|
98
103
|
@runner_context =
|
99
104
|
options[:profile_context] ||
|
100
105
|
Inspec::ProfileContext.for_profile(self, @backend, @attr_values)
|
@@ -531,7 +531,7 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
531
531
|
#
|
532
532
|
def print_control(control)
|
533
533
|
print_line(
|
534
|
-
color:
|
534
|
+
color: control.summary_indicator,
|
535
535
|
indicator: INDICATORS[control.summary_indicator] || INDICATORS['unknown'],
|
536
536
|
summary: format_lines(control.summary, INDICATORS['empty']),
|
537
537
|
id: "#{control.id}: ",
|
@@ -541,7 +541,6 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
541
541
|
|
542
542
|
def print_result(result)
|
543
543
|
test_status = result[:status_type]
|
544
|
-
test_color = COLORS[test_status]
|
545
544
|
indicator = INDICATORS[result[:status]]
|
546
545
|
indicator = INDICATORS['empty'] if indicator.nil?
|
547
546
|
if result[:message]
|
@@ -550,7 +549,7 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
550
549
|
msg = result[:skip_message] || result[:code_desc]
|
551
550
|
end
|
552
551
|
print_line(
|
553
|
-
color:
|
552
|
+
color: test_status,
|
554
553
|
indicator: INDICATORS['small'] + indicator,
|
555
554
|
summary: format_lines(msg, INDICATORS['empty']),
|
556
555
|
id: nil, profile: nil
|
@@ -575,7 +574,7 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
575
574
|
end
|
576
575
|
status_indicator = test[:status_type]
|
577
576
|
print_line(
|
578
|
-
color:
|
577
|
+
color: status_indicator,
|
579
578
|
indicator: INDICATORS['small'] + INDICATORS[status_indicator] || INDICATORS['unknown'],
|
580
579
|
summary: format_lines(test_result, INDICATORS['empty']),
|
581
580
|
id: control_id,
|
@@ -586,36 +585,40 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
586
585
|
|
587
586
|
def print_profile_summary
|
588
587
|
summary = profile_summary
|
588
|
+
return unless summary['total'] > 0
|
589
589
|
|
590
|
-
s = format('Profile Summary: %s
|
591
|
-
|
592
|
-
|
593
|
-
|
590
|
+
s = format('Profile Summary: %s, %s, %s',
|
591
|
+
format_with_color('passed', "#{summary['passed']} successful"),
|
592
|
+
format_with_color('failed', "#{summary['failed']['total']} failures"),
|
593
|
+
format_with_color('skipped', "#{summary['skipped']} skipped"),
|
594
|
+
)
|
594
595
|
output.puts(s) if summary['total'] > 0
|
595
596
|
end
|
596
597
|
|
597
598
|
def print_tests_summary
|
598
599
|
summary = tests_summary
|
599
600
|
|
600
|
-
s = format('Test Summary: %s
|
601
|
-
|
602
|
-
|
603
|
-
|
601
|
+
s = format('Test Summary: %s, %s, %s',
|
602
|
+
format_with_color('passed', "#{summary['passed']} successful"),
|
603
|
+
format_with_color('failed', "#{summary['failed']} failures"),
|
604
|
+
format_with_color('skipped', "#{summary['skipped']} skipped"),
|
605
|
+
)
|
606
|
+
|
604
607
|
output.puts(s)
|
605
608
|
end
|
606
609
|
|
607
610
|
# Formats the line (called from print_line)
|
608
611
|
def format_line(fields)
|
609
|
-
format = '%
|
612
|
+
format = '%indicator%id%summary'
|
610
613
|
format.gsub(/%\w+/) do |x|
|
611
614
|
term = x[1..-1]
|
612
615
|
fields.key?(term.to_sym) ? fields[term.to_sym].to_s : x
|
613
|
-
end
|
616
|
+
end
|
614
617
|
end
|
615
618
|
|
616
619
|
# Prints line; used to print results
|
617
620
|
def print_line(fields)
|
618
|
-
output.puts(format_line(fields))
|
621
|
+
output.puts(format_with_color(fields[:color], format_line(fields)))
|
619
622
|
end
|
620
623
|
|
621
624
|
# Helps formatting summary lines (called from within print_line arguments)
|
@@ -623,6 +626,13 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
|
|
623
626
|
lines.gsub(/\n/, "\n" + indentation)
|
624
627
|
end
|
625
628
|
|
629
|
+
def format_with_color(color_name, text)
|
630
|
+
return text unless RSpec.configuration.color
|
631
|
+
return text unless COLORS.key?(color_name)
|
632
|
+
|
633
|
+
"#{COLORS[color_name]}#{text}#{COLORS['reset']}"
|
634
|
+
end
|
635
|
+
|
626
636
|
#
|
627
637
|
# This class wraps a control hash object to provide a useful inteface for
|
628
638
|
# maintaining the associated profile, ids, results, title, etc.
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# Copyright 2017 Chef Software
|
3
|
+
# author: Dominik Richter
|
4
|
+
# author: Christoph Hartmann
|
5
|
+
|
6
|
+
module Inspec
|
7
|
+
class RuntimeProfile
|
8
|
+
attr_reader :files
|
9
|
+
|
10
|
+
def initialize(profile)
|
11
|
+
@src = profile.source_reader
|
12
|
+
@files = @src.data_files.keys.map do |k|
|
13
|
+
k.sub('files' + File::SEPARATOR, '')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Retrieve a profile file's contents
|
18
|
+
#
|
19
|
+
# @param name [String] the name of the file
|
20
|
+
# @return [String] contents of the file of RuntimeError if missing
|
21
|
+
def file(name)
|
22
|
+
@src.data_files[File.join('files', name)] ||
|
23
|
+
raise("Cannot find file #{name} in profile.")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/inspec/shell.rb
CHANGED
@@ -146,7 +146,7 @@ EOF
|
|
146
146
|
|
147
147
|
#{mark 'Web Reference:'}
|
148
148
|
|
149
|
-
|
149
|
+
https://www.inspec.io/docs/reference/resources/#{topic}
|
150
150
|
|
151
151
|
EOF
|
152
152
|
else
|
@@ -212,7 +212,7 @@ regular expression.
|
|
212
212
|
|
213
213
|
its('content') { should_not match /^MyKey:\\s+some value/ }
|
214
214
|
|
215
|
-
For more examples, see:
|
215
|
+
For more examples, see: https://www.inspec.io/docs/reference/matchers/
|
216
216
|
|
217
217
|
EOL
|
218
218
|
end
|
data/lib/inspec/version.rb
CHANGED
data/lib/matchers/matchers.rb
CHANGED
@@ -70,7 +70,7 @@ end
|
|
70
70
|
# matcher to check /etc/passwd, /etc/shadow and /etc/group
|
71
71
|
RSpec::Matchers.define :contain_legacy_plus do
|
72
72
|
match do |file|
|
73
|
-
warn '[DEPRECATION] `contain_legacy_plus` is deprecated and will be removed
|
73
|
+
warn '[DEPRECATION] `contain_legacy_plus` is deprecated and will be removed in the next major version. Please use `describe file(\'/etc/passwd\') do its(\'content\') { should_not match /^\+:/ } end`'
|
74
74
|
file.content =~ /^\+:/
|
75
75
|
end
|
76
76
|
end
|
@@ -78,7 +78,7 @@ end
|
|
78
78
|
# verifies that no entry in an array contains a value
|
79
79
|
RSpec::Matchers.define :contain_match do |regex|
|
80
80
|
match do |arr|
|
81
|
-
warn '[DEPRECATION] `contain_match` is deprecated and will be removed
|
81
|
+
warn '[DEPRECATION] `contain_match` is deprecated and will be removed in the next major version. See https://github.com/chef/inspec/issues/738 for more details'
|
82
82
|
arr.inject { |result, i|
|
83
83
|
result = i.match(regex)
|
84
84
|
result || i.match(/$/)
|
@@ -88,7 +88,7 @@ end
|
|
88
88
|
|
89
89
|
RSpec::Matchers.define :contain_duplicates do
|
90
90
|
match do |arr|
|
91
|
-
warn '[DEPRECATION] `contain_duplicates` is deprecated and will be removed
|
91
|
+
warn '[DEPRECATION] `contain_duplicates` is deprecated and will be removed in the next major version. See https://github.com/chef/inspec/issues/738 for more details'
|
92
92
|
dup = arr.select { |element| arr.count(element) > 1 }
|
93
93
|
!dup.uniq.empty?
|
94
94
|
end
|
data/lib/resources/passwd.rb
CHANGED
@@ -62,17 +62,17 @@ module Inspec::Resources
|
|
62
62
|
.add(:shells, field: 'shell')
|
63
63
|
|
64
64
|
filter.add(:count) { |t, _|
|
65
|
-
warn '[DEPRECATION] `passwd.count` is deprecated. Please use `passwd.entries.length` instead. It will be removed in version
|
65
|
+
warn '[DEPRECATION] `passwd.count` is deprecated. Please use `passwd.entries.length` instead. It will be removed in the next major version.'
|
66
66
|
t.entries.length
|
67
67
|
}
|
68
68
|
|
69
69
|
filter.add(:usernames) { |t, x|
|
70
|
-
warn '[DEPRECATION] `passwd.usernames` is deprecated. Please use `passwd.users` instead. It will be removed in version
|
70
|
+
warn '[DEPRECATION] `passwd.usernames` is deprecated. Please use `passwd.users` instead. It will be removed in the next major version.'
|
71
71
|
t.users(x)
|
72
72
|
}
|
73
73
|
|
74
74
|
filter.add(:username) { |t, x|
|
75
|
-
warn '[DEPRECATION] `passwd.username` is deprecated. Please use `passwd.users` instead. It will be removed in version
|
75
|
+
warn '[DEPRECATION] `passwd.username` is deprecated. Please use `passwd.users` instead. It will be removed in the next major version.'
|
76
76
|
t.users(x)[0]
|
77
77
|
}
|
78
78
|
|
@@ -84,7 +84,7 @@ module Inspec::Resources
|
|
84
84
|
}
|
85
85
|
|
86
86
|
def uid(x)
|
87
|
-
warn '[DEPRECATION] `passwd.uid(arg)` is deprecated. Please use `passwd.uids(arg)` instead. It will be removed in version
|
87
|
+
warn '[DEPRECATION] `passwd.uid(arg)` is deprecated. Please use `passwd.uids(arg)` instead. It will be removed in the next major version.'
|
88
88
|
uids(x)
|
89
89
|
end
|
90
90
|
|
data/lib/resources/xinetd.rb
CHANGED
data/lib/resources/yaml.rb
CHANGED
@@ -14,8 +14,16 @@ module Inspec::Resources
|
|
14
14
|
name 'yaml'
|
15
15
|
desc 'Use the yaml InSpec audit resource to test configuration data in a YAML file.'
|
16
16
|
example "
|
17
|
-
describe yaml do
|
18
|
-
its('name') { should eq '
|
17
|
+
describe yaml('config.yaml') do
|
18
|
+
its(['driver', 'name']) { should eq 'vagrant' }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe yaml({ command: 'retrieve_data.py --yaml' }) do
|
22
|
+
its('state') { should eq 'open' }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe yaml({ content: \"key1: value1\nkey2: value2\" }) do
|
26
|
+
its('key2') { should cmp 'value2' }
|
19
27
|
end
|
20
28
|
"
|
21
29
|
|
data/lib/source_readers/flat.rb
CHANGED
@@ -20,13 +20,14 @@ module SourceReaders
|
|
20
20
|
new(target, files)
|
21
21
|
end
|
22
22
|
|
23
|
-
attr_reader :metadata, :tests, :libraries
|
23
|
+
attr_reader :metadata, :tests, :libraries, :data_files
|
24
24
|
|
25
25
|
def initialize(target, files)
|
26
26
|
@target = target
|
27
27
|
@metadata = ::Inspec::Metadata.new(nil)
|
28
28
|
@tests = load_tests(files)
|
29
29
|
@libraries = {}
|
30
|
+
@data_files = {}
|
30
31
|
end
|
31
32
|
|
32
33
|
private
|
@@ -23,17 +23,18 @@ module SourceReaders
|
|
23
23
|
nil
|
24
24
|
end
|
25
25
|
|
26
|
-
attr_reader :metadata, :tests, :libraries
|
26
|
+
attr_reader :metadata, :tests, :libraries, :data_files
|
27
27
|
|
28
28
|
# This create a new instance of an InSpec profile source reader
|
29
29
|
#
|
30
30
|
# @param [FileProvider] target An instance of a FileProvider object that can list files and read them
|
31
31
|
# @param [String] metadata_source eg. inspec.yml or metadata.rb
|
32
32
|
def initialize(target, metadata_source)
|
33
|
-
@target
|
34
|
-
@metadata
|
35
|
-
@tests
|
36
|
-
@libraries
|
33
|
+
@target = target
|
34
|
+
@metadata = load_metadata(metadata_source)
|
35
|
+
@tests = load_tests
|
36
|
+
@libraries = load_libs
|
37
|
+
@data_files = load_data_files
|
37
38
|
end
|
38
39
|
|
39
40
|
private
|
@@ -62,5 +63,12 @@ module SourceReaders
|
|
62
63
|
end
|
63
64
|
Hash[tests.map { |x| [x, @target.read(x)] }]
|
64
65
|
end
|
66
|
+
|
67
|
+
def load_data_files
|
68
|
+
files = @target.files.find_all do |path|
|
69
|
+
path.start_with?('files' + File::SEPARATOR)
|
70
|
+
end
|
71
|
+
Hash[files.map { |x| [x, @target.read(x)] }]
|
72
|
+
end
|
65
73
|
end
|
66
74
|
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: 1.
|
4
|
+
version: 1.23.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: 2017-04
|
11
|
+
date: 2017-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: train
|
@@ -461,6 +461,7 @@ files:
|
|
461
461
|
- lib/inspec/cached_fetcher.rb
|
462
462
|
- lib/inspec/cli.rb
|
463
463
|
- lib/inspec/completions/bash.sh.erb
|
464
|
+
- lib/inspec/completions/fish.sh.erb
|
464
465
|
- lib/inspec/completions/zsh.sh.erb
|
465
466
|
- lib/inspec/control_eval_context.rb
|
466
467
|
- lib/inspec/dependencies/cache.rb
|
@@ -506,6 +507,7 @@ files:
|
|
506
507
|
- lib/inspec/runner.rb
|
507
508
|
- lib/inspec/runner_mock.rb
|
508
509
|
- lib/inspec/runner_rspec.rb
|
510
|
+
- lib/inspec/runtime_profile.rb
|
509
511
|
- lib/inspec/schema.rb
|
510
512
|
- lib/inspec/secrets.rb
|
511
513
|
- lib/inspec/secrets/yaml.rb
|