Merge remote-tracking branch 'origin/master' into apache_conf-symlinks

This commit is contained in:
Carl Johnston 2017-02-24 16:07:02 +11:00
commit efa1b951ab
183 changed files with 8798 additions and 14992 deletions

4
.gitignore vendored
View file

@ -19,3 +19,7 @@ habitat/VERSION
habitat/results
/.ruby-gemset
/.ruby-version
www/source/index.html.slim
www/source/index.html.slim

View file

@ -1,7 +1,108 @@
# Change Log
## [1.9.0](https://github.com/chef/inspec/tree/1.9.0) (2017-01-06)
[Full Changelog](https://github.com/chef/inspec/compare/v1.8.0...1.9.0)
## [1.14.1](https://github.com/chef/inspec/tree/1.14.1) (2017-02-10)
[Full Changelog](https://github.com/chef/inspec/compare/v1.14.0...1.14.1)
**Closed issues:**
- go /profiles service modifications [\#1483](https://github.com/chef/inspec/issues/1483)
- inspec compliance login\* should support a hostname for the SERVER argument [\#1473](https://github.com/chef/inspec/issues/1473)
**Merged pull requests:**
- Skip packages resource for unsupported OS [\#1484](https://github.com/chef/inspec/pull/1484) ([alexpop](https://github.com/alexpop))
- add Alex Pop to the list of maintainers [\#1481](https://github.com/chef/inspec/pull/1481) ([arlimus](https://github.com/arlimus))
- remove Jason Reed from the list of maintainers [\#1480](https://github.com/chef/inspec/pull/1480) ([arlimus](https://github.com/arlimus))
- Add Adam Leff as a maintainer [\#1479](https://github.com/chef/inspec/pull/1479) ([adamleff](https://github.com/adamleff))
## [v1.14.0](https://github.com/chef/inspec/tree/v1.14.0) (2017-02-08)
[Full Changelog](https://github.com/chef/inspec/compare/v1.13.0...v1.14.0)
**Fixed bugs:**
- map url to https for compliance plugin [\#1471](https://github.com/chef/inspec/pull/1471) ([arlimus](https://github.com/arlimus))
**Closed issues:**
- Display meaningful error message when uploading profiles to a server with self-signed certs [\#1469](https://github.com/chef/inspec/issues/1469)
**Merged pull requests:**
- Use RuboCop 0.39.0 \(same as chefstyle\) [\#1478](https://github.com/chef/inspec/pull/1478) ([tduffield](https://github.com/tduffield))
- bugfix: warn users about insecure login requirements [\#1472](https://github.com/chef/inspec/pull/1472) ([arlimus](https://github.com/arlimus))
- Add support for "inspec -v" showing the version [\#1470](https://github.com/chef/inspec/pull/1470) ([adamleff](https://github.com/adamleff))
- Replace slack invite form on Community, fix surprise code example [\#1468](https://github.com/chef/inspec/pull/1468) ([adamleff](https://github.com/adamleff))
## [v1.13.0](https://github.com/chef/inspec/tree/v1.13.0) (2017-02-07)
[Full Changelog](https://github.com/chef/inspec/compare/v1.12.0...v1.13.0)
**Implemented enhancements:**
- add "packages" resource [\#1458](https://github.com/chef/inspec/pull/1458) ([jtimberman](https://github.com/jtimberman))
- Provide a way to force it vs its for any argument [\#1457](https://github.com/chef/inspec/pull/1457) ([alexpop](https://github.com/alexpop))
**Closed issues:**
- Ignore me [\#1464](https://github.com/chef/inspec/issues/1464)
- redirect URL downloads.inspec.io to https://downloads.chef.io/inspec [\#1462](https://github.com/chef/inspec/issues/1462)
## [v1.12.0](https://github.com/chef/inspec/tree/v1.12.0) (2017-02-03)
[Full Changelog](https://github.com/chef/inspec/compare/v1.11.0...v1.12.0)
**Implemented enhancements:**
- Allow setting of the tests array [\#1455](https://github.com/chef/inspec/pull/1455) ([alexpop](https://github.com/alexpop))
- switch to faraday as http backend [\#1452](https://github.com/chef/inspec/pull/1452) ([chris-rock](https://github.com/chris-rock))
- Add FilterTable support to processes resource [\#1451](https://github.com/chef/inspec/pull/1451) ([alexpop](https://github.com/alexpop))
**Closed issues:**
- `skip` parameter ignored inside `describe` block [\#1450](https://github.com/chef/inspec/issues/1450)
## [v1.11.0](https://github.com/chef/inspec/tree/v1.11.0) (2017-02-01)
[Full Changelog](https://github.com/chef/inspec/compare/v1.10.0...v1.11.0)
**Implemented enhancements:**
- HTTP request resource [\#336](https://github.com/chef/inspec/issues/336)
- derive xinetd protocol from socket\_type when not defined in the config file [\#1448](https://github.com/chef/inspec/pull/1448) ([alexpop](https://github.com/alexpop))
- Add negate! support for describe.one object [\#1442](https://github.com/chef/inspec/pull/1442) ([alexpop](https://github.com/alexpop))
- Version method for kernel\_module [\#1435](https://github.com/chef/inspec/pull/1435) ([postgred](https://github.com/postgred))
**Fixed bugs:**
- Fix xinetd parsing of services from the same file. Expose resource.protocols [\#1444](https://github.com/chef/inspec/pull/1444) ([alexpop](https://github.com/alexpop))
**Merged pull requests:**
- Make minor grammar/style changes to `inspec.io` [\#1441](https://github.com/chef/inspec/pull/1441) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
## [v1.10.0](https://github.com/chef/inspec/tree/v1.10.0) (2017-01-26)
[Full Changelog](https://github.com/chef/inspec/compare/v1.9.0...v1.10.0)
**Closed issues:**
- fix functional tests [\#1429](https://github.com/chef/inspec/issues/1429)
**Merged pull requests:**
- 1.10.0 [\#1433](https://github.com/chef/inspec/pull/1433) ([chris-rock](https://github.com/chris-rock))
- improve http header handling [\#1432](https://github.com/chef/inspec/pull/1432) ([chris-rock](https://github.com/chris-rock))
- use new devsec baseline [\#1431](https://github.com/chef/inspec/pull/1431) ([chris-rock](https://github.com/chris-rock))
- 'execution' is spelled correctly [\#1428](https://github.com/chef/inspec/pull/1428) ([nathenharvey](https://github.com/nathenharvey))
- Bug fixes + New Elements [\#1426](https://github.com/chef/inspec/pull/1426) ([hannah-radish](https://github.com/hannah-radish))
- Docs: fix resource name \('processes' instead of 'process'\) [\#1423](https://github.com/chef/inspec/pull/1423) ([techraf](https://github.com/techraf))
- update copyright of the year [\#1422](https://github.com/chef/inspec/pull/1422) ([chris-rock](https://github.com/chris-rock))
- Link to the 1.0 release webinar [\#1419](https://github.com/chef/inspec/pull/1419) ([nathenharvey](https://github.com/nathenharvey))
- Updated compliance api requests to actually use refresh token correctly [\#1416](https://github.com/chef/inspec/pull/1416) ([brentm5](https://github.com/brentm5))
- Docs examples: use double quotes to prevent escaping backslash in the expected string [\#1413](https://github.com/chef/inspec/pull/1413) ([techraf](https://github.com/techraf))
- Fixed error in OS docs, added CentOS to redhat family docs. [\#1407](https://github.com/chef/inspec/pull/1407) ([gscho](https://github.com/gscho))
- Solicit talks for ChefConf [\#1405](https://github.com/chef/inspec/pull/1405) ([nathenharvey](https://github.com/nathenharvey))
- Add an http test method [\#1403](https://github.com/chef/inspec/pull/1403) ([guilhem](https://github.com/guilhem))
- new inspec.io frontpage [\#1362](https://github.com/chef/inspec/pull/1362) ([hannah-radish](https://github.com/hannah-radish))
## [v1.9.0](https://github.com/chef/inspec/tree/v1.9.0) (2017-01-06)
[Full Changelog](https://github.com/chef/inspec/compare/v1.8.0...v1.9.0)
**Implemented enhancements:**
@ -195,7 +296,6 @@
- Add file integration tests for docker [\#1277](https://github.com/chef/inspec/issues/1277)
- Solaris Sudo Not Always In /usr/bin/sudo [\#1265](https://github.com/chef/inspec/issues/1265)
- Link to robert\_config.rb is broken on inspec.io [\#1226](https://github.com/chef/inspec/issues/1226)
**Merged pull requests:**
@ -2001,19 +2101,10 @@
**Implemented enhancements:**
- pretty-print resources [\#78](https://github.com/chef/inspec/issues/78)
- Add networking resources [\#68](https://github.com/chef/inspec/issues/68)
- Add WinRM transport layer [\#64](https://github.com/chef/inspec/issues/64)
**Fixed bugs:**
- expose all necessary methods in OS resource [\#79](https://github.com/chef/inspec/issues/79)
**Closed issues:**
- script resource [\#74](https://github.com/chef/inspec/issues/74)
- add project docs [\#72](https://github.com/chef/inspec/issues/72)
- OS detection on debian does not detect versions [\#39](https://github.com/chef/inspec/issues/39)
- ensure all resources have a proper to\_s method [\#98](https://github.com/chef/inspec/issues/98)
- Escape commands before we execute them [\#70](https://github.com/chef/inspec/issues/70)
@ -2040,90 +2131,6 @@
- Improve unit tests [\#106](https://github.com/chef/inspec/pull/106) ([chris-rock](https://github.com/chris-rock))
- add to\_s methods to resources, fixes \#98 [\#105](https://github.com/chef/inspec/pull/105) ([chris-rock](https://github.com/chris-rock))
- 0.7.0 release [\#104](https://github.com/chef/inspec/pull/104) ([chris-rock](https://github.com/chris-rock))
- implement iptables resource [\#103](https://github.com/chef/inspec/pull/103) ([chris-rock](https://github.com/chris-rock))
- bugfix: return function if data is already cached [\#102](https://github.com/chef/inspec/pull/102) ([chris-rock](https://github.com/chris-rock))
- implement apt resource [\#101](https://github.com/chef/inspec/pull/101) ([chris-rock](https://github.com/chris-rock))
- improve shell [\#100](https://github.com/chef/inspec/pull/100) ([chris-rock](https://github.com/chris-rock))
- implement host resource [\#99](https://github.com/chef/inspec/pull/99) ([chris-rock](https://github.com/chris-rock))
- implement bridge resource [\#97](https://github.com/chef/inspec/pull/97) ([chris-rock](https://github.com/chris-rock))
- interactive shell [\#95](https://github.com/chef/inspec/pull/95) ([arlimus](https://github.com/arlimus))
- interface resource [\#94](https://github.com/chef/inspec/pull/94) ([chris-rock](https://github.com/chris-rock))
- lint: dont use undefined vars [\#93](https://github.com/chef/inspec/pull/93) ([arlimus](https://github.com/arlimus))
- fix delivery dependencies [\#92](https://github.com/chef/inspec/pull/92) ([arlimus](https://github.com/arlimus))
- improvement: add default print method to resources [\#91](https://github.com/chef/inspec/pull/91) ([arlimus](https://github.com/arlimus))
- extend os backend helper [\#90](https://github.com/chef/inspec/pull/90) ([chris-rock](https://github.com/chris-rock))
- integrate docs [\#89](https://github.com/chef/inspec/pull/89) ([chris-rock](https://github.com/chris-rock))
- integrate docs [\#88](https://github.com/chef/inspec/pull/88) ([chris-rock](https://github.com/chris-rock))
- script resource [\#87](https://github.com/chef/inspec/pull/87) ([chris-rock](https://github.com/chris-rock))
- implement group resource [\#85](https://github.com/chef/inspec/pull/85) ([chris-rock](https://github.com/chris-rock))
- add author header [\#84](https://github.com/chef/inspec/pull/84) ([chris-rock](https://github.com/chris-rock))
- Resource bugfix [\#83](https://github.com/chef/inspec/pull/83) ([arlimus](https://github.com/arlimus))
- Resource in resource [\#80](https://github.com/chef/inspec/pull/80) ([arlimus](https://github.com/arlimus))
- ignore local delivery config [\#77](https://github.com/chef/inspec/pull/77) ([arlimus](https://github.com/arlimus))
- bugfix user resource for windows [\#76](https://github.com/chef/inspec/pull/76) ([chris-rock](https://github.com/chris-rock))
- activate lint in travis [\#75](https://github.com/chef/inspec/pull/75) ([arlimus](https://github.com/arlimus))
- Simplify SSL configuration [\#69](https://github.com/chef/inspec/pull/69) ([arlimus](https://github.com/arlimus))
- implement user resource [\#67](https://github.com/chef/inspec/pull/67) ([chris-rock](https://github.com/chris-rock))
- switch from open4 -\> mixlib-shellout [\#66](https://github.com/chef/inspec/pull/66) ([arlimus](https://github.com/arlimus))
- WinRM path [\#63](https://github.com/chef/inspec/pull/63) ([arlimus](https://github.com/arlimus))
- bugfix: catch cases where oneget returns an array [\#62](https://github.com/chef/inspec/pull/62) ([chris-rock](https://github.com/chris-rock))
- extend delivery tests to extra docker images [\#61](https://github.com/chef/inspec/pull/61) ([arlimus](https://github.com/arlimus))
- rename --key-file to --key on cli [\#60](https://github.com/chef/inspec/pull/60) ([arlimus](https://github.com/arlimus))
- Simpleconfig groups [\#57](https://github.com/chef/inspec/pull/57) ([arlimus](https://github.com/arlimus))
- OS detection tests [\#56](https://github.com/chef/inspec/pull/56) ([arlimus](https://github.com/arlimus))
- Start Linting remaining resources [\#55](https://github.com/chef/inspec/pull/55) ([arlimus](https://github.com/arlimus))
- fix various robocop lint issues [\#54](https://github.com/chef/inspec/pull/54) ([chris-rock](https://github.com/chris-rock))
- overhaul rule structure [\#53](https://github.com/chef/inspec/pull/53) ([arlimus](https://github.com/arlimus))
- Verify ssh transport backend [\#51](https://github.com/chef/inspec/pull/51) ([arlimus](https://github.com/arlimus))
- Unit test for service resource [\#50](https://github.com/chef/inspec/pull/50) ([chris-rock](https://github.com/chris-rock))
- Ssh backend tests [\#49](https://github.com/chef/inspec/pull/49) ([arlimus](https://github.com/arlimus))
- Docker concurrency [\#48](https://github.com/chef/inspec/pull/48) ([arlimus](https://github.com/arlimus))
- unit tests for package resource [\#47](https://github.com/chef/inspec/pull/47) ([chris-rock](https://github.com/chris-rock))
- Docker runner test [\#46](https://github.com/chef/inspec/pull/46) ([arlimus](https://github.com/arlimus))
- add port resource [\#45](https://github.com/chef/inspec/pull/45) ([chris-rock](https://github.com/chris-rock))
- bugfix: windows server 2008 detection [\#44](https://github.com/chef/inspec/pull/44) ([arlimus](https://github.com/arlimus))
- Add detect command [\#43](https://github.com/chef/inspec/pull/43) ([arlimus](https://github.com/arlimus))
- unit test mock os [\#42](https://github.com/chef/inspec/pull/42) ([chris-rock](https://github.com/chris-rock))
- let travis do dockerized resource tests [\#41](https://github.com/chef/inspec/pull/41) ([arlimus](https://github.com/arlimus))
- docker test run [\#40](https://github.com/chef/inspec/pull/40) ([arlimus](https://github.com/arlimus))
- bugfix: detect os via unames [\#38](https://github.com/chef/inspec/pull/38) ([arlimus](https://github.com/arlimus))
- run kitchen test instead of converge [\#37](https://github.com/chef/inspec/pull/37) ([arlimus](https://github.com/arlimus))
- bugfix: local file owner [\#36](https://github.com/chef/inspec/pull/36) ([arlimus](https://github.com/arlimus))
- bugfix: backend description for local + docker [\#35](https://github.com/chef/inspec/pull/35) ([arlimus](https://github.com/arlimus))
- implement fake os method for mock backend \(for now\) [\#34](https://github.com/chef/inspec/pull/34) ([chris-rock](https://github.com/chris-rock))
- add Windows feature resource [\#33](https://github.com/chef/inspec/pull/33) ([chris-rock](https://github.com/chris-rock))
- add linux kernel resources [\#32](https://github.com/chef/inspec/pull/32) ([chris-rock](https://github.com/chris-rock))
- Exist vs exists [\#31](https://github.com/chef/inspec/pull/31) ([arlimus](https://github.com/arlimus))
- File formats [\#30](https://github.com/chef/inspec/pull/30) ([chris-rock](https://github.com/chris-rock))
- OS detection and resource [\#29](https://github.com/chef/inspec/pull/29) ([arlimus](https://github.com/arlimus))
- bugfix: fix simplified runner configuration [\#28](https://github.com/chef/inspec/pull/28) ([chris-rock](https://github.com/chris-rock))
- improvement: simplify runner configuration [\#27](https://github.com/chef/inspec/pull/27) ([arlimus](https://github.com/arlimus))
- bugfix: catch cases, where no service is available [\#26](https://github.com/chef/inspec/pull/26) ([chris-rock](https://github.com/chris-rock))
- support package for windows [\#25](https://github.com/chef/inspec/pull/25) ([chris-rock](https://github.com/chris-rock))
- implement service for FreeBSD [\#24](https://github.com/chef/inspec/pull/24) ([chris-rock](https://github.com/chris-rock))
- move integration dependencies to Gemfile [\#23](https://github.com/chef/inspec/pull/23) ([chris-rock](https://github.com/chris-rock))
- add oracle linux docker tests [\#22](https://github.com/chef/inspec/pull/22) ([arlimus](https://github.com/arlimus))
- Support FreeBSD [\#21](https://github.com/chef/inspec/pull/21) ([arlimus](https://github.com/arlimus))
- Service resource [\#20](https://github.com/chef/inspec/pull/20) ([chris-rock](https://github.com/chris-rock))
- Improvements [\#19](https://github.com/chef/inspec/pull/19) ([chris-rock](https://github.com/chris-rock))
- bugfix: set host for ssh config in specinfra [\#18](https://github.com/chef/inspec/pull/18) ([chris-rock](https://github.com/chris-rock))
- improve readme [\#17](https://github.com/chef/inspec/pull/17) ([chris-rock](https://github.com/chris-rock))
- Integration tests for the backend runner [\#16](https://github.com/chef/inspec/pull/16) ([arlimus](https://github.com/arlimus))
- Fix specinfra OS detection [\#15](https://github.com/chef/inspec/pull/15) ([arlimus](https://github.com/arlimus))
- Os detection [\#14](https://github.com/chef/inspec/pull/14) ([chris-rock](https://github.com/chris-rock))
- bugfix: require specinfra backend [\#13](https://github.com/chef/inspec/pull/13) ([chris-rock](https://github.com/chris-rock))
- improve docker test runner structure [\#12](https://github.com/chef/inspec/pull/12) ([arlimus](https://github.com/arlimus))
- Concurrent integrationtest [\#11](https://github.com/chef/inspec/pull/11) ([arlimus](https://github.com/arlimus))
- add oneget resource [\#10](https://github.com/chef/inspec/pull/10) ([chris-rock](https://github.com/chris-rock))
- Winrm [\#9](https://github.com/chef/inspec/pull/9) ([chris-rock](https://github.com/chris-rock))
- bugfix: linux file stat parameters and mount [\#8](https://github.com/chef/inspec/pull/8) ([arlimus](https://github.com/arlimus))
- Mysql conf [\#7](https://github.com/chef/inspec/pull/7) ([arlimus](https://github.com/arlimus))
- Lint update [\#6](https://github.com/chef/inspec/pull/6) ([arlimus](https://github.com/arlimus))
- SSH PTY [\#5](https://github.com/chef/inspec/pull/5) ([arlimus](https://github.com/arlimus))
- Start Docker + SSH backends [\#4](https://github.com/chef/inspec/pull/4) ([arlimus](https://github.com/arlimus))
- travis checks [\#3](https://github.com/chef/inspec/pull/3) ([chris-rock](https://github.com/chris-rock))
- Package [\#2](https://github.com/chef/inspec/pull/2) ([chris-rock](https://github.com/chris-rock))
- shared linux file handling + specinfra config + cleanup [\#1](https://github.com/chef/inspec/pull/1) ([arlimus](https://github.com/arlimus))

View file

@ -14,12 +14,13 @@ group :test do
gem 'bundler', '~> 1.5'
gem 'minitest', '~> 5.5'
gem 'rake', '~> 10'
gem 'rubocop', '~> 0.36.0'
gem 'rubocop', '= 0.39.0'
gem 'simplecov', '~> 0.10'
gem 'concurrent-ruby', '~> 0.9'
gem 'mocha', '~> 1.1'
gem 'ruby-progressbar', '~> 1.8'
gem 'nokogiri', '~> 1.6'
gem 'webmock', '~> 2.3.2'
end
group :integration do

View file

@ -27,4 +27,5 @@ To mention the team, use @chef/inspec-maintainers
### Maintainers
* [Christoph Hartmann](https://github.com/chris-rock)
* [Jason Reed](https://github.com/jcreedcmu)
* [Adam Leff](https://github.com/adamleff)
* [Alex Pop](https://github.com/alexpop)

View file

@ -25,7 +25,8 @@ project lead.
maintainers = [
"chris-rock",
"jcreedcmu"
"adamleff",
"alexpop"
]
[people]
@ -37,6 +38,10 @@ project lead.
Name = "Christoph Hartmann"
GitHub = "chris-rock"
[people.jcreedcmu]
Name = "Jason Reed"
GitHub = "jcreedcmu"
[people.adamleff]
Name = "Adam Leff"
GitHub = "adamleff"
[people.alexpop]
Name = "Alex Pop"
GitHub = "alexpop"

View file

@ -87,7 +87,7 @@ The following examples show how to use this InSpec audit resource.
### Test standard output (stdout)
describe command('echo hello') do
its('stdout') { should eq 'hello\n' }
its('stdout') { should eq "hello\n" }
its('stderr') { should eq '' }
its('exit_status') { should eq 0 }
end
@ -96,7 +96,7 @@ The following examples show how to use this InSpec audit resource.
describe command('>&2 echo error') do
its('stdout') { should eq '' }
its('stderr') { should eq 'error\n' }
its('stderr') { should eq "error\n" }
its('exit_status') { should eq 0 }
end

View file

@ -0,0 +1,62 @@
---
title: About the crontab Resource
---
# crontab
Use the `crontab` InSpec audit resource to test the crontab entries for a particular user on the system.
## Syntax
A `crontab` resource block declares a user (which defaults to the current user, if not specified), and then the details to be tested, such as the schedule elements for each crontab entry or the commands itself:
describe crontab do
its('commands') { should include '/some/scheduled/task.sh' }
end
## Matchers
This InSpec audit resource has the following matchers:
### be
<%= partial "/shared/matcher_be" %>
### cmp
<%= partial "/shared/matcher_cmp" %>
### eq
<%= partial "/shared/matcher_eq" %>
### include
<%= partial "/shared/matcher_include" %>
### match
<%= partial "/shared/matcher_match" %>
## Examples
The following examples show how to use this InSpec audit resource.
### Test that root's crontab has a particular command
describe crontab('root') do
its('commands') { should include '/path/to/some/script' }
end
### Test that myuser's crontab entry for command '/home/myuser/build.sh' runs every minute
describe crontab('myuser').commands('/home/myuser/build.sh') do
its('hours') { should cmp '*' }
its('minutes') { should cmp '*' }
end
### Test that the logged-in user's crontab has no tasks set to run on every hour and every minute
describe crontab.where({'hour' => '*', 'minute' => '*'}) do
its('entries.length') { should cmp '0' }
end

View file

@ -0,0 +1,97 @@
---
title: About the http Resource
---
# http
Use the `http` InSpec audit resource to test an http endpoint.
## Syntax
An `http` resource block declares the configuration settings to be tested:
describe http('url', auth: {user: 'user', pass: 'test'}, params: {params}, method: 'method', headers: {headers}, body: body) do
its('status') { should eq number }
its('body') { should eq 'body' }
its('headers.name') { should eq 'header' }
end
where
* `('url')` is the url to test
* `{user: 'user', pass: 'test'}` may be specified for basic auth request
* `{params}` may be specified for http request parameters
* `'method'` may be specified for http request method (default to 'GET')
* `{headers}` may be specified for http request headers
* `body` may be specified for http request body
## Matchers
This InSpec audit resource has the following matchers:
### be
<%= partial "/shared/matcher_be" %>
### body
The `body` matcher tests body content of http response:
its('body') { should eq 'hello\n' }
### cmp
<%= partial "/shared/matcher_cmp" %>
### eq
<%= partial "/shared/matcher_eq" %>
### headers
The `headers` matcher returns an hash of all http headers:
its('headers') { should eq {} }
Individual headers can be tested via:
its('headers.Content-Type') { should cmp 'text/html' }
### include
<%= partial "/shared/matcher_include" %>
### match
<%= partial "/shared/matcher_match" %>
### status
The `status` matcher tests status of the http response:
its('status') { should eq 200 }
## Examples
The following examples show how to use this InSpec audit resource.
### Simple http test
For example, a service is listening on default http port can be tested like this:
describe http('http://localhost') do
its('status') { should cmp 200 }
end
### Complex http test
describe http('http://localhost:8080/ping',
auth: {user: 'user', pass: 'test'},
params: {format: 'html'},
method: 'POST',
headers: {'Content-Type' => 'application/json'},
data: '{"data":{"a":"1","b":"five"}}') do
its('status') { should cmp 200 }
its('body') { should cmp 'pong' }
its('headers.Content-Type') { should cmp 'text/html' }
end

View file

@ -49,6 +49,12 @@ The `be_loaded` matcher tests if the module is a loadable kernel module:
<%= partial "/shared/matcher_match" %>
### version
The `version` matcher tests if the named module version is on the system:
its(:version) { should eq '3.2.2' }
## Examples
The following examples show how to use this InSpec audit resource.
@ -57,4 +63,5 @@ The following examples show how to use this InSpec audit resource.
describe kernel_module('bridge') do
it { should be_loaded }
its(:version) { should cmp >= '2.2.2' }
end

View file

@ -56,7 +56,7 @@ The `os` audit resource includes a collection of helpers that enable more granul
* `debian?`
* `hpux?`
* `linux?` (including Alpine Linux, Amazon Linux, ArchLinux, CoreOS, Exherbo, Fedora, Gentoo, and Slackware)
* `redhat?`
* `redhat?` (including CentOS)
* `solaris?` (including Nexenta Core, OmniOS, Open Indiana, Solaris Open, and SmartOS)
* `suse?`
* `unix?`
@ -103,7 +103,7 @@ Use `os[:family]` to enable more granular testing of platforms, platform names,
* `:debian`
* `:hpux`
* `:linux`. For platforms that are part of the Linux family: `:alpine`, `:amazon`, `:arch`, `:coreos`, `:exherbo`, `:fedora`, `:gentoo`, and `:slackware`.
* `:redhat`
* `:redhat`. For platforms that are part of the Redhat family: `:centos`.
* `:solaris`. For platforms that are part of the Solaris family: `:nexentacore`, `:omnios`, `:openindiana`, `:opensolaris`, and `:smartos`.
* `:suse`
* `:unix`
@ -115,7 +115,7 @@ For example, both of the following tests should have the same result:
describe port(69) do
its('processes') { should include 'in.tftpd' }
end
elsif os[:family] == 'rhel'
elsif os[:family] == 'redhat'
describe port(69) do
its('processes') { should include 'xinetd' }
end
@ -125,7 +125,7 @@ For example, both of the following tests should have the same result:
describe port(69) do
its('processes') { should include 'in.tftpd' }
end
elsif os[:rhel]
elsif os[:redhat]
describe port(69) do
its('processes') { should include 'xinetd' }
end

View file

@ -4,7 +4,7 @@ title: About the sshd_config Resource
# sshd_config
Use the `sshd_config` InSpec audit resource to test configuration data for the OpenSSH daemon located at `/etc/ssh/sshd_config` on Linux and Unix platforms. sshd---the OpenSSH daemon---listens on dedicated ports, starts a daemon for each incoming connection, and then handles encryption, authentication, key exchanges, command executation, and data exchanges.
Use the `sshd_config` InSpec audit resource to test configuration data for the OpenSSH daemon located at `/etc/ssh/sshd_config` on Linux and Unix platforms. sshd---the OpenSSH daemon---listens on dedicated ports, starts a daemon for each incoming connection, and then handles encryption, authentication, key exchanges, command execution, and data exchanges.
## Syntax

View file

@ -3,7 +3,7 @@
# license: All rights reserved
# import full profile
include_controls 'hardening/ssh-hardening'
include_controls 'dev-sec/ssh-baseline'
# select only individual controls
include_controls 'ssl-benchmark' do

View file

@ -7,7 +7,7 @@ license: Apache 2
summary: InSpec Profile that is only consuming dependencies
version: 0.2.0
depends:
- name: hardening/ssh-hardening # defaults to supermarket
- name: dev-sec/ssh-baseline # defaults to supermarket
- url: https://github.com/dev-sec/ssl-benchmark
- name: windows-patch-benchmark
url: https://github.com/chris-rock/windows-patch-benchmark

View file

@ -38,4 +38,5 @@ Gem::Specification.new do |spec|
spec.add_dependency 'sslshake', '~> 1'
spec.add_dependency 'parallel', '~> 1.9'
spec.add_dependency 'rspec_junit_formatter', '~> 0.2.3'
spec.add_dependency 'faraday', '>=0.9.0'
end

View file

@ -154,17 +154,17 @@ module Artifact
p = Pathname.new(path_to_profile)
p = p.join('inspec.yml')
if not p.exist?
fail "#{path_to_profile} doesn't appear to be a valid Inspec profile"
raise "#{path_to_profile} doesn't appear to be a valid Inspec profile"
end
yaml = YAML.load_file(p.to_s)
yaml = yaml.to_hash
if not yaml.key? 'name'
fail 'Profile is invalid, name is not defined'
raise 'Profile is invalid, name is not defined'
end
if not yaml.key? 'version'
fail 'Profile is invalid, version is not defined'
raise 'Profile is invalid, version is not defined'
end
rescue => e
# rewrap it and pass it up to the CLI
@ -212,15 +212,15 @@ module Artifact
public_keyfile = "#{file_keyname}.pem.pub"
puts "Looking for #{public_keyfile} to verify artifact"
if not File.exist? public_keyfile
fail "Can't find #{public_keyfile}"
raise "Can't find #{public_keyfile}"
end
if not VALID_PROFILE_DIGESTS.member? file_alg
fail 'Invalid artifact digest algorithm detected'
raise 'Invalid artifact digest algorithm detected'
end
if not VALID_PROFILE_VERSIONS.member? file_version
fail 'Invalid artifact version detected'
raise 'Invalid artifact version detected'
end
end

View file

@ -81,7 +81,7 @@ Please login using `inspec compliance login https://compliance.test --user admin
[res.is_a?(Net::HTTPSuccess), res.body]
end
# Use username and refresh_toke to get an API access token
# Use username and refresh_token to get an API access token
def self.get_token_via_refresh_token(url, refresh_token, insecure)
uri = URI.parse("#{url}/login")
req = Net::HTTP::Post.new(uri.path)
@ -130,20 +130,27 @@ Please login using `inspec compliance login https://compliance.test --user admin
end
def self.get_headers(config)
token = get_token(config)
if config['server_type'] == 'automate'
headers = { 'chef-delivery-enterprise' => config['automate']['ent'] }
if config['automate']['token_type'] == 'dctoken'
headers['x-data-collector-token'] = config['token']
headers['x-data-collector-token'] = token
else
headers['chef-delivery-user'] = config['user']
headers['chef-delivery-token'] = config['token']
headers['chef-delivery-token'] = token
end
else
headers = { 'Authorization' => "Bearer #{config['token']}" }
headers = { 'Authorization' => "Bearer #{token}" }
end
headers
end
def self.get_token(config)
return config['token'] unless config['refresh_token']
_success, _msg, token = get_token_via_refresh_token(config['server'], config['refresh_token'], config['insecure'])
token
end
def self.target_url(config, profile)
if config['server_type'] == 'automate'
target = "#{config['server']}/#{profile}/tar"

View file

@ -179,7 +179,7 @@ module Compliance
end
# determine user information
if config['token'].nil? || config['user'].nil?
if (config['token'].nil? && config['refresh_token'].nil?) || config['user'].nil?
error.call('Please login via `inspec compliance login`')
end
@ -287,11 +287,10 @@ module Compliance
end
def login_refreshtoken(url, options)
success, msg, access_token = Compliance::API.get_token_via_refresh_token(url, options['refresh_token'], options['insecure'])
success, msg, _access_token = Compliance::API.get_token_via_refresh_token(url, options['refresh_token'], options['insecure'])
if success
config = Compliance::Configuration.new
config['server'] = url
config['token'] = access_token
config['insecure'] = options['insecure']
config['version'] = Compliance::API.version(url, options['insecure'])
config['server_type'] = 'compliance'
@ -344,11 +343,10 @@ module Compliance
success = true
msg = 'API refresh token stored'
else
success, msg, access_token = Compliance::API.get_token_via_refresh_token(url, refresh_token, insecure)
success, msg, _access_token= Compliance::API.get_token_via_refresh_token(url, refresh_token, insecure)
if success
config['token'] = access_token
config.store
msg = 'API access token verified and stored'
msg = 'API access token verified'
end
end

View file

@ -10,6 +10,7 @@ module Compliance
class HTTP
# generic get requires
def self.get(url, headers = nil, insecure)
url = "https://#{url}" if URI.parse(url).scheme.nil?
uri = URI.parse(url)
req = Net::HTTP::Get.new(uri.path)
if !headers.nil?
@ -38,7 +39,7 @@ module Compliance
# post a file
def self.post_file(url, headers, file_path, insecure)
uri = URI.parse(url)
fail "Unable to parse URL: #{url}" if uri.nil? || uri.host.nil?
raise "Unable to parse URL: #{url}" if uri.nil? || uri.host.nil?
http = Net::HTTP.new(uri.host, uri.port)
# set connection flags
@ -67,11 +68,18 @@ module Compliance
}
opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if insecure
fail "Unable to parse URI: #{uri}" if uri.nil? || uri.host.nil?
res = Net::HTTP.start(uri.host, uri.port, opts) {|http|
raise "Unable to parse URI: #{uri}" if uri.nil? || uri.host.nil?
res = Net::HTTP.start(uri.host, uri.port, opts) { |http|
http.request(req)
}
res
rescue OpenSSL::SSL::SSLError => e
raise e unless e.message.include? 'certificate verify failed'
puts "Error: Failed to connect to #{uri}."
puts 'If the server uses a self-signed certificate, please re-run the login command with the --insecure option.'
exit 1
end
end
end

View file

@ -13,7 +13,7 @@ module Compliance
class Fetcher < Fetchers::Url
name 'compliance'
priority 500
def self.resolve(target) # rubocop:disable PerceivedComplexity, Metrics/CyclomaticComplexity
def self.resolve(target) # rubocop:disable PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/AbcSize
uri = if target.is_a?(String) && URI(target).scheme == 'compliance'
URI(target)
elsif target.respond_to?(:key?) && target.key?(:compliance)
@ -29,7 +29,7 @@ module Compliance
else
# check if we have a compliance token
config = Compliance::Configuration.new
if config['token'].nil?
if config['token'].nil? && config['refresh_token'].nil?
if config['server_type'] == 'automate'
server = 'automate'
msg = 'inspec compliance login_automate https://your_automate_server --user USER --ent ENT --dctoken DCTOKEN or --usertoken USERTOKEN'
@ -37,7 +37,7 @@ module Compliance
server = 'compliance'
msg = "inspec compliance login https://your_compliance_server --user admin --insecure --token 'PASTE TOKEN HERE' "
end
fail Inspec::FetcherFailure, <<EOF
raise Inspec::FetcherFailure, <<EOF
Cannot fetch #{uri} because your #{server} token has not been
configured.
@ -51,10 +51,13 @@ EOF
# verifies that the target e.g base/ssh exists
profile = uri.host + uri.path
if !Compliance::API.exist?(config, profile)
fail Inspec::FetcherFailure, "The compliance profile #{profile} was not found on the configured compliance server"
raise Inspec::FetcherFailure, "The compliance profile #{profile} was not found on the configured compliance server"
end
profile_fetch_url = Compliance::API.target_url(config, profile)
end
# We need to pass the token to the fetcher
config['token'] = Compliance::API.get_token(config)
new(profile_fetch_url, config)
rescue URI::Error => _e
nil

View file

@ -45,7 +45,7 @@ module Supermarket
"#{p['tool_owner']}/#{p['slug']}" == profile
}
if found.length == 0
if found.empty?
puts "#{mark_text(profile)} is not available on Supermarket"
return
end

View file

@ -86,7 +86,7 @@ module Fetchers
cmd = shellout("git ls-remote \"#{@remote_url}\" \"#{ref_name}*\"")
ref = parse_ls_remote(cmd.stdout, ref_name)
if !ref
fail "Unable to resolve #{ref_name} to a specific git commit for #{@remote_url}"
raise "Unable to resolve #{ref_name} to a specific git commit for #{@remote_url}"
end
ref
end

View file

@ -17,12 +17,12 @@ module Inspec
name = Train.validate_backend(conf)
transport = Train.create(name, conf)
if transport.nil?
fail "Can't find transport backend '#{name}'."
raise "Can't find transport backend '#{name}'."
end
connection = transport.connection
if connection.nil?
fail "Can't connect to transport backend '#{name}'."
raise "Can't connect to transport backend '#{name}'."
end
cls = Class.new do

View file

@ -142,7 +142,7 @@ module Inspec
$stderr.puts exception.message
exit(1)
else
raise exception # rubocop:disable Style/SignalException
raise exception
end
end

View file

@ -12,7 +12,7 @@ module Inspec
@fetcher = Inspec::Fetcher.resolve(target)
if @fetcher.nil?
fail("Could not fetch inspec profile in #{target.inspect}.")
raise("Could not fetch inspec profile in #{target.inspect}.")
end
@cache = cache
@ -50,7 +50,7 @@ module Inspec
def assert_cache_sanity!
if target.respond_to?(:key?) && target.key?(:sha256)
if fetcher.resolved_source[:sha256] != target[:sha256]
fail <<EOF
raise <<EOF
The remote source #{fetcher} no longer has the requested content:
Request Content Hash: #{target[:sha256]}

View file

@ -230,6 +230,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
puts "\nYour version of InSpec is out of date! The latest version is #{latest}."
end
end
map %w{-v --version} => :version
private

View file

@ -35,8 +35,6 @@ module Inspec
# @param profile_context [Inspec::ProfileContext]
# @param outer_dsl [OuterDSLClass]
# @return [ProfileContextClass]
#
# rubocop:disable Lint/NestedMethodDefinition
def self.create(profile_context, resources_dsl) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
rule_class = rule_context(resources_dsl)
profile_context_owner = profile_context

View file

@ -18,7 +18,7 @@ module Inspec
def self.from_content(content)
parsed_content = YAML.load(content)
version = parsed_content['lockfile_version']
fail "No lockfile_version set in #{path}!" if version.nil?
raise "No lockfile_version set in #{path}!" if version.nil?
validate_lockfile_version!(version.to_i)
new(parsed_content)
end
@ -28,9 +28,10 @@ module Inspec
from_content(content)
end
# rubocop:disable Style/GuardClause
def self.validate_lockfile_version!(version)
if version < MINIMUM_SUPPORTED_VERSION
fail <<EOF
raise <<EOF
This lockfile specifies a lockfile_version of #{version} which is
lower than the minimum supported version #{MINIMUM_SUPPORTED_VERSION}.
@ -39,7 +40,7 @@ Please create a new lockfile for this project by running:
inspec vendor
EOF
elsif version > CURRENT_LOCKFILE_VERSION
fail <<EOF
raise <<EOF
This lockfile claims to be version #{version} which is greater than
the most recent lockfile version(#{CURRENT_LOCKFILE_VERSION}).
@ -48,6 +49,7 @@ used to create the lockfile.
EOF
end
end
# rubocop:enable Style/GuardClause
attr_reader :version, :deps
def initialize(lockfile_content_hash)
@ -80,7 +82,7 @@ EOF
else
# If we've gotten here, there is likely a mistake in the
# lockfile version validation in the constructor.
fail "No lockfile parser for version #{version}"
raise "No lockfile parser for version #{version}"
end
end

View file

@ -10,7 +10,7 @@ module Inspec
#
class Requirement
def self.from_metadata(dep, cache, opts)
fail 'Cannot load empty dependency.' if dep.nil? || dep.empty?
raise 'Cannot load empty dependency.' if dep.nil? || dep.empty?
new(dep[:name], dep[:version], cache, opts[:cwd], opts.merge(dep))
end

View file

@ -26,7 +26,7 @@ module Inspec
def self.resolve(dependencies, cache, working_dir, backend)
reqs = dependencies.map do |dep|
req = Inspec::Requirement.from_metadata(dep, cache, cwd: working_dir, backend: backend)
req || fail("Cannot initialize dependency: #{req}")
req || raise("Cannot initialize dependency: #{req}")
end
new.resolve(reqs)
end
@ -40,7 +40,7 @@ module Inspec
else
"the dependency information for #{path_string.split(' ').last}"
end
fail Inspec::DuplicateDep, "The dependency #{dep.name} is listed twice in #{problem_cookbook}"
raise Inspec::DuplicateDep, "The dependency #{dep.name} is listed twice in #{problem_cookbook}"
else
seen_items_local << dep.name
end
@ -65,13 +65,13 @@ module Inspec
end
if new_seen_items.key?(dep.resolved_source)
fail Inspec::CyclicDependencyError, "Dependency #{dep} would cause a dependency cycle (#{new_path_string})"
raise Inspec::CyclicDependencyError, "Dependency #{dep} would cause a dependency cycle (#{new_path_string})"
else
new_seen_items[dep.resolved_source] = true
end
if !dep.source_satisfies_spec?
fail Inspec::UnsatisfiedVersionSpecification, "The profile #{dep.name} from #{dep.resolved_source} has a version #{dep.source_version} which doesn't match #{dep.required_version}"
raise Inspec::UnsatisfiedVersionSpecification, "The profile #{dep.name} from #{dep.resolved_source} has a version #{dep.source_version} which doesn't match #{dep.required_version}"
end
Inspec::Log.debug("Adding dependency #{dep.name} (#{dep.resolved_source})")

View file

@ -19,7 +19,7 @@ module Inspec::DSL
alias include_rules include_controls
def require_resource(options = {})
fail 'You must specify a specific resource name when calling require_resource()' if options[:resource].nil?
raise 'You must specify a specific resource name when calling require_resource()' if options[:resource].nil?
from_profile = options[:profile] || profile_name
target_name = options[:as] || options[:resource]
@ -33,7 +33,7 @@ module Inspec::DSL
dep_entry = dependencies.list[profile_id]
if dep_entry.nil?
fail <<EOF
raise <<EOF
Cannot load #{profile_id} since it is not listed as a dependency
of #{bind_context.profile_name}.

View file

@ -34,7 +34,7 @@ module Inspec
def self.fetcher(version)
if version != 1
fail 'Only fetcher version 1 is supported!'
raise 'Only fetcher version 1 is supported!'
end
Inspec::Plugins::Fetcher
end

View file

@ -17,7 +17,7 @@ module Inspec
elsif File.exist?(path)
DirProvider.new(path)
else
fail "No file provider for the provided path: #{path}"
raise "No file provider for the provided path: #{path}"
end
end
@ -25,11 +25,11 @@ module Inspec
end
def read(_file)
fail "#{self} does not implement `read(...)`. This is required."
raise "#{self} does not implement `read(...)`. This is required."
end
def files
fail "Fetcher #{self} does not implement `files()`. This is required."
raise "Fetcher #{self} does not implement `files()`. This is required."
end
def relative_provider
@ -148,7 +148,7 @@ module Inspec
@parent = parent_provider
@prefix = get_prefix(parent.files)
if @prefix.nil?
fail "Could not determine path prefix for #{parent}"
raise "Could not determine path prefix for #{parent}"
end
@files = parent.files.find_all { |x| x.start_with?(prefix) && x != prefix }
.map { |x| x[prefix.length..-1] }

View file

@ -35,7 +35,7 @@ module Inspec
c3 = Class.new do
include Inspec::DSL::RequireOverride
def initialize(require_loader) # rubocop:disable Lint/NestedMethodDefinition
def initialize(require_loader)
@require_loader = require_loader
end
end

View file

@ -2,7 +2,8 @@
module Inspec
class EachLoop < List
attr_reader :tests, :variables
attr_reader :variables
attr_accessor :tests
def initialize
super
@tests = []

View file

@ -3,7 +3,7 @@
module Inspec
class List < Value
def map
fail 'Inspec::List.map needs to be called with a block' unless block_given?
raise 'Inspec::List.map needs to be called with a block' unless block_given?
t = List.new
t.qualifier = [['x']]
yield(t)

View file

@ -5,15 +5,30 @@ module Inspec
attr_reader :tests
def initialize(tests)
@tests = tests
@negated = false
end
def skip
nil
end
def negate!
@negated = !@negated
end
def to_ruby
all_tests = @tests.map(&:to_ruby).join("\n").gsub("\n", "\n ")
format("describe.one do\n %s\nend", all_tests)
if @negated
# We don't use the describe.one wrapper when negated because:
# !(test1 || test2) same as (!test1 && !test2) where && is implicit in inspec
all_tests = @tests.map { |test|
test.negate!
test
}.map(&:to_ruby).join("\n")
return all_tests
else
all_tests = @tests.map(&:to_ruby).join("\n").gsub("\n", "\n ")
return format("describe.one do\n %s\nend", all_tests)
end
end
def to_hash

View file

@ -53,7 +53,7 @@ module Inspec
# this will go in its()
xres = last_call
else
res += '.' + ruby_qualifier(last)
res += '.' + ruby_qualifier(last) unless last_call.empty?
end
end
@ -67,7 +67,7 @@ module Inspec
itsy = xtra.nil? ? 'it' : 'its(' + xtra.to_s.inspect + ')'
naughty = @negated ? '_not' : ''
xpect = defined?(@expectation) ? expectation.inspect : ''
if matcher == 'match'
if @expectation.class == Regexp
# without this, xpect values like / \/zones\// will not be parsed properly
xpect = "(#{xpect})"
elsif xpect != ''

View file

@ -51,7 +51,7 @@ module Inspec
def load(name)
path = @registry[name]
if path.nil?
fail "Couldn't find plugin #{name}. Searching in #{@home}"
raise "Couldn't find plugin #{name}. Searching in #{@home}"
end
# puts "Loading plugin #{name} from #{path}"
require path

View file

@ -36,7 +36,7 @@ module Inspec
# profile.
#
def archive_path
fail "Fetcher #{self} does not implement `archive_path()`. This is required."
raise "Fetcher #{self} does not implement `archive_path()`. This is required."
end
#
@ -49,7 +49,7 @@ module Inspec
# /foo/bar/baz.zip
#
def fetch(_path)
fail "Fetcher #{self} does not implement `fetch()`. This is required."
raise "Fetcher #{self} does not implement `fetch()`. This is required."
end
#
@ -59,14 +59,14 @@ module Inspec
# tag will be resolved to an exact revision.
#
def resolved_source
fail "Fetcher #{self} does not implement `resolved_source()`. This is required for terminal fetchers."
raise "Fetcher #{self} does not implement `resolved_source()`. This is required for terminal fetchers."
end
#
# The unique key based on the content of the remote archive.
#
def cache_key
fail "Fetcher #{self} does not implement `cache_key()`. This is required for terminal fetchers."
raise "Fetcher #{self} does not implement `cache_key()`. This is required for terminal fetchers."
end
#

View file

@ -38,7 +38,6 @@ module Inspec
end
def __register(name, obj)
# rubocop:disable Lint/NestedMethodDefinition
cl = Class.new(obj) do
def initialize(backend, name, *args)
# attach the backend to this instance

View file

@ -15,7 +15,7 @@ module Inspec
#
# @return [Inspec::Metadata] profile metadata
def metadata
fail "SourceReader #{self} does not implement `metadata()`. This method is required"
raise "SourceReader #{self} does not implement `metadata()`. This method is required"
end
# Retrieve this profile's tests
@ -26,14 +26,14 @@ module Inspec
#
# @return [Hash] Collection with references pointing to test contents
def tests
fail "SourceReader #{self} does not implement `tests()`. This method is required"
raise "SourceReader #{self} does not implement `tests()`. This method is required"
end
# Retrieve this profile's libraries
#
# @return [Hash] Collection with references pointing to library contents
def libraries
fail "SourceReader #{self} does not implement `libraries()`. This method is required"
raise "SourceReader #{self} does not implement `libraries()`. This method is required"
end
end
end

View file

@ -57,7 +57,7 @@ module Inspec
reader = Inspec::SourceReader.resolve(rp)
if reader.nil?
fail("Don't understand inspec profile in #{path}, it " \
raise("Don't understand inspec profile in #{path}, it " \
"doesn't look like a supported profile structure.")
end
new(reader, opts)
@ -108,7 +108,7 @@ module Inspec
metadata.params[:version]
end
def writable? # rubocop:disable Style/TrivialAccessors
def writable?
@writable
end
@ -397,10 +397,10 @@ module Inspec
end
name = params[:name] ||
fail('Cannot create an archive without a profile name! Please '\
raise('Cannot create an archive without a profile name! Please '\
'specify the name in metadata or use --output to create the archive.')
version = params[:version] ||
fail('Cannot create an archive without a profile version! Please '\
raise('Cannot create an archive without a profile version! Please '\
'specify the version in metadata or use --output to create the archive.')
ext = opts[:zip] ? 'zip' : 'tar.gz'
slug = name.downcase.strip.tr(' ', '-').gsub(/[^\w-]/, '_')

View file

@ -21,7 +21,7 @@ module Inspec
attr_accessor :rules
def initialize(profile_id, backend, conf)
if backend.nil?
fail 'ProfileContext is initiated with a backend == nil. ' \
raise 'ProfileContext is initiated with a backend == nil. ' \
'This is a backend error which must be fixed upstream.'
end
@profile_id = profile_id

View file

@ -39,7 +39,7 @@ module Inspec
profile_context.subcontext_by_name(profile_name)
end
fail ProfileNotFound, "Cannot find profile named: #{profile_name}" if inner_context.nil?
raise ProfileNotFound, "Cannot find profile named: #{profile_name}" if inner_context.nil?
inner_context.resource_registry[resource_name]
end
@ -64,7 +64,7 @@ module Inspec
def self.validate_resource_dsl_version!(version)
if version != 1
fail 'Only resource version 1 is supported!'
raise 'Only resource version 1 is supported!'
end
end
end
@ -79,6 +79,7 @@ require 'resources/bash'
require 'resources/bond'
require 'resources/bridge'
require 'resources/command'
require 'resources/crontab'
require 'resources/directory'
require 'resources/etc_group'
require 'resources/file'
@ -86,6 +87,7 @@ require 'resources/gem'
require 'resources/groups'
require 'resources/grub_conf'
require 'resources/host'
require 'resources/http'
require 'resources/iis_site'
require 'resources/inetd_conf'
require 'resources/interface'
@ -106,6 +108,7 @@ require 'resources/oneget'
require 'resources/os'
require 'resources/os_env'
require 'resources/package'
require 'resources/packages'
require 'resources/parse_config'
require 'resources/passwd'
require 'resources/pip'

View file

@ -166,7 +166,7 @@ module Inspec
backend: @backend,
controls: @controls,
attributes: @conf[:attributes])
fail "Could not resolve #{target} to valid input." if profile.nil?
raise "Could not resolve #{target} to valid input." if profile.nil?
@target_profiles << profile if supports_profile?(profile)
end
@ -174,13 +174,13 @@ module Inspec
return true if @ignore_supports
if !profile.supports_runtime?
fail 'This profile requires InSpec version '\
raise 'This profile requires InSpec version '\
"#{profile.metadata.inspec_requirement}. You are running "\
"InSpec v#{Inspec::VERSION}.\n"
end
if !profile.supports_os?
fail "This OS/platform (#{@backend.os[:name]}) is not supported by this profile."
raise "This OS/platform (#{@backend.os[:name]}) is not supported by this profile."
end
true
@ -249,7 +249,7 @@ module Inspec
# otherwise return all working tests
return ok_tests
else
fail "A rule was registered with #{method_name.inspect}, "\
raise "A rule was registered with #{method_name.inspect}, "\
"which isn't understood and cannot be processed."
end
end

View file

@ -10,7 +10,7 @@ module Inspec
def self.secrets(version)
if version != 1
fail 'Only secrets version 1 is supported!'
raise 'Only secrets version 1 is supported!'
end
Inspec::Plugins::Secret
end

View file

@ -42,6 +42,8 @@ module Inspec
# Add a help menu as the default intro
Pry.hooks.add_hook(:before_session, 'inspec_intro') do
intro
print_target_info
puts
end
# Track the rules currently registered and what their merge count is.
@ -79,7 +81,7 @@ module Inspec
# determine min whitespace that can be removed
min = nil
example.lines.each do |line|
if line.strip.length > 0 # ignore empty lines
if !line.strip.empty? # ignore empty lines
line_whitespace = line.length - line.lstrip.length
min = line_whitespace if min.nil? || line_whitespace < min
end
@ -94,10 +96,20 @@ module Inspec
puts
end
def print_target_info
ctx = @runner.backend
puts <<EOF
You are currently running on:
OS platform: #{mark ctx.os[:name] || 'unknown'}
OS family: #{mark ctx.os[:family] || 'unknown'}
OS release: #{mark ctx.os[:release] || 'unknown'}
EOF
end
def help(resource = nil)
if resource.nil?
ctx = @runner.backend
puts <<EOF
Available commands:
@ -110,14 +122,9 @@ Available commands:
You can use resources in this environment to test the target machine. For example:
command('uname -a').stdout
file('/proc/cpuinfo').content => "value",
You are currently running on:
OS platform: #{mark ctx.os[:name] || 'unknown'}
OS family: #{mark ctx.os[:family] || 'unknown'}
OS release: #{mark ctx.os[:release] || 'unknown'}
file('/proc/cpuinfo').content => "value"
#{print_target_info}
EOF
elsif resource == 'resources'
resources

View file

@ -19,7 +19,7 @@ module Inspec
def self.source_reader(version)
if version != 1
fail 'Only source readers version 1 is supported!'
raise 'Only source readers version 1 is supported!'
end
Inspec::Plugins::SourceReader
end

View file

@ -4,5 +4,5 @@
# author: Christoph Hartmann
module Inspec
VERSION = '1.9.0'.freeze
VERSION = '1.14.1'.freeze
end

View file

@ -105,7 +105,7 @@ RSpec::Matchers.define :be_installed do
end
chain :by do
fail "[UNSUPPORTED] Please use the new resources 'gem', 'npm' or 'pip'."
raise "[UNSUPPORTED] Please use the new resources 'gem', 'npm' or 'pip'."
end
chain :with_version do |version|
@ -121,7 +121,7 @@ RSpec::Matchers.define :be_enabled do
end
chain :with_level do |_level|
fail '[UNSUPPORTED] with level is not supported'
raise '[UNSUPPORTED] with level is not supported'
end
failure_message do |service|
@ -137,7 +137,7 @@ RSpec::Matchers.define :be_running do
end
chain :under do |_under|
fail '[UNSUPPORTED] under is not supported'
raise '[UNSUPPORTED] under is not supported'
end
failure_message do |service|
@ -178,7 +178,7 @@ RSpec::Matchers.define :be_reachable do
end
chain :with do |_attr|
fail '[UNSUPPORTED] `with` is not supported in combination with `be_reachable`'
raise '[UNSUPPORTED] `with` is not supported in combination with `be_reachable`'
end
failure_message do |host|
@ -193,7 +193,7 @@ RSpec::Matchers.define :be_resolvable do
end
chain :by do |_type|
fail "[UNSUPPORTED] `by` is not supported in combination with `be_resolvable`. Please use the following syntax `host('example.com', port: 53, proto: 'udp')`."
raise "[UNSUPPORTED] `by` is not supported in combination with `be_resolvable`. Please use the following syntax `host('example.com', port: 53, proto: 'udp')`."
end
failure_message do |host|
@ -208,11 +208,11 @@ RSpec::Matchers.define :have_rule do |rule|
end
chain :with_table do |_table|
fail "[UNSUPPORTED] `with_table` is not supported in combination with `have_rule`. Please use the following syntax `iptables(table:'mangle', chain: 'input')`."
raise "[UNSUPPORTED] `with_table` is not supported in combination with `have_rule`. Please use the following syntax `iptables(table:'mangle', chain: 'input')`."
end
chain :with_chain do |_chain|
fail "[UNSUPPORTED] `with_table` is not supported in combination with `with_chain`. Please use the following syntax `iptables(table:'mangle', chain: 'input')`."
raise "[UNSUPPORTED] `with_table` is not supported in combination with `with_chain`. Please use the following syntax `iptables(table:'mangle', chain: 'input')`."
end
end

View file

@ -70,7 +70,7 @@ module Inspec::Resources
end
raw_conf = file.content
if raw_conf.empty? && file.size > 0
if raw_conf.empty? && !file.empty?
return skip_resource("Can't read file \"#{@conf_path}\"")
end

View file

@ -41,7 +41,7 @@ module Inspec::Resources
end
content = file.content
if content.empty? && file.size > 0
if content.empty? && !file.empty?
skip_resource "Can't read file '#{@conf_path}'"
return @params = {}
end

View file

@ -93,7 +93,7 @@ module Inspec::Resources
# rubocop:disable Style/MethodName
def LIST_RULES
return @legacy.LIST_RULES if @legacy
fail 'Using legacy auditd_rules LIST_RULES interface with non-legacy audit package. Please use the new syntax.'
raise 'Using legacy auditd_rules LIST_RULES interface with non-legacy audit package. Please use the new syntax.'
end
def status(name = nil)

View file

@ -115,7 +115,7 @@ module Inspec::Resources
adapter_collection.push(info) if info[:name].casecmp(bridge_name) == 0
end
return nil if bridges.size == 0
return nil if bridges.empty?
warn "[Possible Error] detected multiple bridges interfaces with the name #{bridge_name}" if bridges.size > 1
bridges[0]
end

83
lib/resources/crontab.rb Normal file
View file

@ -0,0 +1,83 @@
# encoding: utf-8
# author: Adam Leff
require 'utils/parser'
require 'utils/filter'
module Inspec::Resources
class Crontab < Inspec.resource(1)
name 'crontab'
desc 'Use the crontab InSpec audit resource to test the contents of the crontab for a given user which contains information about scheduled tasks owned by that user.'
example "
describe crontab('root') do
its('commands') { should include '/path/to/some/script' }
end
describe crontab('myuser').commands('/home/myuser/build.sh') do
its('hours') { should cmp '*' }
its('minutes') { should cmp '*' }
end
describe crontab.where({'hour' => '*', 'minute' => '*'}) do
its('entries.length') { should cmp '0' }
end
"
attr_reader :params
include CommentParser
def initialize(user = nil)
@user = user
@params = read_crontab
return skip_resource 'The `crontab` resource is not supported on your OS.' unless inspec.os.unix?
end
def read_crontab
inspec.command(crontab_cmd).stdout.lines.map { |l| parse_crontab_line(l) }.compact
end
def parse_crontab_line(l)
data, = parse_comment_line(l, comment_char: '#', standalone_comments: false)
return nil if data.nil? || data.empty?
elements = data.split(/\s+/, 6)
{
'minute' => elements.at(0),
'hour' => elements.at(1),
'day' => elements.at(2),
'month' => elements.at(3),
'weekday' => elements.at(4),
'command' => elements.at(5),
}
end
def crontab_cmd
@user.nil? ? 'crontab -l' : "crontab -l -u #{@user}"
end
filter = FilterTable.create
filter.add_accessor(:where)
.add_accessor(:entries)
.add(:minutes, field: 'minute')
.add(:hours, field: 'hour')
.add(:days, field: 'day')
.add(:months, field: 'month')
.add(:weekdays, field: 'weekday')
.add(:commands, field: 'command')
# rebuild the crontab line from raw content
filter.add(:content) { |t, _|
t.entries.map do |e|
[e.minute, e.hour, e.day, e.month, e.weekday, e.command].join(' ')
end.join("\n")
}
filter.connect(self, :params)
def to_s
@user.nil? ? 'crontab for current user' : "crontab for user #{@user}"
end
end
end

View file

@ -107,7 +107,7 @@ module Inspec::Resources
# iterate over each line and filter comments
@content.split("\n").each_with_object([]) do |line, lines|
grp_info = parse_group_line(line)
lines.push(grp_info) if !grp_info.nil? && grp_info.size > 0
lines.push(grp_info) if !grp_info.nil? && !grp_info.empty?
end
end
@ -119,7 +119,7 @@ module Inspec::Resources
line, _idx_nl = parse_comment_line(line, opts)
x = line.split(':')
# abort if we have an empty or comment line
return nil if x.size == 0
return nil if x.empty?
# map data
{
'name' => x.at(0), # Name of the group.

View file

@ -61,7 +61,7 @@ module Inspec::Resources
end
def contain(*_)
fail 'Contain is not supported. Please use standard RSpec matchers.'
raise 'Contain is not supported. Please use standard RSpec matchers.'
end
def readable?(by_usergroup, by_specific_user)
@ -128,7 +128,7 @@ module Inspec::Resources
private
def file_permission_granted?(access_type, by_usergroup, by_specific_user)
fail '`file_permission_granted?` is not supported on your OS' if @perms_provider.nil?
raise '`file_permission_granted?` is not supported on your OS' if @perms_provider.nil?
if by_specific_user.nil? || by_specific_user.empty?
@perms_provider.check_file_permission_by_mask(file, access_type, by_usergroup, by_specific_user)
else
@ -154,7 +154,7 @@ module Inspec::Resources
when 'execute'
'x'
else
fail 'Invalid access_type provided'
raise 'Invalid access_type provided'
end
end
@ -172,7 +172,7 @@ module Inspec::Resources
usergroup = usergroup_for(usergroup, specific_user)
flag = permission_flag(access_type)
mask = file.unix_mode_mask(usergroup, flag)
fail 'Invalid usergroup/owner provided' if mask.nil?
raise 'Invalid usergroup/owner provided' if mask.nil?
(file.mode & mask) != 0
end
@ -197,7 +197,7 @@ module Inspec::Resources
class WindowsFilePermissions < FilePermissions
def check_file_permission_by_mask(_file, _access_type, _usergroup, _specific_user)
fail '`check_file_permission_by_mask` is not supported on Windows'
raise '`check_file_permission_by_mask` is not supported on Windows'
end
def check_file_permission_by_user(access_type, user, path)
@ -209,7 +209,7 @@ module Inspec::Resources
when 'execute'
'@(\'FullControl\', \'Modify\', \'ReadAndExecute\', \'ExecuteFile\')'
else
fail 'Invalid access_type provided'
raise 'Invalid access_type provided'
end
cmd = inspec.command("@(@((Get-Acl '#{path}').access | Where-Object {$_.AccessControlType -eq 'Allow' -and $_.IdentityReference -eq '#{user}' }) | Where-Object {($_.FileSystemRights.ToString().Split(',') | % {$_.trim()} | ? {#{access_rule} -contains $_}) -ne $null}) | measure | % { $_.Count }")
cmd.stdout.chomp == '0' ? false : true

View file

@ -99,18 +99,18 @@ module Inspec::Resources
# verifies if a group exists
def exists?
group_info.entries.size > 0
!group_info.entries.empty?
end
def gid
gids = group_info.gids
if gids.size == 0
if gids.empty?
nil
# the default case should be one group
elsif gids.size == 1
gids.entries[0]
else
fail 'found more than one group with the same name, please use `groups` resource'
raise 'found more than one group with the same name, please use `groups` resource'
end
end
@ -144,7 +144,7 @@ module Inspec::Resources
end
def groups
fail 'group provider must implement the `groups` method'
raise 'group provider must implement the `groups` method'
end
end

View file

@ -38,11 +38,11 @@ class GrubConfig < Inspec.resource(1) # rubocop:disable Metrics/ClassLength
@conf_path = path || '/boot/grub/grub.cfg'
@defaults_path = '/etc/default/grub'
@version = 'grub2'
elsif os[:name] == 'amazon' # rubocop:disable Style/GuardClause
elsif os[:name] == 'amazon'
@conf_path = path || '/etc/grub.conf'
@version = 'legacy'
else
fail UnknownGrubConfig
raise UnknownGrubConfig
end
end
@ -145,7 +145,7 @@ class GrubConfig < Inspec.resource(1) # rubocop:disable Metrics/ClassLength
content = file.content
if content.empty? && file.size > 0
if content.empty? && !file.empty?
skip_resource "Can't read file '#{@conf_path}'"
return @params = {}
end

View file

@ -60,7 +60,7 @@ module Inspec::Resources
end
def reachable?(port = nil, proto = nil, timeout = nil)
fail "Use `host` resource with host('#{@hostname}', port: #{port}, proto: '#{proto}') parameters." if !port.nil? || !proto.nil? || !timeout.nil?
raise "Use `host` resource with host('#{@hostname}', port: #{port}, proto: '#{proto}') parameters." if !port.nil? || !proto.nil? || !timeout.nil?
ping.nil? ? false : ping
end

70
lib/resources/http.rb Normal file
View file

@ -0,0 +1,70 @@
# encoding: utf-8
# copyright: 2017, Criteo
# copyright: 2017, Chef Software Inc
# author: Guilhem Lettron, Christoph Hartmann
# license: Apache v2
require 'faraday'
require 'hashie'
module Inspec::Resources
class Http < Inspec.resource(1)
name 'http'
desc 'Use the http InSpec audit resource to test http call.'
example "
describe http('http://localhost:8080/ping', auth: {user: 'user', pass: 'test'}, params: {format: 'html'}) do
its('status') { should cmp 200 }
its('body') { should cmp 'pong' }
its('headers.Content-Type') { should cmp 'text/html' }
end
describe http('http://example.com/ping').headers do
its('Content-Length') { should cmp 258 }
its('Content-Type') { should cmp 'text/html; charset=UTF-8' }
end
"
# rubocop:disable ParameterLists
def initialize(url, method: 'GET', params: nil, auth: {}, headers: {}, data: nil)
@url = url
@method = method
@params = params
@auth = auth
@headers = headers
@data = data
end
def status
response.status
end
def body
response.body
end
def headers
Hashie::Mash.new(response.headers.to_h)
end
def to_s
"http #{@method} on #{@url}"
end
private
def response
conn = Faraday.new url: @url, headers: @headers, params: @params
# set basic authentication
conn.basic_auth @auth[:user], @auth[:pass] unless @auth.empty?
# set default timeout
conn.options.timeout = 5 # open/read timeout in seconds
conn.options.open_timeout = 3 # connection open timeout in seconds
@response = conn.send(@method.downcase) do |req|
req.body = @data
end
end
end
end

View file

@ -43,7 +43,7 @@ module Inspec::Resources
end
content = file.content
if content.empty? && file.size > 0
if content.empty? && !file.empty?
skip_resource "Can't read file \"#{@conf_path}\""
return @params = {}
end

View file

@ -121,7 +121,7 @@ module Inspec::Resources
adapter_collection.push(info) if info[:name].casecmp(iface) == 0
end
return nil if adapters.size == 0
return nil if adapters.empty?
warn "[Possible Error] detected multiple network interfaces with the name #{iface}" if adapters.size > 1
adapters[0]
end

View file

@ -49,7 +49,7 @@ module Inspec::Resources
end
# check if file is readable
if @file_content.nil? && @file.size > 0
if @file_content.nil? && !@file.empty?
skip_resource "Can't read file \"#{@path}\""
return @params = {}
end

View file

@ -36,6 +36,17 @@ module Inspec::Resources
!found.nil?
end
def version
if inspec.os[:name] == 'centos' && inspec.os[:release].to_i == 5
modinfo_cmd = "/sbin/modinfo -F version #{@module}"
else
modinfo_cmd = "modinfo -F version #{@module}"
end
cmd = inspec.command(modinfo_cmd)
cmd.exit_status.zero? ? cmd.stdout.delete("\n") : nil
end
def to_s
"Kernel Module #{@module}"
end

View file

@ -35,7 +35,7 @@ module Inspec::Resources
end
content = file.content
if content.empty? && file.size > 0
if content.empty? && !file.empty?
skip_resource "Can't read file \"#{@conf_path}\""
return @params = {}
end

View file

@ -47,7 +47,7 @@ module Inspec::Resources
end
content = file.content
if content.empty? && file.size > 0
if content.empty? && !file.empty?
skip_resource "Can't read file \"#{@conf_path}\""
return @params = {}
end

View file

@ -73,7 +73,7 @@ module Inspec::Resources
return skip_resource "Can't find file \"#{@conf_path}\""
end
raw_conf = read_file(@conf_path)
if raw_conf.empty? && inspec.file(@conf_path).size > 0
if raw_conf.empty? && !inspec.file(@conf_path).empty?
return skip_resource("Can't read file \"#{@conf_path}\"")
end

View file

@ -43,7 +43,7 @@ module Inspec::Resources
end
content = inspec.file(@conf_path).content
if content.empty? && inspec.file(@conf_path).size > 0
if content.empty? && !inspec.file(@conf_path).empty?
skip_resource "Can't read file \"#{@conf_path}\""
return @params = {}
end

View file

@ -29,7 +29,7 @@ module Inspec::Resources
os = inspec.os
if os.debian?
@pkgman = Deb.new(inspec)
elsif %w{redhat suse amazon fedora}.include?(os[:family])
elsif os.redhat? || %w{suse amazon fedora}.include?(os[:family])
@pkgman = Rpm.new(inspec)
elsif ['arch'].include?(os[:family])
@pkgman = Pacman.new(inspec)

112
lib/resources/packages.rb Normal file
View file

@ -0,0 +1,112 @@
# encoding: utf-8
# copyright: 2017, Chef Software, Inc. <legal@chef.io>
# author: Joshua Timberman
# author: Alex Pop
# license: All rights reserved
require 'utils/filter'
module Inspec::Resources
class Packages < Inspec.resource(1)
name 'packages'
desc 'Use the packages InSpec audit resource to test properties for multiple packages installed on the system'
example "
describe packages(/xserver-xorg.*/) do
its('entries') { should be_empty }
end
describe packages('vim').entries.length do
it { should be > 1 }
end
describe packages(/vi.+/).where { status != 'installed' } do
its('statuses') { should be_empty }
end
"
def initialize(pattern)
os = inspec.os
if os.debian?
@pkgs = Debs.new(inspec)
elsif os.redhat? || %w{suse amazon fedora}.include?(os[:family])
@pkgs = Rpms.new(inspec)
else
return skip_resource "The packages resource is not yet supported on OS #{inspec.os.name}"
end
@pattern = pattern_regexp(pattern)
all_pkgs = @pkgs.build_package_list
@list = all_pkgs.find_all do |hm|
hm[:name] =~ @pattern
end
end
def to_s
"Packages #{@pattern.class == String ? @pattern : @pattern.inspect}"
end
filter = FilterTable.create
filter.add_accessor(:where)
.add_accessor(:entries)
.add(:statuses, field: 'status', style: :simple)
.add(:names, field: 'name')
.add(:versions, field: 'version')
.connect(self, :filtered_packages)
private
def pattern_regexp(p)
if p.class == String
Regexp.new(Regexp.escape(p))
elsif p.class == Regexp
p
else
raise 'Invalid name argument to packages resource, please use a "string" or /regexp/'
end
end
def filtered_packages
warn "The packages resource is not yet supported on OS #{inspec.os.name}" if resource_skipped
@list
end
end
class PkgsManagement
PackageStruct = Struct.new(:status, :name, :version)
attr_reader :inspec
def initialize(inspec)
@inspec = inspec
end
end
# Debian / Ubuntu
class Debs < PkgsManagement
def build_package_list
# use two spaces as delimiter in case any of the fields has a space in it
command = "dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\\n'"
cmd = inspec.command(command)
all = cmd.stdout.split("\n")
return [] if all.nil?
all.map do |m|
a = m.split(/ {2,}/)
a[0] = 'installed' if a[0] =~ /^.i/
a[2] = a[2].split(':').last
PackageStruct.new(*a)
end
end
end
# RedHat family
class Rpms < PkgsManagement
def build_package_list
# use two spaces as delimiter in case any of the fields has a space in it
command = "rpm -qa --queryformat '%{NAME} %{VERSION}-%{RELEASE}\\n'"
cmd = inspec.command(command)
all = cmd.stdout.split("\n")
return [] if all.nil?
all.map do |m|
a = m.split(' ')
a.unshift('installed')
PackageStruct.new(*a)
end
end
end
end

View file

@ -76,7 +76,7 @@ module Inspec::Resources
return skip_resource "Can't find file \"#{conf_path}\""
end
@content = read_file(conf_path).to_s
if @content.empty? && inspec.file(conf_path).size > 0
if @content.empty? && !inspec.file(conf_path).empty?
return skip_resource "Can't read file \"#{conf_path}\""
end

View file

@ -45,7 +45,7 @@ module Inspec::Resources
.add(:protocols, field: 'protocol', style: :simple)
.add(:processes, field: 'process', style: :simple)
.add(:pids, field: 'pid', style: :simple)
.add(:listening?) { |x| x.entries.length > 0 }
.add(:listening?) { |x| !x.entries.empty? }
filter.connect(self, :info)
def to_s
@ -169,7 +169,7 @@ module Inspec::Resources
ports = []
# check that lsof is available, otherwise fail
fail 'Please ensure `lsof` is available on the machine.' if !inspec.command(@lsof.to_s).exist?
raise 'Please ensure `lsof` is available on the machine.' if !inspec.command(@lsof.to_s).exist?
# -F p=pid, c=command, P=protocol name, t=type, n=internet addresses
# see 'OUTPUT FOR OTHER PROGRAMS' in LSOF(8)

View file

@ -65,7 +65,7 @@ module Inspec::Resources
return skip_resource "Can't find file \"#{@conf_path}\""
end
raw_conf = read_file(@conf_path)
if raw_conf.empty? && inspec.file(@conf_path).size > 0
if raw_conf.empty? && !inspec.file(@conf_path).empty?
return skip_resource("Can't read file \"#{@conf_path}\"")
end

View file

@ -4,22 +4,23 @@
# author: Christoph Hartmann
# license: All rights reserved
require 'utils/filter'
module Inspec::Resources
class Processes < Inspec.resource(1)
name 'processes'
desc 'Use the processes InSpec audit resource to test properties for programs that are running on the system.'
example "
describe processes('mysqld') do
its('list.length') { should eq 1 }
its('entries.length') { should eq 1 }
its('users') { should eq ['mysql'] }
its('states') { should include 'S' }
end
describe processes(/.+/).where { label != 'unconfined' && pid < 1000 } do
its('users') { should cmp [] }
end
"
attr_reader :list,
:users,
:states
def initialize(grep)
@grep = grep
# turn into a regexp if it isn't one yet
@ -31,19 +32,40 @@ module Inspec::Resources
@list = all_cmds.find_all do |hm|
hm[:command] =~ grep
end
{ users: :user,
states: :stat }.each do |var, key|
instance_variable_set("@#{var}", @list.map { |l| l[key] }.uniq)
end
end
def to_s
"Processes #{@grep.class == String ? @grep : @grep.inspect}"
end
def list
warn '[DEPRECATION] `processes.list` is deprecated. Please use `processes.entries` instead. It will be removed in version 2.0.0.'
@list
end
filter = FilterTable.create
filter.add_accessor(:where)
.add_accessor(:entries)
.add(:labels, field: 'label')
.add(:pids, field: 'pid')
.add(:cpus, field: 'cpu')
.add(:mem, field: 'mem')
.add(:vsz, field: 'vsz')
.add(:rss, field: 'rss')
.add(:tty, field: 'tty')
.add(:states, field: 'stat')
.add(:start, field: 'start')
.add(:time, field: 'time')
.add(:users, field: 'user')
.add(:commands, field: 'command')
.connect(self, :filtered_processes)
private
def filtered_processes
@list
end
def ps_axo
os = inspec.os

View file

@ -117,7 +117,7 @@ module Inspec::Resources
return skip_resource "Can't read security policy" if cmd.exit_status.to_i != 0
@content = cmd.stdout
if @content.empty? && file.size > 0
if @content.empty? && !file.empty?
return skip_resource "Can't read security policy"
end
@content

View file

@ -9,7 +9,7 @@ require 'utils/simpleconfig'
module Inspec::Resources
class SshConf < Inspec.resource(1)
name 'ssh_config'
desc 'Use the sshd_config InSpec audit resource to test configuration data for the Open SSH daemon located at /etc/ssh/sshd_config on Linux and UNIX platforms. sshd---the Open SSH daemon---listens on dedicated ports, starts a daemon for each incoming connection, and then handles encryption, authentication, key exchanges, command executation, and data exchanges.'
desc 'Use the sshd_config InSpec audit resource to test configuration data for the Open SSH daemon located at /etc/ssh/sshd_config on Linux and UNIX platforms. sshd---the Open SSH daemon---listens on dedicated ports, starts a daemon for each incoming connection, and then handles encryption, authentication, key exchanges, command execution, and data exchanges.'
example "
describe sshd_config do
its('Protocol') { should eq '2' }
@ -62,7 +62,7 @@ module Inspec::Resources
end
@content = file.content
if @content.empty? && file.size > 0
if @content.empty? && !file.empty?
return skip_resource "Can't read file \"#{@conf_path}\""
end

View file

@ -52,7 +52,7 @@ class SSL < Inspec.resource(1)
elsif inspec.backend.class.to_s == 'Train::Transports::Local::Connection'
@host = 'localhost'
else
fail 'Cannot determine host for SSL test. Please specify it or use a different target.'
raise 'Cannot determine host for SSL test. Please specify it or use a different target.'
end
end
@port = opts[:port] || 443

View file

@ -57,7 +57,7 @@ module Inspec::Resources
name 'users'
desc 'Use the users InSpec audit resource to test local user profiles. Users can be filtered by groups to which they belong, the frequency of required password changes, the directory paths to home and shell.'
example "
describe users.where(uid: 0).entries do
describe users.where { uid == 0 }.entries do
it { should eq ['root'] }
its('uids') { should eq [1234] }
its('gids') { should eq [1234] }
@ -242,7 +242,7 @@ module Inspec::Resources
def has_authorized_key?(_compare_key)
deprecated('has_authorized_key?')
fail NotImplementedError
raise NotImplementedError
end
def deprecated(name, alternative = nil)
@ -292,7 +292,7 @@ module Inspec::Resources
# groups: '',
# }
def identity(_username)
fail 'user provider must implement the `identity` method'
raise 'user provider must implement the `identity` method'
end
# returns optional information about a user, eg shell
@ -313,7 +313,7 @@ module Inspec::Resources
# returns an array with users
def list_users
fail 'user provider must implement the `list_users` method'
raise 'user provider must implement the `list_users` method'
end
# retuns all aspects of the user as one hash
@ -556,7 +556,7 @@ module Inspec::Resources
def parse_windows_account(username)
account = username.split('\\')
name = account.pop
domain = account.pop if account.size > 0
domain = account.pop if !account.empty?
[name, domain]
end
@ -565,7 +565,7 @@ module Inspec::Resources
name, _domain = parse_windows_account(username)
return if collect_user_details.nil?
res = collect_user_details.select { |user| user[:username] == name }
res[0] if res.length > 0
res[0] if !res.empty?
end
def list_users

View file

@ -41,6 +41,7 @@ module Inspec::Resources
.add(:ids, field: 'id')
.add(:socket_types, field: 'socket_type')
.add(:types, field: 'type')
.add(:protocols, field: 'protocol')
.add(:wait, field: 'wait')
.add(:disabled?) { |x| x.where('disable' => 'no').services.empty? }
.add(:enabled?) { |x| x.where('disable' => 'yes').services.empty? }
@ -56,7 +57,7 @@ module Inspec::Resources
end
@contents[path] = file.content
if @contents[path].empty? && file.size > 0
if @contents[path].empty? && !file.empty?
return skip_resource "Can't read file \"#{path}\""
end
@ -91,8 +92,23 @@ module Inspec::Resources
params
end
# Method used to derive the default protocol used from the socket_type
def default_protocol(type)
case type
when 'stream'
'tcp'
when 'dgram'
'udp'
else
'unknown'
end
end
def service_lines
@services ||= params['services'].values.flatten.map(&:params)
@services ||= params['services'].values.flatten.map { |service|
service.params['protocol'] ||= default_protocol(service.params['socket_type'])
service.params
}
end
end
end

View file

@ -27,7 +27,7 @@ module SourceReaders
# This create a new instance of an InSpec profile source reader
#
# @param [SourceReader] target
# @param [FileProvider] target An instance of a FileProvider object that can list files and read them
# @param [String] metadata_source eg. inspec.yml or metadata.rb
def initialize(target, metadata_source)
@target = target

View file

@ -9,20 +9,20 @@ class CommandWrapper
def self.wrap(cmd, options)
unless options.is_a?(Hash)
fail 'All options for the command wrapper must be provided as a hash. '\
raise 'All options for the command wrapper must be provided as a hash. '\
"You entered: #{options.inspect}. Please consult the documentation."
end
wrap = options[:wrap]
if !wrap.nil? && !wrap.is_a?(Proc)
fail "Called command wrapper with wrap: #{wrap.inspect}. It must be called with a Proc."
raise "Called command wrapper with wrap: #{wrap.inspect}. It must be called with a Proc."
elsif !wrap.nil?
return wrap.call(cmd)
end
shell = options[:shell]
unless UNIX_SHELLS.include?(shell)
fail "Don't know how to wrap commands for shell: #{shell.inspect}."
raise "Don't know how to wrap commands for shell: #{shell.inspect}."
end
path = options[:path] || shell

View file

@ -70,7 +70,7 @@ module FilterTable
end
def new_entry(*_)
fail "#{self.class} must not be used on its own. It must be inherited "\
raise "#{self.class} must not be used on its own. It must be inherited "\
'and the #new_entry method must be implemented. This is an internal '\
'error and should not happen.'
end

View file

@ -209,7 +209,12 @@ module XinetdParser
next if inner_line.empty?
if inner_line == '}'
res[cur_group] = SimpleConfig.new(simple_conf.join("\n"))
if cur_group == 'defaults'
res[cur_group] = SimpleConfig.new(simple_conf.join("\n"))
else
res[cur_group] ||= []
res[cur_group].push(SimpleConfig.new(simple_conf.join("\n")))
end
cur_group = nil
elsif rest.lstrip[0] == '{'
cur_group = inner_line
@ -224,7 +229,7 @@ module XinetdParser
others.each { |ores|
ores.each { |k, v|
res[k] ||= []
res[k].push(v)
res[k].concat(v)
}
}
else

View file

@ -39,7 +39,7 @@ class PluginRegistry
#
# @return [PluginRegistry] plugin registry for this plugin
def self.plugin_registry
fail "Plugin #{self} does not implement `self.plugin_registry()`. This method is required"
raise "Plugin #{self} does not implement `self.plugin_registry()`. This method is required"
end
# Register a new plugin by name
@ -47,7 +47,7 @@ class PluginRegistry
# @param [String] the unique name of this plugin
# @return [nil] disregard
def self.name(name)
fail "Trying to register #{self} with name == nil" if name.nil?
raise "Trying to register #{self} with name == nil" if name.nil?
@name = name
plugin_registry.registry[name] = self
end
@ -72,7 +72,7 @@ class PluginRegistry
# @param [String] target to try to resolve
# @return [Plugin] instance if it can be resolved, nil otherwise
def self.resolve(_target)
fail "Plugin #{self} does not implement `self.resolve(target)`. This method is required"
raise "Plugin #{self} does not implement `self.resolve(target)`. This method is required"
end
# When a plugin's resolve doesn't lead to the final state, it can

View file

@ -33,7 +33,7 @@ class SimpleConfig
raw_data = raw_data.tr(options[:line_separator], "\n")
end
rest = raw_data
rest = parse_rest(rest, options) while rest.length > 0
rest = parse_rest(rest, options) until rest.empty?
end
private

View file

@ -135,7 +135,7 @@ class ResourceDocs
def render_path(path)
abs = File.join(@root, path)
fail "Can't find file to render in #{abs}" unless File.file?(abs)
raise "Can't find file to render in #{abs}" unless File.file?(abs)
ERB.new(File.read(abs)).result(binding)
end

View file

@ -28,7 +28,7 @@ end
module Verify
def self.file(path)
return print("\033[32m.\033[0m") if File.file?(path)
fail "Failed to build this step. Looking for file in #{path} but it doesn't exist."
raise "Failed to build this step. Looking for file in #{path} but it doesn't exist."
end
def self.ok

View file

@ -44,6 +44,7 @@ namespace :www do
task :assemble do
Log.section 'Copy only tutorial into middleman build directory'
sh('rsync -a --exclude=index.html www/tutorial/dist/* www/build/')
sh('cp www/tutorial/dist/index.html www/build/tutorial.html')
end
desc 'Builds the full site locally'
@ -64,15 +65,15 @@ namespace :www do
end
unless File.directory?(dst) && File.file?(File.join(dst, 'index.html'))
fail 'It looks like the site was not build. Aborting.'
raise 'It looks like the site was not build. Aborting.'
end
# check if git exists
sh('command -v git >/dev/null 2>&1') ||
fail("It looks like `git` isn't installed. It is required to run this build task.")
raise("It looks like `git` isn't installed. It is required to run this build task.")
unless sh('git diff-index --quiet HEAD --')
fail 'Please make sure you have no uncommitted changes in this repository.'
raise 'Please make sure you have no uncommitted changes in this repository.'
end
File.write('www/build/CNAME', 'inspec.io')
@ -86,7 +87,7 @@ namespace :www do
current_branch = `git rev-parse --abbrev-ref HEAD`.strip
if current_branch.empty?
fail 'Cannot determine current branch to go back to! Aborting.'
raise 'Cannot determine current branch to go back to! Aborting.'
end
Log.info 'Create empty gh-pages branch'

View file

@ -127,6 +127,11 @@ describe 'inspec shell tests' do
out
end
it 'displays the target device information for the user without requiring the help command' do
out = do_shell('1+1')
out.stdout.must_include 'You are currently running on:'
end
it 'provides a help command' do
out = do_shell('help')
out.stdout.must_include 'Available commands:'

View file

@ -58,7 +58,7 @@ describe 'example inheritance profile' do
File.exist?(lockfile).must_equal true
out = inspec('exec ' + meta_path + ' -l debug --no-create-lockfile')
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:url=>"https://github.com/dev-sec/tests-ssh-hardening/archive/master.tar.gz"'
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:url=>"https://github.com/dev-sec/ssh-baseline/archive/master.tar.gz"'
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:url=>"https://github.com/dev-sec/ssl-benchmark/archive/master.tar.gz"'
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:url=>"https://github.com/chris-rock/windows-patch-benchmark/archive/master.tar.gz"'
out.stdout.force_encoding(Encoding::UTF_8).index('Fetching URL:').must_be_nil
@ -83,7 +83,7 @@ describe 'example inheritance profile' do
out.exit_status.must_equal 0
hm = JSON.load(File.read(dst.path))
hm['name'].must_equal 'meta-profile'
hm['controls'].length.must_equal 78
hm['controls'].length.must_be :>=, 78
# copies = out.stdout.scan(/Copy .* to cache directory/).length
# copies.must_equal 3
@ -124,7 +124,6 @@ describe 'example inheritance profile' do
it 'use lockfile in tarball' do
# ensure the profile is vendored and packaged as tar
out = inspec('vendor ' + meta_path + ' --overwrite')
out.exit_status.must_equal 0
out = inspec('archive ' + meta_path + ' --overwrite')
out.exit_status.must_equal 0

View file

@ -11,6 +11,7 @@ end
require 'minitest/autorun'
require 'minitest/spec'
require 'webmock/minitest'
require 'mocha/setup'
require 'fileutils'
require 'pathname'
@ -49,6 +50,7 @@ class MockLoader
ubuntu1204: { name: 'ubuntu', family: 'debian', release: '12.04', arch: 'x86_64' },
ubuntu1404: { name: 'ubuntu', family: 'debian', release: '14.04', arch: 'x86_64' },
ubuntu1504: { name: 'ubuntu', family: 'debian', release: '15.04', arch: 'x86_64' },
ubuntu1604: { name: 'ubuntu', family: 'debian', release: '16.04', arch: 'x86_64' },
mint17: { name: 'linuxmint', family: 'debian', release: '17.3', arch: 'x86_64' },
mint18: { name: 'linuxmint', family: 'debian', release: '18', arch: 'x86_64' },
windows: { name: 'windows', family: 'windows', release: '6.2.9200', arch: 'x86_64' },
@ -127,6 +129,7 @@ class MockLoader
'/etc/xinetd.d' => mockfile.call('xinetd.d'),
'/etc/xinetd.d/chargen-stream' => mockfile.call('xinetd.d_chargen-stream'),
'/etc/xinetd.d/chargen-dgram' => mockfile.call('xinetd.d_chargen-dgram'),
'/etc/xinetd.d/echo' => mockfile.call('xinetd.d_echo'),
'/etc/sysctl.conf' => mockfile.call('sysctl.conf'),
'/etc/postgresql/9.4/main/postgresql.conf' => mockfile.call('postgresql.conf'),
}
@ -247,6 +250,10 @@ class MockLoader
'pkginfo -l SUNWzfsr' => cmd.call('pkginfo-l-SUNWzfsr'),
# solaris 11 package manager
'pkg info system/file-system/zfs' => cmd.call('pkg-info-system-file-system-zfs'),
# dpkg-query all packages
"dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\\n'" => cmd.call('dpkg-query-W'),
# rpm query all packages
"rpm -qa --queryformat '%{NAME} %{VERSION}-%{RELEASE}\\n'" => cmd.call('rpm-qa-queryformat'),
# port netstat on solaris 10 & 11
'netstat -an -f inet -f inet6' => cmd.call('s11-netstat-an-finet-finet6'),
# xinetd configuration
@ -269,6 +276,11 @@ class MockLoader
"schtasks /query /v /fo csv /tn 'does-not-exist' | ConvertFrom-Csv | Select @{N='URI';E={$_.TaskName}},@{N='State';E={$_.Status.ToString()}},'Logon Mode','Last Result','Task To Run','Run As User','Scheduled Task State' | ConvertTo-Json -Compress" => cmd.call('schtasks-error'),
# windows_task exist
"schtasks /query /v /fo csv /tn 'WeLovePizza' | ConvertFrom-Csv | Select @{N='URI';E={$_.TaskName}},@{N='State';E={$_.Status.ToString()}},'Logon Mode','Last Result','Task To Run','Run As User','Scheduled Task State' | ConvertTo-Json -Compress" => cmd.call('schtasks-success'),
'modinfo -F version dhcp' => cmd.call('modinfo-f-version-dhcp'),
# crontab display for root / current user
'crontab -l' => cmd.call('crontab-root'),
# crontab display for non-current user
'crontab -l -u foouser' => cmd.call('crontab-foouser')
}
@backend

View file

@ -6,60 +6,329 @@ require 'helper'
require 'inspec/objects'
describe 'Objects' do
describe 'Test' do
describe 'Inspec::Test' do
let(:obj) { Inspec::Test.new }
it 'constructs a simple resource+argument' do
obj.qualifier = [['resource'], ['arg']]
obj.to_ruby.must_equal "
it 'constructs a simple resource + its("argument")' do
obj.qualifier = [['resource'], ['version']]
obj.matcher = 'cmp >='
obj.expectation = '2.4.2'
obj.to_ruby.must_equal '
describe resource do
its(\"arg\") { should }
its("version") { should cmp >= "2.4.2" }
end
".strip
'.strip
end
# same as the above test but with it
it 'constructs a simple resource.argument' do
# [''] forces an 'it' instead of 'its':
obj.qualifier = [['resource'], ['version'], ['']]
obj.matcher = 'cmp >='
obj.expectation = '2.4.2'
obj.to_ruby.must_equal '
describe resource.version do
it { should cmp >= "2.4.2" }
end
'.strip
end
it 'constructs a simple resource+argument with to_s' do
obj.qualifier = [['resource'], ['to_s']]
obj.to_ruby.must_equal "
obj.matcher = 'cmp'
obj.expectation = Regexp.new('^Desc.+$')
obj.to_ruby.must_equal '
describe resource.to_s do
it { should }
it { should cmp(/^Desc.+$/) }
end
".strip
'.strip
end
it 'constructs a simple resource+argument with to_i' do
obj.qualifier = [['resource'], ['to_i']]
obj.to_ruby.must_equal "
obj.matcher = 'cmp >'
obj.expectation = 3
obj.to_ruby.must_equal '
describe resource.to_i do
it { should }
it { should cmp > 3 }
end
".strip
'.strip
end
it 'constructs a simple resource+argument with array accessors' do
obj.qualifier = [['resource'], ['name[2]']]
obj.to_ruby.must_equal "
obj.matcher = 'exist'
obj.matcher = 'eq'
obj.expectation = 'mytest'
obj.to_ruby.must_equal '
describe resource.name[2] do
it { should }
it { should eq "mytest" }
end
".strip
'.strip
end
it 'constructs a simple resource+argument with method calls' do
obj.qualifier = [['resource'], ['hello', 'world']]
obj.to_ruby.must_equal "
describe resource.hello(\"world\") do
it { should }
obj.matcher = 'eq'
obj.expectation = 'mytest'
obj.to_ruby.must_equal '
describe resource.hello("world") do
it { should eq "mytest" }
end
".strip
'.strip
end
it 'constructs a simple resource+argument with method calls' do
obj.qualifier = [['resource'], [:world]]
obj.to_ruby.must_equal "
obj.qualifier = [['resource'], [:mode]]
obj.matcher = 'cmp'
obj.expectation = '0755'
obj.to_ruby.must_equal '
describe resource do
its(\"world\") { should }
its("mode") { should cmp "0755" }
end
".strip
'.strip
end
it 'constructs a resource+argument block with method call, matcher and expectation' do
obj.qualifier = [['command','ls /etc'], ['exit_status']]
obj.matcher = 'eq'
obj.expectation = 0
obj.to_ruby.must_equal '
describe command("ls /etc") do
its("exit_status") { should eq 0 }
end
'.strip
end
it 'constructs a simple describe with static data, negated regex matcher and expectation' do
obj.qualifier = [['"aaa"']]
obj.matcher = 'match'
obj.negate!
obj.expectation = Regexp.new('^aa.*')
obj.to_ruby.must_equal '
describe "aaa" do
it { should_not match(/^aa.*/) }
end
'.strip
end
it 'constructs a resource+argument block without a property call' do
obj.qualifier = [['service', 'avahi-daemon']]
obj.qualifier.push(["info['properties']['UnitFileState']"])
obj.expectation = "enabled"
obj.matcher = 'eq'
obj.to_ruby.must_equal '
describe service("avahi-daemon").info[\'properties\'][\'UnitFileState\'] do
it { should eq "enabled" }
end
'.strip
end
end
describe 'Inspec::EachLoop, each_loop' do
it 'constructs an each loop to match listening addresses' do
loop_obj = Inspec::EachLoop.new
loop_obj.qualifier = [['port', 25]]
loop_obj.qualifier.push(['addresses'])
obj = Inspec::Test.new
obj.matcher = 'match'
obj.negate!
obj.expectation = '0.0.0.0'
loop_obj.add_test(obj)
loop_obj.to_ruby.must_equal '
port(25).addresses.each do |entry|
describe entry do
it { should_not match "0.0.0.0" }
end
end
'.strip
end
end
describe 'Inspec::List' do
it 'constructs a list filtering test' do
list_obj = Inspec::List.new([['passwd']])
list_obj.qualifier.push(["where { user =~ /^(?!root|sync|shutdown|halt).*$/ }"])
obj = Inspec::Test.new
obj.qualifier = list_obj.qualifier
obj.matcher = 'be_empty'
obj.qualifier.push(['entries'])
obj.negate!
obj.to_ruby.must_equal '
describe passwd.where { user =~ /^(?!root|sync|shutdown|halt).*$/ } do
its("entries") { should_not be_empty }
end
'.strip
end
end
describe 'Inspec::OrTest and Inspec::Control' do
let(:obj1) do
obj1 = Inspec::Test.new
obj1.qualifier = [['command','ls /etc'], ['exit_status']]
obj1.matcher = 'eq'
obj1.expectation = 0
obj1
end
let(:obj2) do
obj2 = obj1.dup
obj2.negate!
obj2.expectation = 100
obj2
end
it 'constructs a simple describe.one block wrapping two tests' do
or_obj = Inspec::OrTest.new([obj1,obj2])
or_obj.to_ruby.must_equal '
describe.one do
describe command("ls /etc") do
its("exit_status") { should eq 0 }
end
describe command("ls /etc") do
its("exit_status") { should_not eq 100 }
end
end
'.strip
end
it 'negates a describe.one block, wow!' do
or_obj = Inspec::OrTest.new([obj1,obj2])
or_obj.negate!
or_obj.to_ruby.must_equal '
describe command("ls /etc") do
its("exit_status") { should_not eq 0 }
end
describe command("ls /etc") do
its("exit_status") { should eq 100 }
end
'.strip
end
it 'loops a describe.one block, ooooooo!' do
res = Inspec::EachLoop.new
res.qualifier.push(['(1..5)'])
# already defined in the let block:
obj1.matcher = 'eq entity'
obj2.matcher = 'eq entity'
obj1.remove_expectation
obj2.remove_expectation
or_obj = Inspec::OrTest.new([obj1,obj2])
res.tests = [or_obj]
res.to_ruby.must_equal '
(1..5).each do |entry|
describe.one do
describe command("ls /etc") do
its("exit_status") { should eq entity }
end
describe command("ls /etc") do
its("exit_status") { should_not eq entity }
end
end
end
'.strip
end
it 'constructs a control' do
control = Inspec::Control.new
control.add_test(obj1)
control.id = 'sample.control.id'
control.title = 'Sample Control Important Title'
control.desc = 'The most critical control the world has ever seen'
control.impact = 1.0
control.to_ruby.must_equal '
control "sample.control.id" do
title "Sample Control Important Title"
desc "The most critical control the world has ever seen"
impact 1.0
describe command("ls /etc") do
its("exit_status") { should eq 0 }
end
end
'.strip
end
end
describe 'Inspec::Variable, take #1' do
it 'constructs a control with variable to instantiate a resource only once' do
control = Inspec::Control.new
variable = Inspec::Value.new([['command','which grep']])
variable_id = variable.name_variable.to_s
obj1 = Inspec::Test.new
obj1.variables.push(variable)
obj1.qualifier.push([variable_id])
obj1.qualifier.push(['exit_status'])
obj1.matcher = 'eq'
obj1.expectation = 0
control.add_test(obj1)
obj2 = Inspec::Test.new
obj2.qualifier.push([variable_id.to_s])
obj2.qualifier.push(['stdout'])
obj2.matcher = 'contain'
obj2.expectation = 'grep'
control.add_test(obj2)
control.id = 'variable.control.id'
control.title = 'Variable Control Important Title'
control.desc = 'The most variable control the world has ever seen'
control.impact = 1.0
control.to_ruby.must_equal '
control "variable.control.id" do
title "Variable Control Important Title"
desc "The most variable control the world has ever seen"
impact 1.0
a = command("which grep")
describe a do
its("exit_status") { should eq 0 }
end
describe a do
its("stdout") { should contain "grep" }
end
end
'.strip
end
end
describe 'Inspec::Variable, take #2' do
it 'constructs a control with variable, loop and var reference' do
control = Inspec::Control.new
command_value = /^\/usr\/bin\/chrony/
pid_filter = '>'
pid_value = 0
loopy = Inspec::EachLoop.new
loopy.qualifier = [['processes', command_value]]
loopy.qualifier.push(["where { pid #{pid_filter} #{pid_value} }.entries"])
obj = loopy.add_test
variable = Inspec::Value.new([['passwd.where { user == "_chrony" }.uids.first']])
variable_id = variable.name_variable.to_s
obj.variables.push(variable)
obj.qualifier = [['user(entry.user)'], ['uid']]
obj.matcher = "cmp #{variable_id}"
control.add_test(obj)
control.id = 'variable.control.id'
control.impact = 0.1
control.to_ruby.must_equal '
control "variable.control.id" do
impact 0.1
a = passwd.where { user == "_chrony" }.uids.first
describe user(entry.user) do
its("uid") { should cmp a }
end
end
'.strip
end
end
end

View file

@ -0,0 +1,5 @@
#
# This is a sample crontab file for unit testing, for user 'foouser'
#
* * * * * /path/to/script3

View file

@ -0,0 +1,10 @@
#
# This is a sample crontab file for unit testing
#
# entry number 1
0 2 11 9 4 /path/to/script1
# entry number 2
1 3 12 10 5 /path/to/script2 arg1 arg2

View file

@ -0,0 +1,12 @@
ii bash 4.3-14ubuntu1.1
rc fakeroot 1.20.2-1ubuntu1
rc libfakeroot 1.20.2-1ubuntu1
ii overlayroot 0.27ubuntu1.2
ii vim 2:7.4.1689-3ubuntu1.2
ii vim-common 2:7.4.1689-3ubuntu1.2
ii xorg 1:7.7+13ubuntu3
ii xorg-docs-core 1:1.7.1-1ubuntu1
ii xserver-common 2:1.18.4-0ubuntu0.2
ii xserver-xorg 1:7.7+13ubuntu3
ii xserver-xorg-core 2:1.18.4-0ubuntu0.2
ii xserver-xorg-input-all 1:7.7+13ubuntu3

View file

@ -1,2 +1,3 @@
/etc/xinetd.d/chargen-stream
/etc/xinetd.d/chargen-dgram
/etc/xinetd.d/echo

View file

@ -0,0 +1 @@
3.2.2

View file

@ -0,0 +1,10 @@
attr 2.4.44-7.el6
perl-Pod-Escapes 1.04-141.el6_7.1
perl-version 0.77-141.el6_7.1
perl-Pod-Simple 3.13-141.el6_7.1
vim-filesystem 7.4.629-5.el6
gpm-libs 1.20.6-12.el6
mlocate 0.22.2-6.el6
ntpdate 4.2.6p5-10.el6.centos.1
chef-compliance 1.3.1-1.el6
nc 1.84-24.el6

Some files were not shown because too many files have changed in this diff Show more