mirror of
https://github.com/inspec/inspec
synced 2024-11-26 22:50:36 +00:00
Merge branch 'master' into license-check
This commit is contained in:
commit
aa52697725
774 changed files with 18584 additions and 17644 deletions
|
@ -2,6 +2,9 @@ version: "2"
|
||||||
checks:
|
checks:
|
||||||
file-lines:
|
file-lines:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
identical-code:
|
||||||
|
config:
|
||||||
|
threshold: 40 # Unfortunately, we have a lot of duplicate code in places like lib/inspec/control_eval_context.rb
|
||||||
plugins:
|
plugins:
|
||||||
fixme:
|
fixme:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -11,10 +14,9 @@ plugins:
|
||||||
- rubocop:disable
|
- rubocop:disable
|
||||||
flog:
|
flog:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
config:
|
||||||
|
score_threshold: 30
|
||||||
markdownlint:
|
markdownlint:
|
||||||
enabled: true
|
enabled: true
|
||||||
rubocop:
|
exclude_patterns:
|
||||||
enabled: true
|
- "www/source/javascripts/"
|
||||||
channel: rubocop-0-49
|
|
||||||
config:
|
|
||||||
file: .rubocop.yml
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ rubygems:
|
||||||
- inspec-core
|
- inspec-core
|
||||||
- inspec-bin:
|
- inspec-bin:
|
||||||
gemspec_path: ./inspec-bin/
|
gemspec_path: ./inspec-bin/
|
||||||
|
- inspec-core-bin:
|
||||||
|
gemspec_path: ./inspec-bin/
|
||||||
|
|
||||||
docker_images:
|
docker_images:
|
||||||
- inspec:
|
- inspec:
|
||||||
|
|
|
@ -6,5 +6,5 @@
|
||||||
|
|
||||||
set -evx
|
set -evx
|
||||||
|
|
||||||
sed -i -r "s/VERSION = '.*'/VERSION = '$(cat VERSION)'/" lib/inspec/version.rb
|
sed -i -r "s/VERSION = \".*\"/VERSION = \"$(cat VERSION)\"/" lib/inspec/version.rb
|
||||||
sed -i -r "s/VERSION = '.*'/VERSION = '$(cat VERSION)'/" inspec-bin/lib/inspec-bin/version.rb
|
sed -i -r "s/VERSION = \".*\"/VERSION = \"$(cat VERSION)\"/" inspec-bin/lib/inspec-bin/version.rb
|
||||||
|
|
11
.github/stale.yml
vendored
11
.github/stale.yml
vendored
|
@ -1,7 +1,7 @@
|
||||||
# Number of days of inactivity before an issue becomes stale
|
# Number of days of inactivity before an issue becomes stale
|
||||||
daysUntilStale: 365
|
daysUntilStale: 365
|
||||||
# Number of days of inactivity before a stale issue is closed
|
# Number of days of inactivity before a stale issue is closed
|
||||||
daysUntilClose: false
|
daysUntilClose: 400
|
||||||
# Issues with these labels will never be considered stale
|
# Issues with these labels will never be considered stale
|
||||||
exemptLabels:
|
exemptLabels:
|
||||||
- "Aspect: Security"
|
- "Aspect: Security"
|
||||||
|
@ -11,8 +11,11 @@ staleLabel: Stale
|
||||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||||
markComment: >
|
markComment: >
|
||||||
This issue has been automatically marked as stale because it has not had
|
This issue has been automatically marked as stale because it has not had
|
||||||
recent activity. It will be closed if no further activity occurs.
|
recent activity. It will be closed if no further activity occurs.
|
||||||
We value your input and contribution.
|
We value your input and contribution.
|
||||||
Please leave a comment if this issue still affects you.
|
Please leave a comment if this issue still affects you.
|
||||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||||
closeComment: false
|
closeComment: >
|
||||||
|
This issue has been automatically closed after being stale for 400 days.
|
||||||
|
We still value your input and contribution.
|
||||||
|
Please re-open the issue if desired and leave a comment with details.
|
||||||
|
|
60
.gitignore
vendored
60
.gitignore
vendored
|
@ -1,42 +1,40 @@
|
||||||
Gemfile.lock
|
|
||||||
Gemfile.local
|
|
||||||
coverage
|
|
||||||
*.gem
|
*.gem
|
||||||
|
.attribute.yml
|
||||||
|
.bundle
|
||||||
|
.delivery/cli.toml
|
||||||
.gallery
|
.gallery
|
||||||
.kitchen
|
.kitchen
|
||||||
.delivery/cli.toml
|
|
||||||
Berksfile.lock
|
|
||||||
.bundle
|
|
||||||
.librarian
|
|
||||||
Puppetfile.lock
|
|
||||||
.kitchen.local.yml
|
.kitchen.local.yml
|
||||||
kitchen.local.yml
|
.librarian
|
||||||
profile.tar.gz
|
.terraform/
|
||||||
omnibus/.cache
|
/.direnv
|
||||||
omnibus/pkg
|
/.envrc
|
||||||
test/**/*.lock
|
/.ruby-gemset
|
||||||
|
/.ruby-version
|
||||||
|
/Berksfile.lock
|
||||||
|
/Gemfile.local
|
||||||
|
Gemfile.lock
|
||||||
|
Puppetfile.lock
|
||||||
|
contrib/*
|
||||||
|
coverage
|
||||||
examples/**/*.lock
|
examples/**/*.lock
|
||||||
examples/meta-profile/vendor/
|
examples/meta-profile/vendor/
|
||||||
habitat/VERSION
|
habitat/VERSION
|
||||||
habitat/results
|
habitat/results
|
||||||
/.ruby-gemset
|
|
||||||
/.ruby-version
|
|
||||||
/.direnv
|
|
||||||
/.envrc
|
|
||||||
results/
|
|
||||||
|
|
||||||
www/source/index.html.slim
|
|
||||||
www/Gemfile.lock
|
|
||||||
|
|
||||||
meta-profile-0.2.0.tar.gz
|
|
||||||
profile-1.0.0.tar.gz
|
|
||||||
.attribute.yml
|
|
||||||
.terraform/
|
|
||||||
terraform.tfvars
|
|
||||||
terraform.tfstate*
|
|
||||||
terraform.tfstate.backup
|
|
||||||
inspec-azure.plan
|
|
||||||
inspec-aws-*.plan
|
inspec-aws-*.plan
|
||||||
contrib/*
|
inspec-azure.plan
|
||||||
inspec-deprecations-in-cfg.txt
|
inspec-deprecations-in-cfg.txt
|
||||||
inspec-deprecations-in-lib.txt
|
inspec-deprecations-in-lib.txt
|
||||||
|
kitchen.local.yml
|
||||||
|
meta-profile-0.2.0.tar.gz
|
||||||
|
omnibus/.cache
|
||||||
|
omnibus/pkg
|
||||||
|
profile-1.0.0.tar.gz
|
||||||
|
profile.tar.gz
|
||||||
|
results/
|
||||||
|
terraform.tfstate*
|
||||||
|
terraform.tfstate.backup
|
||||||
|
terraform.tfvars
|
||||||
|
test/**/*.lock
|
||||||
|
www/Gemfile.lock
|
||||||
|
www/source/index.html.slim
|
||||||
|
|
1
.mdlrc
Normal file
1
.mdlrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
line-length false
|
116
.rubocop.yml
116
.rubocop.yml
|
@ -1,112 +1,8 @@
|
||||||
---
|
|
||||||
AllCops:
|
AllCops:
|
||||||
DisplayCopNames: true
|
|
||||||
TargetRubyVersion: 2.4
|
|
||||||
Exclude:
|
Exclude:
|
||||||
- Gemfile
|
- 'test/integration/**/controls/**/*.rb'
|
||||||
- Rakefile
|
- 'test/unit/mock/profiles/**/*.rb'
|
||||||
- 'test/**/*'
|
- 'test/unit/mock/config_dirs/**/*.rb'
|
||||||
- 'lib/plugins/*/test/**/*'
|
- 'lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/**/*'
|
||||||
- 'lib/plugins/inspec-init/templates/**/*'
|
- 'examples/**/controls/*.rb'
|
||||||
# This is delicate; we want to include examples/plugins/*/lib
|
- 'vendor/bundle/**/*'
|
||||||
# but not anything else.
|
|
||||||
- 'examples/*profile*/**/*'
|
|
||||||
- 'examples/kitchen*/**/*'
|
|
||||||
- 'examples/inheritance/**/*'
|
|
||||||
- 'examples/custom-resource/**/*'
|
|
||||||
- 'examples/plugins/*/test/**/*'
|
|
||||||
- 'vendor/**/*'
|
|
||||||
- 'lib/bundles/inspec-init/templates/**/*'
|
|
||||||
- 'www/demo/**/*'
|
|
||||||
AlignParameters:
|
|
||||||
Enabled: true
|
|
||||||
BlockDelimiters:
|
|
||||||
Enabled: false
|
|
||||||
Documentation:
|
|
||||||
Enabled: false
|
|
||||||
EmptyLinesAroundBlockBody:
|
|
||||||
Enabled: false
|
|
||||||
FrozenStringLiteralComment:
|
|
||||||
Enabled: false
|
|
||||||
HashSyntax:
|
|
||||||
Enabled: true
|
|
||||||
LineLength:
|
|
||||||
Enabled: false
|
|
||||||
Layout/AlignHash:
|
|
||||||
Enabled: false
|
|
||||||
Layout/EmptyLineAfterMagicComment:
|
|
||||||
Enabled: false
|
|
||||||
Layout/EndOfLine:
|
|
||||||
Enabled: true
|
|
||||||
EnforcedStyle: lf
|
|
||||||
Layout/SpaceAroundOperators:
|
|
||||||
Enabled: false
|
|
||||||
MethodLength:
|
|
||||||
Max: 40
|
|
||||||
Metrics/AbcSize:
|
|
||||||
Max: 33
|
|
||||||
Metrics/BlockLength:
|
|
||||||
Max: 50
|
|
||||||
Metrics/ClassLength:
|
|
||||||
Enabled: false
|
|
||||||
Metrics/CyclomaticComplexity:
|
|
||||||
Max: 10
|
|
||||||
Metrics/PerceivedComplexity:
|
|
||||||
Max: 11
|
|
||||||
NumericLiterals:
|
|
||||||
MinDigits: 10
|
|
||||||
Performance/RegexpMatch:
|
|
||||||
Enabled: false
|
|
||||||
Security/YAMLLoad:
|
|
||||||
Enabled: false
|
|
||||||
Style/AndOr:
|
|
||||||
Enabled: false
|
|
||||||
Style/BracesAroundHashParameters:
|
|
||||||
Enabled: false
|
|
||||||
Style/ClassAndModuleChildren:
|
|
||||||
Enabled: false
|
|
||||||
Style/ConditionalAssignment:
|
|
||||||
Enabled: false
|
|
||||||
Style/EmptyMethod:
|
|
||||||
Enabled: false
|
|
||||||
Style/Encoding:
|
|
||||||
Enabled: false
|
|
||||||
Style/FileName:
|
|
||||||
Enabled: false
|
|
||||||
Style/GuardClause:
|
|
||||||
Enabled: false
|
|
||||||
Style/IfUnlessModifier:
|
|
||||||
Enabled: false
|
|
||||||
Style/MethodMissing:
|
|
||||||
Enabled: false
|
|
||||||
Style/MultilineIfModifier:
|
|
||||||
Enabled: false
|
|
||||||
Style/NegatedIf:
|
|
||||||
Enabled: false
|
|
||||||
Style/Not:
|
|
||||||
Enabled: false
|
|
||||||
Style/NumericLiteralPrefix:
|
|
||||||
Enabled: false
|
|
||||||
Style/NumericPredicate:
|
|
||||||
Enabled: false
|
|
||||||
Style/PercentLiteralDelimiters:
|
|
||||||
PreferredDelimiters:
|
|
||||||
'%': '{}'
|
|
||||||
'%i': ()
|
|
||||||
'%q': '{}'
|
|
||||||
'%Q': ()
|
|
||||||
'%r': '{}'
|
|
||||||
'%s': ()
|
|
||||||
'%w': '{}'
|
|
||||||
'%W': ()
|
|
||||||
'%x': ()
|
|
||||||
Style/PredicateName:
|
|
||||||
Enabled: false
|
|
||||||
Style/SymbolArray:
|
|
||||||
Enabled: false
|
|
||||||
Style/TrailingCommaInArguments:
|
|
||||||
EnforcedStyleForMultiline: comma
|
|
||||||
Style/TrailingCommaInLiteral:
|
|
||||||
EnforcedStyleForMultiline: comma
|
|
||||||
Style/UnlessElse:
|
|
||||||
Enabled: false
|
|
||||||
|
|
124
.travis.yml
124
.travis.yml
|
@ -1,110 +1,50 @@
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- 3-stable
|
- /.*-stable/
|
||||||
|
- /cw.*/
|
||||||
|
- /mj.*/
|
||||||
|
- /zenspider.*/
|
||||||
language: ruby
|
language: ruby
|
||||||
cache:
|
cache:
|
||||||
- bundler
|
bundler: true
|
||||||
- directories:
|
directories:
|
||||||
- /home/travis/.rvm
|
- /home/travis/.rvm
|
||||||
dist: xenial
|
dist: xenial
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
bundler_args: "--without integration tools maintenance deploy"
|
bundler_args: "--without tools maintenance deploy"
|
||||||
before_install:
|
before_install:
|
||||||
- gem update --system
|
- "gem update --system '3.0'"
|
||||||
- gem --version
|
- gem --version
|
||||||
- bundle --version
|
- bundle --version
|
||||||
env:
|
env:
|
||||||
- SLOW=1
|
- SLOW=1 NO_AWS=1
|
||||||
|
- CI_ENABLE_COVERAGE=true SLOW=1
|
||||||
|
script: bundle exec rake $SUITE
|
||||||
matrix:
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
exclude:
|
||||||
|
- os: osx
|
||||||
|
env: CI_ENABLE_COVERAGE=true SLOW=1
|
||||||
|
- os: linux
|
||||||
|
env: SLOW=1 NO_AWS=1
|
||||||
include:
|
include:
|
||||||
- rvm: 2.4.5
|
|
||||||
env: UNIT_TESTS_24=1
|
|
||||||
- rvm: 2.5.5
|
|
||||||
env: UNIT_TESTS_25=1
|
|
||||||
- rvm: 2.6.3
|
- rvm: 2.6.3
|
||||||
env: UNIT_TESTS_26=1
|
- rvm: 2.5.5
|
||||||
- rvm: 2.4.5
|
- rvm: 2.4.5
|
||||||
script: bundle exec rake $SUITE
|
- env: SUITE=test:integration[default-ubuntu-1604]
|
||||||
env: SUITE="test:functional"
|
- env: SUITE=test:integration[default-ubuntu-1804]
|
||||||
- rvm: 2.5.5
|
- env: SUITE=test:integration[default-centos-6]
|
||||||
script: bundle exec rake $SUITE
|
- env: SUITE=test:integration[default-centos-7]
|
||||||
env: SUITE="test:functional"
|
- env: SUITE=test:integration[default-debian-8]
|
||||||
- rvm: 2.6.2
|
- env: SUITE=test:integration[default-debian-9]
|
||||||
script: bundle exec rake $SUITE
|
- env: SUITE=test:integration[default-debian-10]
|
||||||
env: SUITE="test:functional"
|
- env: SUITE=test:integration[default-oraclelinux-6]
|
||||||
- rvm: 2.5.5
|
- env: SUITE=test:integration[default-oraclelinux-7]
|
||||||
script: bundle exec rake $SUITE
|
- env: SUITE=test:integration[default-fedora-29]
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-ubuntu-1604]
|
|
||||||
- rvm: 2.5.5
|
|
||||||
script: bundle exec rake $SUITE
|
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-ubuntu-1804]
|
|
||||||
- rvm: 2.5.5
|
|
||||||
script: bundle exec rake $SUITE
|
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-centos-6]
|
|
||||||
- rvm: 2.5.5
|
|
||||||
script: bundle exec rake $SUITE
|
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-centos-7]
|
|
||||||
- rvm: 2.5.5
|
|
||||||
script: bundle exec rake $SUITE
|
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-debian-8]
|
|
||||||
- rvm: 2.5.5
|
|
||||||
script: bundle exec rake $SUITE
|
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-debian-9]
|
|
||||||
- rvm: 2.5.5
|
|
||||||
script: bundle exec rake $SUITE
|
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-debian-10]
|
|
||||||
- rvm: 2.5.5
|
|
||||||
script: bundle exec rake $SUITE
|
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-oraclelinux-6]
|
|
||||||
- rvm: 2.5.5
|
|
||||||
script: bundle exec rake $SUITE
|
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-oraclelinux-7]
|
|
||||||
- rvm: 2.5.5
|
|
||||||
script: bundle exec rake $SUITE
|
|
||||||
bundler_args: "--without tools maintenance deploy"
|
|
||||||
env: SUITE=test:integration[default-fedora-29]
|
|
||||||
- rvm: 2.4.5
|
|
||||||
sudo: false
|
|
||||||
cache:
|
|
||||||
apt: true
|
|
||||||
bundle: true
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- curl
|
|
||||||
- nodejs
|
|
||||||
env:
|
|
||||||
- AFFECTED_DIRS="www"
|
|
||||||
- secure: "jdzXUhP1o7RkfSikZLKgUcCIaKqLjqWa35dnxWnz7qAQ2draRKa7I7cXmUv76BZkW8HBUUH11dOi8YOVxPYPOzaqvcTCfqNqGVxsT9epgWa7rA8aXMXkECp548ry1rYJQpti9zpwsoe2GQyNPr9vNiWMiyj51CaABmZ6JzmFEEqlZc8vqpqWeqJvIqaibQGk7ByLKmi4R44fVwFKIG39RuxV+alc/G4nnQ2zmNTFuy8uFGs5EghQvRytzWY+s2AKtDiZ0YXYOII1Nl1unXNnNoQt9oI209ztlSm1+XOuTPelW6bEIx5i7OZFaSRPgJzWnkGN85C9nBE08L2az9Jz18/rYJF4fdVRttdGskueyYI21lh1FwlAg51ZG0RfLTYk2Pq+k4c+NO1cfmGcaXBwihfD5BWqrILU5HHkYszXCSmgl4hscC7/BS4Kgcq2z32JJwV8B+x4XngM0G4uzIn1Soia3lZXEKdnfVsxFDdMQ7FK60F3uQlq/44LRkZujRhqfAKOiz+0tsLexWzj7wK+DJY9Y00CUfh7xcxRxDxFNpOv1FWYFB9lUlaOt3HDHgUoksqbURiUzhOZZzTE/1MAtF2K6mbpME5CbN08J88L5JBlb+CX79XCzj30lNMeS0I/dCRQEmkygr2eJYxvRO2qsBNuphs4SWk8NZyS/llVZFI="
|
|
||||||
before_install: ./support/ci/fast_pass.sh || exit 0
|
|
||||||
script: ./support/ci/deploy_website_to_acceptance.sh
|
|
||||||
|
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- env:
|
- env: CI_ENABLE_COVERAGE=true SLOW=1
|
||||||
- AFFECTED_DIRS="www"
|
|
||||||
- secure: "jdzXUhP1o7RkfSikZLKgUcCIaKqLjqWa35dnxWnz7qAQ2draRKa7I7cXmUv76BZkW8HBUUH11dOi8YOVxPYPOzaqvcTCfqNqGVxsT9epgWa7rA8aXMXkECp548ry1rYJQpti9zpwsoe2GQyNPr9vNiWMiyj51CaABmZ6JzmFEEqlZc8vqpqWeqJvIqaibQGk7ByLKmi4R44fVwFKIG39RuxV+alc/G4nnQ2zmNTFuy8uFGs5EghQvRytzWY+s2AKtDiZ0YXYOII1Nl1unXNnNoQt9oI209ztlSm1+XOuTPelW6bEIx5i7OZFaSRPgJzWnkGN85C9nBE08L2az9Jz18/rYJF4fdVRttdGskueyYI21lh1FwlAg51ZG0RfLTYk2Pq+k4c+NO1cfmGcaXBwihfD5BWqrILU5HHkYszXCSmgl4hscC7/BS4Kgcq2z32JJwV8B+x4XngM0G4uzIn1Soia3lZXEKdnfVsxFDdMQ7FK60F3uQlq/44LRkZujRhqfAKOiz+0tsLexWzj7wK+DJY9Y00CUfh7xcxRxDxFNpOv1FWYFB9lUlaOt3HDHgUoksqbURiUzhOZZzTE/1MAtF2K6mbpME5CbN08J88L5JBlb+CX79XCzj30lNMeS0I/dCRQEmkygr2eJYxvRO2qsBNuphs4SWk8NZyS/llVZFI="
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
slack:
|
|
||||||
secure: zwOu1gWt8wBDzlhXrYJ39jBDYTYj4Zb8/Z5XH6PalFOyYBytOLYqmpPzxw5KTzFapmcxYt1/biViX25+zapSSmDBuDa94ZneaXuCZAPXX0UJb82ORALMDsdbV1TkkS4Q6N4soigLJ5UaJwIgkZze9VtXeUvo3g8L8+mDYX4J0Poi7Kf/f1KZycNhgaVs7N/i2AI3lBeiVJv+giQbA99OR5dxPzkbx1BeZCK+W+YEPFmg1xycAItiHq0unT+kBN4pm9gW8TT1s/ZucUsKVu6Q8inw5N0PjZwboOkqsQFi5BweVicZBcbOVsW3Xs/f8DX2G823y73Al3QQg+ENxnIpizsHfjE+YzXUVsZ7v/UdsOq01Khxz1GK/X/PYrvIdHQKBwZ86RPJP61BvGIaQ4Hy6f9z+o2Tl/EaAmiOMScpdFi7sMskm8xknI0G24ZG5hkd7XNQ1eVvu33dvs+u12DsBGIylnwrppMDGnh022I5Hg8pS9tJ9gAsJlSFoIBn/yOryoFYb4avB8ujvN6+8cbZgkQ41k6ydqCHk2DxWmhsM4dUVXqC36sOePDE8a/DK5uQ057DSai5M+go5LeEJyK5r4fT5nbTk3nW6CGH0k2bPGWH5aP22mSKB9r2alDzqVfVyArfgtBIX2OXS/cZLER26a1EcB4mf3PMPDB06Aekyj0=
|
|
||||||
on_success: change
|
|
||||||
on_failure: always
|
|
||||||
on_pull_requests: false
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
provider: rubygems
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
api_key:
|
|
||||||
secure: uI2Zy3z4ljvOoG/6E4XPmSDg4QX5jmUfp6N9lzOfOosuZGjiGG6cWe4QMfidIz4/B5Ctp9X78bYCPxLkhCPmY9qcsR6eimQsC5AwGJhQF2Fz5fSX12LO+P4H7bis/A7cP+6QYNU8n9oXy6MYIdaw8aLJoEK4tKlNueWYhKG99O1taiF6qXsKkuNXZW7LT3B774IRCK0+BUknfW22ksAOeSpk10dkPXW5lEluXq/Q60L6+Cy01Yix1gLNav7ftMeOtE968mK3L1mzf0L3q8Tih3PLwEzYZRYQRTsd8f1J6XmNZtpdW5QiehvX08ZiFT28Dx15GMp5OKc7TnfU5avm8ryxFJB8xfdrkwNPf/UB3z1IVpHIJ6ZQlHDaiJBL429ZgYSCwrdk71IHWaAK4zSuOZyE+y9EmXbdgLLMgY6QIVrgoBLzzHLCQADXchrMaYR8LIkKI5euOfl3d96sSqXrIN/v1LSlPG/Z1LVO07cYarVGy3J/iM5aTghw3ixZcdlepGrU9DIxe7kRhmz7OLDGTZiPyRzXX1IRjaxSBMGmQSJVv6+r2UJRLmpC3W+1ysXY7nZtffzrFXHGacyvcIHxm8KSPvHgfloPvgFeebcTHcly50TOcZuBc4ZF9HZwWR5lEg/1OX5puBYE7IYfLyFm48+pqFk++tbn2glE742BhkY=
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
source 'https://supermarket.chef.io'
|
source "https://supermarket.chef.io"
|
||||||
|
|
||||||
cookbook 'audit'
|
cookbook "audit"
|
||||||
cookbook 'os_prepare', path: './test/cookbooks/os_prepare'
|
cookbook "os_prepare", path: "./test/cookbooks/os_prepare"
|
||||||
|
|
200
CHANGELOG.md
200
CHANGELOG.md
|
@ -1,96 +1,123 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
|
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
|
||||||
<!-- latest_release 4.4.65 -->
|
<!-- latest_release -->
|
||||||
## [v4.4.65](https://github.com/inspec/inspec/tree/v4.4.65) (2019-05-31)
|
|
||||||
|
|
||||||
#### Merged Pull Requests
|
|
||||||
- Remove all leading newlines. [#4152](https://github.com/inspec/inspec/pull/4152) ([miah](https://github.com/miah))
|
|
||||||
<!-- latest_release -->
|
<!-- latest_release -->
|
||||||
|
|
||||||
<!-- release_rollup since=4.3.2 -->
|
<!-- release_rollup -->
|
||||||
### Changes since 4.3.2 release
|
|
||||||
|
|
||||||
#### Bug Fixes
|
|
||||||
- inspec check: Send log to STDERR when running with --format json [#4001](https://github.com/inspec/inspec/pull/4001) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 4.4.55 -->
|
|
||||||
|
|
||||||
#### New Features
|
|
||||||
- Rename 'attribute' DSL method to 'input' [#4008](https://github.com/inspec/inspec/pull/4008) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 4.4.0 -->
|
|
||||||
|
|
||||||
#### Enhancements
|
|
||||||
- Add missing tests for DataSeries#enabled? #disable [#4036](https://github.com/inspec/inspec/pull/4036) ([miah](https://github.com/miah)) <!-- 4.4.5 -->
|
|
||||||
- Improve testing on inputs that do not have values [#4007](https://github.com/inspec/inspec/pull/4007) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 4.4.0 -->
|
|
||||||
- Add inspec-*-bin to the plugin filter list [#4018](https://github.com/inspec/inspec/pull/4018) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 4.3.5 -->
|
|
||||||
|
|
||||||
#### Merged Pull Requests
|
|
||||||
- Remove all leading newlines. [#4152](https://github.com/inspec/inspec/pull/4152) ([miah](https://github.com/miah)) <!-- 4.4.65 -->
|
|
||||||
- Mention inspec-bin gem in installation instructions [#4163](https://github.com/inspec/inspec/pull/4163) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 4.4.64 -->
|
|
||||||
- Replace Jenkins omnibus build/test pipeline with Buildkite [#4169](https://github.com/inspec/inspec/pull/4169) ([jeremiahsnapp](https://github.com/jeremiahsnapp)) <!-- 4.4.63 -->
|
|
||||||
- This should fix our licensing failures [#4165](https://github.com/inspec/inspec/pull/4165) ([zenspider](https://github.com/zenspider)) <!-- 4.4.62 -->
|
|
||||||
- Update sunset messages on 2 resources [#4164](https://github.com/inspec/inspec/pull/4164) ([clintoncwolfe](https://github.com/clintoncwolfe)) <!-- 4.4.61 -->
|
|
||||||
- Clean unnecessary requires [#4142](https://github.com/inspec/inspec/pull/4142) ([zenspider](https://github.com/zenspider)) <!-- 4.4.61 -->
|
|
||||||
- Windows fixes [#4159](https://github.com/inspec/inspec/pull/4159) ([zenspider](https://github.com/zenspider)) <!-- 4.4.60 -->
|
|
||||||
- Make travis green again [#4160](https://github.com/inspec/inspec/pull/4160) ([zenspider](https://github.com/zenspider)) <!-- 4.4.59 -->
|
|
||||||
- Cache the .rvm directory in travis [#4153](https://github.com/inspec/inspec/pull/4153) ([miah](https://github.com/miah)) <!-- 4.4.58 -->
|
|
||||||
- Dist branding for some of plugins [#4136](https://github.com/inspec/inspec/pull/4136) ([artem-sidorenko](https://github.com/artem-sidorenko)) <!-- 4.4.57 -->
|
|
||||||
- Remove authors tags from source files. [#4147](https://github.com/inspec/inspec/pull/4147) ([miah](https://github.com/miah)) <!-- 4.4.56 -->
|
|
||||||
- Move utils under inspec directory namespace [#4063](https://github.com/inspec/inspec/pull/4063) ([miah](https://github.com/miah)) <!-- 4.4.54 -->
|
|
||||||
- Update author/email tags in gemspec [#4137](https://github.com/inspec/inspec/pull/4137) ([miah](https://github.com/miah)) <!-- 4.4.53 -->
|
|
||||||
- Extracting mock_loader to its own helper file. [#4141](https://github.com/inspec/inspec/pull/4141) ([zenspider](https://github.com/zenspider)) <!-- 4.4.52 -->
|
|
||||||
- supermakert -> supermarket [#4140](https://github.com/inspec/inspec/pull/4140) ([zenspider](https://github.com/zenspider)) <!-- 4.4.51 -->
|
|
||||||
- No tabs. [#4143](https://github.com/inspec/inspec/pull/4143) ([zenspider](https://github.com/zenspider)) <!-- 4.4.50 -->
|
|
||||||
- Flag `rubocop:disable` comments as something to be fixed. [#4123](https://github.com/inspec/inspec/pull/4123) ([miah](https://github.com/miah)) <!-- 4.4.49 -->
|
|
||||||
- GCP Update for InSpec Cloud Platform documentation [#4122](https://github.com/inspec/inspec/pull/4122) ([mjingle](https://github.com/mjingle)) <!-- 4.4.48 -->
|
|
||||||
- Fix github url regex. Add period for repo [#4089](https://github.com/inspec/inspec/pull/4089) ([mirskiy](https://github.com/mirskiy)) <!-- 4.4.47 -->
|
|
||||||
- Ensure AwsResourceMixin returns a resource name in deprecation message [#4104](https://github.com/inspec/inspec/pull/4104) ([miah](https://github.com/miah)) <!-- 4.4.46 -->
|
|
||||||
- Minor require cleanup for telemetry. [#4107](https://github.com/inspec/inspec/pull/4107) ([zenspider](https://github.com/zenspider)) <!-- 4.4.45 -->
|
|
||||||
- Fixed missing requires. [#4100](https://github.com/inspec/inspec/pull/4100) ([zenspider](https://github.com/zenspider)) <!-- 4.4.44 -->
|
|
||||||
- Delete test/unit/helper.rb [#4108](https://github.com/inspec/inspec/pull/4108) ([zenspider](https://github.com/zenspider)) <!-- 4.4.43 -->
|
|
||||||
- Stop using method(...).call(...) [#4115](https://github.com/inspec/inspec/pull/4115) ([zenspider](https://github.com/zenspider)) <!-- 4.4.42 -->
|
|
||||||
- Clean more requires [#4116](https://github.com/inspec/inspec/pull/4116) ([zenspider](https://github.com/zenspider)) <!-- 4.4.41 -->
|
|
||||||
- Just use math. [#4113](https://github.com/inspec/inspec/pull/4113) ([zenspider](https://github.com/zenspider)) <!-- 4.4.40 -->
|
|
||||||
- Clean up API doco [#4114](https://github.com/inspec/inspec/pull/4114) ([zenspider](https://github.com/zenspider)) <!-- 4.4.39 -->
|
|
||||||
- Add support for Gemfile.local [#4105](https://github.com/inspec/inspec/pull/4105) ([zenspider](https://github.com/zenspider)) <!-- 4.4.38 -->
|
|
||||||
- Fix missing requires in toml, postgres_conf resources [#4119](https://github.com/inspec/inspec/pull/4119) ([miah](https://github.com/miah)) <!-- 4.4.37 -->
|
|
||||||
- json was required twice. [#4118](https://github.com/inspec/inspec/pull/4118) ([miah](https://github.com/miah)) <!-- 4.4.36 -->
|
|
||||||
- Fixes a test interaction bug between installer and loader. [#4111](https://github.com/inspec/inspec/pull/4111) ([zenspider](https://github.com/zenspider)) <!-- 4.4.35 -->
|
|
||||||
- This needed to be a flat_map because :profiles was an array. [#4110](https://github.com/inspec/inspec/pull/4110) ([zenspider](https://github.com/zenspider)) <!-- 4.4.34 -->
|
|
||||||
- Fix @unique_controls uninitialized warning [#4079](https://github.com/inspec/inspec/pull/4079) ([miah](https://github.com/miah)) <!-- 4.4.33 -->
|
|
||||||
- Turn off logging in our test. [#4103](https://github.com/inspec/inspec/pull/4103) ([zenspider](https://github.com/zenspider)) <!-- 4.4.32 -->
|
|
||||||
- Use #key? rather than #has_key? in profile_name ternary [#4101](https://github.com/inspec/inspec/pull/4101) ([miah](https://github.com/miah)) <!-- 4.4.31 -->
|
|
||||||
- Fix @profile_name not initialized [#4081](https://github.com/inspec/inspec/pull/4081) ([miah](https://github.com/miah)) <!-- 4.4.30 -->
|
|
||||||
- Fix circular require in telemetry [#4083](https://github.com/inspec/inspec/pull/4083) ([miah](https://github.com/miah)) <!-- 4.4.29 -->
|
|
||||||
- Fix up sporadically failing tests and ensure tests can run independently [#4031](https://github.com/inspec/inspec/pull/4031) ([zenspider](https://github.com/zenspider)) <!-- 4.4.28 -->
|
|
||||||
- Updates the init profile description to show proper usage [#4085](https://github.com/inspec/inspec/pull/4085) ([burtlo](https://github.com/burtlo)) <!-- 4.4.27 -->
|
|
||||||
- `rubocop -a` on kitchen directory [#4082](https://github.com/inspec/inspec/pull/4082) ([miah](https://github.com/miah)) <!-- 4.4.26 -->
|
|
||||||
- Remove the deprecated linux_kernel_parameter resource test [#4078](https://github.com/inspec/inspec/pull/4078) ([tas50](https://github.com/tas50)) <!-- 4.4.25 -->
|
|
||||||
- Build the InSpec gem directly in Kitchen so we can run locally [#4077](https://github.com/inspec/inspec/pull/4077) ([tas50](https://github.com/tas50)) <!-- 4.4.24 -->
|
|
||||||
- Add kitchen rake testing [#4076](https://github.com/inspec/inspec/pull/4076) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 4.4.23 -->
|
|
||||||
- Cleanup and fix failing Kitchen tests [#4074](https://github.com/inspec/inspec/pull/4074) ([tas50](https://github.com/tas50)) <!-- 4.4.22 -->
|
|
||||||
- Upgrade to Ruby 2.6.3 [#4073](https://github.com/inspec/inspec/pull/4073) ([tas50](https://github.com/tas50)) <!-- 4.4.21 -->
|
|
||||||
- Update our Code of Conduct [#4072](https://github.com/inspec/inspec/pull/4072) ([miah](https://github.com/miah)) <!-- 4.4.20 -->
|
|
||||||
- Include info about Chef License Requirements [#4071](https://github.com/inspec/inspec/pull/4071) ([mjingle](https://github.com/mjingle)) <!-- 4.4.19 -->
|
|
||||||
- Removed unneeded 'supports: windows' [#4052](https://github.com/inspec/inspec/pull/4052) ([aaronlippold](https://github.com/aaronlippold)) <!-- 4.4.18 -->
|
|
||||||
- Make the postgres resource more defensive [#4037](https://github.com/inspec/inspec/pull/4037) ([alexpop](https://github.com/alexpop)) <!-- 4.4.17 -->
|
|
||||||
- Add codeclimate to our pipeline [#4044](https://github.com/inspec/inspec/pull/4044) ([miah](https://github.com/miah)) <!-- 4.4.16 -->
|
|
||||||
- Emergency test fixes! [#4066](https://github.com/inspec/inspec/pull/4066) ([zenspider](https://github.com/zenspider)) <!-- 4.4.15 -->
|
|
||||||
- Remove more magic comments [#4050](https://github.com/inspec/inspec/pull/4050) ([miah](https://github.com/miah)) <!-- 4.4.14 -->
|
|
||||||
- Fix broken tests after removing magic comments. [#4046](https://github.com/inspec/inspec/pull/4046) ([miah](https://github.com/miah)) <!-- 4.4.13 -->
|
|
||||||
- Wrap resources in backticks and remove resource name capitalizing [#4043](https://github.com/inspec/inspec/pull/4043) ([alexpop](https://github.com/alexpop)) <!-- 4.4.12 -->
|
|
||||||
- Relocate core resources from lib/resources to lib/inspec/resources [#4042](https://github.com/inspec/inspec/pull/4042) ([miah](https://github.com/miah)) <!-- 4.4.11 -->
|
|
||||||
- Convert Chef EULA to a local file [#4045](https://github.com/inspec/inspec/pull/4045) ([btm](https://github.com/btm)) <!-- 4.4.10 -->
|
|
||||||
- Configure expeditor to delete the branch after it is merged. [#4024](https://github.com/inspec/inspec/pull/4024) ([miah](https://github.com/miah)) <!-- 4.4.9 -->
|
|
||||||
- Remove `# encoding: utf8` magic comments [#4041](https://github.com/inspec/inspec/pull/4041) ([miah](https://github.com/miah)) <!-- 4.4.8 -->
|
|
||||||
- Add Coveralls.io support to InSpec [#3988](https://github.com/inspec/inspec/pull/3988) ([miah](https://github.com/miah)) <!-- 4.4.7 -->
|
|
||||||
- Enable user telemetry opt-in / opt-out on cli [#4025](https://github.com/inspec/inspec/pull/4025) ([miah](https://github.com/miah)) <!-- 4.4.6 -->
|
|
||||||
- First step to get inspec names changeable [#3954](https://github.com/inspec/inspec/pull/3954) ([artem-sidorenko](https://github.com/artem-sidorenko)) <!-- 4.4.4 -->
|
|
||||||
- Change software name from InSpec to Chef Inspec in documentation [#3987](https://github.com/inspec/inspec/pull/3987) ([IanMadd](https://github.com/IanMadd)) <!-- 4.4.3 -->
|
|
||||||
- Modernize use of Minitest. [#4023](https://github.com/inspec/inspec/pull/4023) ([zenspider](https://github.com/zenspider)) <!-- 4.4.2 -->
|
|
||||||
- Update the omnibus build license to the Chef EULA [#4038](https://github.com/inspec/inspec/pull/4038) ([btm](https://github.com/btm)) <!-- 4.4.1 -->
|
|
||||||
- Update resource registry_key documentation example [#4004](https://github.com/inspec/inspec/pull/4004) ([miah](https://github.com/miah)) <!-- 4.3.4 -->
|
|
||||||
- Update software names in readme [#4014](https://github.com/inspec/inspec/pull/4014) ([mjingle](https://github.com/mjingle)) <!-- 4.3.3 -->
|
|
||||||
<!-- release_rollup -->
|
<!-- release_rollup -->
|
||||||
|
|
||||||
<!-- latest_stable_release -->
|
<!-- latest_stable_release -->
|
||||||
|
## [v4.6.4](https://github.com/inspec/inspec/tree/v4.6.4) (2019-06-19)
|
||||||
|
|
||||||
|
#### Bug Fixes
|
||||||
|
- nginx_conf: Fix commented/empty file parsing [#4215](https://github.com/inspec/inspec/pull/4215) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
|
||||||
|
<!-- latest_stable_release -->
|
||||||
|
|
||||||
|
## [v4.6.3](https://github.com/inspec/inspec/tree/v4.6.3) (2019-06-17)
|
||||||
|
|
||||||
|
#### New Features
|
||||||
|
- Rename 'attribute' DSL method to 'input' [#4008](https://github.com/inspec/inspec/pull/4008) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- New plugin type: Input [#4019](https://github.com/inspec/inspec/pull/4019) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- Rename attributes -> inputs in profile metadata files [#4017](https://github.com/inspec/inspec/pull/4017) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
|
||||||
|
#### Enhancements
|
||||||
|
- Add inspec-*-bin to the plugin filter list [#4018](https://github.com/inspec/inspec/pull/4018) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- Improve testing on inputs that do not have values [#4007](https://github.com/inspec/inspec/pull/4007) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- Add missing tests for DataSeries#enabled? #disable [#4036](https://github.com/inspec/inspec/pull/4036) ([miah](https://github.com/miah))
|
||||||
|
- Add inspec-core-bin as a gem [#4009](https://github.com/inspec/inspec/pull/4009) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
|
||||||
|
#### Bug Fixes
|
||||||
|
- inspec check: Send log to STDERR when running with --format json [#4001](https://github.com/inspec/inspec/pull/4001) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- Fix two misrendering hyperlinks in resource docs [#4173](https://github.com/inspec/inspec/pull/4173) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- Fix Expeditor Version Bump Script [#4205](https://github.com/inspec/inspec/pull/4205) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- Remove clean-static-libs from omnibus build [#4207](https://github.com/inspec/inspec/pull/4207) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
|
||||||
|
#### Merged Pull Requests
|
||||||
|
- Update software names in readme [#4014](https://github.com/inspec/inspec/pull/4014) ([mjingle](https://github.com/mjingle))
|
||||||
|
- Update resource registry_key documentation example [#4004](https://github.com/inspec/inspec/pull/4004) ([miah](https://github.com/miah))
|
||||||
|
- Update the omnibus build license to the Chef EULA [#4038](https://github.com/inspec/inspec/pull/4038) ([btm](https://github.com/btm))
|
||||||
|
- Modernize use of Minitest. [#4023](https://github.com/inspec/inspec/pull/4023) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Change software name from InSpec to Chef Inspec in documentation [#3987](https://github.com/inspec/inspec/pull/3987) ([IanMadd](https://github.com/IanMadd))
|
||||||
|
- First step to get inspec names changeable [#3954](https://github.com/inspec/inspec/pull/3954) ([artem-sidorenko](https://github.com/artem-sidorenko))
|
||||||
|
- Enable user telemetry opt-in / opt-out on cli [#4025](https://github.com/inspec/inspec/pull/4025) ([miah](https://github.com/miah))
|
||||||
|
- Add Coveralls.io support to InSpec [#3988](https://github.com/inspec/inspec/pull/3988) ([miah](https://github.com/miah))
|
||||||
|
- Remove `# encoding: utf8` magic comments [#4041](https://github.com/inspec/inspec/pull/4041) ([miah](https://github.com/miah))
|
||||||
|
- Configure expeditor to delete the branch after it is merged. [#4024](https://github.com/inspec/inspec/pull/4024) ([miah](https://github.com/miah))
|
||||||
|
- Convert Chef EULA to a local file [#4045](https://github.com/inspec/inspec/pull/4045) ([btm](https://github.com/btm))
|
||||||
|
- Relocate core resources from lib/resources to lib/inspec/resources [#4042](https://github.com/inspec/inspec/pull/4042) ([miah](https://github.com/miah))
|
||||||
|
- Wrap resources in backticks and remove resource name capitalizing [#4043](https://github.com/inspec/inspec/pull/4043) ([alexpop](https://github.com/alexpop))
|
||||||
|
- Fix broken tests after removing magic comments. [#4046](https://github.com/inspec/inspec/pull/4046) ([miah](https://github.com/miah))
|
||||||
|
- Remove more magic comments [#4050](https://github.com/inspec/inspec/pull/4050) ([miah](https://github.com/miah))
|
||||||
|
- Emergency test fixes! [#4066](https://github.com/inspec/inspec/pull/4066) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Add codeclimate to our pipeline [#4044](https://github.com/inspec/inspec/pull/4044) ([miah](https://github.com/miah))
|
||||||
|
- Make the postgres resource more defensive [#4037](https://github.com/inspec/inspec/pull/4037) ([alexpop](https://github.com/alexpop))
|
||||||
|
- Removed unneeded 'supports: windows' [#4052](https://github.com/inspec/inspec/pull/4052) ([aaronlippold](https://github.com/aaronlippold))
|
||||||
|
- Include info about Chef License Requirements [#4071](https://github.com/inspec/inspec/pull/4071) ([mjingle](https://github.com/mjingle))
|
||||||
|
- Update our Code of Conduct [#4072](https://github.com/inspec/inspec/pull/4072) ([miah](https://github.com/miah))
|
||||||
|
- Upgrade to Ruby 2.6.3 [#4073](https://github.com/inspec/inspec/pull/4073) ([tas50](https://github.com/tas50))
|
||||||
|
- Cleanup and fix failing Kitchen tests [#4074](https://github.com/inspec/inspec/pull/4074) ([tas50](https://github.com/tas50))
|
||||||
|
- Add kitchen rake testing [#4076](https://github.com/inspec/inspec/pull/4076) ([lamont-granquist](https://github.com/lamont-granquist))
|
||||||
|
- Build the InSpec gem directly in Kitchen so we can run locally [#4077](https://github.com/inspec/inspec/pull/4077) ([tas50](https://github.com/tas50))
|
||||||
|
- Remove the deprecated linux_kernel_parameter resource test [#4078](https://github.com/inspec/inspec/pull/4078) ([tas50](https://github.com/tas50))
|
||||||
|
- `rubocop -a` on kitchen directory [#4082](https://github.com/inspec/inspec/pull/4082) ([miah](https://github.com/miah))
|
||||||
|
- Updates the init profile description to show proper usage [#4085](https://github.com/inspec/inspec/pull/4085) ([burtlo](https://github.com/burtlo))
|
||||||
|
- Fix up sporadically failing tests and ensure tests can run independently [#4031](https://github.com/inspec/inspec/pull/4031) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Fix circular require in telemetry [#4083](https://github.com/inspec/inspec/pull/4083) ([miah](https://github.com/miah))
|
||||||
|
- Fix @profile_name not initialized [#4081](https://github.com/inspec/inspec/pull/4081) ([miah](https://github.com/miah))
|
||||||
|
- Use #key? rather than #has_key? in profile_name ternary [#4101](https://github.com/inspec/inspec/pull/4101) ([miah](https://github.com/miah))
|
||||||
|
- Turn off logging in our test. [#4103](https://github.com/inspec/inspec/pull/4103) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Fix @unique_controls uninitialized warning [#4079](https://github.com/inspec/inspec/pull/4079) ([miah](https://github.com/miah))
|
||||||
|
- This needed to be a flat_map because :profiles was an array. [#4110](https://github.com/inspec/inspec/pull/4110) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Fixes a test interaction bug between installer and loader. [#4111](https://github.com/inspec/inspec/pull/4111) ([zenspider](https://github.com/zenspider))
|
||||||
|
- json was required twice. [#4118](https://github.com/inspec/inspec/pull/4118) ([miah](https://github.com/miah))
|
||||||
|
- Fix missing requires in toml, postgres_conf resources [#4119](https://github.com/inspec/inspec/pull/4119) ([miah](https://github.com/miah))
|
||||||
|
- Add support for Gemfile.local [#4105](https://github.com/inspec/inspec/pull/4105) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Clean up API doco [#4114](https://github.com/inspec/inspec/pull/4114) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Just use math. [#4113](https://github.com/inspec/inspec/pull/4113) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Clean more requires [#4116](https://github.com/inspec/inspec/pull/4116) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Stop using method(...).call(...) [#4115](https://github.com/inspec/inspec/pull/4115) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Delete test/unit/helper.rb [#4108](https://github.com/inspec/inspec/pull/4108) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Fixed missing requires. [#4100](https://github.com/inspec/inspec/pull/4100) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Minor require cleanup for telemetry. [#4107](https://github.com/inspec/inspec/pull/4107) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Ensure AwsResourceMixin returns a resource name in deprecation message [#4104](https://github.com/inspec/inspec/pull/4104) ([miah](https://github.com/miah))
|
||||||
|
- Fix github url regex. Add period for repo [#4089](https://github.com/inspec/inspec/pull/4089) ([mirskiy](https://github.com/mirskiy))
|
||||||
|
- GCP Update for InSpec Cloud Platform documentation [#4122](https://github.com/inspec/inspec/pull/4122) ([mjingle](https://github.com/mjingle))
|
||||||
|
- Flag `rubocop:disable` comments as something to be fixed. [#4123](https://github.com/inspec/inspec/pull/4123) ([miah](https://github.com/miah))
|
||||||
|
- No tabs. [#4143](https://github.com/inspec/inspec/pull/4143) ([zenspider](https://github.com/zenspider))
|
||||||
|
- supermakert -> supermarket [#4140](https://github.com/inspec/inspec/pull/4140) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Extracting mock_loader to its own helper file. [#4141](https://github.com/inspec/inspec/pull/4141) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Update author/email tags in gemspec [#4137](https://github.com/inspec/inspec/pull/4137) ([miah](https://github.com/miah))
|
||||||
|
- Move utils under inspec directory namespace [#4063](https://github.com/inspec/inspec/pull/4063) ([miah](https://github.com/miah))
|
||||||
|
- Remove authors tags from source files. [#4147](https://github.com/inspec/inspec/pull/4147) ([miah](https://github.com/miah))
|
||||||
|
- Dist branding for some of plugins [#4136](https://github.com/inspec/inspec/pull/4136) ([artem-sidorenko](https://github.com/artem-sidorenko))
|
||||||
|
- Cache the .rvm directory in travis [#4153](https://github.com/inspec/inspec/pull/4153) ([miah](https://github.com/miah))
|
||||||
|
- Make travis green again [#4160](https://github.com/inspec/inspec/pull/4160) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Windows fixes [#4159](https://github.com/inspec/inspec/pull/4159) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Clean unnecessary requires [#4142](https://github.com/inspec/inspec/pull/4142) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Update sunset messages on 2 resources [#4164](https://github.com/inspec/inspec/pull/4164) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- This should fix our licensing failures [#4165](https://github.com/inspec/inspec/pull/4165) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Replace Jenkins omnibus build/test pipeline with Buildkite [#4169](https://github.com/inspec/inspec/pull/4169) ([jeremiahsnapp](https://github.com/jeremiahsnapp))
|
||||||
|
- Mention inspec-bin gem in installation instructions [#4163](https://github.com/inspec/inspec/pull/4163) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- Remove all leading newlines. [#4152](https://github.com/inspec/inspec/pull/4152) ([miah](https://github.com/miah))
|
||||||
|
- Minor cleanup on test/helper.rb [#4109](https://github.com/inspec/inspec/pull/4109) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Creating and Publishing InSpec Team Working Agreement [#4171](https://github.com/inspec/inspec/pull/4171) ([kekaichinose](https://github.com/kekaichinose))
|
||||||
|
- Replace jsonschema with json-schema [#4172](https://github.com/inspec/inspec/pull/4172) ([miah](https://github.com/miah))
|
||||||
|
- Turn off parallel testing (for now?) [#4177](https://github.com/inspec/inspec/pull/4177) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Stabilize windows functional testing [#4180](https://github.com/inspec/inspec/pull/4180) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Fixing docs so Warning note appears [#4183](https://github.com/inspec/inspec/pull/4183) ([mjingle](https://github.com/mjingle))
|
||||||
|
- Changed version check network timeout from 1 to 3 seconds. [#4132](https://github.com/inspec/inspec/pull/4132) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Fixed up interactions between minitest & simplecov. [#4188](https://github.com/inspec/inspec/pull/4188) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Add maintainer branches to travis [#4184](https://github.com/inspec/inspec/pull/4184) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Test execution changes for Rake, Travis, and Appveyor [#4102](https://github.com/inspec/inspec/pull/4102) ([miah](https://github.com/miah))
|
||||||
|
- Close at 400 days, with a message. [#4189](https://github.com/inspec/inspec/pull/4189) ([miah](https://github.com/miah))
|
||||||
|
- Apply chefstyle to codebase [#4194](https://github.com/inspec/inspec/pull/4194) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Speed up inspec [#4193](https://github.com/inspec/inspec/pull/4193) ([zenspider](https://github.com/zenspider))
|
||||||
|
- Disable rubocop on Code Climate. [#4195](https://github.com/inspec/inspec/pull/4195) ([miah](https://github.com/miah))
|
||||||
|
- Create Inputs documentation page [#4185](https://github.com/inspec/inspec/pull/4185) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- Re-add `rake test:` [#4197](https://github.com/inspec/inspec/pull/4197) ([miah](https://github.com/miah))
|
||||||
|
- Update test code to rename attribute() to input() in DSL [#4192](https://github.com/inspec/inspec/pull/4192) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
|
- Lets discuss this next week when we're all around =) [#4204](https://github.com/inspec/inspec/pull/4204) ([miah](https://github.com/miah))
|
||||||
|
|
||||||
## [v4.3.2](https://github.com/inspec/inspec/tree/v4.3.2) (2019-04-30)
|
## [v4.3.2](https://github.com/inspec/inspec/tree/v4.3.2) (2019-04-30)
|
||||||
|
|
||||||
#### New Features
|
#### New Features
|
||||||
|
@ -146,7 +173,6 @@
|
||||||
- Use a updated OS Image in Appveyor [#3985](https://github.com/inspec/inspec/pull/3985) ([miah](https://github.com/miah))
|
- Use a updated OS Image in Appveyor [#3985](https://github.com/inspec/inspec/pull/3985) ([miah](https://github.com/miah))
|
||||||
- Package inspec executable as a separate gem [#3982](https://github.com/inspec/inspec/pull/3982) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
- Package inspec executable as a separate gem [#3982](https://github.com/inspec/inspec/pull/3982) ([clintoncwolfe](https://github.com/clintoncwolfe))
|
||||||
- Accidently not updating main InSpec version via Expeditor [#3997](https://github.com/inspec/inspec/pull/3997) ([tyler-ball](https://github.com/tyler-ball))
|
- Accidently not updating main InSpec version via Expeditor [#3997](https://github.com/inspec/inspec/pull/3997) ([tyler-ball](https://github.com/tyler-ball))
|
||||||
<!-- latest_stable_release -->
|
|
||||||
|
|
||||||
## [v3.9.0](https://github.com/inspec/inspec/tree/v3.9.0) (2019-04-02)
|
## [v3.9.0](https://github.com/inspec/inspec/tree/v3.9.0) (2019-04-02)
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
FROM ruby:alpine
|
FROM ruby:alpine
|
||||||
MAINTAINER Chef Software, Inc. <docker@chef.io>
|
MAINTAINER Chef Software, Inc. <docker@chef.io>
|
||||||
|
|
||||||
ARG VERSION=4.3.2
|
ARG VERSION=
|
||||||
ARG GEM_SOURCE=https://rubygems.org
|
ARG GEM_SOURCE=https://rubygems.org
|
||||||
|
|
||||||
RUN mkdir -p /share
|
RUN mkdir -p /share
|
||||||
|
|
71
Gemfile
71
Gemfile
|
@ -1,66 +1,61 @@
|
||||||
source 'https://rubygems.org'
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gem 'inspec', path: '.'
|
gem "inspec", path: "."
|
||||||
|
|
||||||
# This dependency is NOT used for normal gem deployment
|
# This dependency is NOT used for normal gem deployment
|
||||||
# - instead, inspec-bin gemspec-depends on inspec
|
# - instead, inspec-bin gemspec-depends on inspec
|
||||||
#
|
#
|
||||||
# However, AppBundler requires a top-level Gemfile.lock with inspec-bin
|
# However, AppBundler requires a top-level Gemfile.lock with inspec-bin
|
||||||
# in it in order to package the executable. Hence the odd backwards dependency.
|
# in it in order to package the executable. Hence the odd backwards dependency.
|
||||||
gem 'inspec-bin', path: './inspec-bin'
|
gem "inspec-bin", path: "./inspec-bin"
|
||||||
|
|
||||||
gem 'ffi', '>= 1.9.14'
|
gem "ffi", ">= 1.9.14"
|
||||||
|
|
||||||
group :omnibus do
|
group :omnibus do
|
||||||
gem 'rb-readline'
|
gem "rb-readline"
|
||||||
gem 'appbundler'
|
gem "appbundler"
|
||||||
gem 'ed25519' # ed25519 ssh key support done here as its a native gem we can't put in the gemspec
|
gem "ed25519" # ed25519 ssh key support done here as its a native gem we can't put in the gemspec
|
||||||
gem 'bcrypt_pbkdf' # ed25519 ssh key support done here as its a native gem we can't put in the gemspec
|
gem "bcrypt_pbkdf" # ed25519 ssh key support done here as its a native gem we can't put in the gemspec
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'coveralls', require: false
|
gem "chefstyle", "~> 0.6"
|
||||||
gem 'minitest', '~> 5.5'
|
gem "coveralls", require: false
|
||||||
gem 'rake', '>= 10'
|
gem "minitest", "~> 5.5"
|
||||||
gem 'rubocop', '= 0.49.1'
|
gem "rake", ">= 10"
|
||||||
gem 'simplecov', '~> 0.10'
|
gem "simplecov", "~> 0.10"
|
||||||
gem 'concurrent-ruby', '~> 1.0'
|
gem "concurrent-ruby", "~> 1.0"
|
||||||
gem 'mocha', '~> 1.1'
|
gem "mocha", "~> 1.1"
|
||||||
gem 'ruby-progressbar', '~> 1.8'
|
gem "ruby-progressbar", "~> 1.8"
|
||||||
gem 'webmock', '~> 3.0'
|
gem "webmock", "~> 3.0"
|
||||||
gem 'jsonschema', '~> 2.0.2'
|
gem "passgen"
|
||||||
gem 'passgen'
|
gem "m"
|
||||||
gem 'm'
|
gem "pry", "~> 0.10"
|
||||||
gem 'pry-byebug'
|
gem "pry-byebug"
|
||||||
end
|
end
|
||||||
|
|
||||||
group :integration do
|
group :integration do
|
||||||
gem 'berkshelf', '~> 7'
|
gem "berkshelf"
|
||||||
gem 'test-kitchen', '~> 1.17'
|
gem "chef", "< 15"
|
||||||
gem 'kitchen-vagrant'
|
gem "test-kitchen"
|
||||||
# we need winrm v2 support >= 0.15.1
|
gem "kitchen-vagrant"
|
||||||
gem 'kitchen-inspec', '>= 0.15.1'
|
gem "kitchen-inspec"
|
||||||
gem 'kitchen-ec2'
|
gem "kitchen-ec2"
|
||||||
gem 'kitchen-dokken'
|
gem "kitchen-dokken"
|
||||||
end
|
gem "git"
|
||||||
|
|
||||||
group :tools do
|
|
||||||
gem 'pry', '~> 0.10'
|
|
||||||
gem 'license_finder'
|
|
||||||
gem 'git', '~> 1.4'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# gems for Maintainers.md generation
|
# gems for Maintainers.md generation
|
||||||
group :maintenance do
|
group :maintenance do
|
||||||
gem 'tomlrb'
|
gem "tomlrb"
|
||||||
|
|
||||||
# To sync maintainers with github
|
# To sync maintainers with github
|
||||||
gem 'octokit'
|
gem "octokit"
|
||||||
gem 'netrc'
|
gem "netrc"
|
||||||
end
|
end
|
||||||
|
|
||||||
group :deploy do
|
group :deploy do
|
||||||
gem 'inquirer'
|
gem "inquirer"
|
||||||
end
|
end
|
||||||
|
|
||||||
# add these additional dependencies into Gemfile.local
|
# add these additional dependencies into Gemfile.local
|
||||||
|
|
273
Rakefile
273
Rakefile
|
@ -1,15 +1,15 @@
|
||||||
#!/usr/bin/env rake
|
#!/usr/bin/env rake
|
||||||
|
|
||||||
require 'bundler'
|
require "bundler"
|
||||||
require 'bundler/gem_helper'
|
require "bundler/gem_helper"
|
||||||
require 'rake/testtask'
|
require "rake/testtask"
|
||||||
require 'passgen'
|
require "passgen"
|
||||||
require 'train'
|
require "train"
|
||||||
require_relative 'tasks/maintainers'
|
require_relative "tasks/maintainers"
|
||||||
require_relative 'tasks/spdx'
|
require_relative "tasks/spdx"
|
||||||
require 'fileutils'
|
require "fileutils"
|
||||||
|
|
||||||
Bundler::GemHelper.install_tasks name: 'inspec'
|
Bundler::GemHelper.install_tasks name: "inspec"
|
||||||
|
|
||||||
def prompt(message)
|
def prompt(message)
|
||||||
print(message)
|
print(message)
|
||||||
|
@ -21,25 +21,17 @@ end
|
||||||
# when the "tests" gem group in the Gemfile has been excluded, such as
|
# when the "tests" gem group in the Gemfile has been excluded, such as
|
||||||
# during an appbundle-updater run.
|
# during an appbundle-updater run.
|
||||||
begin
|
begin
|
||||||
require 'ruby-progressbar'
|
require "ruby-progressbar"
|
||||||
require_relative 'tasks/docs'
|
require_relative "tasks/docs"
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
puts 'docs tasks are unavailable because the ruby-progressbar gem is not available.'
|
puts "docs tasks are unavailable because the ruby-progressbar gem is not available."
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
require 'git'
|
require "git"
|
||||||
require_relative 'tasks/contrib'
|
require_relative "tasks/contrib"
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
puts 'contrib tasks are unavailable because the git gem is not available.'
|
puts "contrib tasks are unavailable because the git gem is not available."
|
||||||
end
|
|
||||||
|
|
||||||
# Rubocop
|
|
||||||
begin
|
|
||||||
require 'rubocop/rake_task'
|
|
||||||
RuboCop::RakeTask.new(:lint)
|
|
||||||
rescue LoadError
|
|
||||||
puts 'rubocop is not available. Install the rubocop gem to run the lint tests.'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
task :install do
|
task :install do
|
||||||
|
@ -48,45 +40,46 @@ task :install do
|
||||||
sh("rake install")
|
sh("rake install")
|
||||||
end
|
end
|
||||||
|
|
||||||
# update command output for demo
|
GLOBS = [
|
||||||
desc 'Run inspec commands and save results to www/app/responses'
|
"test/unit/**/*_test.rb",
|
||||||
task :update_demo do
|
"test/functional/**/*_test.rb",
|
||||||
ruby 'www/tutorial/scripts/build_simulator_runtime.rb'
|
"lib/plugins/inspec-*/test/**/*_test.rb",
|
||||||
ruby 'www/tutorial/scripts/run_simulator_recording.rb'
|
].freeze
|
||||||
end
|
|
||||||
|
|
||||||
# run tests
|
# run tests
|
||||||
task default: [:lint, :test]
|
task default: ["test:lint", "test:default"]
|
||||||
|
task test: ["test:lint", "test:default"]
|
||||||
Rake::TestTask.new do |t|
|
|
||||||
t.libs << 'test'
|
|
||||||
t.test_files = Dir.glob([
|
|
||||||
'test/unit/**/*_test.rb',
|
|
||||||
'lib/plugins/inspec-*/test/unit/**/*_test.rb',
|
|
||||||
])
|
|
||||||
t.warning = false
|
|
||||||
t.verbose = !!ENV["V"] # default to off. the test commands are _huge_.
|
|
||||||
t.ruby_opts = ['--dev'] if defined?(JRUBY_VERSION)
|
|
||||||
end
|
|
||||||
|
|
||||||
namespace :test do
|
namespace :test do
|
||||||
GLOBS = [
|
|
||||||
"test/unit/**/*_test.rb",
|
Rake::TestTask.new(:default) do |t|
|
||||||
"test/functional/**/*_test.rb",
|
t.libs << "test"
|
||||||
"lib/plugins/inspec-*/test/**/*_test.rb",
|
t.test_files = Dir[*GLOBS].sort
|
||||||
]
|
t.warning = !!ENV["W"]
|
||||||
|
t.verbose = !!ENV["V"] # default to off. the test commands are _huge_.
|
||||||
|
t.ruby_opts = ["--dev"] if defined?(JRUBY_VERSION)
|
||||||
|
end
|
||||||
|
task default: [:accept_license]
|
||||||
|
|
||||||
|
begin
|
||||||
|
require "chefstyle"
|
||||||
|
require "rubocop/rake_task"
|
||||||
|
RuboCop::RakeTask.new(:lint) do |task|
|
||||||
|
task.options += ["--display-cop-names", "--no-color", "--parallel"]
|
||||||
|
end
|
||||||
|
rescue LoadError
|
||||||
|
puts "rubocop is not available. Install the rubocop gem to run the lint tests."
|
||||||
|
end
|
||||||
|
|
||||||
task :list do
|
task :list do
|
||||||
puts Dir[*GLOBS].sort
|
puts Dir[*GLOBS].sort
|
||||||
end
|
end
|
||||||
|
|
||||||
task :isolated do
|
task :isolated do
|
||||||
clean = true
|
|
||||||
|
|
||||||
failures = Dir[*GLOBS]
|
failures = Dir[*GLOBS]
|
||||||
failures.reject! { |file|
|
failures.reject! do |file|
|
||||||
system(Gem.ruby, '-Ilib:test', file)
|
system(Gem.ruby, "-Ilib:test", file)
|
||||||
}
|
end
|
||||||
|
|
||||||
unless failures.empty?
|
unless failures.empty?
|
||||||
puts "These test files failed:\n"
|
puts "These test files failed:\n"
|
||||||
|
@ -96,97 +89,91 @@ namespace :test do
|
||||||
end
|
end
|
||||||
|
|
||||||
task :accept_license do
|
task :accept_license do
|
||||||
FileUtils.mkdir_p(File.join(Dir.home, '.chef', 'accepted_licenses'))
|
FileUtils.mkdir_p(File.join(Dir.home, ".chef", "accepted_licenses"))
|
||||||
# If the user has not accepted the license, touch the acceptance
|
# If the user has not accepted the license, touch the acceptance
|
||||||
# file, but also touch a marker that it is only for testing.
|
# file, but also touch a marker that it is only for testing.
|
||||||
unless File.exist?(File.join(Dir.home, '.chef', 'accepted_licenses', 'inspec'))
|
unless File.exist?(File.join(Dir.home, ".chef", "accepted_licenses", "inspec"))
|
||||||
puts "\n\nTemporarily accepting Chef user license for the duration of testing...\n"
|
puts "\n\nTemporarily accepting Chef user license for the duration of testing...\n"
|
||||||
FileUtils.touch(File.join(Dir.home, '.chef', 'accepted_licenses', 'inspec'))
|
FileUtils.touch(File.join(Dir.home, ".chef", "accepted_licenses", "inspec"))
|
||||||
FileUtils.touch(File.join(Dir.home, '.chef', 'accepted_licenses', 'inspec.for_testing'))
|
FileUtils.touch(File.join(Dir.home, ".chef", "accepted_licenses", "inspec.for_testing"))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Regardless of what happens, when this process exits, check for cleanup.
|
# Regardless of what happens, when this process exits, check for cleanup.
|
||||||
at_exit do
|
at_exit do
|
||||||
if File.exist?(File.join(Dir.home, '.chef', 'accepted_licenses', 'inspec.for_testing'))
|
if File.exist?(File.join(Dir.home, ".chef", "accepted_licenses", "inspec.for_testing"))
|
||||||
puts "\n\nRemoving temporary Chef user license acceptance file that was placed for test duration.\n"
|
puts "\n\nRemoving temporary Chef user license acceptance file that was placed for test duration.\n"
|
||||||
FileUtils.rm_f(File.join(Dir.home, '.chef', 'accepted_licenses', 'inspec'))
|
FileUtils.rm_f(File.join(Dir.home, ".chef", "accepted_licenses", "inspec"))
|
||||||
FileUtils.rm_f(File.join(Dir.home, '.chef', 'accepted_licenses', 'inspec.for_testing'))
|
FileUtils.rm_f(File.join(Dir.home, ".chef", "accepted_licenses", "inspec.for_testing"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Rake::TestTask.new(:functional) do |t|
|
Rake::TestTask.new(:functional) do |t|
|
||||||
t.libs << 'test'
|
t.libs << "test"
|
||||||
t.test_files = Dir.glob([
|
t.test_files = Dir.glob([
|
||||||
'test/functional/**/*_test.rb',
|
"test/functional/**/*_test.rb",
|
||||||
'lib/plugins/inspec-*/test/functional/**/*_test.rb',
|
"lib/plugins/inspec-*/test/functional/**/*_test.rb",
|
||||||
])
|
])
|
||||||
t.warning = false # This just complains about things in underlying libraries
|
t.warning = !!ENV["W"]
|
||||||
t.verbose = true
|
t.verbose = !!ENV["V"] # default to off. the test commands are _huge_.
|
||||||
t.ruby_opts = ['--dev'] if defined?(JRUBY_VERSION)
|
t.ruby_opts = ["--dev"] if defined?(JRUBY_VERSION)
|
||||||
end
|
end
|
||||||
# Inject a prerequisite task
|
# Inject a prerequisite task
|
||||||
task :functional => [:accept_license]
|
task functional: [:accept_license]
|
||||||
|
|
||||||
# Functional tests on Windows take a bit to run. This
|
Rake::TestTask.new(:unit) do |t|
|
||||||
# optionally takes a env to breake the tests up into 3 workers.
|
t.libs << "test"
|
||||||
Rake::TestTask.new(:'functional:windows') do |t, args|
|
t.test_files = Dir.glob([
|
||||||
files = Dir.glob('test/functional/*_test.rb').sort
|
"test/unit/**/*_test.rb",
|
||||||
if ENV['WORKER_NUMBER']
|
"lib/plugins/inspec-*/test/unit/**/*_test.rb",
|
||||||
count = (files.count / 3).abs+1
|
])
|
||||||
start = (ENV['WORKER_NUMBER'].to_i - 1) * count
|
t.warning = !!ENV["W"]
|
||||||
files = files[start..start+count-1]
|
t.verbose = !!ENV["V"] # default to off. the test commands are _huge_.
|
||||||
end
|
t.ruby_opts = ["--dev"] if defined?(JRUBY_VERSION)
|
||||||
|
|
||||||
t.libs << 'test'
|
|
||||||
t.test_files = files
|
|
||||||
t.warning = false # This just complains about things in underlying libraries
|
|
||||||
t.verbose = true
|
|
||||||
t.ruby_opts = ['--dev'] if defined?(JRUBY_VERSION)
|
|
||||||
end
|
end
|
||||||
# Inject a prerequisite task
|
# Inject a prerequisite task
|
||||||
task :'functional:windows' => [:accept_license]
|
task unit: [:accept_license]
|
||||||
|
|
||||||
task :resources do
|
task :resources do
|
||||||
tests = Dir['test/unit/resource/*_test.rb']
|
tests = Dir["test/unit/resource/*_test.rb"]
|
||||||
return if tests.empty?
|
return if tests.empty?
|
||||||
sh(Gem.ruby, 'test/docker_test.rb', *tests)
|
sh(Gem.ruby, "test/docker_test.rb", *tests)
|
||||||
end
|
end
|
||||||
|
|
||||||
task :integration, [:os] do |task, args|
|
task :integration, [:os] do |task, args|
|
||||||
concurrency = ENV['CONCURRENCY'] || 1
|
concurrency = ENV["CONCURRENCY"] || 1
|
||||||
os = args[:os] || ENV['OS'] || ''
|
os = args[:os] || ENV["OS"] || ""
|
||||||
ENV['DOCKER'] = 'true' if ENV['docker'].nil?
|
ENV["DOCKER"] = "true" if ENV["docker"].nil?
|
||||||
sh("bundle exec kitchen test -c #{concurrency} #{os}")
|
sh("bundle exec kitchen test -c #{concurrency} #{os}")
|
||||||
end
|
end
|
||||||
# Inject a prerequisite task
|
# Inject a prerequisite task
|
||||||
task :'integration' => [:accept_license]
|
task 'integration': [:accept_license]
|
||||||
|
|
||||||
task :ssh, [:target] do |_t, args|
|
task :ssh, [:target] do |_t, args|
|
||||||
tests_path = File.join(File.dirname(__FILE__), 'test', 'integration', 'test', 'integration', 'default')
|
tests_path = File.join(File.dirname(__FILE__), "test", "integration", "test", "integration", "default")
|
||||||
key_files = ENV['key_files'] || File.join(ENV['HOME'], '.ssh', 'id_rsa')
|
key_files = ENV["key_files"] || File.join(ENV["HOME"], ".ssh", "id_rsa")
|
||||||
|
|
||||||
sh_cmd = "bin/inspec exec #{tests_path}/"
|
sh_cmd = "bin/inspec exec #{tests_path}/"
|
||||||
sh_cmd += ENV['test'] ? "#{ENV['test']}_spec.rb" : '*'
|
sh_cmd += ENV["test"] ? "#{ENV['test']}_spec.rb" : "*"
|
||||||
sh_cmd += " --sudo" unless args[:target].split('@')[0] == 'root'
|
sh_cmd += " --sudo" unless args[:target].split("@")[0] == "root"
|
||||||
sh_cmd += " -t ssh://#{args[:target]}"
|
sh_cmd += " -t ssh://#{args[:target]}"
|
||||||
sh_cmd += " --key_files=#{key_files}"
|
sh_cmd += " --key_files=#{key_files}"
|
||||||
sh_cmd += " --format=#{ENV['format']}" if ENV['format']
|
sh_cmd += " --format=#{ENV['format']}" if ENV["format"]
|
||||||
|
|
||||||
sh('sh', '-c', sh_cmd)
|
sh("sh", "-c", sh_cmd)
|
||||||
end
|
end
|
||||||
|
|
||||||
project_dir = File.dirname(__FILE__)
|
project_dir = File.dirname(__FILE__)
|
||||||
namespace :aws do
|
namespace :aws do
|
||||||
['default', 'minimal'].each do |account|
|
%w{default minimal}.each do |account|
|
||||||
integration_dir = File.join(project_dir, 'test', 'integration', 'aws', account)
|
integration_dir = File.join(project_dir, "test", "integration", "aws", account)
|
||||||
attribute_file = File.join(integration_dir, '.attribute.yml')
|
attribute_file = File.join(integration_dir, ".attribute.yml")
|
||||||
|
|
||||||
task :"setup:#{account}", :tf_workspace do |t, args|
|
task :"setup:#{account}", :tf_workspace do |t, args|
|
||||||
tf_workspace = args[:tf_workspace] || ENV['INSPEC_TERRAFORM_ENV']
|
tf_workspace = args[:tf_workspace] || ENV["INSPEC_TERRAFORM_ENV"]
|
||||||
abort("You must either call the top-level test:aws:#{account} task, or set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
abort("You must either call the top-level test:aws:#{account} task, or set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
||||||
puts "----> Setup"
|
puts "----> Setup"
|
||||||
abort("You must set the environment variable AWS_REGION") unless ENV['AWS_REGION']
|
abort("You must set the environment variable AWS_REGION") unless ENV["AWS_REGION"]
|
||||||
puts "----> Checking for required AWS profile..."
|
puts "----> Checking for required AWS profile..."
|
||||||
sh("aws configure get aws_access_key_id --profile inspec-aws-test-#{account} > /dev/null")
|
sh("aws configure get aws_access_key_id --profile inspec-aws-test-#{account} > /dev/null")
|
||||||
sh("cd #{integration_dir}/build/ && terraform init -upgrade")
|
sh("cd #{integration_dir}/build/ && terraform init -upgrade")
|
||||||
|
@ -200,7 +187,7 @@ namespace :test do
|
||||||
sh("cd #{integration_dir}/build/ && AWS_PROFILE=inspec-aws-test-#{account} terraform output > #{attribute_file}")
|
sh("cd #{integration_dir}/build/ && AWS_PROFILE=inspec-aws-test-#{account} terraform output > #{attribute_file}")
|
||||||
raw_output = File.read(attribute_file)
|
raw_output = File.read(attribute_file)
|
||||||
yaml_output = raw_output.gsub(" = ", " : ")
|
yaml_output = raw_output.gsub(" = ", " : ")
|
||||||
File.open(attribute_file, "w") {|file| file.puts yaml_output}
|
File.open(attribute_file, "w") { |file| file.puts yaml_output }
|
||||||
end
|
end
|
||||||
|
|
||||||
task :"run:#{account}" do
|
task :"run:#{account}" do
|
||||||
|
@ -209,7 +196,7 @@ namespace :test do
|
||||||
end
|
end
|
||||||
|
|
||||||
task :"cleanup:#{account}", :tf_workspace do |t, args|
|
task :"cleanup:#{account}", :tf_workspace do |t, args|
|
||||||
tf_workspace = args[:tf_workspace] || ENV['INSPEC_TERRAFORM_ENV']
|
tf_workspace = args[:tf_workspace] || ENV["INSPEC_TERRAFORM_ENV"]
|
||||||
abort("You must either call the top-level test:aws:#{account} task, or set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
abort("You must either call the top-level test:aws:#{account} task, or set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
||||||
puts "----> Cleanup"
|
puts "----> Cleanup"
|
||||||
sh("cd #{integration_dir}/build/ && AWS_PROFILE=inspec-aws-test-#{account} terraform destroy -force")
|
sh("cd #{integration_dir}/build/ && AWS_PROFILE=inspec-aws-test-#{account} terraform destroy -force")
|
||||||
|
@ -218,14 +205,14 @@ namespace :test do
|
||||||
end
|
end
|
||||||
|
|
||||||
task :"#{account}" do
|
task :"#{account}" do
|
||||||
tf_workspace = ENV['INSPEC_TERRAFORM_ENV'] || prompt("Please enter a workspace for your integration tests to run in: ")
|
tf_workspace = ENV["INSPEC_TERRAFORM_ENV"] || prompt("Please enter a workspace for your integration tests to run in: ")
|
||||||
begin
|
begin
|
||||||
Rake::Task["test:aws:setup:#{account}"].execute({:tf_workspace => tf_workspace})
|
Rake::Task["test:aws:setup:#{account}"].execute({ tf_workspace: tf_workspace })
|
||||||
Rake::Task["test:aws:run:#{account}"].execute
|
Rake::Task["test:aws:run:#{account}"].execute
|
||||||
rescue
|
rescue
|
||||||
abort("Integration testing has failed for the #{account} account")
|
abort("Integration testing has failed for the #{account} account")
|
||||||
ensure
|
ensure
|
||||||
Rake::Task["test:aws:cleanup:#{account}"].execute({:tf_workspace => tf_workspace})
|
Rake::Task["test:aws:cleanup:#{account}"].execute({ tf_workspace: tf_workspace })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -235,15 +222,15 @@ namespace :test do
|
||||||
|
|
||||||
namespace :azure do
|
namespace :azure do
|
||||||
# Specify the directory for the integration tests
|
# Specify the directory for the integration tests
|
||||||
integration_dir = File.join(project_dir, 'test', 'integration', 'azure')
|
integration_dir = File.join(project_dir, "test", "integration", "azure")
|
||||||
tf_vars_file = File.join(integration_dir, 'build', 'terraform.tfvars')
|
tf_vars_file = File.join(integration_dir, "build", "terraform.tfvars")
|
||||||
attribute_file = File.join(integration_dir, '.attribute.yml')
|
attribute_file = File.join(integration_dir, ".attribute.yml")
|
||||||
|
|
||||||
task :setup, :tf_workspace do |t, args|
|
task :setup, :tf_workspace do |t, args|
|
||||||
tf_workspace = args[:tf_workspace] || ENV['INSPEC_TERRAFORM_ENV']
|
tf_workspace = args[:tf_workspace] || ENV["INSPEC_TERRAFORM_ENV"]
|
||||||
abort("You must either call the top-level test:azure task, or set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
abort("You must either call the top-level test:azure task, or set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
||||||
|
|
||||||
puts '----> Setup Terraform Workspace'
|
puts "----> Setup Terraform Workspace"
|
||||||
|
|
||||||
sh("cd #{integration_dir}/build/ && terraform init -upgrade")
|
sh("cd #{integration_dir}/build/ && terraform init -upgrade")
|
||||||
sh("cd #{integration_dir}/build/ && terraform workspace new #{tf_workspace}")
|
sh("cd #{integration_dir}/build/ && terraform workspace new #{tf_workspace}")
|
||||||
|
@ -258,15 +245,15 @@ namespace :test do
|
||||||
|
|
||||||
next if File.exist?(tf_vars_file)
|
next if File.exist?(tf_vars_file)
|
||||||
|
|
||||||
puts '----> Generating Vars'
|
puts "----> Generating Vars"
|
||||||
|
|
||||||
# Generate Azure crendentials
|
# Generate Azure crendentials
|
||||||
connection = Train.create('azure').connection
|
connection = Train.create("azure").connection
|
||||||
creds = connection.options
|
creds = connection.options
|
||||||
|
|
||||||
# Determine the storage account name and the admin password
|
# Determine the storage account name and the admin password
|
||||||
sa_name = (0...15).map { (65 + rand(26)).chr }.join.downcase
|
sa_name = (0...15).map { (65 + rand(26)).chr }.join.downcase
|
||||||
admin_password = Passgen::generate(length: 12, uppercase: true, lowercase: true, symbols: true, digits: true)
|
admin_password = Passgen.generate(length: 12, uppercase: true, lowercase: true, symbols: true, digits: true)
|
||||||
|
|
||||||
# Use the first 4 characters of the storage account to create a suffix
|
# Use the first 4 characters of the storage account to create a suffix
|
||||||
suffix = sa_name[0..3]
|
suffix = sa_name[0..3]
|
||||||
|
@ -281,28 +268,26 @@ namespace :test do
|
||||||
suffix = "#{suffix}"
|
suffix = "#{suffix}"
|
||||||
VARS
|
VARS
|
||||||
|
|
||||||
content << "location = \"#{ENV['AZURE_LOCATION']}\"\n" if ENV['AZURE_LOCATION']
|
content << "location = \"#{ENV['AZURE_LOCATION']}\"\n" if ENV["AZURE_LOCATION"]
|
||||||
|
|
||||||
File.write(tf_vars_file, content)
|
File.write(tf_vars_file, content)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "generate plan from state using terraform.tfvars file"
|
desc "generate plan from state using terraform.tfvars file"
|
||||||
task :plan, [:tf_workspace] => [:vars] do |t, args|
|
task :plan, [:tf_workspace] => [:vars] do |t, args|
|
||||||
tf_workspace = args[:tf_workspace] || ENV['INSPEC_TERRAFORM_ENV']
|
tf_workspace = args[:tf_workspace] || ENV["INSPEC_TERRAFORM_ENV"]
|
||||||
abort("You must set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
abort("You must set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
||||||
|
|
||||||
puts '----> Generating Plan'
|
puts "----> Generating Plan"
|
||||||
|
|
||||||
result = sh("cd #{integration_dir}/build/ && terraform workspace select #{tf_workspace}")
|
|
||||||
|
|
||||||
sh("cd #{integration_dir}/build/ && terraform plan -out inspec-azure.plan")
|
sh("cd #{integration_dir}/build/ && terraform plan -out inspec-azure.plan")
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "apply terraform plan"
|
desc "apply terraform plan"
|
||||||
task :apply, [:tf_workspace] => [:plan] do |t, args|
|
task :apply, [:tf_workspace] => [:plan] do |t, args|
|
||||||
tf_workspace = args[:tf_workspace] || ENV['INSPEC_TERRAFORM_ENV']
|
tf_workspace = args[:tf_workspace] || ENV["INSPEC_TERRAFORM_ENV"]
|
||||||
abort("You must set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
abort("You must set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
||||||
puts '----> Applying Plan'
|
puts "----> Applying Plan"
|
||||||
|
|
||||||
sh("cd #{integration_dir}/build/ && terraform workspace select #{tf_workspace}")
|
sh("cd #{integration_dir}/build/ && terraform workspace select #{tf_workspace}")
|
||||||
|
|
||||||
|
@ -311,22 +296,22 @@ namespace :test do
|
||||||
Rake::Task["test:azure:dump_attrs"].execute
|
Rake::Task["test:azure:dump_attrs"].execute
|
||||||
end
|
end
|
||||||
|
|
||||||
task :"dump_attrs" do
|
task :dump_attrs do
|
||||||
sh("cd #{integration_dir}/build/ && terraform output > #{attribute_file}")
|
sh("cd #{integration_dir}/build/ && terraform output > #{attribute_file}")
|
||||||
raw_output = File.read(attribute_file)
|
raw_output = File.read(attribute_file)
|
||||||
yaml_output = raw_output.gsub(" = ", " : ")
|
yaml_output = raw_output.gsub(" = ", " : ")
|
||||||
File.open(attribute_file, "w") {|file| file.puts yaml_output}
|
File.open(attribute_file, "w") { |file| file.puts yaml_output }
|
||||||
end
|
end
|
||||||
|
|
||||||
task :run do
|
task :run do
|
||||||
puts '----> Run'
|
puts "----> Run"
|
||||||
sh("bundle exec inspec exec #{integration_dir}/verify -t azure://1e0b427a-d58b-494e-ae4f-ee558463ebbf")
|
sh("bundle exec inspec exec #{integration_dir}/verify -t azure://1e0b427a-d58b-494e-ae4f-ee558463ebbf")
|
||||||
end
|
end
|
||||||
|
|
||||||
task :cleanup, :tf_workspace do |t, args|
|
task :cleanup, :tf_workspace do |t, args|
|
||||||
tf_workspace = args[:tf_workspace] || ENV['INSPEC_TERRAFORM_ENV']
|
tf_workspace = args[:tf_workspace] || ENV["INSPEC_TERRAFORM_ENV"]
|
||||||
abort("You must either call the top-level test:azure task, or set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
abort("You must either call the top-level test:azure task, or set the INSPEC_TERRAFORM_ENV variable.") unless tf_workspace
|
||||||
puts '----> Cleanup'
|
puts "----> Cleanup"
|
||||||
|
|
||||||
sh("cd #{integration_dir}/build/ && terraform destroy -force ")
|
sh("cd #{integration_dir}/build/ && terraform destroy -force ")
|
||||||
|
|
||||||
|
@ -338,14 +323,14 @@ namespace :test do
|
||||||
|
|
||||||
desc "Perform Azure Integration Tests"
|
desc "Perform Azure Integration Tests"
|
||||||
task :azure do
|
task :azure do
|
||||||
tf_workspace = ENV['INSPEC_TERRAFORM_ENV'] || prompt("Please enter a workspace for your integration tests to run in: ")
|
tf_workspace = ENV["INSPEC_TERRAFORM_ENV"] || prompt("Please enter a workspace for your integration tests to run in: ")
|
||||||
begin
|
begin
|
||||||
Rake::Task["test:azure:setup"].execute({:tf_workspace => tf_workspace})
|
Rake::Task["test:azure:setup"].execute({ tf_workspace: tf_workspace })
|
||||||
Rake::Task["test:azure:run"].execute
|
Rake::Task["test:azure:run"].execute
|
||||||
rescue
|
rescue
|
||||||
abort("Integration testing has failed")
|
abort("Integration testing has failed")
|
||||||
ensure
|
ensure
|
||||||
Rake::Task["test:azure:cleanup"].execute({:tf_workspace => tf_workspace})
|
Rake::Task["test:azure:cleanup"].execute({ tf_workspace: tf_workspace })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -354,10 +339,10 @@ end
|
||||||
#
|
#
|
||||||
# @param [Type] target the new version you want to set, or nil if you only want to show
|
# @param [Type] target the new version you want to set, or nil if you only want to show
|
||||||
def inspec_version(target = nil)
|
def inspec_version(target = nil)
|
||||||
path = 'lib/inspec/version.rb'
|
path = "lib/inspec/version.rb"
|
||||||
require_relative path.sub(/.rb$/, '')
|
require_relative path.sub(/.rb$/, "")
|
||||||
|
|
||||||
nu_version = target.nil? ? '' : " -> #{target}"
|
nu_version = target.nil? ? "" : " -> #{target}"
|
||||||
puts "Inspec: #{Inspec::VERSION}#{nu_version}"
|
puts "Inspec: #{Inspec::VERSION}#{nu_version}"
|
||||||
|
|
||||||
unless target.nil?
|
unless target.nil?
|
||||||
|
@ -374,7 +359,7 @@ end
|
||||||
# @param [Type] msg the message to display if the command is missing
|
# @param [Type] msg the message to display if the command is missing
|
||||||
def require_command(x, msg = nil)
|
def require_command(x, msg = nil)
|
||||||
return if system("command -v #{x} || exit 1")
|
return if system("command -v #{x} || exit 1")
|
||||||
msg ||= 'Please install it first!'
|
msg ||= "Please install it first!"
|
||||||
puts "\033[31;1mCan't find command #{x.inspect}. #{msg}\033[0m"
|
puts "\033[31;1mCan't find command #{x.inspect}. #{msg}\033[0m"
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
@ -392,16 +377,16 @@ end
|
||||||
|
|
||||||
# Check the requirements for running an update of this repository.
|
# Check the requirements for running an update of this repository.
|
||||||
def check_update_requirements
|
def check_update_requirements
|
||||||
require_command 'git'
|
require_command "git"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Show the current version of this gem.
|
# Show the current version of this gem.
|
||||||
desc 'Show the version of this gem'
|
desc "Show the version of this gem"
|
||||||
task :version do
|
task :version do
|
||||||
inspec_version
|
inspec_version
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Release a new docker image'
|
desc "Release a new docker image"
|
||||||
task :release_docker do
|
task :release_docker do
|
||||||
version = Inspec::VERSION
|
version = Inspec::VERSION
|
||||||
cmd = "rm *.gem; gem build *gemspec && "\
|
cmd = "rm *.gem; gem build *gemspec && "\
|
||||||
|
@ -411,21 +396,5 @@ task :release_docker do
|
||||||
"docker tag chef/inspec:#{version} chef/inspec:latest &&"\
|
"docker tag chef/inspec:#{version} chef/inspec:latest &&"\
|
||||||
"docker push chef/inspec:latest"
|
"docker push chef/inspec:latest"
|
||||||
puts "--> #{cmd}"
|
puts "--> #{cmd}"
|
||||||
sh('sh', '-c', cmd)
|
sh("sh", "-c", cmd)
|
||||||
end
|
|
||||||
|
|
||||||
desc 'Release the website [deprecated]'
|
|
||||||
task :www do
|
|
||||||
puts 'The Rake tasks for releasing the website are now in the www/ directory.'
|
|
||||||
puts 'Run `cd www` and then `rake --tasks` for a list of the www-related tasks available.'
|
|
||||||
exit(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
namespace :www do
|
|
||||||
desc 'Release the website [deprecated]'
|
|
||||||
task :release do
|
|
||||||
puts 'The Rake tasks for releasing the website are now in the www/ directory.'
|
|
||||||
puts 'Run `cd www` and then `rake --tasks` for a list of the www-related tasks available.'
|
|
||||||
exit(1)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
4.4.65
|
4.6.4
|
45
appveyor.yml
45
appveyor.yml
|
@ -10,18 +10,12 @@ platform:
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- name: unit-tests-ruby-2.4.4
|
- name: ruby-2.6
|
||||||
ruby_version: "24-x64"
|
ruby_version: "26-x64"
|
||||||
- name: unit-tests-ruby-2.5
|
- name: ruby-2.5
|
||||||
ruby_version: "25-x64"
|
ruby_version: "25-x64"
|
||||||
- name: unit-tests-ruby-2.6
|
- name: ruby-2.4
|
||||||
ruby_version: "26-x64"
|
ruby_version: "24-x64"
|
||||||
- name: functional-tests-1
|
|
||||||
ruby_version: "26-x64"
|
|
||||||
- name: functional-tests-2
|
|
||||||
ruby_version: "26-x64"
|
|
||||||
- name: functional-tests-3
|
|
||||||
ruby_version: "26-x64"
|
|
||||||
clone_folder: c:\projects\inspec
|
clone_folder: c:\projects\inspec
|
||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
# Disable MSBuild mode entirely
|
# Disable MSBuild mode entirely
|
||||||
|
@ -67,32 +61,3 @@ test_script:
|
||||||
- SET SPEC_OPTS=--format progress
|
- SET SPEC_OPTS=--format progress
|
||||||
- SET SLOW=1
|
- SET SLOW=1
|
||||||
- bundle exec rake
|
- bundle exec rake
|
||||||
|
|
||||||
for:
|
|
||||||
-
|
|
||||||
matrix:
|
|
||||||
only:
|
|
||||||
- name: functional-tests-1
|
|
||||||
test_script:
|
|
||||||
- SET SPEC_OPTS=--format progress
|
|
||||||
- SET WORKER_NUMBER=1
|
|
||||||
- SET SLOW=1
|
|
||||||
- bundle exec rake test:functional:windows
|
|
||||||
-
|
|
||||||
matrix:
|
|
||||||
only:
|
|
||||||
- name: functional-tests-2
|
|
||||||
test_script:
|
|
||||||
- SET SPEC_OPTS=--format progress
|
|
||||||
- SET WORKER_NUMBER=2
|
|
||||||
- SET SLOW=1
|
|
||||||
- bundle exec rake test:functional:windows
|
|
||||||
-
|
|
||||||
matrix:
|
|
||||||
only:
|
|
||||||
- name: functional-tests-3
|
|
||||||
test_script:
|
|
||||||
- SET SPEC_OPTS=--format progress
|
|
||||||
- SET WORKER_NUMBER=3
|
|
||||||
- SET SLOW=1
|
|
||||||
- bundle exec rake test:functional:windows
|
|
||||||
|
|
|
@ -322,6 +322,101 @@ no_command do
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Implementing Input Plugins
|
||||||
|
|
||||||
|
Input plugins provide values for Chef InSpec Inputs - the parameters you can place within profile control code.
|
||||||
|
|
||||||
|
For example, you might implement an Input plugin to fetch vales from a key-value store, such as `etcd`.
|
||||||
|
|
||||||
|
Input plugins have a simple API which is intended to be easy to adapt to a number of input backend implementations.
|
||||||
|
|
||||||
|
### Declare your input plugin activators
|
||||||
|
|
||||||
|
Generally speaking, an input plugin will only need to have one activator.
|
||||||
|
|
||||||
|
In your `plugin.rb`, include one or more `input` activation blocks. The activation block will fire when the InputRegistry is initialized, at which time case it should load any needed libraries and should return your implementation class.
|
||||||
|
|
||||||
|
The Input subsystem always activates all activators.
|
||||||
|
|
||||||
|
#### Input Activator Example
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
|
||||||
|
# In plugin.rb
|
||||||
|
module InspecPlugins::Sweeten
|
||||||
|
class Plugin < Inspec.plugin(2)
|
||||||
|
# ... other plugin stuff
|
||||||
|
|
||||||
|
input :coffee_fixins_bar do
|
||||||
|
require_relative 'input.rb'
|
||||||
|
InspecPlugins::Sweeten::Input
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
The Input subsystem always activates all activators when InputRegistry is initialized. Future work may enable us to dynamically load plugins; but we need to poll plugins when any input value is used.
|
||||||
|
|
||||||
|
### Implementation class for Input plugins
|
||||||
|
|
||||||
|
In your `input.rb`, you should begin by requesting the superclass from `Inspec.plugin`:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
module InspecPlugins::Sweeten
|
||||||
|
class Input < Inspec.plugin(2, :input)
|
||||||
|
# ...
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Implementing your Input plugin
|
||||||
|
|
||||||
|
Within your implementation, you need to implement 2 mandatory methods and two optional methods.
|
||||||
|
|
||||||
|
#### default_priority
|
||||||
|
|
||||||
|
Optional, returns an integer 0-100, default 60. This value determines precedence when multiple input providers supply a value; higher values lend more precedence.
|
||||||
|
|
||||||
|
#### list_inputs(profile_name)
|
||||||
|
|
||||||
|
Mandatory. Given a String profile name, return an Array of String input names that may be fetched from this plugin. This may be used to optimize calls to fetch().
|
||||||
|
|
||||||
|
#### fetch(profile_name, input_name)
|
||||||
|
|
||||||
|
Mandatory. Given a String profile_name and String input_name, return the input value (whatever that means for your plugin).
|
||||||
|
|
||||||
|
#### Using a constructor to get config values
|
||||||
|
|
||||||
|
Optional. Implement `initialize()` to perform any startup tasks such as authorization. You can get to the InSpec config settings via `Inspec::Config.cached[some_key]`.
|
||||||
|
|
||||||
|
#### Implementation example
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
module InspecPlugins::Sweeten
|
||||||
|
class Input < Inspec.plugin(2, :input)
|
||||||
|
|
||||||
|
def default_priority
|
||||||
|
99 # Extremely opinionated
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch(profile_name, input_name)
|
||||||
|
return nil unless profile_name = 'coffee_shop'
|
||||||
|
|
||||||
|
case input_name
|
||||||
|
when 'sugar'
|
||||||
|
'delicious raw sugar in an eclectic brown packet'
|
||||||
|
when "sweet'n'low"
|
||||||
|
'how can you even do that to yourself'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def list_input_names
|
||||||
|
['sugar',"sweet'n'low"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
## Implementing DSL Plugins
|
## Implementing DSL Plugins
|
||||||
|
|
||||||
A DSL is a _domain specific language_, or a set of keywords you can use to write Chef InSpec profiles and resources more fluently.
|
A DSL is a _domain specific language_, or a set of keywords you can use to write Chef InSpec profiles and resources more fluently.
|
||||||
|
|
|
@ -108,11 +108,7 @@ _be >=_ is an [operator matcher](#operator matcher). It allows you to perform nu
|
||||||
|
|
||||||
### attribute
|
### attribute
|
||||||
|
|
||||||
An _attribute_ is a parameter that Chef InSpec reads from a YAML file provided on the command line. You can use this feature either to change a [profile's](#profile) behavior by passing different attribute files or to store secrets that should not be directly present in a profile. Chef InSpec attributes are unrelated to Chef attributes.
|
Deprecated name for [input](#input).
|
||||||
|
|
||||||
The CLI syntax for attributes is documented under the [`inspec exec`](https://www.inspec.io/docs/reference/cli/#exec) command.
|
|
||||||
|
|
||||||
The syntax for accessing attributes within a profile is documented in the [profiles documentation](https://www.inspec.io/docs/reference/profiles/#profile-attributes).
|
|
||||||
|
|
||||||
### control
|
### control
|
||||||
|
|
||||||
|
@ -204,6 +200,16 @@ describe cars.where { engine_cylinders >= 6 } do
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### input
|
||||||
|
|
||||||
|
An _`input`_ is a value that Chef InSpec can source from a number of providers, including from the command line, profile metadata, or within the control file DSL itself. You can use this feature either to change a [profile's](#profile) behavior by passing different attribute files or to store secrets that should not be directly present in a profile.
|
||||||
|
|
||||||
|
Inputs were formerly known as `attributes`. Chef InSpec inputs are unrelated to Chef Infra attributes.
|
||||||
|
|
||||||
|
The CLI syntax for inputs is documented under the [`inspec exec`](https://www.inspec.io/docs/reference/cli/#exec) command.
|
||||||
|
|
||||||
|
Inputs are documented in detail in the [input documentation](https://www.inspec.io/docs/reference/inputs/).
|
||||||
|
|
||||||
### it
|
### it
|
||||||
|
|
||||||
Within a [describe block](#describe), _`it`_ declares an individual [test](#test) directly against the [resource](#resource) (as opposed to testing against one of the resource's [properties](#property), as [its](#its) does). Though it is possible to use [universal matchers](#universal-matcher) with `it`, it is much more typical to use [resource-specific matchers](#resource-specific-matchers).
|
Within a [describe block](#describe), _`it`_ declares an individual [test](#test) directly against the [resource](#resource) (as opposed to testing against one of the resource's [properties](#property), as [its](#its) does). Though it is possible to use [universal matchers](#universal-matcher) with `it`, it is much more typical to use [resource-specific matchers](#resource-specific-matchers).
|
||||||
|
|
320
docs/inputs.md
Normal file
320
docs/inputs.md
Normal file
|
@ -0,0 +1,320 @@
|
||||||
|
# Chef InSpec Inputs
|
||||||
|
|
||||||
|
## What are Inputs?
|
||||||
|
|
||||||
|
Inputs are the "knobs" you can use to customize the behavior of Chef InSpec profiles. If a profile supports inputs, you can set the inputs in a variety of ways, allowing flexibility. Profiles that include other profiles can set inputs in the included profile, enabling a multi-layered approach to configuring profiles.
|
||||||
|
|
||||||
|
### A Simple Example
|
||||||
|
|
||||||
|
Suppose you have a profile named `rock_critic`. In its profile metadata file (inspec.yml):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Optionally declare inputs in the profile metadata
|
||||||
|
# This lets you set up things like type checking, etc.
|
||||||
|
inputs:
|
||||||
|
- name: amplifier_max_volume
|
||||||
|
description: How loud the amplifiers can go
|
||||||
|
type: numeric
|
||||||
|
# More options, including value: and priority: are possible here
|
||||||
|
```
|
||||||
|
|
||||||
|
In the profile's control code:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# Set a default value for an input. This is optional.
|
||||||
|
input('amplifier_max_volume', value: 10)
|
||||||
|
|
||||||
|
control 'Big Rock Show' do
|
||||||
|
describe input('amplifier_max_volume') do # This line reads the value of the input
|
||||||
|
it { should eq 11 } # The UK'S LOUDEST BAND
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
When the above profile is executed by using `inspec exec rock_critic`, you would see something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
11
|
||||||
|
× should eq 10
|
||||||
|
|
||||||
|
expected: 10
|
||||||
|
got: 11
|
||||||
|
|
||||||
|
(compared using ==)
|
||||||
|
Test Summary: 0 successful, 1 failure, 0 skipped
|
||||||
|
```
|
||||||
|
|
||||||
|
That result clearly won't do. Let's override the input's default value. Create a file, `custom_amps.yml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
amplifier_max_volume: 11
|
||||||
|
```
|
||||||
|
|
||||||
|
We can now run that profile with `inspec exec rock_critic --input-file custom_amps.yaml`:
|
||||||
|
|
||||||
|
```
|
||||||
|
11
|
||||||
|
✔ should eq 11
|
||||||
|
|
||||||
|
Test Summary: 1 successful, 0 failures, 0 skipped
|
||||||
|
```
|
||||||
|
|
||||||
|
### Which profiles support inputs?
|
||||||
|
|
||||||
|
The best way for a profile to indicate it supports inputs is to list them in the metadata file, `inspec.yml`. Any profile that has an `inputs` (or the deprecated `attributes`) section in its `inspec.yml` metadata file is [configuring](#configuring-inputs-in-profile-metadata) inputs.
|
||||||
|
|
||||||
|
That said, any profile that uses the DSL keyword `input()` (or the deprecated `attribute()`) in the control source code supports inputs. These profiles are *reading* (and possibly setting) input values and using them to make decisions.
|
||||||
|
|
||||||
|
### How can I set Inputs?
|
||||||
|
|
||||||
|
As installed (without specialized plugins), Chef InSpec supports five ways of setting inputs:
|
||||||
|
|
||||||
|
* Inline in control code, using `input('input_name', value: 42)`.
|
||||||
|
* In profile `inspec.yml` metadata files
|
||||||
|
* Using the CLI option `--input-file somefile.yaml`
|
||||||
|
* In kitchen-inspec, using the `verifier/inputs` settings
|
||||||
|
* In the Audit Cookbook, using the `node[:audit][:inputs]`
|
||||||
|
|
||||||
|
In addition, Chef InSpec supports Input Plugins, which can provide optional integrations to specific key-value stores.
|
||||||
|
|
||||||
|
### How does Input precedence work?
|
||||||
|
|
||||||
|
#### Simple Precedence
|
||||||
|
|
||||||
|
Briefly:
|
||||||
|
|
||||||
|
inline DSL < metadata < ( cli-input-file or kitchen-inspec or audit-cookbook )
|
||||||
|
|
||||||
|
In addition, for inherited profiles:
|
||||||
|
|
||||||
|
dependent profile metadata < wrapper profile metadata
|
||||||
|
|
||||||
|
This precedence lets you override input values on the command line, as well as override child profile inline values from the parent profile.
|
||||||
|
This description matches the general behavior of InSpec v3, while also making some edge cases easier to reason.
|
||||||
|
|
||||||
|
#### The Details of Input Precedence
|
||||||
|
|
||||||
|
Whenever an input provider sets a value on an input, a *priority value* is assigned to the operation. Over the life of the input, multiple assignments with varying priority values may occur. When the input is evaluated, the current value is determined by finding the setting event with the highest priority.
|
||||||
|
|
||||||
|
Note that this approach does not rely on execution order, nor does it rely on multiple named precedence levels. Each setting operation is preserved and this allows the user to [debug](#debugging-inputs-with-the-event-log) the history of the input values.
|
||||||
|
|
||||||
|
Some input providers allow you to set a priority when you set the value. For example, to set a priority of 50 in a metadata file, use:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
inputs:
|
||||||
|
- name: very_important_input
|
||||||
|
value: 12
|
||||||
|
priority: 50
|
||||||
|
```
|
||||||
|
|
||||||
|
To set a priority in DSL, use:
|
||||||
|
```ruby
|
||||||
|
input('also_important', value: 42, priority: 45)
|
||||||
|
```
|
||||||
|
|
||||||
|
As packaged, Chef InSpec uses the following priority values:
|
||||||
|
|
||||||
|
| Input Provider | Priority | May change priority |
|
||||||
|
| -------------------------------------- | -------- | ------------------- |
|
||||||
|
| Inline DSL | 20 | Yes |
|
||||||
|
| Metadata | 30 | Yes |
|
||||||
|
| Metadata in a wrapper cookbook | 35 | Yes |
|
||||||
|
| CLI `--input-file` option | 40 | No |
|
||||||
|
| inspec-kitchen `inputs:` section | 40 | No |
|
||||||
|
| audit cookbook `node[:audit][:inputs]` | 40 | No |
|
||||||
|
|
||||||
|
|
||||||
|
### What happened to "Attributes"?
|
||||||
|
|
||||||
|
When originally introduced, the Input facility was named *Attributes*. This name was problematic, because:
|
||||||
|
|
||||||
|
* The Chef Infra tool uses the same word to describe its parameterization system.
|
||||||
|
* Chef Infra attributes have a completely different and much more complex precedence system.
|
||||||
|
* This caused confusion about passing Chef Infra attributes into InSpec when using Audit Cookbook and kitchen-inspec.
|
||||||
|
|
||||||
|
Based on these concerns, InSpec attributes have been renamed to InSpec inputs in Chef InSpec v4.
|
||||||
|
|
||||||
|
Support for using the DSL keyword `attribute()`, the metadata field `attributes:`, and the corresponding kitchen-inspec and audit cookbook values are anticipated to continue through Chef InSpec v5.
|
||||||
|
|
||||||
|
## Working with Inputs in Control Code
|
||||||
|
|
||||||
|
### Input Scope
|
||||||
|
|
||||||
|
Inputs are available throughout the InSpec profile DSL. You can use them anywhere.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# some_controls.rb
|
||||||
|
|
||||||
|
input('outer_input', value: 1) # here
|
||||||
|
|
||||||
|
control 'control-1' do
|
||||||
|
input('control_dsl_input', value: 2) # here too
|
||||||
|
describe some_resource do
|
||||||
|
input('test_dsl_input', value: 3) # even here
|
||||||
|
it { should cmp input('expectation_dsl_input') } # and yes here too
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setting Inputs in Control DSL
|
||||||
|
|
||||||
|
When you write `input('some_name', value: 'some_value')`, you are *setting* an input value in the DSL. Because the `value:` option is present, a new value will be set. You may also pass any other option listed in the [input option reference](#input-options-reference).
|
||||||
|
|
||||||
|
### Reading Inputs in Control DSL
|
||||||
|
|
||||||
|
When you call `input('some_name')`, with or without additional options, the value of the input will be resolved and returned. Note that this process may involve sourcing the value from another provider, using the value set in DSL, or overriding the value provided in the same call.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
|
||||||
|
# You can use the value in a Ruby variable
|
||||||
|
some_var = input('some_input_name')
|
||||||
|
|
||||||
|
# Or more directly in a resource parameter
|
||||||
|
describe file(input('important_path')) do
|
||||||
|
it { should exist }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Or as the resource itself (this could be a string, here)
|
||||||
|
describe input('some_setting') do
|
||||||
|
it { should cmp 'correct_value' }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Or as the expected value
|
||||||
|
describe file('/etc/httpd/httpd.conf') do
|
||||||
|
its('owner') { should_not cmp input('webserver_user') }
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
The value returned can be used anywhere a Ruby value is used.
|
||||||
|
|
||||||
|
## Configuring Inputs in Profile Metadata
|
||||||
|
|
||||||
|
Each Chef InSpec profile has a metadata file at the top level named `inspec.yml`. In that file, you may add a section for inputs. You may define inputs there, clearly setting options including values, type checking, and whether the input is required.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: my_profile
|
||||||
|
inputs:
|
||||||
|
- name: webserver_user # Name is the only required field
|
||||||
|
- name: favorite_fruit
|
||||||
|
value: banana # You can set a value; priority is 30 for metadata
|
||||||
|
- name: meaning_of_life
|
||||||
|
type: Numeric
|
||||||
|
value: 42
|
||||||
|
required: true
|
||||||
|
priority: 70
|
||||||
|
```
|
||||||
|
|
||||||
|
All [input options](#input-options-reference) are supported in metadata files.
|
||||||
|
|
||||||
|
There are two major advantages to defining inputs in profile metadata:
|
||||||
|
1. The inputs and their configuration are listed explicitly in simple YAML in one place - a consumer of your profile does not need to read through the control code to find the inputs.
|
||||||
|
2. You can set inputs in other profiles that you depend on using profile inheritance.
|
||||||
|
|
||||||
|
### Using inputs with Profile inheritance
|
||||||
|
|
||||||
|
When your profile relies on another profile using the `depends` key in the metadata file, you can set — that is, override — the value of the input in the dependent profile by including the `profile` option and naming the dependent profile.
|
||||||
|
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# child inspec.yml
|
||||||
|
name: child
|
||||||
|
inputs:
|
||||||
|
- name: favorite_food
|
||||||
|
value: pizza
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# wrapper inspec.yml
|
||||||
|
name: wrapper
|
||||||
|
depends:
|
||||||
|
- name: child
|
||||||
|
path: ../child
|
||||||
|
inputs:
|
||||||
|
- name: favorite_food
|
||||||
|
value: broccoli
|
||||||
|
profile: child # <----- REQUIRED to override the value in InSpec 4
|
||||||
|
```
|
||||||
|
|
||||||
|
In Chef InSpec 4+, every input is namespaced. For example, you could have an input named `wrapper/favorite_food` and one named `child/favorite_food`. If no explicit profile option is set within the `wrapper` profile metadata file, then `wrapper` is assumed to be the profile.
|
||||||
|
|
||||||
|
## Setting Input values using `--input-file`
|
||||||
|
|
||||||
|
You may also provide inputs and values via YAML files on the command line. The format can be seen below:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
an_input: a_value
|
||||||
|
another_input: another_value
|
||||||
|
```
|
||||||
|
|
||||||
|
CLI-set inputs have a priority of 40.
|
||||||
|
|
||||||
|
As of Chef InSpec 4.3.2, this mechanism has the following limitations:
|
||||||
|
|
||||||
|
1. No [input options](#input-options-reference) may be set - only the name and value.
|
||||||
|
2. Because the CLI is outside the scope of any individual profile and the inputs don't take options, the inputs are clumsily copied into every profile, effectively making the CLI mechanism global.
|
||||||
|
|
||||||
|
## Input Options Reference
|
||||||
|
|
||||||
|
### Name
|
||||||
|
|
||||||
|
Required `String`. This option identifies the input.
|
||||||
|
|
||||||
|
Allowed in: All. When used in DSL and Metadata, the name is unique within the current profile. When used in CLI input files, audit cookbook, and kitchen-inspec, the input is copied across all profiles using the same name.
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
Optional `String`. Human-meaningful explanation of the input.
|
||||||
|
|
||||||
|
Allowed in: DSL, Metadata
|
||||||
|
|
||||||
|
### Value
|
||||||
|
|
||||||
|
Optional, any Ruby or YAML type. This is the value that will be available when you read the input. See the [Reading Inputs](#reading-inputs-in-control-dsl) section for more information.
|
||||||
|
|
||||||
|
Allowed in: All
|
||||||
|
|
||||||
|
### Type
|
||||||
|
|
||||||
|
Optional, `String`. This value must be one of `String`, `Numeric`, `Regexp`, `Array`, `Hash`, `Boolean`, or `Any`. If provided, the value of the input will be checked to see if it is of the corresponding type. Note that `Regexp` indicates that the input value itself should be a regular expression, not that it should match any particular regular expression.
|
||||||
|
|
||||||
|
Allowed in: DSL, Metadata
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
Optional, `true` or `false`. If `true`, a control using the input will be failed if it [reads](#reading-inputs-in-control-dsl) the value when none has been set.
|
||||||
|
|
||||||
|
Allowed in: DSL, Metadata
|
||||||
|
|
||||||
|
### Priority
|
||||||
|
|
||||||
|
Optional, `Integer`, 0-100. Higher values make this assignment have higher precedence. This is an advanced feature.
|
||||||
|
|
||||||
|
Allowed in: DSL, Metadata
|
||||||
|
|
||||||
|
### Profile
|
||||||
|
|
||||||
|
Optional, `String`. Allows you to set an input in another profile from your profile.
|
||||||
|
|
||||||
|
Allowed in: DSL, Metadata
|
||||||
|
|
||||||
|
## Advanced Topics
|
||||||
|
|
||||||
|
### Debugging Inputs with the Event Log
|
||||||
|
|
||||||
|
If it is difficult to determine why a particular value is being used, you can use the Event Log to determine what is happening.
|
||||||
|
|
||||||
|
First, use the `input_object()` DSL method. This method is like `input()` in that it looks up an input, but instead of evaluating the current value, it returns the underlying `Inspec::Input` object.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
|
||||||
|
puts input_object('troublesome_input').diagnostic_string
|
||||||
|
|
||||||
|
# Or
|
||||||
|
require 'pp'
|
||||||
|
pp input_object('troublesome_input').events
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
`diagnostic_string` assembles the Event Log into a printable log message for convenience.
|
||||||
|
|
||||||
|
The Event Log contains entries for every time that the value changed, as well as one for when the input was first created. When possible, stack probing is used to determine file and line numbers. Most importantly, you will see priority numbers; remember that highest priority wins; order only matters to break a tie.
|
161
docs/profiles.md
161
docs/profiles.md
|
@ -335,166 +335,9 @@ require_resource(profile: 'my_dep', resource: 'my_res',
|
||||||
This will allow you to reference the resource `my_res` from the
|
This will allow you to reference the resource `my_res` from the
|
||||||
profile `my_dep` using the name `my_res2`.
|
profile `my_dep` using the name `my_res2`.
|
||||||
|
|
||||||
# Profile Attributes
|
# Profile Inputs
|
||||||
|
|
||||||
Attributes are frequently used to parameterize a profile for use in different environments or targets. It can also be used define secrets, such as user names and passwords, that should not otherwise be stored in plain-text in a cookbook. Attributes may be set for the whole profile in the `inspec.yml`.
|
Our documentation regarding [Inputs](docs/reference/inputs/) is now on a dedicated page.
|
||||||
|
|
||||||
Attributes may contain the following options:
|
|
||||||
|
|
||||||
* Use `value` to set a value for the attribute.
|
|
||||||
* Use `type` to restrict an attribute to a specific type (any, string, numeric, array, hash, boolean, regex).
|
|
||||||
* Use `required` to mandate the attribute has a value at the time of evaluation.
|
|
||||||
* Use `description` to set a brief description for the attribute.
|
|
||||||
|
|
||||||
|
|
||||||
## Setting Attributes in the Profile Metadata File
|
|
||||||
|
|
||||||
You can specify attributes in your `inspec.yml` using the `attributes` setting. For example, to add a `user` attribute for your profile:
|
|
||||||
|
|
||||||
```YAML
|
|
||||||
attributes:
|
|
||||||
- name: user
|
|
||||||
type: string
|
|
||||||
value: bob
|
|
||||||
```
|
|
||||||
|
|
||||||
Example of adding a array object of servers:
|
|
||||||
|
|
||||||
```YAML
|
|
||||||
attributes:
|
|
||||||
- name: servers
|
|
||||||
type: array
|
|
||||||
value:
|
|
||||||
- server1
|
|
||||||
- server2
|
|
||||||
- server3
|
|
||||||
```
|
|
||||||
|
|
||||||
To access an attribute you will use the `attribute` keyword. You can use this anywhere in your control code.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```Ruby
|
|
||||||
current_user = attribute('user')
|
|
||||||
|
|
||||||
control 'system-users' do
|
|
||||||
describe attribute('user') do
|
|
||||||
it { should eq 'bob' }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe current_user do
|
|
||||||
it { should eq attribute('user') }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
## Setting Attributes in an External YAML Attributes File
|
|
||||||
|
|
||||||
For sensitive data it is recommended to use a YAML file located on the local machine to populate the values of attributes. To read values from a YAML file, use run `inspec exec` and specify the path to that YAML file using the `--attrs` attribute.
|
|
||||||
|
|
||||||
For example, your profile's metadata file, inspec.yml:
|
|
||||||
|
|
||||||
```YAML
|
|
||||||
attributes:
|
|
||||||
- name: username
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
- name: password
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
```
|
|
||||||
|
|
||||||
The control:
|
|
||||||
|
|
||||||
```Ruby
|
|
||||||
control 'system-users' do
|
|
||||||
impact 0.8
|
|
||||||
desc '
|
|
||||||
This test assures that the user "Bob" has a user installed on the system, along with a
|
|
||||||
specified password.
|
|
||||||
'
|
|
||||||
|
|
||||||
describe attribute('username') do
|
|
||||||
it { should eq 'bob' }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe attribute('password') do
|
|
||||||
it { should eq 'secret' }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
And a YAML file named `profile-attribute.yml`:
|
|
||||||
|
|
||||||
```YAML
|
|
||||||
username: bob
|
|
||||||
password: secret
|
|
||||||
```
|
|
||||||
|
|
||||||
The following command runs the tests and applies the secrets specified in `profile-attribute.yml`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ inspec exec examples/profile-attribute --attrs examples/profile-attribute.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
To change your attributes for platform specific cases you can setup multiple `--attrs` files.
|
|
||||||
|
|
||||||
For example, a inspec.yml:
|
|
||||||
|
|
||||||
```YAML
|
|
||||||
attributes:
|
|
||||||
- name: users
|
|
||||||
type: array
|
|
||||||
required: true
|
|
||||||
```
|
|
||||||
|
|
||||||
A YAML file named `windows.yml`
|
|
||||||
|
|
||||||
```YAML
|
|
||||||
users:
|
|
||||||
- Administrator
|
|
||||||
- Guest
|
|
||||||
- Randy
|
|
||||||
```
|
|
||||||
|
|
||||||
A YAML file named `linux.yml`
|
|
||||||
|
|
||||||
```YAML
|
|
||||||
users:
|
|
||||||
- root
|
|
||||||
- shadow
|
|
||||||
- rmadison
|
|
||||||
```
|
|
||||||
|
|
||||||
The control file:
|
|
||||||
|
|
||||||
```RUBY
|
|
||||||
control 'system-users' do
|
|
||||||
impact 0.8
|
|
||||||
desc 'Confirm the proper users are created on the system'
|
|
||||||
|
|
||||||
describe users do
|
|
||||||
its('usernames') { should eq attribute('users') }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
```
|
|
||||||
|
|
||||||
The following command runs the tests and applies the attributes specified:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ inspec exec examples/profile-attribute --attrs examples/windows.yml
|
|
||||||
$ inspec exec examples/profile-attribute --attrs examples/linux.yml
|
|
||||||
```
|
|
||||||
|
|
||||||
See the full example in the Chef InSpec open source repository: [Example Chef InSpec Profile with Attributes](https://github.com/chef/inspec/tree/master/examples/profile-attribute)
|
|
||||||
|
|
||||||
## Attribute Value Precedence
|
|
||||||
|
|
||||||
Attribute values are always set in the following precedence (highest to lowest):
|
|
||||||
|
|
||||||
1. Values from a file specified on the command line using --attrs
|
|
||||||
2. Values from a profile metadata file - an inspec.yml with an `attributes:` section
|
|
||||||
3. Values provided directly in control code - `attribute('user', value: 'bob')`
|
|
||||||
|
|
||||||
# Profile files
|
# Profile files
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ platform: linux
|
||||||
|
|
||||||
# apache
|
# apache
|
||||||
|
|
||||||
<p class="warning">This resource is deprecated and should not be used. It was removed in Chef InSpec 4.0. The documentation below is preserved as a reference. Replacement functionality is available in the [apache_conf](apache_conf/) resource.</p>
|
**Warning**:This resource is deprecated and should not be used. It was removed in Chef InSpec 4.0. The documentation below is preserved as a reference. Replacement functionality is available in the [`apache_conf`](/docs/reference/resources/apache_conf) resource.
|
||||||
|
|
||||||
Use the `apache` Chef InSpec audit resource to test the state of the Apache server on Linux/Unix systems.
|
Use the `apache` Chef InSpec audit resource to test the state of the Apache server on Linux/Unix systems.
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ title: About the azure_generic_resource Resource
|
||||||
|
|
||||||
# azure\_generic\_resource
|
# azure\_generic\_resource
|
||||||
|
|
||||||
<p class="warning">This resource is deprecated and should not be used. It will be removed in Chef InSpec 5.0. Instead of using any of the demonstration Azure resources included with Chef InSpec, use the [`inspec-azure`](https://github.com/inspec/inspec-azure) resource pack, which offers rich functionality and specific resources to fit many common use cases.</p>
|
**Warning**: This resource is deprecated and should not be used. It will be removed in Chef InSpec 5.0. Instead of using any of the demonstration Azure resources included with Chef InSpec, use the [`inspec-azure`](https://github.com/inspec/inspec-azure) resource pack, which offers rich functionality and specific resources to fit many common use cases.
|
||||||
|
|
||||||
Use the `azure_generic_resource` Chef InSpec audit resource to test any valid Azure Resource. This is very useful if you need to test something that we do not yet have a specific Chef InSpec resource for.
|
Use the `azure_generic_resource` Chef InSpec audit resource to test any valid Azure Resource. This is very useful if you need to test something that we do not yet have a specific Chef InSpec resource for.
|
||||||
|
|
||||||
|
|
|
@ -61,9 +61,8 @@ or may be enclosed in a double-quoted string with an extra backslash as an escap
|
||||||
"HKCU\\SOFTWARE\\path\\to\\key\\Themes"
|
"HKCU\\SOFTWARE\\path\\to\\key\\Themes"
|
||||||
|
|
||||||
|
|
||||||
<p class="warning">
|
**Warning**: Please make sure that you use backslashes instead of forward slashes. Forward slashes will not work for registry keys.
|
||||||
Please make sure that you use backslashes instead of forward slashes. Forward slashes will not work for registry keys.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
# The following will not work:
|
# The following will not work:
|
||||||
# describe registry_key('HKLM/SOFTWARE/Microsoft/NET Framework Setup/NDP/v4/Full/1033') do
|
# describe registry_key('HKLM/SOFTWARE/Microsoft/NET Framework Setup/NDP/v4/Full/1033') do
|
||||||
|
@ -158,9 +157,8 @@ The `name` matcher tests the value for the specified registry setting:
|
||||||
its('name') { should eq 'value' }
|
its('name') { should eq 'value' }
|
||||||
|
|
||||||
|
|
||||||
<p class="warning">
|
**Warning**: Any name with a dot will not work as expected: <code>its('explorer.exe') { should eq 'test' }</code>. For details, see <a href="https://github.com/inspec/inspec/issues/1281">https://github.com/inspec/inspec/issues/1281</a>
|
||||||
Any name with a dot will not work as expected: <code>its('explorer.exe') { should eq 'test' }</code>. For details, see <a href="https://github.com/inspec/inspec/issues/1281">https://github.com/inspec/inspec/issues/1281</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
# instead of:
|
# instead of:
|
||||||
# its('explorer.exe') { should eq 'test' }
|
# its('explorer.exe') { should eq 'test' }
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
"comment": "See #3853",
|
"comment": "See #3853",
|
||||||
"prefix": "The 'attribute' DSL keyword is being replaced by 'input' - please use it instead."
|
"prefix": "The 'attribute' DSL keyword is being replaced by 'input' - please use it instead."
|
||||||
},
|
},
|
||||||
|
"attrs_rename_in_metadata": {
|
||||||
|
"action": "ignore",
|
||||||
|
"comment": "See 3854",
|
||||||
|
"prefix": "Inputs should be specified by using the 'inputs' key in profile metadata, not 'attributes'."
|
||||||
|
},
|
||||||
"aws_resources_in_resource_pack": {
|
"aws_resources_in_resource_pack": {
|
||||||
"comment": "See #3822",
|
"comment": "See #3822",
|
||||||
"action": "warn",
|
"action": "warn",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class Batsignal < Inspec.resource(1)
|
class Batsignal < Inspec.resource(1)
|
||||||
name 'batsignal'
|
name "batsignal"
|
||||||
|
|
||||||
example "
|
example "
|
||||||
describe batsignal do
|
describe batsignal do
|
||||||
|
@ -15,6 +15,6 @@ class Batsignal < Inspec.resource(1)
|
||||||
|
|
||||||
def local_command_call
|
def local_command_call
|
||||||
# call out to a core resource
|
# call out to a core resource
|
||||||
inspec.command('echo 4').stdout.to_i
|
inspec.command("echo 4").stdout.to_i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class Gordon < Inspec.resource(1)
|
class Gordon < Inspec.resource(1)
|
||||||
name 'gordon'
|
name "gordon"
|
||||||
|
|
||||||
example "
|
example "
|
||||||
describe gordon do
|
describe gordon do
|
||||||
|
@ -18,4 +18,3 @@ class Gordon < Inspec.resource(1)
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
source 'https://rubygems.org'
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gem 'inspec', path: '../../.'
|
gem "inspec", path: "../../."
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'bundler', '~> 1.5'
|
gem "bundler", "~> 1.5"
|
||||||
gem 'minitest', '~> 5.5'
|
gem "minitest", "~> 5.5"
|
||||||
gem 'rake', '~> 10'
|
gem "rake", "~> 10"
|
||||||
gem 'simplecov', '~> 0.10'
|
gem "simplecov", "~> 0.10"
|
||||||
end
|
end
|
||||||
|
|
||||||
group :integration do
|
group :integration do
|
||||||
gem 'test-kitchen', '~> 1.4'
|
gem "test-kitchen", "~> 1.4"
|
||||||
gem 'kitchen-ansible'
|
gem "kitchen-ansible"
|
||||||
gem 'kitchen-vagrant'
|
gem "kitchen-vagrant"
|
||||||
gem 'kitchen-inspec'
|
gem "kitchen-inspec"
|
||||||
gem 'concurrent-ruby', '~> 1.0'
|
gem "concurrent-ruby", "~> 1.0"
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
# use basic tests
|
# use basic tests
|
||||||
describe package('nginx') do
|
describe package("nginx") do
|
||||||
it { should be_installed }
|
it { should be_installed }
|
||||||
end
|
end
|
||||||
|
|
||||||
# extend tests with metadata
|
# extend tests with metadata
|
||||||
control '01' do
|
control "01" do
|
||||||
impact 0.7
|
impact 0.7
|
||||||
title 'Verify nginx service'
|
title "Verify nginx service"
|
||||||
desc 'Ensures nginx service is up and running'
|
desc "Ensures nginx service is up and running"
|
||||||
describe service('nginx') do
|
describe service("nginx") do
|
||||||
it { should be_enabled }
|
it { should be_enabled }
|
||||||
it { should be_installed }
|
it { should be_installed }
|
||||||
it { should be_running }
|
it { should be_running }
|
||||||
|
@ -16,8 +16,8 @@ control '01' do
|
||||||
end
|
end
|
||||||
|
|
||||||
# implement os dependent tests
|
# implement os dependent tests
|
||||||
web_user = 'www-data'
|
web_user = "www-data"
|
||||||
web_user = 'nginx' if os[:family] == 'centos'
|
web_user = "nginx" if os[:family] == "centos"
|
||||||
|
|
||||||
describe user(web_user) do
|
describe user(web_user) do
|
||||||
it { should exist }
|
it { should exist }
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
source 'https://supermarket.chef.io'
|
source "https://supermarket.chef.io"
|
||||||
|
|
||||||
metadata
|
metadata
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
source 'https://rubygems.org'
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gem 'inspec', path: '../../.'
|
gem "inspec", path: "../../."
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'bundler', '~> 1.5'
|
gem "bundler", "~> 1.5"
|
||||||
gem 'minitest', '~> 5.5'
|
gem "minitest", "~> 5.5"
|
||||||
gem 'rake', '~> 10'
|
gem "rake", "~> 10"
|
||||||
gem 'simplecov', '~> 0.10'
|
gem "simplecov", "~> 0.10"
|
||||||
end
|
end
|
||||||
|
|
||||||
group :integration do
|
group :integration do
|
||||||
gem 'berkshelf', '~> 4.0'
|
gem "berkshelf", "~> 4.0"
|
||||||
gem 'test-kitchen', '~> 1.4'
|
gem "test-kitchen", "~> 1.4"
|
||||||
gem 'kitchen-vagrant'
|
gem "kitchen-vagrant"
|
||||||
gem 'kitchen-inspec'
|
gem "kitchen-inspec"
|
||||||
gem 'concurrent-ruby', '~> 0.9'
|
gem "concurrent-ruby", "~> 0.9"
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name 'prepare'
|
name "prepare"
|
||||||
maintainer 'Chef Software, Inc.'
|
maintainer "Chef Software, Inc."
|
||||||
maintainer_email 'support@chef.io'
|
maintainer_email "support@chef.io"
|
||||||
description 'This cookbook prepares the test operating systems'
|
description "This cookbook prepares the test operating systems"
|
||||||
version '1.0.0'
|
version "1.0.0"
|
||||||
depends 'apt'
|
depends "apt"
|
||||||
depends 'yum'
|
depends "yum"
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
# install nginx
|
# install nginx
|
||||||
include_recipe('prepare::nginx')
|
include_recipe("prepare::nginx")
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
# install repositories for nginx
|
# install repositories for nginx
|
||||||
case node['platform']
|
case node["platform"]
|
||||||
when 'ubuntu'
|
when "ubuntu"
|
||||||
# if ubuntu, install
|
# if ubuntu, install
|
||||||
apt_repository 'nginx-php' do
|
apt_repository "nginx-php" do
|
||||||
uri 'ppa:nginx/stable'
|
uri "ppa:nginx/stable"
|
||||||
distribution node['lsb']['codename']
|
distribution node["lsb"]["codename"]
|
||||||
end
|
end
|
||||||
when 'centos'
|
when "centos"
|
||||||
# add repo for Centos 7
|
# add repo for Centos 7
|
||||||
yum_repository 'nginx' do
|
yum_repository "nginx" do
|
||||||
description 'Nginx Repo'
|
description "Nginx Repo"
|
||||||
baseurl 'http://nginx.org/packages/centos/7/x86_64'
|
baseurl "http://nginx.org/packages/centos/7/x86_64"
|
||||||
gpgkey 'http://nginx.org/keys/nginx_signing.key'
|
gpgkey "http://nginx.org/keys/nginx_signing.key"
|
||||||
action :create
|
action :create
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# install nginx package
|
# install nginx package
|
||||||
package 'nginx'
|
package "nginx"
|
||||||
|
|
||||||
# start the service
|
# start the service
|
||||||
service 'nginx' do
|
service "nginx" do
|
||||||
action :start
|
action :start
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
# use basic tests
|
# use basic tests
|
||||||
describe package('nginx') do
|
describe package("nginx") do
|
||||||
it { should be_installed }
|
it { should be_installed }
|
||||||
end
|
end
|
||||||
|
|
||||||
# extend tests with metadata
|
# extend tests with metadata
|
||||||
control '01' do
|
control "01" do
|
||||||
impact 0.7
|
impact 0.7
|
||||||
title 'Verify nginx service'
|
title "Verify nginx service"
|
||||||
desc 'Ensures nginx service is up and running'
|
desc "Ensures nginx service is up and running"
|
||||||
describe service('nginx') do
|
describe service("nginx") do
|
||||||
it { should be_enabled }
|
it { should be_enabled }
|
||||||
it { should be_installed }
|
it { should be_installed }
|
||||||
it { should be_running }
|
it { should be_running }
|
||||||
|
@ -16,8 +16,8 @@ control '01' do
|
||||||
end
|
end
|
||||||
|
|
||||||
# implement os dependent tests
|
# implement os dependent tests
|
||||||
web_user = 'www-data'
|
web_user = "www-data"
|
||||||
web_user = 'nginx' if os[:family] == 'centos'
|
web_user = "nginx" if os[:family] == "centos"
|
||||||
|
|
||||||
describe user(web_user) do
|
describe user(web_user) do
|
||||||
it { should exist }
|
it { should exist }
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
source 'https://rubygems.org'
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gem 'inspec', path: '../../.'
|
gem "inspec", path: "../../."
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'bundler', '~> 1.5'
|
gem "bundler", "~> 1.5"
|
||||||
gem 'minitest', '~> 5.5'
|
gem "minitest", "~> 5.5"
|
||||||
gem 'rake', '~> 10'
|
gem "rake", "~> 10"
|
||||||
gem 'simplecov', '~> 0.10'
|
gem "simplecov", "~> 0.10"
|
||||||
end
|
end
|
||||||
|
|
||||||
group :integration do
|
group :integration do
|
||||||
gem 'test-kitchen', '~> 1.4'
|
gem "test-kitchen", "~> 1.4"
|
||||||
gem 'kitchen-vagrant'
|
gem "kitchen-vagrant"
|
||||||
gem 'kitchen-puppet'
|
gem "kitchen-puppet"
|
||||||
gem 'librarian-puppet'
|
gem "librarian-puppet"
|
||||||
gem 'kitchen-inspec'
|
gem "kitchen-inspec"
|
||||||
gem 'concurrent-ruby', '~> 0.9'
|
gem "concurrent-ruby", "~> 0.9"
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
#^syntax detection
|
# ^syntax detection
|
||||||
|
|
||||||
forge "https://forgeapi.puppetlabs.com"
|
forge "https://forgeapi.puppetlabs.com"
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
# use basic tests
|
# use basic tests
|
||||||
describe package('nginx') do
|
describe package("nginx") do
|
||||||
it { should be_installed }
|
it { should be_installed }
|
||||||
end
|
end
|
||||||
|
|
||||||
# extend tests with metadata
|
# extend tests with metadata
|
||||||
control '01' do
|
control "01" do
|
||||||
impact 0.7
|
impact 0.7
|
||||||
title 'Verify nginx service'
|
title "Verify nginx service"
|
||||||
desc 'Ensures nginx service is up and running'
|
desc "Ensures nginx service is up and running"
|
||||||
describe service('nginx') do
|
describe service("nginx") do
|
||||||
it { should be_enabled }
|
it { should be_enabled }
|
||||||
it { should be_installed }
|
it { should be_installed }
|
||||||
it { should be_running }
|
it { should be_running }
|
||||||
|
@ -16,8 +16,8 @@ control '01' do
|
||||||
end
|
end
|
||||||
|
|
||||||
# implement os dependent tests
|
# implement os dependent tests
|
||||||
web_user = 'www-data'
|
web_user = "www-data"
|
||||||
web_user = 'nginx' if os[:family] == 'centos'
|
web_user = "nginx" if os[:family] == "centos"
|
||||||
|
|
||||||
describe user(web_user) do
|
describe user(web_user) do
|
||||||
it { should exist }
|
it { should exist }
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
source 'https://rubygems.org'
|
source "https://rubygems.org"
|
||||||
|
|
||||||
gemspec
|
gemspec
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem 'bundler'
|
gem "bundler"
|
||||||
gem 'byebug'
|
gem "byebug"
|
||||||
gem 'minitest'
|
gem "minitest"
|
||||||
gem 'rake'
|
gem "rake"
|
||||||
gem 'rubocop', '= 0.49.1' # Need to keep in sync with main InSpec project, so config files will work
|
gem "rubocop", "= 0.49.1" # Need to keep in sync with main InSpec project, so config files will work
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
# This task template will make a task named 'test', and run
|
# This task template will make a task named 'test', and run
|
||||||
# the tests that it finds.
|
# the tests that it finds.
|
||||||
require 'rake/testtask'
|
require "rake/testtask"
|
||||||
|
|
||||||
Rake::TestTask.new do |t|
|
Rake::TestTask.new do |t|
|
||||||
t.libs.push 'lib'
|
t.libs.push "lib"
|
||||||
t.test_files = FileList[
|
t.test_files = FileList[
|
||||||
'test/unit/*_test.rb',
|
"test/unit/*_test.rb",
|
||||||
'test/functional/*_test.rb',
|
"test/functional/*_test.rb",
|
||||||
]
|
]
|
||||||
t.verbose = true
|
t.verbose = true
|
||||||
# Ideally, we'd run tests with warnings enabled,
|
# Ideally, we'd run tests with warnings enabled,
|
||||||
|
@ -26,15 +26,15 @@ end
|
||||||
#------------------------------------------------------------------#
|
#------------------------------------------------------------------#
|
||||||
# Code Style Tasks
|
# Code Style Tasks
|
||||||
#------------------------------------------------------------------#
|
#------------------------------------------------------------------#
|
||||||
require 'rubocop/rake_task'
|
require "rubocop/rake_task"
|
||||||
|
|
||||||
RuboCop::RakeTask.new(:lint) do |t|
|
RuboCop::RakeTask.new(:lint) do |t|
|
||||||
# Choices of rubocop rules to enforce are deeply personal.
|
# Choices of rubocop rules to enforce are deeply personal.
|
||||||
# Here, we set things up so that your plugin will use the Bundler-installed
|
# Here, we set things up so that your plugin will use the Bundler-installed
|
||||||
# inspec gem's copy of the InSpec project's rubocop.yml file (which
|
# inspec gem's copy of the InSpec project's rubocop.yml file (which
|
||||||
# is indeed packaged with the inspec gem).
|
# is indeed packaged with the inspec gem).
|
||||||
require 'inspec/globals'
|
require "inspec/globals"
|
||||||
inspec_rubocop_yml = File.join(Inspec.src_root, '.rubocop.yml')
|
inspec_rubocop_yml = File.join(Inspec.src_root, ".rubocop.yml")
|
||||||
|
|
||||||
t.options = ['--display-cop-names', '--config', inspec_rubocop_yml]
|
t.options = ["--display-cop-names", "--config", inspec_rubocop_yml]
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,23 +4,23 @@
|
||||||
|
|
||||||
# It is traditional in a gemspec to dynamically load the current version
|
# It is traditional in a gemspec to dynamically load the current version
|
||||||
# from a file in the source tree. The next three lines make that happen.
|
# from a file in the source tree. The next three lines make that happen.
|
||||||
lib = File.expand_path('../lib', __FILE__)
|
lib = File.expand_path("../lib", __FILE__)
|
||||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
require 'inspec-resource-lister/version'
|
require "inspec-resource-lister/version"
|
||||||
|
|
||||||
Gem::Specification.new do |spec|
|
Gem::Specification.new do |spec|
|
||||||
# Importantly, all InSpec plugins must be prefixed with `inspec-` (most
|
# Importantly, all InSpec plugins must be prefixed with `inspec-` (most
|
||||||
# plugins) or `train-` (plugins which add new connectivity features).
|
# plugins) or `train-` (plugins which add new connectivity features).
|
||||||
spec.name = 'inspec-resource-lister'
|
spec.name = "inspec-resource-lister"
|
||||||
|
|
||||||
# It is polite to namespace your plugin under InspecPlugins::YourPluginInCamelCase
|
# It is polite to namespace your plugin under InspecPlugins::YourPluginInCamelCase
|
||||||
spec.version = InspecPlugins::ResourceLister::VERSION
|
spec.version = InspecPlugins::ResourceLister::VERSION
|
||||||
spec.authors = ['Clinton Wolfe']
|
spec.authors = ["Clinton Wolfe"]
|
||||||
spec.email = ['cwolfe@chef.io']
|
spec.email = ["cwolfe@chef.io"]
|
||||||
spec.summary = 'InSpec Plugin example, lists available resources'
|
spec.summary = "InSpec Plugin example, lists available resources"
|
||||||
spec.description = 'Example for implementing an InSpec Plugin. This simply lists available resources.'
|
spec.description = "Example for implementing an InSpec Plugin. This simply lists available resources."
|
||||||
spec.homepage = 'https://github.com/inspec/inspec/tree/master/examples/plugin'
|
spec.homepage = "https://github.com/inspec/inspec/tree/master/examples/plugin"
|
||||||
spec.license = 'Apache-2.0'
|
spec.license = "Apache-2.0"
|
||||||
|
|
||||||
# Though complicated-looking, this is pretty standard for a gemspec.
|
# Though complicated-looking, this is pretty standard for a gemspec.
|
||||||
# It just filters what will actually be packaged in the gem (leaving
|
# It just filters what will actually be packaged in the gem (leaving
|
||||||
|
@ -28,9 +28,9 @@ Gem::Specification.new do |spec|
|
||||||
spec.files = %w{
|
spec.files = %w{
|
||||||
README.md inspec-resource-lister.gemspec Gemfile
|
README.md inspec-resource-lister.gemspec Gemfile
|
||||||
} + Dir.glob(
|
} + Dir.glob(
|
||||||
'lib/**/*', File::FNM_DOTMATCH
|
"lib/**/*", File::FNM_DOTMATCH
|
||||||
).reject { |f| File.directory?(f) }
|
).reject { |f| File.directory?(f) }
|
||||||
spec.require_paths = ['lib']
|
spec.require_paths = ["lib"]
|
||||||
|
|
||||||
# If you rely on any other gems, list them here with any constraints.
|
# If you rely on any other gems, list them here with any constraints.
|
||||||
# This is how `inspec plugin install` is able to manage your dependencies.
|
# This is how `inspec plugin install` is able to manage your dependencies.
|
||||||
|
@ -39,5 +39,5 @@ Gem::Specification.new do |spec|
|
||||||
|
|
||||||
# All plugins should mention inspec, > 2.2.78
|
# All plugins should mention inspec, > 2.2.78
|
||||||
# 2.2.78 included the v2 Plugin API
|
# 2.2.78 included the v2 Plugin API
|
||||||
spec.add_dependency 'inspec', '>=2.2.78', '<4.0.0'
|
spec.add_dependency "inspec", ">=2.2.78", "<4.0.0"
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,4 +11,4 @@
|
||||||
libdir = File.dirname(__FILE__)
|
libdir = File.dirname(__FILE__)
|
||||||
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
||||||
|
|
||||||
require 'inspec-resource-lister/plugin'
|
require "inspec-resource-lister/plugin"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require 'inspec/resource'
|
require "inspec/resource"
|
||||||
|
|
||||||
module InspecPlugins::ResourceLister
|
module InspecPlugins::ResourceLister
|
||||||
# This class will provide the actual CLI implementation.
|
# This class will provide the actual CLI implementation.
|
||||||
|
@ -16,18 +16,18 @@ module InspecPlugins::ResourceLister
|
||||||
# register the subcommand. Args are a usage message, and a short decription.
|
# register the subcommand. Args are a usage message, and a short decription.
|
||||||
# These will appear when someone has installed the plugin, and then they
|
# These will appear when someone has installed the plugin, and then they
|
||||||
# run `inspec help`.
|
# run `inspec help`.
|
||||||
subcommand_desc 'list-resources [COMMAND]', 'List resources that InSpec finds.'
|
subcommand_desc "list-resources [COMMAND]", "List resources that InSpec finds."
|
||||||
|
|
||||||
# The usual rhythm for a Thor CLI file is description, options, command method.
|
# The usual rhythm for a Thor CLI file is description, options, command method.
|
||||||
# Thor just has you call DSL methods in sequence prior to each command.
|
# Thor just has you call DSL methods in sequence prior to each command.
|
||||||
# Let's make a command, 'core', that lists all of the resources included with InSpec.
|
# Let's make a command, 'core', that lists all of the resources included with InSpec.
|
||||||
|
|
||||||
# First, provide a usage / description. This will appear in `inspec help list-resources`.
|
# First, provide a usage / description. This will appear in `inspec help list-resources`.
|
||||||
desc 'core [OPTIONS]', 'List resources that are included with InSpec.'
|
desc "core [OPTIONS]", "List resources that are included with InSpec."
|
||||||
|
|
||||||
# Let's include an option, -s, to summarize the list.
|
# Let's include an option, -s, to summarize the list.
|
||||||
# Refer to the Thors docs; there is a lot you can do here.
|
# Refer to the Thors docs; there is a lot you can do here.
|
||||||
option :summary, desc: 'Include a total at the bottom', \
|
option :summary, desc: "Include a total at the bottom", \
|
||||||
type: :boolean, default: true, aliases: [:s]
|
type: :boolean, default: true, aliases: [:s]
|
||||||
|
|
||||||
# OK, now the actual method itself. If you provide params, you're telling Thor that
|
# OK, now the actual method itself. If you provide params, you're telling Thor that
|
||||||
|
@ -42,7 +42,7 @@ module InspecPlugins::ResourceLister
|
||||||
# If we were passed a CLI arg, wrap the arg in Regexp matchers so
|
# If we were passed a CLI arg, wrap the arg in Regexp matchers so
|
||||||
# we will match anywhere in the name.
|
# we will match anywhere in the name.
|
||||||
unless pattern == /.+/
|
unless pattern == /.+/
|
||||||
pattern = Regexp.new('.*' + pattern + '.*')
|
pattern = Regexp.new(".*" + pattern + ".*")
|
||||||
end
|
end
|
||||||
|
|
||||||
# This gets a bit into InSpec innards; but this is simply a Hash.
|
# This gets a bit into InSpec innards; but this is simply a Hash.
|
||||||
|
@ -53,7 +53,7 @@ module InspecPlugins::ResourceLister
|
||||||
resource_names.each { |name| puts name }
|
resource_names.each { |name| puts name }
|
||||||
|
|
||||||
if options[:summary]
|
if options[:summary]
|
||||||
puts '-' * 30
|
puts "-" * 30
|
||||||
puts "#{resource_names.count} resources total"
|
puts "#{resource_names.count} resources total"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
# fast and light by only loading heavy things when they are needed.
|
# fast and light by only loading heavy things when they are needed.
|
||||||
|
|
||||||
# Presumably this is light
|
# Presumably this is light
|
||||||
require 'inspec-resource-lister/version'
|
require "inspec-resource-lister/version"
|
||||||
|
|
||||||
# The InspecPlugins namespace is where all plugins should declare themselves.
|
# The InspecPlugins namespace is where all plugins should declare themselves.
|
||||||
# The 'Inspec' capitalization is used throughout the InSpec source code; yes, it's
|
# The 'Inspec' capitalization is used throughout the InSpec source code; yes, it's
|
||||||
|
@ -42,7 +42,7 @@ module InspecPlugins
|
||||||
# functionality.
|
# functionality.
|
||||||
# For example, InSpec will activate this hook when `inspec help` is
|
# For example, InSpec will activate this hook when `inspec help` is
|
||||||
# executed, so that this plugin's usage message will be included in the help.
|
# executed, so that this plugin's usage message will be included in the help.
|
||||||
require 'inspec-resource-lister/cli_command'
|
require "inspec-resource-lister/cli_command"
|
||||||
|
|
||||||
# Having loaded our functionality, return a class that will let the
|
# Having loaded our functionality, return a class that will let the
|
||||||
# CLI engine tap into it.
|
# CLI engine tap into it.
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
# to learn the current version.
|
# to learn the current version.
|
||||||
module InspecPlugins
|
module InspecPlugins
|
||||||
module ResourceLister
|
module ResourceLister
|
||||||
VERSION = '0.1.0'.freeze
|
VERSION = "0.1.0".freeze
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
# Functional tests generally do not have inside knowledge of how the plugin works.
|
# Functional tests generally do not have inside knowledge of how the plugin works.
|
||||||
|
|
||||||
# Include our test harness
|
# Include our test harness
|
||||||
require_relative '../helper'
|
require_relative "../helper"
|
||||||
|
|
||||||
# Because InSpec is a Spec-style test suite, we're going to use Minitest::Spec
|
# Because InSpec is a Spec-style test suite, we're going to use Minitest::Spec
|
||||||
# here, for familiar look and feel. However, this isn't InSpec (or RSpec) code.
|
# here, for familiar look and feel. However, this isn't InSpec (or RSpec) code.
|
||||||
describe 'inspec list-resources core' do
|
describe "inspec list-resources core" do
|
||||||
# Our helper.rb locates this library from the InSpec install that
|
# Our helper.rb locates this library from the InSpec install that
|
||||||
# Bundler installed for us. If we want its methods, we still must
|
# Bundler installed for us. If we want its methods, we still must
|
||||||
# import it. Including it here will make it available in all child
|
# import it. Including it here will make it available in all child
|
||||||
|
@ -30,7 +30,7 @@ describe 'inspec list-resources core' do
|
||||||
# think that this plugin we are currently testing is installed as a
|
# think that this plugin we are currently testing is installed as a
|
||||||
# user plugin, by writing a plugin config file in a temp dir.
|
# user plugin, by writing a plugin config file in a temp dir.
|
||||||
# To use it, just provide a command line, minus the word `inspec`.
|
# To use it, just provide a command line, minus the word `inspec`.
|
||||||
let (:outcome) { run_inspec_process_with_this_plugin('listresources core') }
|
let(:outcome) { run_inspec_process_with_this_plugin("listresources core") }
|
||||||
|
|
||||||
# Some tests through here use minitest Expectations, which attach to all
|
# Some tests through here use minitest Expectations, which attach to all
|
||||||
# Objects, and begin with 'must' (positive) or 'wont' (negative)
|
# Objects, and begin with 'must' (positive) or 'wont' (negative)
|
||||||
|
@ -40,7 +40,7 @@ describe 'inspec list-resources core' do
|
||||||
|
|
||||||
# A selection of core resources, just spot checking.
|
# A selection of core resources, just spot checking.
|
||||||
# This is an example of using Ruby to define sets of tests.
|
# This is an example of using Ruby to define sets of tests.
|
||||||
['process', 'service', 'user', 'file'].each do |resource_name|
|
%w{process service user file}.each do |resource_name|
|
||||||
it "should mention the '#{resource_name}' resource" do
|
it "should mention the '#{resource_name}' resource" do
|
||||||
outcome.stdout.must_include(resource_name)
|
outcome.stdout.must_include(resource_name)
|
||||||
end
|
end
|
||||||
|
@ -48,7 +48,7 @@ describe 'inspec list-resources core' do
|
||||||
|
|
||||||
# Check for the summary
|
# Check for the summary
|
||||||
it "should mention the summary" do
|
it "should mention the summary" do
|
||||||
outcome.stdout.must_include('resources total')
|
outcome.stdout.must_include("resources total")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -56,19 +56,19 @@ describe 'inspec list-resources core' do
|
||||||
describe "when run with a search pattern that matches things" do
|
describe "when run with a search pattern that matches things" do
|
||||||
# Notice that the command line is changed here:
|
# Notice that the command line is changed here:
|
||||||
# "list all resources that have the word user in them"
|
# "list all resources that have the word user in them"
|
||||||
let (:outcome) { run_inspec_process_with_this_plugin('listresources core user') }
|
let(:outcome) { run_inspec_process_with_this_plugin("listresources core user") }
|
||||||
|
|
||||||
# Should be well-behaved...
|
# Should be well-behaved...
|
||||||
it("should exit successfully") { outcome.exit_status.must_equal(0) }
|
it("should exit successfully") { outcome.exit_status.must_equal(0) }
|
||||||
it("should be silent on stderr") { outcome.stderr.must_be_empty }
|
it("should be silent on stderr") { outcome.stderr.must_be_empty }
|
||||||
|
|
||||||
# Here, we want to know it DID match some things, and NOT some others.
|
# Here, we want to know it DID match some things, and NOT some others.
|
||||||
['user', 'users'].each do |resource_name|
|
%w{user users}.each do |resource_name|
|
||||||
it "should mention the '#{resource_name}' resource" do
|
it "should mention the '#{resource_name}' resource" do
|
||||||
outcome.stdout.must_include(resource_name)
|
outcome.stdout.must_include(resource_name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
['process', 'service', 'file'].each do |resource_name|
|
%w{process service file}.each do |resource_name|
|
||||||
it "should NOT mention the '#{resource_name}' resource" do
|
it "should NOT mention the '#{resource_name}' resource" do
|
||||||
outcome.stdout.wont_include(resource_name)
|
outcome.stdout.wont_include(resource_name)
|
||||||
end
|
end
|
||||||
|
@ -76,7 +76,7 @@ describe 'inspec list-resources core' do
|
||||||
end
|
end
|
||||||
describe "when run with a search pattern that matches nothing" do
|
describe "when run with a search pattern that matches nothing" do
|
||||||
# Unlikely we'll have a resource with the string 'autogyro' in it.
|
# Unlikely we'll have a resource with the string 'autogyro' in it.
|
||||||
let (:outcome) { run_inspec_process_with_this_plugin('listresources core autogyro') }
|
let(:outcome) { run_inspec_process_with_this_plugin("listresources core autogyro") }
|
||||||
|
|
||||||
# Should be well-behaved...
|
# Should be well-behaved...
|
||||||
it("should exit successfully") { outcome.exit_status.must_equal(0) }
|
it("should exit successfully") { outcome.exit_status.must_equal(0) }
|
||||||
|
@ -89,14 +89,14 @@ describe 'inspec list-resources core' do
|
||||||
|
|
||||||
# Check for the summary
|
# Check for the summary
|
||||||
it "should mention a zero-resource summary" do
|
it "should mention a zero-resource summary" do
|
||||||
outcome.stdout.must_include('0 resources total')
|
outcome.stdout.must_include("0 resources total")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Exercise the summary option, which defaults to 'true'.
|
# Exercise the summary option, which defaults to 'true'.
|
||||||
describe "when run with the no-summary flag" do
|
describe "when run with the no-summary flag" do
|
||||||
# Alter the command string to include the no-summary option
|
# Alter the command string to include the no-summary option
|
||||||
let(:outcome) { run_inspec_process_with_this_plugin('listresources core --no-summary') }
|
let(:outcome) { run_inspec_process_with_this_plugin("listresources core --no-summary") }
|
||||||
|
|
||||||
# Should be well-behaved...
|
# Should be well-behaved...
|
||||||
it("should exit successfully") { outcome.exit_status.must_equal(0) }
|
it("should exit successfully") { outcome.exit_status.must_equal(0) }
|
||||||
|
@ -104,7 +104,7 @@ describe 'inspec list-resources core' do
|
||||||
|
|
||||||
# Check for the summary
|
# Check for the summary
|
||||||
it "should NOT mention summary" do
|
it "should NOT mention summary" do
|
||||||
outcome.stdout.wont_include('0 resources total')
|
outcome.stdout.wont_include("0 resources total")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
# InSpec core provides a number of such libraries and facilities, in the file
|
# InSpec core provides a number of such libraries and facilities, in the file
|
||||||
# lib/pligins/shared/core_plugin_test_helper.rb . So, one job in this file is
|
# lib/pligins/shared/core_plugin_test_helper.rb . So, one job in this file is
|
||||||
# to locate and load that file.
|
# to locate and load that file.
|
||||||
require 'inspec/../plugins/shared/core_plugin_test_helper'
|
require "inspec/../plugins/shared/core_plugin_test_helper"
|
||||||
|
|
||||||
# Also load the InSpec plugin system. We need this so we can unit-test the plugin
|
# Also load the InSpec plugin system. We need this so we can unit-test the plugin
|
||||||
# classes, which will rely on the plugin system.
|
# classes, which will rely on the plugin system.
|
||||||
require 'inspec/plugin/v2'
|
require "inspec/plugin/v2"
|
||||||
|
|
||||||
# Caution: loading all of InSpec (i.e. require 'inspec') may cause interference with
|
# Caution: loading all of InSpec (i.e. require 'inspec') may cause interference with
|
||||||
# minitest/spec; one symptom would be appearing to have no tests.
|
# minitest/spec; one symptom would be appearing to have no tests.
|
||||||
|
@ -19,8 +19,8 @@ require 'inspec/plugin/v2'
|
||||||
# You can select from a number of test harnesses. Since InSpec uses Spec-style controls
|
# You can select from a number of test harnesses. Since InSpec uses Spec-style controls
|
||||||
# in profile code, you will probably want to use something like minitest/spec, which provides
|
# in profile code, you will probably want to use something like minitest/spec, which provides
|
||||||
# Spec-style tests.
|
# Spec-style tests.
|
||||||
require 'minitest/spec'
|
require "minitest/spec"
|
||||||
require 'minitest/autorun'
|
require "minitest/autorun"
|
||||||
|
|
||||||
# You might want to put some debugging tools here. We run tests to find bugs, after all.
|
# You might want to put some debugging tools here. We run tests to find bugs, after all.
|
||||||
# require 'byebug'
|
# require 'byebug'
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
# inspec-resource-lister are correct.
|
# inspec-resource-lister are correct.
|
||||||
|
|
||||||
# Include our test harness
|
# Include our test harness
|
||||||
require_relative '../helper'
|
require_relative "../helper"
|
||||||
|
|
||||||
# Load the class under test, the CliCommand definition.
|
# Load the class under test, the CliCommand definition.
|
||||||
require 'inspec-resource-lister/cli_command'
|
require "inspec-resource-lister/cli_command"
|
||||||
|
|
||||||
# Because InSpec is a Spec-style test suite, we're going to use Minitest::Spec
|
# Because InSpec is a Spec-style test suite, we're going to use Minitest::Spec
|
||||||
# here, for familiar look and feel. However, this isn't InSpec (or RSpec) code.
|
# here, for familiar look and feel. However, this isn't InSpec (or RSpec) code.
|
||||||
|
@ -20,11 +20,11 @@ describe InspecPlugins::ResourceLister::CliCommand do
|
||||||
let(:cli_class) { InspecPlugins::ResourceLister::CliCommand }
|
let(:cli_class) { InspecPlugins::ResourceLister::CliCommand }
|
||||||
|
|
||||||
# This is a Hash of Structs that tells us details of options for the 'core' subcommand.
|
# This is a Hash of Structs that tells us details of options for the 'core' subcommand.
|
||||||
let(:core_options) { cli_class.all_commands['core'].options }
|
let(:core_options) { cli_class.all_commands["core"].options }
|
||||||
|
|
||||||
# To group tests together, you can nest 'describe' in minitest/spec
|
# To group tests together, you can nest 'describe' in minitest/spec
|
||||||
# (that is discouraged in InSpec control code.)
|
# (that is discouraged in InSpec control code.)
|
||||||
describe 'the core command' do
|
describe "the core command" do
|
||||||
|
|
||||||
# Some tests through here use minitest Expectations, which attach to all
|
# Some tests through here use minitest Expectations, which attach to all
|
||||||
# Objects, and begin with 'must' (positive) or 'wont' (negative)
|
# Objects, and begin with 'must' (positive) or 'wont' (negative)
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
# the inspec-resource-lister plugin is configured correctly.
|
# the inspec-resource-lister plugin is configured correctly.
|
||||||
|
|
||||||
# Include our test harness
|
# Include our test harness
|
||||||
require_relative '../helper'
|
require_relative "../helper"
|
||||||
|
|
||||||
# Load the class under test, the Plugin definition.
|
# Load the class under test, the Plugin definition.
|
||||||
require 'inspec-resource-lister/plugin'
|
require "inspec-resource-lister/plugin"
|
||||||
|
|
||||||
# Because InSpec is a Spec-style test suite, we're going to use Minitest::Spec
|
# Because InSpec is a Spec-style test suite, we're going to use Minitest::Spec
|
||||||
# here, for familiar look and feel. However, this isn't InSpec (or RSpec) code.
|
# here, for familiar look and feel. However, this isn't InSpec (or RSpec) code.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
val_user = attribute('user', value: 'alice', description: 'An identification for the user')
|
val_user = input('user', value: 'alice', description: 'An identification for the user')
|
||||||
val_password = attribute('password', description: 'A value for the password')
|
val_password = input('password', description: 'A value for the password')
|
||||||
|
|
||||||
describe val_user do
|
describe val_user do
|
||||||
it { should eq 'bob' }
|
it { should eq 'bob' }
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
require 'yaml'
|
require "yaml"
|
||||||
|
|
||||||
# Custom resource based on the InSpec resource DSL
|
# Custom resource based on the InSpec resource DSL
|
||||||
class GordonConfig < Inspec.resource(1)
|
class GordonConfig < Inspec.resource(1)
|
||||||
name 'gordon_config'
|
name "gordon_config"
|
||||||
|
|
||||||
supports platform: 'unix'
|
supports platform: "unix"
|
||||||
supports platform: 'windows'
|
supports platform: "windows"
|
||||||
|
|
||||||
desc "
|
desc "
|
||||||
Gordon's resource description ...
|
Gordon's resource description ...
|
||||||
|
@ -21,7 +21,7 @@ class GordonConfig < Inspec.resource(1)
|
||||||
# Load the configuration file on initialization
|
# Load the configuration file on initialization
|
||||||
def initialize
|
def initialize
|
||||||
@params = {}
|
@params = {}
|
||||||
@path = '/tmp/gordon/config.yaml'
|
@path = "/tmp/gordon/config.yaml"
|
||||||
@file = inspec.file(@path)
|
@file = inspec.file(@path)
|
||||||
|
|
||||||
unless @file.file?
|
unless @file.file?
|
||||||
|
@ -32,9 +32,9 @@ class GordonConfig < Inspec.resource(1)
|
||||||
begin
|
begin
|
||||||
@params = YAML.load(@file.content)
|
@params = YAML.load(@file.content)
|
||||||
# Add two extra matchers
|
# Add two extra matchers
|
||||||
@params['file_size'] = @file.size
|
@params["file_size"] = @file.size
|
||||||
@params['file_path'] = @path
|
@params["file_path"] = @path
|
||||||
@params['ruby'] = 'RUBY IS HERE TO HELP ME!'
|
@params["ruby"] = "RUBY IS HERE TO HELP ME!"
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
raise Inspec::Exceptions::ResourceSkipped, "#{@file}: #{e.message}"
|
raise Inspec::Exceptions::ResourceSkipped, "#{@file}: #{e.message}"
|
||||||
end
|
end
|
||||||
|
@ -49,7 +49,7 @@ class GordonConfig < Inspec.resource(1)
|
||||||
# Example matcher for the number of commas in the file
|
# Example matcher for the number of commas in the file
|
||||||
def comma_count
|
def comma_count
|
||||||
text = @file.content
|
text = @file.content
|
||||||
text.count(',')
|
text.count(",")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Expose all parameters
|
# Expose all parameters
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
source 'https://rubygems.org'
|
source "https://rubygems.org"
|
||||||
gemspec
|
gemspec name: "inspec-bin"
|
||||||
|
|
|
@ -4,9 +4,8 @@
|
||||||
Encoding.default_external = Encoding::UTF_8
|
Encoding.default_external = Encoding::UTF_8
|
||||||
Encoding.default_internal = Encoding::UTF_8
|
Encoding.default_internal = Encoding::UTF_8
|
||||||
|
|
||||||
lib = File.expand_path('../lib', __FILE__)
|
lib = File.expand_path("../lib", __FILE__)
|
||||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
|
|
||||||
require 'inspec'
|
require "inspec/cli"
|
||||||
require 'inspec/cli'
|
|
||||||
Inspec::InspecCLI.start(ARGV, enforce_license: true)
|
Inspec::InspecCLI.start(ARGV, enforce_license: true)
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
lib = File.expand_path('../lib', __FILE__)
|
lib = File.expand_path("../lib", __FILE__)
|
||||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
require 'inspec-bin/version'
|
require "inspec-bin/version"
|
||||||
|
|
||||||
Gem::Specification.new do |spec|
|
Gem::Specification.new do |spec|
|
||||||
spec.name = 'inspec-bin'
|
spec.name = "inspec-bin"
|
||||||
spec.version = InspecBin::VERSION
|
spec.version = InspecBin::VERSION
|
||||||
spec.authors = ['Chef InSpec Core Engineering ']
|
spec.authors = ["Chef InSpec Core Engineering "]
|
||||||
spec.email = ['inspec@chef.io']
|
spec.email = ["inspec@chef.io"]
|
||||||
spec.summary = 'Infrastructure and compliance testing.'
|
spec.summary = "Infrastructure and compliance testing."
|
||||||
spec.description = 'InSpec executable for inspec gem. Use of this executable may require accepting a license agreement.'
|
spec.description = "InSpec executable for inspec gem. Use of this executable may require accepting a license agreement."
|
||||||
spec.homepage = 'https://github.com/inspec/inspec/tree/master/inspec-bin'
|
spec.homepage = "https://github.com/inspec/inspec/tree/master/inspec-bin"
|
||||||
spec.license = 'Apache-2.0'
|
spec.license = "Apache-2.0"
|
||||||
|
|
||||||
spec.require_paths = ['lib']
|
spec.require_paths = ["lib"]
|
||||||
spec.required_ruby_version = '>= 2.4'
|
spec.required_ruby_version = ">= 2.4"
|
||||||
|
|
||||||
spec.add_dependency 'inspec', "= #{InspecBin::VERSION}"
|
spec.add_dependency "inspec", "= #{InspecBin::VERSION}"
|
||||||
spec.add_development_dependency 'rake'
|
spec.add_development_dependency "rake"
|
||||||
|
|
||||||
spec.files = %w{README.md LICENSE Gemfile} + Dir.glob('*.gemspec') +
|
spec.files = %w{README.md LICENSE Gemfile} + Dir.glob("*.gemspec") +
|
||||||
Dir.glob('{lib,bin}/**/*', File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
|
Dir.glob("{lib,bin}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
|
||||||
|
|
||||||
spec.bindir = 'bin'
|
spec.bindir = "bin"
|
||||||
spec.executables = %w{inspec}
|
spec.executables = %w{inspec}
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
30
inspec-bin/inspec-core-bin.gemspec
Normal file
30
inspec-bin/inspec-core-bin.gemspec
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
lib = File.expand_path("../lib", __FILE__)
|
||||||
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
|
require "inspec-bin/version"
|
||||||
|
|
||||||
|
# This is just link inspec-bin, but relies on inspec-core instead of inspec
|
||||||
|
# inspec-core is a stripped-down version of the inspec gem with fewer exotic dependencies
|
||||||
|
|
||||||
|
Gem::Specification.new do |spec|
|
||||||
|
spec.name = "inspec-core-bin" # dallas multi-pass
|
||||||
|
spec.version = InspecBin::VERSION
|
||||||
|
spec.authors = ["Chef InSpec Core Engineering "]
|
||||||
|
spec.email = ["inspec@chef.io"]
|
||||||
|
spec.summary = "Infrastructure and compliance testing."
|
||||||
|
spec.description = "InSpec executable for inspec-core gem. Use of this executable may require accepting a license agreement."
|
||||||
|
spec.homepage = "https://github.com/inspec/inspec/tree/master/inspec-bin"
|
||||||
|
spec.license = "Apache-2.0"
|
||||||
|
|
||||||
|
spec.require_paths = ["lib"]
|
||||||
|
spec.required_ruby_version = ">= 2.4"
|
||||||
|
|
||||||
|
spec.add_dependency "inspec-core", "= #{InspecBin::VERSION}"
|
||||||
|
spec.add_development_dependency "rake"
|
||||||
|
|
||||||
|
spec.files = %w{README.md LICENSE Gemfile} + ["inspec-core-bin.gemspec"] +
|
||||||
|
Dir.glob("{lib,bin}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
|
||||||
|
|
||||||
|
spec.bindir = "bin"
|
||||||
|
spec.executables = %w{inspec}
|
||||||
|
|
||||||
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
# This file managed by automation - do not edit manually
|
# This file managed by automation - do not edit manually
|
||||||
module InspecBin
|
module InspecBin
|
||||||
INSPECBIN_ROOT = File.expand_path('../..', __FILE__)
|
INSPECBIN_ROOT = File.expand_path("../..", __FILE__)
|
||||||
VERSION = '4.4.65'.freeze
|
VERSION = "4.6.4".freeze
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,46 +1,46 @@
|
||||||
lib = File.expand_path('../lib', __FILE__)
|
lib = File.expand_path("../lib", __FILE__)
|
||||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
require 'inspec/version'
|
require "inspec/version"
|
||||||
|
|
||||||
Gem::Specification.new do |spec|
|
Gem::Specification.new do |spec|
|
||||||
spec.name = 'inspec-core'
|
spec.name = "inspec-core"
|
||||||
spec.version = Inspec::VERSION
|
spec.version = Inspec::VERSION
|
||||||
spec.authors = ['Dominik Richter']
|
spec.authors = ["Dominik Richter"]
|
||||||
spec.email = ['dominik.richter@gmail.com']
|
spec.email = ["dominik.richter@gmail.com"]
|
||||||
spec.summary = 'Just InSpec'
|
spec.summary = "Just InSpec"
|
||||||
spec.description = 'Core InSpec, local support only. See `inspec` for full support.'
|
spec.description = "Core InSpec, local support only. See `inspec` for full support."
|
||||||
spec.homepage = 'https://github.com/chef/inspec'
|
spec.homepage = "https://github.com/chef/inspec"
|
||||||
spec.license = 'Apache-2.0'
|
spec.license = "Apache-2.0"
|
||||||
|
|
||||||
spec.files = %w{README.md LICENSE} + Dir.glob('{bin,lib,etc}/**/*', File::FNM_DOTMATCH)
|
spec.files = %w{README.md LICENSE} + Dir.glob("{bin,lib,etc}/**/*", File::FNM_DOTMATCH)
|
||||||
.reject { |f| File.directory?(f) || f =~ /aws|azure|gcp/ || f =~ %r{lib/plugins/.*/test/} }
|
.reject { |f| File.directory?(f) || f =~ /aws|azure|gcp/ || f =~ %r{lib/plugins/.*/test/} }
|
||||||
|
|
||||||
spec.require_paths = ['lib']
|
spec.require_paths = ["lib"]
|
||||||
|
|
||||||
spec.required_ruby_version = '>= 2.4'
|
spec.required_ruby_version = ">= 2.4"
|
||||||
|
|
||||||
spec.add_dependency 'train-core', '~> 2.0'
|
spec.add_dependency "train-core", "~> 2.0"
|
||||||
spec.add_dependency 'license-acceptance', '>= 0.2.13', '< 2.0'
|
spec.add_dependency "license-acceptance", ">= 0.2.13", "< 2.0"
|
||||||
spec.add_dependency 'thor', '~> 0.20'
|
spec.add_dependency "thor", "~> 0.20"
|
||||||
spec.add_dependency 'json', '>= 1.8', '< 3.0'
|
spec.add_dependency "json-schema", "~> 2.8"
|
||||||
spec.add_dependency 'method_source', '~> 0.8'
|
spec.add_dependency "method_source", "~> 0.8"
|
||||||
spec.add_dependency 'rubyzip', '~> 1.1'
|
spec.add_dependency "rubyzip", "~> 1.1"
|
||||||
spec.add_dependency 'rspec', '~> 3'
|
spec.add_dependency "rspec", "~> 3"
|
||||||
spec.add_dependency 'rspec-its', '~> 1.2'
|
spec.add_dependency "rspec-its", "~> 1.2"
|
||||||
spec.add_dependency 'hashie', '~> 3.4'
|
spec.add_dependency "hashie", "~> 3.4"
|
||||||
spec.add_dependency 'mixlib-log'
|
spec.add_dependency "mixlib-log"
|
||||||
spec.add_dependency 'pry', '~> 0'
|
spec.add_dependency "pry", "~> 0"
|
||||||
spec.add_dependency 'sslshake', '~> 1.2'
|
spec.add_dependency "sslshake", "~> 1.2"
|
||||||
spec.add_dependency 'parallel', '~> 1.9'
|
spec.add_dependency "parallel", "~> 1.9"
|
||||||
spec.add_dependency 'faraday', '>=0.9.0'
|
spec.add_dependency "faraday", ">=0.9.0"
|
||||||
spec.add_dependency 'faraday_middleware', '~> 0.12.2'
|
spec.add_dependency "faraday_middleware", "~> 0.12.2"
|
||||||
spec.add_dependency 'tomlrb', '~> 1.2'
|
spec.add_dependency "tomlrb", "~> 1.2"
|
||||||
spec.add_dependency 'addressable', '~> 2.4'
|
spec.add_dependency "addressable", "~> 2.4"
|
||||||
spec.add_dependency 'parslet', '~> 1.5'
|
spec.add_dependency "parslet", "~> 1.5"
|
||||||
spec.add_dependency 'semverse'
|
spec.add_dependency "semverse"
|
||||||
spec.add_dependency 'htmlentities'
|
spec.add_dependency "htmlentities"
|
||||||
spec.add_dependency 'multipart-post'
|
spec.add_dependency "multipart-post"
|
||||||
spec.add_dependency 'tty-table', '~> 0.10'
|
spec.add_dependency "tty-table", "~> 0.10"
|
||||||
spec.add_dependency 'tty-prompt', '~> 0.17'
|
spec.add_dependency "tty-prompt", "~> 0.17"
|
||||||
spec.add_dependency 'term-ansicolor'
|
spec.add_dependency "term-ansicolor"
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,56 +1,56 @@
|
||||||
lib = File.expand_path('../lib', __FILE__)
|
lib = File.expand_path("../lib", __FILE__)
|
||||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
require 'inspec/version'
|
require "inspec/version"
|
||||||
|
|
||||||
Gem::Specification.new do |spec|
|
Gem::Specification.new do |spec|
|
||||||
spec.name = 'inspec'
|
spec.name = "inspec"
|
||||||
spec.version = Inspec::VERSION
|
spec.version = Inspec::VERSION
|
||||||
spec.authors = ['Chef InSpec Team']
|
spec.authors = ["Chef InSpec Team"]
|
||||||
spec.email = ['inspec@chef.io']
|
spec.email = ["inspec@chef.io"]
|
||||||
spec.summary = 'Infrastructure and compliance testing.'
|
spec.summary = "Infrastructure and compliance testing."
|
||||||
spec.description = 'InSpec provides a framework for creating end-to-end infrastructure tests. You can use it for integration or even compliance testing. Create fully portable test profiles and use them in your workflow to ensure stability and security. Integrate InSpec in your change lifecycle for local testing, CI/CD, and deployment verification.'
|
spec.description = "InSpec provides a framework for creating end-to-end infrastructure tests. You can use it for integration or even compliance testing. Create fully portable test profiles and use them in your workflow to ensure stability and security. Integrate InSpec in your change lifecycle for local testing, CI/CD, and deployment verification."
|
||||||
spec.homepage = 'https://github.com/inspec/inspec'
|
spec.homepage = "https://github.com/inspec/inspec"
|
||||||
spec.license = 'Apache-2.0'
|
spec.license = "Apache-2.0"
|
||||||
|
|
||||||
# the gemfile and gemspec are necessary for appbundler so don't remove it
|
# the gemfile and gemspec are necessary for appbundler so don't remove it
|
||||||
spec.files = %w{Gemfile inspec.gemspec README.md LICENSE} + Dir.glob(
|
spec.files = %w{Gemfile inspec.gemspec README.md LICENSE} + Dir.glob(
|
||||||
'{bin,lib,etc}/**/*', File::FNM_DOTMATCH
|
"{bin,lib,etc}/**/*", File::FNM_DOTMATCH
|
||||||
).reject { |f| File.directory?(f) }
|
).reject { |f| File.directory?(f) }
|
||||||
|
|
||||||
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
||||||
.reject { |f| File.directory?(f) || f =~ %r{lib/plugins/.*/test/} }
|
.reject { |f| File.directory?(f) || f =~ %r{lib/plugins/.*/test/} }
|
||||||
spec.require_paths = ['lib']
|
spec.require_paths = ["lib"]
|
||||||
|
|
||||||
spec.required_ruby_version = '>= 2.4'
|
spec.required_ruby_version = ">= 2.4"
|
||||||
|
|
||||||
spec.add_dependency 'train', '~> 2.0' # Inspec 4 must have train 2+
|
spec.add_dependency "train", "~> 2.0" # Inspec 4 must have train 2+
|
||||||
# Train plugins we ship with InSpec
|
# Train plugins we ship with InSpec
|
||||||
spec.add_dependency 'train-habitat', '~> 0.1'
|
spec.add_dependency "train-habitat", "~> 0.1"
|
||||||
spec.add_dependency 'train-aws', '~> 0.1'
|
spec.add_dependency "train-aws", "~> 0.1"
|
||||||
|
|
||||||
# Implementation dependencies
|
# Implementation dependencies
|
||||||
spec.add_dependency 'license-acceptance', '>= 0.2.13', '< 2.0'
|
spec.add_dependency "license-acceptance", ">= 0.2.13", "< 2.0"
|
||||||
spec.add_dependency 'thor', '~> 0.20'
|
spec.add_dependency "thor", "~> 0.20"
|
||||||
spec.add_dependency 'json', '>= 1.8', '< 3.0'
|
spec.add_dependency "json-schema", "~> 2.8"
|
||||||
spec.add_dependency 'method_source', '~> 0.8'
|
spec.add_dependency "method_source", "~> 0.8"
|
||||||
spec.add_dependency 'rubyzip', '~> 1.2', '>= 1.2.2'
|
spec.add_dependency "rubyzip", "~> 1.2", ">= 1.2.2"
|
||||||
spec.add_dependency 'rspec', '~> 3'
|
spec.add_dependency "rspec", "~> 3"
|
||||||
spec.add_dependency 'rspec-its', '~> 1.2'
|
spec.add_dependency "rspec-its", "~> 1.2"
|
||||||
spec.add_dependency 'pry', '~> 0'
|
spec.add_dependency "pry", "~> 0"
|
||||||
spec.add_dependency 'hashie', '~> 3.4'
|
spec.add_dependency "hashie", "~> 3.4"
|
||||||
spec.add_dependency 'mixlib-log'
|
spec.add_dependency "mixlib-log"
|
||||||
spec.add_dependency 'sslshake', '~> 1.2'
|
spec.add_dependency "sslshake", "~> 1.2"
|
||||||
spec.add_dependency 'parallel', '~> 1.9'
|
spec.add_dependency "parallel", "~> 1.9"
|
||||||
spec.add_dependency 'faraday', '>=0.9.0'
|
spec.add_dependency "faraday", ">=0.9.0"
|
||||||
spec.add_dependency 'tty-table', '~> 0.10'
|
spec.add_dependency "tty-table", "~> 0.10"
|
||||||
spec.add_dependency 'tty-prompt', '~> 0.17'
|
spec.add_dependency "tty-prompt", "~> 0.17"
|
||||||
# Used for Azure profile until integrated into train
|
# Used for Azure profile until integrated into train
|
||||||
spec.add_dependency 'faraday_middleware', '~> 0.12.2'
|
spec.add_dependency "faraday_middleware", "~> 0.12.2"
|
||||||
spec.add_dependency 'tomlrb', '~> 1.2'
|
spec.add_dependency "tomlrb", "~> 1.2"
|
||||||
spec.add_dependency 'addressable', '~> 2.4'
|
spec.add_dependency "addressable", "~> 2.4"
|
||||||
spec.add_dependency 'parslet', '~> 1.5'
|
spec.add_dependency "parslet", "~> 1.5"
|
||||||
spec.add_dependency 'semverse'
|
spec.add_dependency "semverse"
|
||||||
spec.add_dependency 'htmlentities'
|
spec.add_dependency "htmlentities"
|
||||||
spec.add_dependency 'multipart-post'
|
spec.add_dependency "multipart-post"
|
||||||
spec.add_dependency 'term-ansicolor'
|
spec.add_dependency "term-ansicolor"
|
||||||
end
|
end
|
||||||
|
|
128
inspec_team-working_agreement.md
Normal file
128
inspec_team-working_agreement.md
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
# Overview
|
||||||
|
This document covers the working agreement used by the Chef InSpec team. Its goal is to make transparent the team's practices, processes, communication, and coordination functions.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
While the key audience of the working agreement is the Chef InSpec product and engineering team, it is expected that all contributors of Chef InSpec abide by the agreement if they are contributing code to the product.
|
||||||
|
|
||||||
|
# Practices
|
||||||
|
*(e.g. Test Driven Development, Pairing, etc)*
|
||||||
|
|
||||||
|
## Architecture/Design
|
||||||
|
* Group discussion for new major tickets or responsibilities
|
||||||
|
* We do Agile, and this tends to get covered in sprint planning.
|
||||||
|
* Software design / architecture is a group effort
|
||||||
|
* done with pictures or prose, not code
|
||||||
|
* Graphical software design technology
|
||||||
|
* google slides is generally "good enough"
|
||||||
|
* capture final approach in version control ... or GH issue?
|
||||||
|
* must link or otherwise ensure searchability later
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
* We embrace TDD as often as possible, which (practically) means tests for functionality exists on the same or a preceding commit.
|
||||||
|
* Testing requirements for community PRs
|
||||||
|
* acknowledge it is currently a barrier
|
||||||
|
* may have an initiative to improve in 2019H2
|
||||||
|
* may adopt PRs - discuss in triage
|
||||||
|
|
||||||
|
## Other
|
||||||
|
* When doing a pairing session, mention it in the group chat in case others want to watch and learn.
|
||||||
|
* Keep your calendar up to date. Make it a reliable place to know your availability.
|
||||||
|
* It's OK to iterate. For example, a new resource doesn't have to be 100% "feature complete" (whatever that means!)... if it adds value to our users, and their feedback can help make the next iteration better, it's worth shipping.
|
||||||
|
* What we DO ship should still be our best work for the value that we choose to ship.
|
||||||
|
* We strictly follow SemVer, especially with regards to breaking changes.
|
||||||
|
* Any breaking change must happen in a major release and be preceded by deprecation warnings.
|
||||||
|
|
||||||
|
# Processes
|
||||||
|
*(e.g. board, demos, etc)*
|
||||||
|
* Do engineering prod demos on Fridays for your new work!
|
||||||
|
* Only demo completed (merged) work.
|
||||||
|
* When working on a contribution, we create a short-lived topic branch that contains the topic contribution.
|
||||||
|
* Naming convention: `<initials/name>/<shortname>`
|
||||||
|
* Remember when creating an issue to add plenty of context - even things that are "obvious". Depending on when the issue is addressed, you may not be the one working on it so giving context to the assignee is important.
|
||||||
|
|
||||||
|
## Issues
|
||||||
|
* __SLA: 3 business days__
|
||||||
|
* This applies to all contributors - both InSpec team members as well as the community
|
||||||
|
* EXAMPLE:
|
||||||
|
* I'm a community member
|
||||||
|
* I file a PR
|
||||||
|
* InSpec team member reviews PR; provides feedback to be fixed
|
||||||
|
* If I don't respond within 3 business days, I can expect the issue to be closed
|
||||||
|
* For more info on SLAs, see [this documentation](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md)
|
||||||
|
|
||||||
|
## Pull Requests
|
||||||
|
* __SLA: 3 business days__
|
||||||
|
* This applies to all contributors - both InSpec team members as well as the community
|
||||||
|
* EXAMPLE:
|
||||||
|
* I'm a community member
|
||||||
|
* I file a PR
|
||||||
|
* InSpec team member reviews PR; provides feedback to be fixed
|
||||||
|
* If I don't respond within 3 business days, I can expect the PR to be closed
|
||||||
|
* For more info on SLAs, see [this documentation](https://github.com/chef/chef-oss-practices/blob/master/repo-management/repo-states.md)
|
||||||
|
* Have a reasonable number of commits per PR.
|
||||||
|
* For a typical PR, 1 is too few and 50 is too many.
|
||||||
|
* As we work on a PR, we occasionally rebase to master. We always rebase prior to merge.
|
||||||
|
* When merging a PR, we do not squash.
|
||||||
|
* Keep your PR Title and Description on topic for the entire change.
|
||||||
|
* Prefer small, frequent, coherent commits during development on your PR. (see commits-per-PR note)
|
||||||
|
* Avoid stale PRs
|
||||||
|
* Consider GH feature which allow "not-a-PR PRs"
|
||||||
|
* Avoid WIP PRs by pairing and additional collaboration.
|
||||||
|
* Assign issues to yourself when working them.
|
||||||
|
* Try to keep number of active assigned issues low.
|
||||||
|
* If you're not working on an issue or seeing it through to completion then unassign.
|
||||||
|
* Break down overcomplicated issues into smaller issues and relate them accordingly.
|
||||||
|
* To break down, pull out all info from the parent ticket then close it.
|
||||||
|
* When a PR resolves an open issue, use GitHub keywords in the PR description to automatically close the issue upon merge.
|
||||||
|
* https://help.GitHub.com/articles/closing-issues-using-keywords/
|
||||||
|
|
||||||
|
# Communication
|
||||||
|
*(e.g. leaving context, cross team coordination)*
|
||||||
|
* Keep conversations as public as possible
|
||||||
|
* Default to team chat rather than DMs
|
||||||
|
* Default to GitHub issues or PR comments as much as possible
|
||||||
|
* Also use community-slack inpsec-dev, but be sure to capture important conversations in a persistent medium (i.e. issues)
|
||||||
|
* Feedback on code reviews go in GitHub reviews
|
||||||
|
* InSpec code reviews require two sign-offs
|
||||||
|
|
||||||
|
## Chat
|
||||||
|
* Does not convey emotion well.
|
||||||
|
* Emojis can help that.
|
||||||
|
* If conversations become tense in chat, shift to Zoom.
|
||||||
|
* Please recap the conversation from zoom with any outcome. This way anyone who saw the conversation started in slack can see the outcome
|
||||||
|
* Consider if the outcome should go on GitHub as well
|
||||||
|
|
||||||
|
## Etiquette
|
||||||
|
* Be aware
|
||||||
|
* Be gentle and sensitive when telling another team member something that is obvious to you.
|
||||||
|
* Don't call out ignorance - the field is way too large for us all to have been exposed to everything.
|
||||||
|
* These are a good starting point: https://www.recurse.com/manual#sec-environment
|
||||||
|
* Be gentle about the state of the codebase
|
||||||
|
* Avoid insulting it
|
||||||
|
* Avoid associating personal ownership as you critique something (e.g. "Ugh, you are doing X, yuck")
|
||||||
|
* Be thankful
|
||||||
|
* Thank community members verbosely
|
||||||
|
* Reach out to first time contributors and welcome them!
|
||||||
|
* Be a mentor
|
||||||
|
* Explaining something to another person can be a great way to check knowledge
|
||||||
|
* You also solidify your knowledge of a topic as a different rigor is required to teach that very topic
|
||||||
|
* Be curious
|
||||||
|
* Don't hesitate to ask questions! Asking questions helps check if a topic has shared understanding among the team
|
||||||
|
|
||||||
|
## Miscellaneous
|
||||||
|
* Coffeeshops
|
||||||
|
* Sure! but...
|
||||||
|
* be respectful about background noise
|
||||||
|
* mute while in a conference
|
||||||
|
* Slack
|
||||||
|
* is an asynchronous communication medium
|
||||||
|
* We will endeavor to respond to our colleagues in a timely manner, but there is no guarantee on response time.
|
||||||
|
* @here messages in #inspec-team are completely acceptable; users should alter their own personal notification settings as they see fit.
|
||||||
|
* Recommended Channels
|
||||||
|
* #inspec - where community members can chat with each other about how to use InSpec, idea sharing, etc.
|
||||||
|
* #inspec-dev - where developers go to chat about specific development efforts around InSpec
|
||||||
|
* #general - treated like #random
|
||||||
|
|
||||||
|
# Coordination
|
||||||
|
*(e.g. how we prioritize work)*
|
||||||
|
|
|
@ -22,8 +22,6 @@ provisioner:
|
||||||
verifier:
|
verifier:
|
||||||
name: inspec
|
name: inspec
|
||||||
sudo: true
|
sudo: true
|
||||||
attributes:
|
|
||||||
verifier_attribute: 'Attribute Override!'
|
|
||||||
|
|
||||||
platforms:
|
platforms:
|
||||||
- name: amazonlinux
|
- name: amazonlinux
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
source 'https://www.rubygems.org'
|
source "https://www.rubygems.org"
|
||||||
|
|
||||||
gem 'kitchen-docker'
|
gem "kitchen-docker"
|
||||||
gem 'test-kitchen'
|
gem "test-kitchen"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
||||||
# TODO: Remove in inspec 4.0
|
# TODO: Remove in inspec 4.0
|
||||||
|
|
||||||
require 'plugins/inspec-compliance/lib/inspec-compliance/api'
|
require "plugins/inspec-compliance/lib/inspec-compliance/api"
|
||||||
|
|
||||||
# Backport old namespace
|
# Backport old namespace
|
||||||
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
||||||
# TODO: Remove in inspec 4.0
|
# TODO: Remove in inspec 4.0
|
||||||
|
|
||||||
require 'plugins/inspec-compliance/lib/inspec-compliance/configuration'
|
require "plugins/inspec-compliance/lib/inspec-compliance/configuration"
|
||||||
|
|
||||||
# Backport old namespace
|
# Backport old namespace
|
||||||
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
||||||
# TODO: Remove in inspec 4.0
|
# TODO: Remove in inspec 4.0
|
||||||
|
|
||||||
require 'plugins/inspec-compliance/lib/inspec-compliance/http'
|
require "plugins/inspec-compliance/lib/inspec-compliance/http"
|
||||||
|
|
||||||
# Backport old namespace
|
# Backport old namespace
|
||||||
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
||||||
# TODO: Remove in inspec 4.0
|
# TODO: Remove in inspec 4.0
|
||||||
|
|
||||||
require 'plugins/inspec-compliance/lib/inspec-compliance/support'
|
require "plugins/inspec-compliance/lib/inspec-compliance/support"
|
||||||
|
|
||||||
# Backport old namespace
|
# Backport old namespace
|
||||||
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
# This file has been moved to the v2.0 plugins. This redirect allows for legacy use.
|
||||||
# TODO: Remove in inspec 4.0
|
# TODO: Remove in inspec 4.0
|
||||||
|
|
||||||
require 'plugins/inspec-compliance/lib/inspec-compliance/target'
|
require "plugins/inspec-compliance/lib/inspec-compliance/target"
|
||||||
|
|
||||||
# Backport old namespace
|
# Backport old namespace
|
||||||
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
Compliance = InspecPlugins::Compliance unless defined?(Compliance)
|
||||||
|
|
|
@ -2,8 +2,8 @@ libdir = File.dirname(__FILE__)
|
||||||
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
||||||
|
|
||||||
module Supermarket
|
module Supermarket
|
||||||
autoload :API, 'inspec-supermarket/api'
|
autoload :API, "inspec-supermarket/api"
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'inspec-supermarket/cli'
|
require "inspec-supermarket/cli"
|
||||||
require 'inspec-supermarket/target'
|
require "inspec-supermarket/target"
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'net/http'
|
require "net/http"
|
||||||
require 'addressable/uri'
|
require "addressable/uri"
|
||||||
|
|
||||||
module Supermarket
|
module Supermarket
|
||||||
class API
|
class API
|
||||||
SUPERMARKET_URL = 'https://supermarket.chef.io'
|
SUPERMARKET_URL = "https://supermarket.chef.io"
|
||||||
|
|
||||||
# displays a list of profiles
|
# displays a list of profiles
|
||||||
def self.profiles(supermarket_url = SUPERMARKET_URL)
|
def self.profiles(supermarket_url = SUPERMARKET_URL)
|
||||||
url = "#{supermarket_url}/api/v1/tools-search"
|
url = "#{supermarket_url}/api/v1/tools-search"
|
||||||
_success, data = get(url, { type: 'compliance_profile', items: 100 })
|
_success, data = get(url, { type: "compliance_profile", items: 100 })
|
||||||
if !data.nil?
|
if !data.nil?
|
||||||
profiles = JSON.parse(data)
|
profiles = JSON.parse(data)
|
||||||
profiles['items'].map { |x|
|
profiles["items"].map do |x|
|
||||||
m = %r{^#{supermarket_url}/api/v1/tools/(?<slug>[\w-]+)(/)?$}.match(x['tool'])
|
m = %r{^#{supermarket_url}/api/v1/tools/(?<slug>[\w-]+)(/)?$}.match(x["tool"])
|
||||||
x['slug'] = m[:slug]
|
x["slug"] = m[:slug]
|
||||||
x
|
x
|
||||||
}
|
end
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
@ -51,7 +51,7 @@ module Supermarket
|
||||||
|
|
||||||
# Tool name in Supermarket URL is downcased so we need to downcase
|
# Tool name in Supermarket URL is downcased so we need to downcase
|
||||||
tool = "#{supermarket_url}/api/v1/tools/#{tool_name.downcase}"
|
tool = "#{supermarket_url}/api/v1/tools/#{tool_name.downcase}"
|
||||||
supermarket_tool['tool_owner'] == tool_owner && supermarket_tool['tool'] == tool
|
supermarket_tool["tool_owner"] == tool_owner && supermarket_tool["tool"] == tool
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find(profile, supermarket_url = SUPERMARKET_URL)
|
def self.find(profile, supermarket_url = SUPERMARKET_URL)
|
||||||
|
@ -77,7 +77,7 @@ module Supermarket
|
||||||
|
|
||||||
def self.send_request(uri, req)
|
def self.send_request(uri, req)
|
||||||
# send request
|
# send request
|
||||||
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
|
||||||
http.request(req)
|
http.request(req)
|
||||||
end
|
end
|
||||||
[res.is_a?(Net::HTTPSuccess), res.body]
|
[res.is_a?(Net::HTTPSuccess), res.body]
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
require 'inspec/base_cli'
|
require "inspec/base_cli"
|
||||||
|
|
||||||
module Supermarket
|
module Supermarket
|
||||||
class SupermarketCLI < Inspec::BaseCLI
|
class SupermarketCLI < Inspec::BaseCLI
|
||||||
namespace 'supermarket'
|
namespace "supermarket"
|
||||||
|
|
||||||
# TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
|
# TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
|
||||||
def self.banner(command, _namespace = nil, _subcommand = false)
|
def self.banner(command, _namespace = nil, _subcommand = false)
|
||||||
|
@ -13,18 +13,18 @@ module Supermarket
|
||||||
namespace
|
namespace
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'profiles', 'list all available profiles in Chef Supermarket'
|
desc "profiles", "list all available profiles in Chef Supermarket"
|
||||||
def profiles
|
def profiles
|
||||||
# display profiles in format user/profile
|
# display profiles in format user/profile
|
||||||
supermarket_profiles = Supermarket::API.profiles
|
supermarket_profiles = Supermarket::API.profiles
|
||||||
|
|
||||||
headline('Available profiles:')
|
headline("Available profiles:")
|
||||||
supermarket_profiles.each { |p|
|
supermarket_profiles.each do |p|
|
||||||
li("#{p['tool_name']} #{mark_text(p['tool_owner'] + '/' + p['slug'])}")
|
li("#{p['tool_name']} #{mark_text(p['tool_owner'] + '/' + p['slug'])}")
|
||||||
}
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'exec PROFILE', 'execute a Supermarket profile'
|
desc "exec PROFILE", "execute a Supermarket profile"
|
||||||
exec_options
|
exec_options
|
||||||
def exec(*tests)
|
def exec(*tests)
|
||||||
o = config
|
o = config
|
||||||
|
@ -32,7 +32,7 @@ module Supermarket
|
||||||
configure_logger(o)
|
configure_logger(o)
|
||||||
|
|
||||||
# iterate over tests and add compliance scheme
|
# iterate over tests and add compliance scheme
|
||||||
tests = tests.map { |t| 'supermarket://' + t }
|
tests = tests.map { |t| "supermarket://" + t }
|
||||||
|
|
||||||
runner = Inspec::Runner.new(o)
|
runner = Inspec::Runner.new(o)
|
||||||
tests.each { |target| runner.add_target(target) }
|
tests.each { |target| runner.add_target(target) }
|
||||||
|
@ -43,13 +43,13 @@ module Supermarket
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'info PROFILE', 'display Supermarket profile details'
|
desc "info PROFILE", "display Supermarket profile details"
|
||||||
def info(profile)
|
def info(profile)
|
||||||
# check that the profile is available
|
# check that the profile is available
|
||||||
supermarket_profiles = Supermarket::API.profiles
|
supermarket_profiles = Supermarket::API.profiles
|
||||||
found = supermarket_profiles.select { |p|
|
found = supermarket_profiles.select do |p|
|
||||||
profile == "#{p['tool_owner']}/#{p['slug']}"
|
profile == "#{p['tool_owner']}/#{p['slug']}"
|
||||||
}
|
end
|
||||||
|
|
||||||
if found.empty?
|
if found.empty?
|
||||||
puts "#{mark_text(profile)} is not available on Supermarket"
|
puts "#{mark_text(profile)} is not available on Supermarket"
|
||||||
|
@ -67,5 +67,5 @@ module Supermarket
|
||||||
end
|
end
|
||||||
|
|
||||||
# register the subcommand to InSpec CLI registry
|
# register the subcommand to InSpec CLI registry
|
||||||
Inspec::Plugins::CLI.add_subcommand(SupermarketCLI, 'supermarket', 'supermarket SUBCOMMAND ...', 'Supermarket commands', {})
|
Inspec::Plugins::CLI.add_subcommand(SupermarketCLI, "supermarket", "supermarket SUBCOMMAND ...", "Supermarket commands", {})
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
require 'uri'
|
require "uri"
|
||||||
require 'inspec/fetcher'
|
require "inspec/fetcher"
|
||||||
require 'fetchers/url'
|
require "fetchers/url"
|
||||||
|
|
||||||
# InSpec Target Helper for Supermarket
|
# InSpec Target Helper for Supermarket
|
||||||
module Supermarket
|
module Supermarket
|
||||||
class Fetcher < Inspec.fetcher(1)
|
class Fetcher < Inspec.fetcher(1)
|
||||||
name 'supermarket'
|
name "supermarket"
|
||||||
priority 500
|
priority 500
|
||||||
|
|
||||||
def self.resolve(target, opts = {})
|
def self.resolve(target, opts = {})
|
||||||
supermarket_uri, supermarket_server = if target.is_a?(String) && URI(target).scheme == 'supermarket'
|
supermarket_uri, supermarket_server = if target.is_a?(String) && URI(target).scheme == "supermarket"
|
||||||
[target, Supermarket::API::SUPERMARKET_URL]
|
[target, Supermarket::API::SUPERMARKET_URL]
|
||||||
elsif target.respond_to?(:key?) && target.key?(:supermarket)
|
elsif target.respond_to?(:key?) && target.key?(:supermarket)
|
||||||
supermarket_server = target[:supermarket_url] || Supermarket::API::SUPERMARKET_URL
|
supermarket_server = target[:supermarket_url] || Supermarket::API::SUPERMARKET_URL
|
||||||
|
@ -18,13 +18,13 @@ module Supermarket
|
||||||
return nil unless supermarket_uri
|
return nil unless supermarket_uri
|
||||||
return nil unless Supermarket::API.exist?(supermarket_uri, supermarket_server)
|
return nil unless Supermarket::API.exist?(supermarket_uri, supermarket_server)
|
||||||
tool_info = Supermarket::API.find(supermarket_uri, supermarket_server)
|
tool_info = Supermarket::API.find(supermarket_uri, supermarket_server)
|
||||||
resolve_next(tool_info['tool_source_url'], opts)
|
resolve_next(tool_info["tool_source_url"], opts)
|
||||||
rescue URI::Error
|
rescue URI::Error
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
'Chef Compliance Profile Loader'
|
"Chef Compliance Profile Loader"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
require 'tmpdir'
|
require "tmpdir"
|
||||||
require 'fileutils'
|
require "fileutils"
|
||||||
require 'mixlib/shellout'
|
require "mixlib/shellout"
|
||||||
require 'inspec/log'
|
require "inspec/log"
|
||||||
|
|
||||||
module Fetchers
|
module Fetchers
|
||||||
#
|
#
|
||||||
|
@ -24,12 +24,12 @@ module Fetchers
|
||||||
# omnibus source for hints.
|
# omnibus source for hints.
|
||||||
#
|
#
|
||||||
class Git < Inspec.fetcher(1)
|
class Git < Inspec.fetcher(1)
|
||||||
name 'git'
|
name "git"
|
||||||
priority 200
|
priority 200
|
||||||
|
|
||||||
def self.resolve(target, opts = {})
|
def self.resolve(target, opts = {})
|
||||||
if target.is_a?(String)
|
if target.is_a?(String)
|
||||||
new(target, opts) if target.start_with?('git@') || target.end_with?('.git')
|
new(target, opts) if target.start_with?("git@") || target.end_with?(".git")
|
||||||
elsif target.respond_to?(:has_key?) && target.key?(:git)
|
elsif target.respond_to?(:has_key?) && target.key?(:git)
|
||||||
new(target[:git], opts.merge(target))
|
new(target[:git], opts.merge(target))
|
||||||
end
|
end
|
||||||
|
@ -53,7 +53,7 @@ module Fetchers
|
||||||
Dir.mktmpdir do |tmpdir|
|
Dir.mktmpdir do |tmpdir|
|
||||||
checkout(tmpdir)
|
checkout(tmpdir)
|
||||||
Inspec::Log.debug("Checkout of #{resolved_ref} successful. Moving checkout to #{dir}")
|
Inspec::Log.debug("Checkout of #{resolved_ref} successful. Moving checkout to #{dir}")
|
||||||
FileUtils.cp_r(tmpdir + '/.', @repo_directory)
|
FileUtils.cp_r(tmpdir + "/.", @repo_directory)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@repo_directory
|
@repo_directory
|
||||||
|
@ -81,7 +81,7 @@ module Fetchers
|
||||||
elsif @tag
|
elsif @tag
|
||||||
resolve_ref(@tag)
|
resolve_ref(@tag)
|
||||||
else
|
else
|
||||||
resolve_ref('master')
|
resolve_ref("master")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ module Fetchers
|
||||||
end
|
end
|
||||||
|
|
||||||
def cloned?
|
def cloned?
|
||||||
File.directory?(File.join(@repo_directory, '.git'))
|
File.directory?(File.join(@repo_directory, ".git"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def clone(dir = @repo_directory)
|
def clone(dir = @repo_directory)
|
||||||
|
@ -148,7 +148,7 @@ module Fetchers
|
||||||
cmd.error!
|
cmd.error!
|
||||||
cmd.status
|
cmd.status
|
||||||
rescue Errno::ENOENT
|
rescue Errno::ENOENT
|
||||||
raise 'To use git sources, you must have git installed.'
|
raise "To use git sources, you must have git installed."
|
||||||
end
|
end
|
||||||
|
|
||||||
def shellout(cmd, opts = {})
|
def shellout(cmd, opts = {})
|
||||||
|
@ -156,12 +156,12 @@ module Fetchers
|
||||||
cmd = Mixlib::ShellOut.new(cmd, opts)
|
cmd = Mixlib::ShellOut.new(cmd, opts)
|
||||||
cmd.run_command
|
cmd.run_command
|
||||||
Inspec::Log.debug("External command: completed with exit status: #{cmd.exitstatus}")
|
Inspec::Log.debug("External command: completed with exit status: #{cmd.exitstatus}")
|
||||||
Inspec::Log.debug('External command: STDOUT BEGIN')
|
Inspec::Log.debug("External command: STDOUT BEGIN")
|
||||||
Inspec::Log.debug(cmd.stdout)
|
Inspec::Log.debug(cmd.stdout)
|
||||||
Inspec::Log.debug('External command: STDOUT END')
|
Inspec::Log.debug("External command: STDOUT END")
|
||||||
Inspec::Log.debug('External command: STDERR BEGIN')
|
Inspec::Log.debug("External command: STDERR BEGIN")
|
||||||
Inspec::Log.debug(cmd.stderr)
|
Inspec::Log.debug(cmd.stderr)
|
||||||
Inspec::Log.debug('External command: STDERR END')
|
Inspec::Log.debug("External command: STDERR END")
|
||||||
cmd
|
cmd
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
require 'openssl'
|
require "openssl"
|
||||||
|
|
||||||
module Fetchers
|
module Fetchers
|
||||||
class Local < Inspec.fetcher(1)
|
class Local < Inspec.fetcher(1)
|
||||||
name 'local'
|
name "local"
|
||||||
priority 0
|
priority 0
|
||||||
|
|
||||||
def self.resolve(target)
|
def self.resolve(target)
|
||||||
|
@ -27,11 +27,11 @@ module Fetchers
|
||||||
|
|
||||||
def self.resolve_from_string(target)
|
def self.resolve_from_string(target)
|
||||||
# Support "urls" in the form of file://
|
# Support "urls" in the form of file://
|
||||||
if target.start_with?('file://')
|
if target.start_with?("file://")
|
||||||
target = target.gsub(%r{^file://}, '')
|
target = target.gsub(%r{^file://}, "")
|
||||||
else
|
else
|
||||||
# support for windows paths
|
# support for windows paths
|
||||||
target = target.tr('\\', '/')
|
target = target.tr('\\', "/")
|
||||||
end
|
end
|
||||||
|
|
||||||
target if File.exist?(File.expand_path(target))
|
target if File.exist?(File.expand_path(target))
|
||||||
|
@ -101,7 +101,7 @@ module Fetchers
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform_shasum(target)
|
def perform_shasum(target)
|
||||||
@archive_shasum ||= OpenSSL::Digest::SHA256.digest(File.read(target)).unpack('H*')[0]
|
@archive_shasum ||= OpenSSL::Digest::SHA256.digest(File.read(target)).unpack("H*")[0]
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolved_source
|
def resolved_source
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
require "inspec/fetcher"
|
||||||
|
|
||||||
module Fetchers
|
module Fetchers
|
||||||
class Mock < Inspec.fetcher(1)
|
class Mock < Inspec.fetcher(1)
|
||||||
name 'mock'
|
name "mock"
|
||||||
priority 0
|
priority 0
|
||||||
|
|
||||||
def self.resolve(target)
|
def self.resolve(target)
|
||||||
|
@ -25,7 +27,7 @@ module Fetchers
|
||||||
end
|
end
|
||||||
|
|
||||||
def cache_key
|
def cache_key
|
||||||
''
|
""
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
require 'uri'
|
require "uri"
|
||||||
require 'openssl'
|
require "openssl"
|
||||||
require 'tempfile'
|
require "tempfile"
|
||||||
require 'open-uri'
|
require "open-uri"
|
||||||
|
|
||||||
module Fetchers
|
module Fetchers
|
||||||
class Url < Inspec.fetcher(1)
|
class Url < Inspec.fetcher(1)
|
||||||
MIME_TYPES = {
|
MIME_TYPES = {
|
||||||
'application/x-zip-compressed' => '.zip',
|
"application/x-zip-compressed" => ".zip",
|
||||||
'application/zip' => '.zip',
|
"application/zip" => ".zip",
|
||||||
'application/x-gzip' => '.tar.gz',
|
"application/x-gzip" => ".tar.gz",
|
||||||
'application/gzip' => '.tar.gz',
|
"application/gzip" => ".tar.gz",
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
name 'url'
|
name "url"
|
||||||
priority 200
|
priority 200
|
||||||
|
|
||||||
def self.resolve(target, opts = {})
|
def self.resolve(target, opts = {})
|
||||||
|
@ -27,7 +27,7 @@ module Fetchers
|
||||||
|
|
||||||
def self.resolve_from_string(target, opts, username = nil, password = nil)
|
def self.resolve_from_string(target, opts, username = nil, password = nil)
|
||||||
uri = URI.parse(target)
|
uri = URI.parse(target)
|
||||||
return nil if uri.nil? or uri.scheme.nil?
|
return nil if uri.nil? || uri.scheme.nil?
|
||||||
return nil unless %{ http https }.include? uri.scheme
|
return nil unless %{ http https }.include? uri.scheme
|
||||||
target = transform(target)
|
target = transform(target)
|
||||||
opts[:username] = username if username
|
opts[:username] = username if username
|
||||||
|
@ -62,11 +62,11 @@ module Fetchers
|
||||||
# https://bitbucket.org/username/repo/commits/95ce1f83d5bbe9eec34c5973f6894617e8d6d8cc is transformed to
|
# https://bitbucket.org/username/repo/commits/95ce1f83d5bbe9eec34c5973f6894617e8d6d8cc is transformed to
|
||||||
# https://bitbucket.org/username/repo/get/95ce1f83d5bbe9eec34c5973f6894617e8d6d8cc.tar.gz
|
# https://bitbucket.org/username/repo/get/95ce1f83d5bbe9eec34c5973f6894617e8d6d8cc.tar.gz
|
||||||
|
|
||||||
GITHUB_URL_REGEX = %r{^https?://(www\.)?github\.com/(?<user>[\w-]+)/(?<repo>[\w.-]+?)(\.git)?(/)?$}
|
GITHUB_URL_REGEX = %r{^https?://(www\.)?github\.com/(?<user>[\w-]+)/(?<repo>[\w.-]+?)(\.git)?(/)?$}.freeze
|
||||||
GITHUB_URL_WITH_TREE_REGEX = %r{^https?://(www\.)?github\.com/(?<user>[\w-]+)/(?<repo>[\w.-]+)/tree/(?<commit>[\w\.]+)(/)?$}
|
GITHUB_URL_WITH_TREE_REGEX = %r{^https?://(www\.)?github\.com/(?<user>[\w-]+)/(?<repo>[\w.-]+)/tree/(?<commit>[\w\.]+)(/)?$}.freeze
|
||||||
BITBUCKET_URL_REGEX = %r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)(\.git)?(/)?$}
|
BITBUCKET_URL_REGEX = %r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)(\.git)?(/)?$}.freeze
|
||||||
BITBUCKET_URL_BRANCH_REGEX = %r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)/branch/(?<branch>[\w\.]+)(/)?$}
|
BITBUCKET_URL_BRANCH_REGEX = %r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)/branch/(?<branch>[\w\.]+)(/)?$}.freeze
|
||||||
BITBUCKET_URL_COMMIT_REGEX = %r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)/commits/(?<commit>[\w\.]+)(/)?$}
|
BITBUCKET_URL_COMMIT_REGEX = %r{^https?://(www\.)?bitbucket\.org/(?<user>[\w-]+)/(?<repo>[\w-]+)/commits/(?<commit>[\w\.]+)(/)?$}.freeze
|
||||||
|
|
||||||
def self.transform(target)
|
def self.transform(target)
|
||||||
transformed_target = if m = GITHUB_URL_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
|
transformed_target = if m = GITHUB_URL_REGEX.match(target) # rubocop:disable Lint/AssignmentInCondition
|
||||||
|
@ -94,8 +94,8 @@ module Fetchers
|
||||||
def initialize(url, opts)
|
def initialize(url, opts)
|
||||||
@target = url.to_s
|
@target = url.to_s
|
||||||
@target_uri = url.is_a?(URI) ? url : parse_uri(url)
|
@target_uri = url.is_a?(URI) ? url : parse_uri(url)
|
||||||
@insecure = opts['insecure']
|
@insecure = opts["insecure"]
|
||||||
@token = opts['token']
|
@token = opts["token"]
|
||||||
@config = opts
|
@config = opts
|
||||||
@archive_path = nil
|
@archive_path = nil
|
||||||
@temp_archive_path = nil
|
@temp_archive_path = nil
|
||||||
|
@ -126,23 +126,23 @@ module Fetchers
|
||||||
|
|
||||||
def sha256
|
def sha256
|
||||||
file = @archive_path || temp_archive_path
|
file = @archive_path || temp_archive_path
|
||||||
OpenSSL::Digest::SHA256.digest(File.read(file)).unpack('H*')[0]
|
OpenSSL::Digest::SHA256.digest(File.read(file)).unpack("H*")[0]
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_type_from_remote(remote)
|
def file_type_from_remote(remote)
|
||||||
content_type = remote.meta['content-type']
|
content_type = remote.meta["content-type"]
|
||||||
file_type = MIME_TYPES[content_type]
|
file_type = MIME_TYPES[content_type]
|
||||||
|
|
||||||
if file_type.nil?
|
if file_type.nil?
|
||||||
Inspec::Log.warn("Unrecognized content type: #{content_type}. Assuming tar.gz")
|
Inspec::Log.warn("Unrecognized content type: #{content_type}. Assuming tar.gz")
|
||||||
file_type = '.tar.gz'
|
file_type = ".tar.gz"
|
||||||
end
|
end
|
||||||
|
|
||||||
file_type
|
file_type
|
||||||
end
|
end
|
||||||
|
|
||||||
def temp_archive_path
|
def temp_archive_path
|
||||||
@temp_archive_path ||= if @config['server_type'] == 'automate2'
|
@temp_archive_path ||= if @config["server_type"] == "automate2"
|
||||||
download_automate2_archive_to_temp
|
download_automate2_archive_to_temp
|
||||||
else
|
else
|
||||||
download_archive_to_temp
|
download_archive_to_temp
|
||||||
|
@ -154,13 +154,13 @@ module Fetchers
|
||||||
|
|
||||||
Inspec::Log.debug("Fetching URL: #{@target}")
|
Inspec::Log.debug("Fetching URL: #{@target}")
|
||||||
json = {
|
json = {
|
||||||
owner: @config['profile'][0],
|
owner: @config["profile"][0],
|
||||||
name: @config['profile'][1],
|
name: @config["profile"][1],
|
||||||
version: @config['profile'][2],
|
version: @config["profile"][2],
|
||||||
}.to_json
|
}.to_json
|
||||||
|
|
||||||
opts = http_opts
|
opts = http_opts
|
||||||
opts[:use_ssl] = @target_uri.scheme == 'https'
|
opts[:use_ssl] = @target_uri.scheme == "https"
|
||||||
|
|
||||||
if @insecure
|
if @insecure
|
||||||
opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
|
opts[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
|
||||||
|
@ -173,12 +173,12 @@ module Fetchers
|
||||||
req.add_field(key, value)
|
req.add_field(key, value)
|
||||||
end
|
end
|
||||||
req.body = json
|
req.body = json
|
||||||
res = Net::HTTP.start(@target_uri.host, @target_uri.port, opts) { |http|
|
res = Net::HTTP.start(@target_uri.host, @target_uri.port, opts) do |http|
|
||||||
http.request(req)
|
http.request(req)
|
||||||
}
|
end
|
||||||
|
|
||||||
@archive_type = '.tar.gz'
|
@archive_type = ".tar.gz"
|
||||||
archive = Tempfile.new(['inspec-dl-', @archive_type])
|
archive = Tempfile.new(["inspec-dl-", @archive_type])
|
||||||
archive.binmode
|
archive.binmode
|
||||||
archive.write(res.body)
|
archive.write(res.body)
|
||||||
archive.rewind
|
archive.rewind
|
||||||
|
@ -193,7 +193,7 @@ module Fetchers
|
||||||
Inspec::Log.debug("Fetching URL: #{@target}")
|
Inspec::Log.debug("Fetching URL: #{@target}")
|
||||||
remote = open_via_uri(@target)
|
remote = open_via_uri(@target)
|
||||||
@archive_type = file_type_from_remote(remote) # side effect :(
|
@archive_type = file_type_from_remote(remote) # side effect :(
|
||||||
archive = Tempfile.new(['inspec-dl-', @archive_type])
|
archive = Tempfile.new(["inspec-dl-", @archive_type])
|
||||||
archive.binmode
|
archive.binmode
|
||||||
archive.write(remote.read)
|
archive.write(remote.read)
|
||||||
archive.rewind
|
archive.rewind
|
||||||
|
@ -207,7 +207,7 @@ module Fetchers
|
||||||
|
|
||||||
if opts[:http_basic_authentication]
|
if opts[:http_basic_authentication]
|
||||||
# OpenURI does not support userinfo so we need to remove it
|
# OpenURI does not support userinfo so we need to remove it
|
||||||
open(target.sub("#{@target_uri.userinfo}@", ''), opts)
|
open(target.sub("#{@target_uri.userinfo}@", ""), opts)
|
||||||
else
|
else
|
||||||
open(target, opts)
|
open(target, opts)
|
||||||
end
|
end
|
||||||
|
@ -227,16 +227,16 @@ module Fetchers
|
||||||
opts = {}
|
opts = {}
|
||||||
opts[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if @insecure
|
opts[:ssl_verify_mode] = OpenSSL::SSL::VERIFY_NONE if @insecure
|
||||||
|
|
||||||
if @config['server_type'] =~ /automate/
|
if @config["server_type"] =~ /automate/
|
||||||
opts['chef-delivery-enterprise'] = @config['automate']['ent']
|
opts["chef-delivery-enterprise"] = @config["automate"]["ent"]
|
||||||
if @config['automate']['token_type'] == 'dctoken'
|
if @config["automate"]["token_type"] == "dctoken"
|
||||||
opts['x-data-collector-token'] = @config['token']
|
opts["x-data-collector-token"] = @config["token"]
|
||||||
else
|
else
|
||||||
opts['chef-delivery-user'] = @config['user']
|
opts["chef-delivery-user"] = @config["user"]
|
||||||
opts['chef-delivery-token'] = @config['token']
|
opts["chef-delivery-token"] = @config["token"]
|
||||||
end
|
end
|
||||||
elsif @token
|
elsif @token
|
||||||
opts['Authorization'] = "Bearer #{@token}"
|
opts["Authorization"] = "Bearer #{@token}"
|
||||||
end
|
end
|
||||||
|
|
||||||
username = @config[:username] || @target_uri.user
|
username = @config[:username] || @target_uri.user
|
||||||
|
@ -260,8 +260,10 @@ module Fetchers
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
raise 'Unable to fetch profile - the following HTTP headers have no value: ' \
|
unless keys_missing_values.empty?
|
||||||
"#{keys_missing_values.join(', ')}" unless keys_missing_values.empty?
|
raise "Unable to fetch profile - the following HTTP headers have no value: " \
|
||||||
|
"#{keys_missing_values.join(', ')}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,29 +3,29 @@
|
||||||
libdir = File.dirname(__FILE__)
|
libdir = File.dirname(__FILE__)
|
||||||
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
||||||
|
|
||||||
require 'inspec/version'
|
require "inspec/version"
|
||||||
require 'inspec/exceptions'
|
require "inspec/exceptions"
|
||||||
require 'inspec/utils/deprecation'
|
require "inspec/utils/deprecation"
|
||||||
require 'inspec/profile'
|
require "inspec/profile"
|
||||||
require 'inspec/rule'
|
require "inspec/rule"
|
||||||
require 'matchers/matchers'
|
require "matchers/matchers"
|
||||||
require 'inspec/runner'
|
require "inspec/runner"
|
||||||
require 'inspec/shell'
|
require "inspec/shell"
|
||||||
require 'inspec/formatters'
|
require "inspec/formatters"
|
||||||
require 'inspec/reporters'
|
require "inspec/reporters"
|
||||||
require 'inspec/input_registry'
|
require "inspec/input_registry"
|
||||||
require 'inspec/rspec_extensions'
|
require "inspec/rspec_extensions"
|
||||||
require 'inspec/globals'
|
require "inspec/globals"
|
||||||
require 'inspec/impact'
|
require "inspec/impact"
|
||||||
require 'inspec/utils/telemetry'
|
require "inspec/utils/telemetry"
|
||||||
require 'inspec/utils/telemetry/global_methods'
|
require "inspec/utils/telemetry/global_methods"
|
||||||
|
|
||||||
require 'inspec/plugin/v2'
|
require "inspec/plugin/v2"
|
||||||
require 'inspec/plugin/v1'
|
require "inspec/plugin/v1"
|
||||||
|
|
||||||
# all utils that may be required by legacy plugins
|
# all utils that may be required by legacy plugins
|
||||||
require 'inspec/base_cli'
|
require "inspec/base_cli"
|
||||||
require 'inspec/fetcher'
|
require "inspec/fetcher"
|
||||||
require 'inspec/source_reader'
|
require "inspec/source_reader"
|
||||||
require 'inspec/resource'
|
require "inspec/resource"
|
||||||
require 'inspec/resources'
|
require "inspec/resources"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
require 'rubygems/package'
|
require "rubygems/package"
|
||||||
|
|
||||||
module Inspec::Archive
|
module Inspec::Archive
|
||||||
class TarArchiveGenerator
|
class TarArchiveGenerator
|
||||||
def archive(base_dir, files, archive)
|
def archive(base_dir, files, archive)
|
||||||
File.open(archive, 'wb') do |file|
|
File.open(archive, "wb") do |file|
|
||||||
Zlib::GzipWriter.wrap(file) do |gz|
|
Zlib::GzipWriter.wrap(file) do |gz|
|
||||||
Gem::Package::TarWriter.new(gz) do |tar|
|
Gem::Package::TarWriter.new(gz) do |tar|
|
||||||
files.each do |input_filename|
|
files.each do |input_filename|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
require 'rubygems'
|
require "rubygems"
|
||||||
require 'zip'
|
require "zip"
|
||||||
require 'pathname'
|
require "pathname"
|
||||||
|
|
||||||
module Inspec::Archive
|
module Inspec::Archive
|
||||||
class ZipArchiveGenerator
|
class ZipArchiveGenerator
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
# copyright: 2015, Dominik Richter
|
# copyright: 2015, Dominik Richter
|
||||||
|
|
||||||
require 'train'
|
require "train"
|
||||||
require 'inspec/config'
|
require "inspec/config"
|
||||||
|
require "inspec/version"
|
||||||
|
require "inspec/resource"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
module Backend
|
module Backend
|
||||||
|
@ -25,7 +27,7 @@ module Inspec
|
||||||
|
|
||||||
# Ruby internal for printing a nice name for this class
|
# Ruby internal for printing a nice name for this class
|
||||||
def to_s
|
def to_s
|
||||||
'Inspec::Backend::Class'
|
"Inspec::Backend::Class"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Ruby internal for pretty-printing a summary for this class
|
# Ruby internal for pretty-printing a summary for this class
|
||||||
|
@ -54,15 +56,15 @@ module Inspec
|
||||||
# Set caching settings. We always want to enable caching for
|
# Set caching settings. We always want to enable caching for
|
||||||
# the Mock transport for testing.
|
# the Mock transport for testing.
|
||||||
if config[:backend_cache] || config[:backend] == :mock
|
if config[:backend_cache] || config[:backend] == :mock
|
||||||
Inspec::Log.debug 'Option backend_cache is enabled'
|
Inspec::Log.debug "Option backend_cache is enabled"
|
||||||
connection.enable_cache(:file)
|
connection.enable_cache(:file)
|
||||||
connection.enable_cache(:command)
|
connection.enable_cache(:command)
|
||||||
elsif config[:debug_shell]
|
elsif config[:debug_shell]
|
||||||
Inspec::Log.debug 'Option backend_cache is disabled'
|
Inspec::Log.debug "Option backend_cache is disabled"
|
||||||
connection.disable_cache(:file)
|
connection.disable_cache(:file)
|
||||||
connection.disable_cache(:command)
|
connection.disable_cache(:command)
|
||||||
else
|
else
|
||||||
Inspec::Log.debug 'Option backend_cache is disabled'
|
Inspec::Log.debug "Option backend_cache is disabled"
|
||||||
connection.disable_cache(:file)
|
connection.disable_cache(:file)
|
||||||
connection.disable_cache(:command)
|
connection.disable_cache(:command)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
require 'thor'
|
require "thor"
|
||||||
require 'inspec/log'
|
require "inspec/log"
|
||||||
require 'inspec/profile_vendor'
|
require "inspec/ui"
|
||||||
require 'inspec/ui'
|
require "inspec/config"
|
||||||
require 'inspec/dist'
|
require "inspec/dist"
|
||||||
|
require "inspec/utils/deprecation/global_method"
|
||||||
|
|
||||||
# Allow end of options during array type parsing
|
# Allow end of options during array type parsing
|
||||||
# https://github.com/erikhuda/thor/issues/631
|
# https://github.com/erikhuda/thor/issues/631
|
||||||
|
@ -57,107 +58,107 @@ module Inspec
|
||||||
|
|
||||||
def self.target_options # rubocop:disable MethodLength
|
def self.target_options # rubocop:disable MethodLength
|
||||||
option :target, aliases: :t, type: :string,
|
option :target, aliases: :t, type: :string,
|
||||||
desc: 'Simple targeting option using URIs, e.g. ssh://user:pass@host:port'
|
desc: "Simple targeting option using URIs, e.g. ssh://user:pass@host:port"
|
||||||
option :backend, aliases: :b, type: :string,
|
option :backend, aliases: :b, type: :string,
|
||||||
desc: 'Choose a backend: local, ssh, winrm, docker.'
|
desc: "Choose a backend: local, ssh, winrm, docker."
|
||||||
option :host, type: :string,
|
option :host, type: :string,
|
||||||
desc: 'Specify a remote host which is tested.'
|
desc: "Specify a remote host which is tested."
|
||||||
option :port, aliases: :p, type: :numeric,
|
option :port, aliases: :p, type: :numeric,
|
||||||
desc: 'Specify the login port for a remote scan.'
|
desc: "Specify the login port for a remote scan."
|
||||||
option :user, type: :string,
|
option :user, type: :string,
|
||||||
desc: 'The login user for a remote scan.'
|
desc: "The login user for a remote scan."
|
||||||
option :password, type: :string, lazy_default: -1,
|
option :password, type: :string, lazy_default: -1,
|
||||||
desc: 'Login password for a remote scan, if required.'
|
desc: "Login password for a remote scan, if required."
|
||||||
option :enable_password, type: :string, lazy_default: -1,
|
option :enable_password, type: :string, lazy_default: -1,
|
||||||
desc: 'Password for enable mode on Cisco IOS devices.'
|
desc: "Password for enable mode on Cisco IOS devices."
|
||||||
option :key_files, aliases: :i, type: :array,
|
option :key_files, aliases: :i, type: :array,
|
||||||
desc: 'Login key or certificate file for a remote scan.'
|
desc: "Login key or certificate file for a remote scan."
|
||||||
option :path, type: :string,
|
option :path, type: :string,
|
||||||
desc: 'Login path to use when connecting to the target (WinRM).'
|
desc: "Login path to use when connecting to the target (WinRM)."
|
||||||
option :sudo, type: :boolean,
|
option :sudo, type: :boolean,
|
||||||
desc: 'Run scans with sudo. Only activates on Unix and non-root user.'
|
desc: "Run scans with sudo. Only activates on Unix and non-root user."
|
||||||
option :sudo_password, type: :string, lazy_default: -1,
|
option :sudo_password, type: :string, lazy_default: -1,
|
||||||
desc: 'Specify a sudo password, if it is required.'
|
desc: "Specify a sudo password, if it is required."
|
||||||
option :sudo_options, type: :string,
|
option :sudo_options, type: :string,
|
||||||
desc: 'Additional sudo options for a remote scan.'
|
desc: "Additional sudo options for a remote scan."
|
||||||
option :sudo_command, type: :string,
|
option :sudo_command, type: :string,
|
||||||
desc: 'Alternate command for sudo.'
|
desc: "Alternate command for sudo."
|
||||||
option :shell, type: :boolean,
|
option :shell, type: :boolean,
|
||||||
desc: 'Run scans in a subshell. Only activates on Unix.'
|
desc: "Run scans in a subshell. Only activates on Unix."
|
||||||
option :shell_options, type: :string,
|
option :shell_options, type: :string,
|
||||||
desc: 'Additional shell options.'
|
desc: "Additional shell options."
|
||||||
option :shell_command, type: :string,
|
option :shell_command, type: :string,
|
||||||
desc: 'Specify a particular shell to use.'
|
desc: "Specify a particular shell to use."
|
||||||
option :ssl, type: :boolean,
|
option :ssl, type: :boolean,
|
||||||
desc: 'Use SSL for transport layer encryption (WinRM).'
|
desc: "Use SSL for transport layer encryption (WinRM)."
|
||||||
option :self_signed, type: :boolean,
|
option :self_signed, type: :boolean,
|
||||||
desc: 'Allow remote scans with self-signed certificates (WinRM).'
|
desc: "Allow remote scans with self-signed certificates (WinRM)."
|
||||||
option :winrm_transport, type: :string, default: 'negotiate',
|
option :winrm_transport, type: :string, default: "negotiate",
|
||||||
desc: 'Specify which transport to use, defaults to negotiate (WinRM).'
|
desc: "Specify which transport to use, defaults to negotiate (WinRM)."
|
||||||
option :winrm_disable_sspi, type: :boolean,
|
option :winrm_disable_sspi, type: :boolean,
|
||||||
desc: 'Whether to use disable sspi authentication, defaults to false (WinRM).'
|
desc: "Whether to use disable sspi authentication, defaults to false (WinRM)."
|
||||||
option :winrm_basic_auth, type: :boolean,
|
option :winrm_basic_auth, type: :boolean,
|
||||||
desc: 'Whether to use basic authentication, defaults to false (WinRM).'
|
desc: "Whether to use basic authentication, defaults to false (WinRM)."
|
||||||
option :config, type: :string,
|
option :config, type: :string,
|
||||||
desc: 'Read configuration from JSON file (`-` reads from stdin).'
|
desc: "Read configuration from JSON file (`-` reads from stdin)."
|
||||||
option :json_config, type: :string, hide: true
|
option :json_config, type: :string, hide: true
|
||||||
option :proxy_command, type: :string,
|
option :proxy_command, type: :string,
|
||||||
desc: 'Specifies the command to use to connect to the server'
|
desc: "Specifies the command to use to connect to the server"
|
||||||
option :bastion_host, type: :string,
|
option :bastion_host, type: :string,
|
||||||
desc: 'Specifies the bastion host if applicable'
|
desc: "Specifies the bastion host if applicable"
|
||||||
option :bastion_user, type: :string,
|
option :bastion_user, type: :string,
|
||||||
desc: 'Specifies the bastion user if applicable'
|
desc: "Specifies the bastion user if applicable"
|
||||||
option :bastion_port, type: :string,
|
option :bastion_port, type: :string,
|
||||||
desc: 'Specifies the bastion port if applicable'
|
desc: "Specifies the bastion port if applicable"
|
||||||
option :insecure, type: :boolean, default: false,
|
option :insecure, type: :boolean, default: false,
|
||||||
desc: 'Disable SSL verification on select targets'
|
desc: "Disable SSL verification on select targets"
|
||||||
option :target_id, type: :string,
|
option :target_id, type: :string,
|
||||||
desc: 'Provide a ID which will be included on reports'
|
desc: "Provide a ID which will be included on reports"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.profile_options
|
def self.profile_options
|
||||||
option :profiles_path, type: :string,
|
option :profiles_path, type: :string,
|
||||||
desc: 'Folder which contains referenced profiles.'
|
desc: "Folder which contains referenced profiles."
|
||||||
option :vendor_cache, type: :string,
|
option :vendor_cache, type: :string,
|
||||||
desc: 'Use the given path for caching dependencies. (default: ~/.inspec/cache)'
|
desc: "Use the given path for caching dependencies. (default: ~/.inspec/cache)"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.exec_options
|
def self.exec_options
|
||||||
target_options
|
target_options
|
||||||
profile_options
|
profile_options
|
||||||
option :controls, type: :array,
|
option :controls, type: :array,
|
||||||
desc: 'A list of control names to run, or a list of /regexes/ to match against control names. Ignore all other tests.'
|
desc: "A list of control names to run, or a list of /regexes/ to match against control names. Ignore all other tests."
|
||||||
option :reporter, type: :array,
|
option :reporter, type: :array,
|
||||||
banner: 'one two:/output/file/path',
|
banner: "one two:/output/file/path",
|
||||||
desc: 'Enable one or more output reporters: cli, documentation, html, progress, json, json-min, json-rspec, junit, yaml'
|
desc: "Enable one or more output reporters: cli, documentation, html, progress, json, json-min, json-rspec, junit, yaml"
|
||||||
option :input_file, type: :array,
|
option :input_file, type: :array,
|
||||||
desc: 'Load one or more input files, a YAML file with values for the profile to use'
|
desc: "Load one or more input files, a YAML file with values for the profile to use"
|
||||||
option :attrs, type: :array,
|
option :attrs, type: :array,
|
||||||
desc: 'Legacy name for --input-file - deprecated.'
|
desc: "Legacy name for --input-file - deprecated."
|
||||||
option :create_lockfile, type: :boolean,
|
option :create_lockfile, type: :boolean,
|
||||||
desc: 'Write out a lockfile based on this execution (unless one already exists)'
|
desc: "Write out a lockfile based on this execution (unless one already exists)"
|
||||||
option :backend_cache, type: :boolean,
|
option :backend_cache, type: :boolean,
|
||||||
desc: 'Allow caching for backend command output. (default: true)'
|
desc: "Allow caching for backend command output. (default: true)"
|
||||||
option :show_progress, type: :boolean,
|
option :show_progress, type: :boolean,
|
||||||
desc: 'Show progress while executing tests.'
|
desc: "Show progress while executing tests."
|
||||||
option :distinct_exit, type: :boolean, default: true,
|
option :distinct_exit, type: :boolean, default: true,
|
||||||
desc: 'Exit with code 101 if any tests fail, and 100 if any are skipped (default). If disabled, exit 0 on skips and 1 for failures.'
|
desc: "Exit with code 101 if any tests fail, and 100 if any are skipped (default). If disabled, exit 0 on skips and 1 for failures."
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.format_platform_info(params: {}, indent: 0, color: 39)
|
def self.format_platform_info(params: {}, indent: 0, color: 39)
|
||||||
str = ''
|
str = ""
|
||||||
params.each { |item, info|
|
params.each do |item, info|
|
||||||
data = info
|
data = info
|
||||||
|
|
||||||
# Format Array for better output if applicable
|
# Format Array for better output if applicable
|
||||||
data = data.join(', ') if data.is_a?(Array)
|
data = data.join(", ") if data.is_a?(Array)
|
||||||
|
|
||||||
# Do not output fields of data is missing ('unknown' is fine)
|
# Do not output fields of data is missing ('unknown' is fine)
|
||||||
next if data.nil?
|
next if data.nil?
|
||||||
|
|
||||||
data = "\e[1m\e[#{color}m#{data}\e[0m"
|
data = "\e[1m\e[#{color}m#{data}\e[0m"
|
||||||
str << format("#{' ' * indent}%-10s %s\n", item.to_s.capitalize + ':', data)
|
str << format("#{' ' * indent}%-10s %s\n", item.to_s.capitalize + ":", data)
|
||||||
}
|
end
|
||||||
str
|
str
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -216,12 +217,12 @@ module Inspec
|
||||||
private
|
private
|
||||||
|
|
||||||
def suppress_log_output?(opts)
|
def suppress_log_output?(opts)
|
||||||
return false if opts['reporter'].nil?
|
return false if opts["reporter"].nil?
|
||||||
match = %w{json json-min json-rspec json-automate junit html yaml documentation progress} & opts['reporter'].keys
|
match = %w{json json-min json-rspec json-automate junit html yaml documentation progress} & opts["reporter"].keys
|
||||||
unless match.empty?
|
unless match.empty?
|
||||||
match.each do |m|
|
match.each do |m|
|
||||||
# check to see if we are outputting to stdout
|
# check to see if we are outputting to stdout
|
||||||
return true if opts['reporter'][m]['stdout'] == true
|
return true if opts["reporter"][m]["stdout"] == true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
false
|
false
|
||||||
|
@ -243,7 +244,7 @@ module Inspec
|
||||||
if valid.include?(level)
|
if valid.include?(level)
|
||||||
l = level
|
l = level
|
||||||
else
|
else
|
||||||
l = 'info'
|
l = "info"
|
||||||
end
|
end
|
||||||
|
|
||||||
Logger.const_get(l.upcase)
|
Logger.const_get(l.upcase)
|
||||||
|
@ -260,11 +261,13 @@ module Inspec
|
||||||
end
|
end
|
||||||
|
|
||||||
def vendor_deps(path, opts)
|
def vendor_deps(path, opts)
|
||||||
|
require "inspec/profile_vendor"
|
||||||
|
|
||||||
profile_path = path || Dir.pwd
|
profile_path = path || Dir.pwd
|
||||||
profile_vendor = Inspec::ProfileVendor.new(profile_path)
|
profile_vendor = Inspec::ProfileVendor.new(profile_path)
|
||||||
|
|
||||||
if (profile_vendor.cache_path.exist? || profile_vendor.lockfile.exist?) && !opts[:overwrite]
|
if (profile_vendor.cache_path.exist? || profile_vendor.lockfile.exist?) && !opts[:overwrite]
|
||||||
puts 'Profile is already vendored. Use --overwrite.'
|
puts "Profile is already vendored. Use --overwrite."
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -280,8 +283,8 @@ module Inspec
|
||||||
# logging singleton Inspec::Log. Eventually it would be nice to
|
# logging singleton Inspec::Log. Eventually it would be nice to
|
||||||
# move internal debug logging to use this logging singleton.
|
# move internal debug logging to use this logging singleton.
|
||||||
#
|
#
|
||||||
loc = if o['log_location']
|
loc = if o["log_location"]
|
||||||
o['log_location']
|
o["log_location"]
|
||||||
elsif suppress_log_output?(o)
|
elsif suppress_log_output?(o)
|
||||||
$stderr
|
$stderr
|
||||||
else
|
else
|
||||||
|
@ -289,14 +292,14 @@ module Inspec
|
||||||
end
|
end
|
||||||
|
|
||||||
Inspec::Log.init(loc)
|
Inspec::Log.init(loc)
|
||||||
Inspec::Log.level = get_log_level(o['log_level'])
|
Inspec::Log.level = get_log_level(o["log_level"])
|
||||||
|
|
||||||
o[:logger] = Logger.new(loc)
|
o[:logger] = Logger.new(loc)
|
||||||
# output json if we have activated the json formatter
|
# output json if we have activated the json formatter
|
||||||
if o['log-format'] == 'json'
|
if o["log-format"] == "json"
|
||||||
o[:logger].formatter = Logger::JSONFormatter.new
|
o[:logger].formatter = Logger::JSONFormatter.new
|
||||||
end
|
end
|
||||||
o[:logger].level = get_log_level(o['log_level'])
|
o[:logger].level = get_log_level(o["log_level"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'inspec/fetcher'
|
require "inspec/fetcher"
|
||||||
require 'forwardable'
|
require "forwardable"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
class CachedFetcher
|
class CachedFetcher
|
||||||
|
|
|
@ -1,58 +1,75 @@
|
||||||
# Copyright 2015 Dominik Richter
|
# Copyright 2015 Dominik Richter
|
||||||
|
|
||||||
require 'logger'
|
require "inspec/utils/deprecation/deprecator"
|
||||||
require 'thor'
|
require "inspec/dist"
|
||||||
require 'json'
|
require "inspec/backend"
|
||||||
require 'pp'
|
require "inspec/dependencies/cache"
|
||||||
require 'inspec/utils/json_log'
|
|
||||||
require 'inspec/utils/latest_version'
|
module Inspec # TODO: move this somewhere "better"?
|
||||||
require 'inspec/base_cli'
|
autoload :BaseCLI, "inspec/base_cli"
|
||||||
require 'inspec/plugin/v1'
|
autoload :Deprecation, "inspec/utils/deprecation"
|
||||||
require 'inspec/plugin/v2'
|
autoload :Exceptions, "inspec/exceptions"
|
||||||
require 'inspec/runner_mock'
|
autoload :Fetcher, "inspec/fetcher"
|
||||||
require 'inspec/env_printer'
|
autoload :Formatters, "inspec/formatters"
|
||||||
require 'inspec/schema'
|
autoload :Globals, "inspec/globals"
|
||||||
require 'inspec/config'
|
autoload :Impact, "inspec/impact"
|
||||||
require 'inspec/dist'
|
autoload :Impact, "inspec/impact"
|
||||||
|
autoload :InputRegistry, "inspec/input_registry"
|
||||||
|
autoload :Profile, "inspec/profile"
|
||||||
|
autoload :Reporters, "inspec/reporters"
|
||||||
|
autoload :Resource, "inspec/resource"
|
||||||
|
autoload :Rule, "inspec/rule"
|
||||||
|
autoload :Runner, "inspec/runner"
|
||||||
|
autoload :Runner, "inspec/runner"
|
||||||
|
autoload :Shell, "inspec/shell"
|
||||||
|
autoload :SourceReader, "inspec/source_reader"
|
||||||
|
autoload :Telemetry, "inspec/utils/telemetry"
|
||||||
|
autoload :V1, "inspec/plugin/v1"
|
||||||
|
autoload :V2, "inspec/plugin/v2"
|
||||||
|
autoload :VERSION, "inspec/version"
|
||||||
|
end
|
||||||
|
|
||||||
class Inspec::InspecCLI < Inspec::BaseCLI
|
class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
class_option :log_level, aliases: :l, type: :string,
|
class_option :log_level, aliases: :l, type: :string,
|
||||||
desc: 'Set the log level: info (default), debug, warn, error'
|
desc: "Set the log level: info (default), debug, warn, error"
|
||||||
|
|
||||||
class_option :log_location, type: :string,
|
class_option :log_location, type: :string,
|
||||||
desc: 'Location to send diagnostic log messages to. (default: $stdout or Inspec::Log.error)'
|
desc: "Location to send diagnostic log messages to. (default: $stdout or Inspec::Log.error)"
|
||||||
|
|
||||||
class_option :diagnose, type: :boolean,
|
class_option :diagnose, type: :boolean,
|
||||||
desc: 'Show diagnostics (versions, configurations)'
|
desc: "Show diagnostics (versions, configurations)"
|
||||||
|
|
||||||
class_option :color, type: :boolean,
|
class_option :color, type: :boolean,
|
||||||
desc: 'Use colors in output.'
|
desc: "Use colors in output."
|
||||||
|
|
||||||
class_option :interactive, type: :boolean,
|
class_option :interactive, type: :boolean,
|
||||||
desc: 'Allow or disable user interaction'
|
desc: "Allow or disable user interaction"
|
||||||
|
|
||||||
class_option :disable_core_plugins, type: :string, banner: '', # Actually a boolean, but this suppresses the creation of a --no-disable...
|
class_option :disable_core_plugins, type: :string, banner: "", # Actually a boolean, but this suppresses the creation of a --no-disable...
|
||||||
desc: 'Disable loading all plugins that are shipped in the lib/plugins directory of InSpec. Useful in development.'
|
desc: "Disable loading all plugins that are shipped in the lib/plugins directory of InSpec. Useful in development."
|
||||||
|
|
||||||
class_option :disable_user_plugins, type: :string, banner: '',
|
class_option :disable_user_plugins, type: :string, banner: "",
|
||||||
desc: 'Disable loading all plugins that the user installed.'
|
desc: "Disable loading all plugins that the user installed."
|
||||||
|
|
||||||
class_option :enable_telemetry, type: :boolean,
|
class_option :enable_telemetry, type: :boolean,
|
||||||
desc: 'Allow or disable telemetry', default: false
|
desc: "Allow or disable telemetry", default: false
|
||||||
|
|
||||||
require 'license_acceptance/cli_flags/thor'
|
require "license_acceptance/cli_flags/thor"
|
||||||
include LicenseAcceptance::CLIFlags::Thor
|
include LicenseAcceptance::CLIFlags::Thor
|
||||||
|
|
||||||
desc 'json PATH', 'read all tests in PATH and generate a JSON summary'
|
desc "json PATH", "read all tests in PATH and generate a JSON summary"
|
||||||
option :output, aliases: :o, type: :string,
|
option :output, aliases: :o, type: :string,
|
||||||
desc: 'Save the created profile to a path'
|
desc: "Save the created profile to a path"
|
||||||
option :controls, type: :array,
|
option :controls, type: :array,
|
||||||
desc: 'A list of controls to include. Ignore all other tests.'
|
desc: "A list of controls to include. Ignore all other tests."
|
||||||
profile_options
|
profile_options
|
||||||
def json(target)
|
def json(target)
|
||||||
|
require "inspec/resources"
|
||||||
|
require "json"
|
||||||
|
|
||||||
o = config
|
o = config
|
||||||
diagnose(o)
|
diagnose(o)
|
||||||
o['log_location'] = $stderr
|
o["log_location"] = $stderr
|
||||||
configure_logger(o)
|
configure_logger(o)
|
||||||
|
|
||||||
o[:backend] = Inspec::Backend.create(Inspec::Config.mock)
|
o[:backend] = Inspec::Backend.create(Inspec::Config.mock)
|
||||||
|
@ -63,7 +80,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
info = profile.info
|
info = profile.info
|
||||||
# add in inspec version
|
# add in inspec version
|
||||||
info[:generator] = {
|
info[:generator] = {
|
||||||
name: 'inspec',
|
name: "inspec",
|
||||||
version: Inspec::VERSION,
|
version: Inspec::VERSION,
|
||||||
}
|
}
|
||||||
dst = o[:output].to_s
|
dst = o[:output].to_s
|
||||||
|
@ -82,14 +99,16 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
pretty_handle_exception(e)
|
pretty_handle_exception(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'check PATH', 'verify all tests at the specified PATH'
|
desc "check PATH", "verify all tests at the specified PATH"
|
||||||
option :format, type: :string
|
option :format, type: :string
|
||||||
profile_options
|
profile_options
|
||||||
def check(path) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
def check(path) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
||||||
|
require "inspec/resources"
|
||||||
|
|
||||||
o = config
|
o = config
|
||||||
diagnose(o)
|
diagnose(o)
|
||||||
o['log_location'] ||= STDERR if o['format'] == 'json'
|
o["log_location"] ||= STDERR if o["format"] == "json"
|
||||||
o['log_level'] ||= 'warn'
|
o["log_level"] ||= "warn"
|
||||||
configure_logger(o)
|
configure_logger(o)
|
||||||
|
|
||||||
o[:backend] = Inspec::Backend.create(Inspec::Config.mock)
|
o[:backend] = Inspec::Backend.create(Inspec::Config.mock)
|
||||||
|
@ -100,25 +119,25 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
profile = Inspec::Profile.for_target(path, o)
|
profile = Inspec::Profile.for_target(path, o)
|
||||||
result = profile.check
|
result = profile.check
|
||||||
|
|
||||||
if o['format'] == 'json'
|
if o["format"] == "json"
|
||||||
puts JSON.generate(result)
|
puts JSON.generate(result)
|
||||||
else
|
else
|
||||||
%w{location profile controls timestamp valid}.each do |item|
|
%w{location profile controls timestamp valid}.each do |item|
|
||||||
puts format('%-12s %s', item.to_s.capitalize + ':',
|
puts format("%-12s %s", item.to_s.capitalize + ":",
|
||||||
mark_text(result[:summary][item.to_sym]))
|
mark_text(result[:summary][item.to_sym]))
|
||||||
end
|
end
|
||||||
puts
|
puts
|
||||||
|
|
||||||
if result[:errors].empty? and result[:warnings].empty?
|
if result[:errors].empty? && result[:warnings].empty?
|
||||||
puts 'No errors or warnings'
|
puts "No errors or warnings"
|
||||||
else
|
else
|
||||||
red = "\033[31m"
|
red = "\033[31m"
|
||||||
yellow = "\033[33m"
|
yellow = "\033[33m"
|
||||||
rst = "\033[0m"
|
rst = "\033[0m"
|
||||||
|
|
||||||
item_msg = lambda { |item|
|
item_msg = lambda { |item|
|
||||||
pos = [item[:file], item[:line], item[:column]].compact.join(':')
|
pos = [item[:file], item[:line], item[:column]].compact.join(":")
|
||||||
pos.empty? ? item[:msg] : pos + ': ' + item[:msg]
|
pos.empty? ? item[:msg] : pos + ": " + item[:msg]
|
||||||
}
|
}
|
||||||
result[:errors].each do |item|
|
result[:errors].each do |item|
|
||||||
puts "#{red} ✖ #{item_msg.call(item)}#{rst}"
|
puts "#{red} ✖ #{item_msg.call(item)}#{rst}"
|
||||||
|
@ -128,7 +147,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
end
|
end
|
||||||
|
|
||||||
puts
|
puts
|
||||||
puts format('Summary: %s%d errors%s, %s%d warnings%s',
|
puts format("Summary: %s%d errors%s, %s%d warnings%s",
|
||||||
red, result[:errors].length, rst,
|
red, result[:errors].length, rst,
|
||||||
yellow, result[:warnings].length, rst)
|
yellow, result[:warnings].length, rst)
|
||||||
end
|
end
|
||||||
|
@ -138,10 +157,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
pretty_handle_exception(e)
|
pretty_handle_exception(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'vendor PATH', 'Download all dependencies and generate a lockfile in a `vendor` directory'
|
desc "vendor PATH", "Download all dependencies and generate a lockfile in a `vendor` directory"
|
||||||
option :overwrite, type: :boolean, default: false,
|
option :overwrite, type: :boolean, default: false,
|
||||||
desc: 'Overwrite existing vendored dependencies and lockfile.'
|
desc: "Overwrite existing vendored dependencies and lockfile."
|
||||||
def vendor(path = nil)
|
def vendor(path = nil)
|
||||||
|
require "inspec/resources"
|
||||||
|
|
||||||
o = config
|
o = config
|
||||||
configure_logger(o)
|
configure_logger(o)
|
||||||
o[:logger] = Logger.new($stdout)
|
o[:logger] = Logger.new($stdout)
|
||||||
|
@ -150,19 +171,21 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
vendor_deps(path, o)
|
vendor_deps(path, o)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'archive PATH', 'archive a profile to tar.gz (default) or zip'
|
desc "archive PATH", "archive a profile to tar.gz (default) or zip"
|
||||||
profile_options
|
profile_options
|
||||||
option :output, aliases: :o, type: :string,
|
option :output, aliases: :o, type: :string,
|
||||||
desc: 'Save the archive to a path'
|
desc: "Save the archive to a path"
|
||||||
option :zip, type: :boolean, default: false,
|
option :zip, type: :boolean, default: false,
|
||||||
desc: 'Generates a zip archive.'
|
desc: "Generates a zip archive."
|
||||||
option :tar, type: :boolean, default: false,
|
option :tar, type: :boolean, default: false,
|
||||||
desc: 'Generates a tar.gz archive.'
|
desc: "Generates a tar.gz archive."
|
||||||
option :overwrite, type: :boolean, default: false,
|
option :overwrite, type: :boolean, default: false,
|
||||||
desc: 'Overwrite existing archive.'
|
desc: "Overwrite existing archive."
|
||||||
option :ignore_errors, type: :boolean, default: false,
|
option :ignore_errors, type: :boolean, default: false,
|
||||||
desc: 'Ignore profile warnings.'
|
desc: "Ignore profile warnings."
|
||||||
def archive(path)
|
def archive(path)
|
||||||
|
require "inspec/resources"
|
||||||
|
|
||||||
o = config
|
o = config
|
||||||
diagnose(o)
|
diagnose(o)
|
||||||
|
|
||||||
|
@ -179,7 +202,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
result = profile.check
|
result = profile.check
|
||||||
|
|
||||||
if result && !o[:ignore_errors] == false
|
if result && !o[:ignore_errors] == false
|
||||||
o[:logger].info 'Profile check failed. Please fix the profile before generating an archive.'
|
o[:logger].info "Profile check failed. Please fix the profile before generating an archive."
|
||||||
return exit 1
|
return exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -189,7 +212,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
pretty_handle_exception(e)
|
pretty_handle_exception(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'exec LOCATIONS', 'run all test files at the specified LOCATIONS.'
|
desc "exec LOCATIONS", "run all test files at the specified LOCATIONS."
|
||||||
# TODO: find a way for Thor not to butcher the formatting of this
|
# TODO: find a way for Thor not to butcher the formatting of this
|
||||||
long_desc <<~EOT
|
long_desc <<~EOT
|
||||||
Loads the given profile(s) and fetches their dependencies if needed. Then
|
Loads the given profile(s) and fetches their dependencies if needed. Then
|
||||||
|
@ -279,17 +302,17 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
pretty_handle_exception(e)
|
pretty_handle_exception(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'detect', 'detect the target OS'
|
desc "detect", "detect the target OS"
|
||||||
target_options
|
target_options
|
||||||
option :format, type: :string
|
option :format, type: :string
|
||||||
def detect
|
def detect
|
||||||
o = config
|
o = config
|
||||||
o[:command] = 'platform.params'
|
o[:command] = "platform.params"
|
||||||
(_, res) = run_command(o)
|
(_, res) = run_command(o)
|
||||||
if o['format'] == 'json'
|
if o["format"] == "json"
|
||||||
puts res.to_json
|
puts res.to_json
|
||||||
else
|
else
|
||||||
headline('Platform Details')
|
headline("Platform Details")
|
||||||
puts Inspec::BaseCLI.format_platform_info(params: res, indent: 0, color: 36)
|
puts Inspec::BaseCLI.format_platform_info(params: res, indent: 0, color: 36)
|
||||||
end
|
end
|
||||||
rescue ArgumentError, RuntimeError, Train::UserError => e
|
rescue ArgumentError, RuntimeError, Train::UserError => e
|
||||||
|
@ -299,17 +322,17 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
pretty_handle_exception(e)
|
pretty_handle_exception(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'shell', 'open an interactive debugging shell'
|
desc "shell", "open an interactive debugging shell"
|
||||||
target_options
|
target_options
|
||||||
option :command, aliases: :c,
|
option :command, aliases: :c,
|
||||||
desc: 'A single command string to run instead of launching the shell'
|
desc: "A single command string to run instead of launching the shell"
|
||||||
option :reporter, type: :array,
|
option :reporter, type: :array,
|
||||||
banner: 'one two:/output/file/path',
|
banner: "one two:/output/file/path",
|
||||||
desc: 'Enable one or more output reporters: cli, documentation, html, progress, json, json-min, json-rspec, junit'
|
desc: "Enable one or more output reporters: cli, documentation, html, progress, json, json-min, json-rspec, junit"
|
||||||
option :depends, type: :array, default: [],
|
option :depends, type: :array, default: [],
|
||||||
desc: 'A space-delimited list of local folders containing profiles whose libraries and resources will be loaded into the new shell'
|
desc: "A space-delimited list of local folders containing profiles whose libraries and resources will be loaded into the new shell"
|
||||||
option :distinct_exit, type: :boolean, default: true,
|
option :distinct_exit, type: :boolean, default: true,
|
||||||
desc: 'Exit with code 100 if any tests fail, and 101 if any are skipped but none failed (default). If disabled, exit 0 on skips and 1 for failures.'
|
desc: "Exit with code 100 if any tests fail, and 101 if any are skipped but none failed (default). If disabled, exit 0 on skips and 1 for failures."
|
||||||
def shell_func
|
def shell_func
|
||||||
o = config
|
o = config
|
||||||
diagnose(o)
|
diagnose(o)
|
||||||
|
@ -328,7 +351,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
exit res unless run_type == :ruby_eval
|
exit res unless run_type == :ruby_eval
|
||||||
|
|
||||||
# No InSpec tests - just print evaluation output.
|
# No InSpec tests - just print evaluation output.
|
||||||
res = (res.respond_to?(:to_json) ? res.to_json : JSON.dump(res)) if o['reporter']&.keys&.include?('json')
|
res = (res.respond_to?(:to_json) ? res.to_json : JSON.dump(res)) if o["reporter"]&.keys&.include?("json")
|
||||||
puts res
|
puts res
|
||||||
exit 0
|
exit 0
|
||||||
rescue RuntimeError, Train::UserError => e
|
rescue RuntimeError, Train::UserError => e
|
||||||
|
@ -337,7 +360,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
pretty_handle_exception(e)
|
pretty_handle_exception(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'env', 'Output shell-appropriate completion configuration'
|
desc "env", "Output shell-appropriate completion configuration"
|
||||||
def env(shell = nil)
|
def env(shell = nil)
|
||||||
p = Inspec::EnvPrinter.new(self.class, shell)
|
p = Inspec::EnvPrinter.new(self.class, shell)
|
||||||
p.print_and_exit!
|
p.print_and_exit!
|
||||||
|
@ -345,24 +368,28 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
pretty_handle_exception(e)
|
pretty_handle_exception(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'schema NAME', 'print the JSON schema', hide: true
|
desc "schema NAME", "print the JSON schema", hide: true
|
||||||
def schema(name)
|
def schema(name)
|
||||||
|
require "inspec/schema"
|
||||||
|
|
||||||
puts Inspec::Schema.json(name)
|
puts Inspec::Schema.json(name)
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
puts e
|
puts e
|
||||||
puts "Valid schemas are #{Inspec::Schema.names.join(', ')}"
|
puts "Valid schemas are #{Inspec::Schema.names.join(', ')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'version', 'prints the version of this tool'
|
desc "version", "prints the version of this tool"
|
||||||
option :format, type: :string
|
option :format, type: :string
|
||||||
def version
|
def version
|
||||||
if config['format'] == 'json'
|
if config["format"] == "json"
|
||||||
v = { version: Inspec::VERSION }
|
v = { version: Inspec::VERSION }
|
||||||
puts v.to_json
|
puts v.to_json
|
||||||
else
|
else
|
||||||
|
require "inspec/utils/latest_version"
|
||||||
puts Inspec::VERSION
|
puts Inspec::VERSION
|
||||||
# display outdated version
|
# display outdated version
|
||||||
latest = LatestInSpecVersion.new.latest
|
# TODO: remove this. Don't notify of update to a gem when they install omnibus
|
||||||
|
latest = LatestInSpecVersion.new.latest || Inspec::VERSION
|
||||||
if Gem::Version.new(Inspec::VERSION) < Gem::Version.new(latest)
|
if Gem::Version.new(Inspec::VERSION) < Gem::Version.new(latest)
|
||||||
puts "\nYour version of #{Inspec::Dist::PRODUCT_NAME} is out of date! The latest version is #{latest}."
|
puts "\nYour version of #{Inspec::Dist::PRODUCT_NAME} is out of date! The latest version is #{latest}."
|
||||||
end
|
end
|
||||||
|
@ -370,6 +397,11 @@ class Inspec::InspecCLI < Inspec::BaseCLI
|
||||||
end
|
end
|
||||||
map %w{-v --version} => :version
|
map %w{-v --version} => :version
|
||||||
|
|
||||||
|
desc "nothing", "does nothing"
|
||||||
|
def nothing
|
||||||
|
puts "you did nothing"
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def run_command(opts)
|
def run_command(opts)
|
||||||
|
@ -403,10 +435,12 @@ end
|
||||||
#---------------------------------------------------------------------#
|
#---------------------------------------------------------------------#
|
||||||
# Plugin Loading
|
# Plugin Loading
|
||||||
#---------------------------------------------------------------------#
|
#---------------------------------------------------------------------#
|
||||||
|
require "inspec/plugin/v2"
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Load v2 plugins. Manually check for plugin disablement.
|
# Load v2 plugins. Manually check for plugin disablement.
|
||||||
omit_core = ARGV.delete('--disable-core-plugins')
|
omit_core = ARGV.delete("--disable-core-plugins")
|
||||||
omit_user = ARGV.delete('--disable-user-plugins')
|
omit_user = ARGV.delete("--disable-user-plugins")
|
||||||
v2_loader = Inspec::Plugin::V2::Loader.new(omit_core_plugins: omit_core, omit_user_plugins: omit_user)
|
v2_loader = Inspec::Plugin::V2::Loader.new(omit_core_plugins: omit_core, omit_user_plugins: omit_user)
|
||||||
v2_loader.load_all
|
v2_loader.load_all
|
||||||
v2_loader.exit_on_load_error
|
v2_loader.exit_on_load_error
|
||||||
|
@ -417,23 +451,23 @@ begin
|
||||||
ctl.list.each { |x| ctl.load(x) }
|
ctl.list.each { |x| ctl.load(x) }
|
||||||
|
|
||||||
# load v1 CLI plugins before the InSpec CLI has been started
|
# load v1 CLI plugins before the InSpec CLI has been started
|
||||||
Inspec::Plugins::CLI.subcommands.each { |_subcommand, params|
|
Inspec::Plugins::CLI.subcommands.each do |_subcommand, params|
|
||||||
Inspec::InspecCLI.register(
|
Inspec::InspecCLI.register(
|
||||||
params[:klass],
|
params[:klass],
|
||||||
params[:subcommand_name],
|
params[:subcommand_name],
|
||||||
params[:usage],
|
params[:usage],
|
||||||
params[:description],
|
params[:description],
|
||||||
params[:options],
|
params[:options]
|
||||||
)
|
)
|
||||||
}
|
end
|
||||||
rescue Inspec::Plugin::V2::Exception => v2ex
|
rescue Inspec::Plugin::V2::Exception => v2ex
|
||||||
Inspec::Log.error v2ex.message
|
Inspec::Log.error v2ex.message
|
||||||
|
|
||||||
if ARGV.include?('--debug')
|
if ARGV.include?("--debug")
|
||||||
Inspec::Log.error v2ex.class.name
|
Inspec::Log.error v2ex.class.name
|
||||||
Inspec::Log.error v2ex.backtrace.join("\n")
|
Inspec::Log.error v2ex.backtrace.join("\n")
|
||||||
else
|
else
|
||||||
Inspec::Log.error 'Run again with --debug for a stacktrace.'
|
Inspec::Log.error "Run again with --debug for a stacktrace."
|
||||||
end
|
end
|
||||||
exit 2
|
exit 2
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
# Represents InSpec configuration. Merges defaults, config file options,
|
# Represents InSpec configuration. Merges defaults, config file options,
|
||||||
# and CLI arguments.
|
# and CLI arguments.
|
||||||
|
|
||||||
require 'pp'
|
require "pp"
|
||||||
require 'stringio'
|
require "stringio"
|
||||||
require 'forwardable'
|
require "forwardable"
|
||||||
require 'thor'
|
require "thor"
|
||||||
require 'base64'
|
require "base64"
|
||||||
require 'inspec/base_cli'
|
require "inspec/base_cli"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
class Config
|
class Config
|
||||||
|
@ -31,7 +31,7 @@ module Inspec
|
||||||
|
|
||||||
# This makes it easy to make a config with a mock backend.
|
# This makes it easy to make a config with a mock backend.
|
||||||
def self.mock(opts = {})
|
def self.mock(opts = {})
|
||||||
Inspec::Config.new({ backend: :mock }.merge(opts), StringIO.new('{}'))
|
Inspec::Config.new({ backend: :mock }.merge(opts), StringIO.new("{}"))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Use this to get a cached version of the config. This prevents you from
|
# Use this to get a cached version of the config. This prevents you from
|
||||||
|
@ -62,11 +62,11 @@ module Inspec
|
||||||
return unless self[:diagnose]
|
return unless self[:diagnose]
|
||||||
puts "InSpec version: #{Inspec::VERSION}"
|
puts "InSpec version: #{Inspec::VERSION}"
|
||||||
puts "Train version: #{Train::VERSION}"
|
puts "Train version: #{Train::VERSION}"
|
||||||
puts 'Command line configuration:'
|
puts "Command line configuration:"
|
||||||
pp @cli_opts
|
pp @cli_opts
|
||||||
puts 'JSON configuration file:'
|
puts "JSON configuration file:"
|
||||||
pp @cfg_file_contents
|
pp @cfg_file_contents
|
||||||
puts 'Merged configuration:'
|
puts "Merged configuration:"
|
||||||
pp @merged_options
|
pp @merged_options
|
||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
|
@ -74,7 +74,7 @@ module Inspec
|
||||||
# return all telemetry options from config
|
# return all telemetry options from config
|
||||||
# @return [Hash]
|
# @return [Hash]
|
||||||
def telemetry_options
|
def telemetry_options
|
||||||
final_options.select { |key, _| key.include?('telemetry') }
|
final_options.select { |key, _| key.include?("telemetry") }
|
||||||
end
|
end
|
||||||
|
|
||||||
#-----------------------------------------------------------------------#
|
#-----------------------------------------------------------------------#
|
||||||
|
@ -131,7 +131,7 @@ module Inspec
|
||||||
credentials.merge!(unprefixed_transport_options)
|
credentials.merge!(unprefixed_transport_options)
|
||||||
|
|
||||||
# If there are any prefixed options, merge them in, stripping the prefix.
|
# If there are any prefixed options, merge them in, stripping the prefix.
|
||||||
transport_prefix = transport_name.downcase.tr('-', '_') + '_'
|
transport_prefix = transport_name.downcase.tr("-", "_") + "_"
|
||||||
transport_options.each do |bare_option_name|
|
transport_options.each do |bare_option_name|
|
||||||
prefixed_option_name = transport_prefix + bare_option_name.to_s
|
prefixed_option_name = transport_prefix + bare_option_name.to_s
|
||||||
if final_options.key?(prefixed_option_name)
|
if final_options.key?(prefixed_option_name)
|
||||||
|
@ -150,7 +150,7 @@ module Inspec
|
||||||
|
|
||||||
# Default to local
|
# Default to local
|
||||||
unless @final_options.key?(:target)
|
unless @final_options.key?(:target)
|
||||||
credentials[:backend] = 'local'
|
credentials[:backend] = "local"
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ module Inspec
|
||||||
credset_name = _utc_find_credset_name(credentials, transport_name)
|
credset_name = _utc_find_credset_name(credentials, transport_name)
|
||||||
|
|
||||||
if credset_name
|
if credset_name
|
||||||
credset = @cfg_file_contents.dig('credentials', transport_name, credset_name)
|
credset = @cfg_file_contents.dig("credentials", transport_name, credset_name)
|
||||||
if credset
|
if credset
|
||||||
credentials.merge!(credset)
|
credentials.merge!(credset)
|
||||||
else
|
else
|
||||||
|
@ -195,7 +195,7 @@ module Inspec
|
||||||
|
|
||||||
# Regardless of our situation, end up with a readable IO object
|
# Regardless of our situation, end up with a readable IO object
|
||||||
def resolve_cfg_io(cli_opts, cfg_io)
|
def resolve_cfg_io(cli_opts, cfg_io)
|
||||||
raise(ArgumentError, 'Inspec::Config must use an IO to read from') if cfg_io && !cfg_io.respond_to?(:read)
|
raise(ArgumentError, "Inspec::Config must use an IO to read from") if cfg_io && !cfg_io.respond_to?(:read)
|
||||||
cfg_io ||= check_for_piped_config(cli_opts)
|
cfg_io ||= check_for_piped_config(cli_opts)
|
||||||
return cfg_io if cfg_io
|
return cfg_io if cfg_io
|
||||||
|
|
||||||
|
@ -210,10 +210,10 @@ module Inspec
|
||||||
Inspec.deprecate(:cli_option_json_config) if cli_opts.key?(:json_config)
|
Inspec.deprecate(:cli_option_json_config) if cli_opts.key?(:json_config)
|
||||||
|
|
||||||
return nil unless cli_opt
|
return nil unless cli_opt
|
||||||
return nil unless cli_opt == '-'
|
return nil unless cli_opt == "-"
|
||||||
# This warning is here so that if a user invokes inspec with --config=-,
|
# This warning is here so that if a user invokes inspec with --config=-,
|
||||||
# they will have an explanation for why it appears to hang.
|
# they will have an explanation for why it appears to hang.
|
||||||
Inspec::Log.warn 'Reading JSON config from standard input' if STDIN.tty?
|
Inspec::Log.warn "Reading JSON config from standard input" if STDIN.tty?
|
||||||
STDIN
|
STDIN
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ module Inspec
|
||||||
Inspec.deprecate(:cli_option_json_config) if cli_opts.key?(:json_config)
|
Inspec.deprecate(:cli_option_json_config) if cli_opts.key?(:json_config)
|
||||||
|
|
||||||
if path.nil?
|
if path.nil?
|
||||||
default_path = File.join(Inspec.config_dir, 'config.json')
|
default_path = File.join(Inspec.config_dir, "config.json")
|
||||||
path = default_path if File.exist?(default_path)
|
path = default_path if File.exist?(default_path)
|
||||||
elsif !File.exist?(path)
|
elsif !File.exist?(path)
|
||||||
raise ArgumentError, "Could not read configuration file at #{path}"
|
raise ArgumentError, "Could not read configuration file at #{path}"
|
||||||
|
@ -249,7 +249,7 @@ module Inspec
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_version
|
def file_version
|
||||||
@cfg_file_contents['version'] || :legacy
|
@cfg_file_contents["version"] || :legacy
|
||||||
end
|
end
|
||||||
|
|
||||||
def legacy_file?
|
def legacy_file?
|
||||||
|
@ -261,26 +261,26 @@ module Inspec
|
||||||
# Assume everything in the file is a CLI option
|
# Assume everything in the file is a CLI option
|
||||||
@cfg_file_contents
|
@cfg_file_contents
|
||||||
else
|
else
|
||||||
@cfg_file_contents['cli_options'] || {}
|
@cfg_file_contents["cli_options"] || {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def config_file_reporter_options
|
def config_file_reporter_options
|
||||||
# This is assumed to be top-level in both legacy and 1.1.
|
# This is assumed to be top-level in both legacy and 1.1.
|
||||||
# Technically, you could sneak it in the 1.1 cli opts area.
|
# Technically, you could sneak it in the 1.1 cli opts area.
|
||||||
@cfg_file_contents.key?('reporter') ? { 'reporter' => @cfg_file_contents['reporter'] } : {}
|
@cfg_file_contents.key?("reporter") ? { "reporter" => @cfg_file_contents["reporter"] } : {}
|
||||||
end
|
end
|
||||||
|
|
||||||
#-----------------------------------------------------------------------#
|
#-----------------------------------------------------------------------#
|
||||||
# Validation
|
# Validation
|
||||||
#-----------------------------------------------------------------------#
|
#-----------------------------------------------------------------------#
|
||||||
def validate_config_file_contents!
|
def validate_config_file_contents!
|
||||||
version = @cfg_file_contents['version']
|
version = @cfg_file_contents["version"]
|
||||||
|
|
||||||
# Assume legacy format, which is unconstrained
|
# Assume legacy format, which is unconstrained
|
||||||
return unless version
|
return unless version
|
||||||
|
|
||||||
unless version == '1.1'
|
unless version == "1.1"
|
||||||
raise Inspec::ConfigError::Invalid, "Unsupported config file version '#{version}' - currently supported versions: 1.1"
|
raise Inspec::ConfigError::Invalid, "Unsupported config file version '#{version}' - currently supported versions: 1.1"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -296,23 +296,23 @@ module Inspec
|
||||||
return if reporters.nil?
|
return if reporters.nil?
|
||||||
# TODO: move this into a reporter plugin type system
|
# TODO: move this into a reporter plugin type system
|
||||||
valid_types = [
|
valid_types = [
|
||||||
'automate',
|
"automate",
|
||||||
'cli',
|
"cli",
|
||||||
'documentation',
|
"documentation",
|
||||||
'html',
|
"html",
|
||||||
'json',
|
"json",
|
||||||
'json-automate',
|
"json-automate",
|
||||||
'json-min',
|
"json-min",
|
||||||
'json-rspec',
|
"json-rspec",
|
||||||
'junit',
|
"junit",
|
||||||
'progress',
|
"progress",
|
||||||
'yaml',
|
"yaml",
|
||||||
]
|
]
|
||||||
|
|
||||||
reporters.each do |reporter_name, reporter_config|
|
reporters.each do |reporter_name, reporter_config|
|
||||||
raise NotImplementedError, "'#{reporter_name}' is not a valid reporter type." unless valid_types.include?(reporter_name)
|
raise NotImplementedError, "'#{reporter_name}' is not a valid reporter type." unless valid_types.include?(reporter_name)
|
||||||
|
|
||||||
next unless reporter_name == 'automate'
|
next unless reporter_name == "automate"
|
||||||
%w{token url}.each do |option|
|
%w{token url}.each do |option|
|
||||||
raise Inspec::ReporterError, "You must specify a automate #{option} via the config file." if reporter_config[option].nil?
|
raise Inspec::ReporterError, "You must specify a automate #{option} via the config file." if reporter_config[option].nil?
|
||||||
end
|
end
|
||||||
|
@ -321,10 +321,10 @@ module Inspec
|
||||||
# check to make sure we are only reporting one type to stdout
|
# check to make sure we are only reporting one type to stdout
|
||||||
stdout_reporters = 0
|
stdout_reporters = 0
|
||||||
reporters.each_value do |reporter_config|
|
reporters.each_value do |reporter_config|
|
||||||
stdout_reporters += 1 if reporter_config['stdout'] == true
|
stdout_reporters += 1 if reporter_config["stdout"] == true
|
||||||
end
|
end
|
||||||
|
|
||||||
raise ArgumentError, 'The option --reporter can only have a single report outputting to stdout.' if stdout_reporters > 1
|
raise ArgumentError, "The option --reporter can only have a single report outputting to stdout." if stdout_reporters > 1
|
||||||
end
|
end
|
||||||
|
|
||||||
#-----------------------------------------------------------------------#
|
#-----------------------------------------------------------------------#
|
||||||
|
@ -368,36 +368,36 @@ module Inspec
|
||||||
|
|
||||||
def finalize_parse_reporters(options) # rubocop:disable Metrics/AbcSize
|
def finalize_parse_reporters(options) # rubocop:disable Metrics/AbcSize
|
||||||
# default to cli report for ad-hoc runners
|
# default to cli report for ad-hoc runners
|
||||||
options['reporter'] = ['cli'] if options['reporter'].nil?
|
options["reporter"] = ["cli"] if options["reporter"].nil?
|
||||||
|
|
||||||
# parse out cli to proper report format
|
# parse out cli to proper report format
|
||||||
if options['reporter'].is_a?(Array)
|
if options["reporter"].is_a?(Array)
|
||||||
reports = {}
|
reports = {}
|
||||||
options['reporter'].each do |report|
|
options["reporter"].each do |report|
|
||||||
reporter_name, destination = report.split(':', 2)
|
reporter_name, destination = report.split(":", 2)
|
||||||
if destination.nil? || destination.strip == '-'
|
if destination.nil? || destination.strip == "-"
|
||||||
reports[reporter_name] = { 'stdout' => true }
|
reports[reporter_name] = { "stdout" => true }
|
||||||
else
|
else
|
||||||
reports[reporter_name] = {
|
reports[reporter_name] = {
|
||||||
'file' => destination,
|
"file" => destination,
|
||||||
'stdout' => false,
|
"stdout" => false,
|
||||||
}
|
}
|
||||||
reports[reporter_name]['target_id'] = options['target_id'] if options['target_id']
|
reports[reporter_name]["target_id"] = options["target_id"] if options["target_id"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
options['reporter'] = reports
|
options["reporter"] = reports
|
||||||
end
|
end
|
||||||
|
|
||||||
# add in stdout if not specified
|
# add in stdout if not specified
|
||||||
if options['reporter'].is_a?(Hash)
|
if options["reporter"].is_a?(Hash)
|
||||||
options['reporter'].each do |reporter_name, config|
|
options["reporter"].each do |reporter_name, config|
|
||||||
options['reporter'][reporter_name] = {} if config.nil?
|
options["reporter"][reporter_name] = {} if config.nil?
|
||||||
options['reporter'][reporter_name]['stdout'] = true if options['reporter'][reporter_name].empty?
|
options["reporter"][reporter_name]["stdout"] = true if options["reporter"][reporter_name].empty?
|
||||||
options['reporter'][reporter_name]['target_id'] = options['target_id'] if options['target_id']
|
options["reporter"][reporter_name]["target_id"] = options["target_id"] if options["target_id"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
validate_reporters!(options['reporter'])
|
validate_reporters!(options["reporter"])
|
||||||
options
|
options
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -408,38 +408,38 @@ module Inspec
|
||||||
# whenever it is used, it requires a value. Handle options that were
|
# whenever it is used, it requires a value. Handle options that were
|
||||||
# defined in such a way and require a value here:
|
# defined in such a way and require a value here:
|
||||||
%w{password sudo-password}.each do |option_name|
|
%w{password sudo-password}.each do |option_name|
|
||||||
snake_case_option_name = option_name.tr('-', '_').to_s
|
snake_case_option_name = option_name.tr("-", "_").to_s
|
||||||
next unless options[snake_case_option_name] == -1 # Thor sets -1 for missing value - see #1918
|
next unless options[snake_case_option_name] == -1 # Thor sets -1 for missing value - see #1918
|
||||||
raise ArgumentError, "Please provide a value for --#{option_name}. For example: --#{option_name}=hello."
|
raise ArgumentError, "Please provide a value for --#{option_name}. For example: --#{option_name}=hello."
|
||||||
end
|
end
|
||||||
|
|
||||||
# Infer `--sudo` if using `--sudo-password` without `--sudo`
|
# Infer `--sudo` if using `--sudo-password` without `--sudo`
|
||||||
if options['sudo_password'] && !options['sudo']
|
if options["sudo_password"] && !options["sudo"]
|
||||||
options['sudo'] = true
|
options["sudo"] = true
|
||||||
Inspec::Log.warn '`--sudo-password` used without `--sudo`. Adding `--sudo`.'
|
Inspec::Log.warn "`--sudo-password` used without `--sudo`. Adding `--sudo`."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize_compliance_login(options)
|
def finalize_compliance_login(options)
|
||||||
# check for compliance settings
|
# check for compliance settings
|
||||||
# This is always a hash, comes from config file, not CLI opts
|
# This is always a hash, comes from config file, not CLI opts
|
||||||
if options.key?('compliance')
|
if options.key?("compliance")
|
||||||
require 'plugins/inspec-compliance/lib/inspec-compliance/api'
|
require "plugins/inspec-compliance/lib/inspec-compliance/api"
|
||||||
InspecPlugins::Compliance::API.login(options['compliance'])
|
InspecPlugins::Compliance::API.login(options["compliance"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Defaults
|
class Defaults
|
||||||
DEFAULTS = {
|
DEFAULTS = {
|
||||||
exec: {
|
exec: {
|
||||||
'reporter' => ['cli'],
|
"reporter" => ["cli"],
|
||||||
'show_progress' => false,
|
"show_progress" => false,
|
||||||
'color' => true,
|
"color" => true,
|
||||||
'create_lockfile' => true,
|
"create_lockfile" => true,
|
||||||
'backend_cache' => true,
|
"backend_cache" => true,
|
||||||
},
|
},
|
||||||
shell: {
|
shell: {
|
||||||
'reporter' => ['cli'],
|
"reporter" => ["cli"],
|
||||||
},
|
},
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
require 'inspec/dsl'
|
require "inspec/dsl"
|
||||||
require 'inspec/dsl_shared'
|
require "inspec/dsl_shared"
|
||||||
require 'rspec/core/dsl'
|
require "rspec/core/dsl"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
#
|
#
|
||||||
|
@ -28,7 +28,7 @@ module Inspec
|
||||||
# Simply an access, no event here
|
# Simply an access, no event here
|
||||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_id).value
|
Inspec::InputRegistry.find_or_register_input(input_name, profile_id).value
|
||||||
else
|
else
|
||||||
options[:priority] = 20
|
options[:priority] ||= 20
|
||||||
options[:provider] = :inline_control_code
|
options[:provider] = :inline_control_code
|
||||||
evt = Inspec::Input.infer_event(options)
|
evt = Inspec::Input.infer_event(options)
|
||||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_id, event: evt).value
|
Inspec::InputRegistry.find_or_register_input(input_name, profile_id, event: evt).value
|
||||||
|
@ -188,7 +188,7 @@ module Inspec
|
||||||
# Simply an access, no event here
|
# Simply an access, no event here
|
||||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_id).value
|
Inspec::InputRegistry.find_or_register_input(input_name, profile_id).value
|
||||||
else
|
else
|
||||||
options[:priority] = 20
|
options[:priority] ||= 20
|
||||||
options[:provider] = :inline_control_code
|
options[:provider] = :inline_control_code
|
||||||
evt = Inspec::Input.infer_event(options)
|
evt = Inspec::Input.infer_event(options)
|
||||||
Inspec::InputRegistry.find_or_register_input(input_name, profile_id, event: evt).value
|
Inspec::InputRegistry.find_or_register_input(input_name, profile_id, event: evt).value
|
||||||
|
@ -233,7 +233,7 @@ module Inspec
|
||||||
|
|
||||||
def block_location(block, alternate_caller)
|
def block_location(block, alternate_caller)
|
||||||
if block.nil?
|
if block.nil?
|
||||||
alternate_caller[/^(.+:\d+):in .+$/, 1] || 'unknown'
|
alternate_caller[/^(.+:\d+):in .+$/, 1] || "unknown"
|
||||||
else
|
else
|
||||||
path, line = block.source_location
|
path, line = block.source_location
|
||||||
"#{File.basename(path)}:#{line}"
|
"#{File.basename(path)}:#{line}"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require 'fileutils'
|
require "fileutils"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
#
|
#
|
||||||
|
@ -17,7 +17,7 @@ module Inspec
|
||||||
class Cache
|
class Cache
|
||||||
attr_reader :path
|
attr_reader :path
|
||||||
def initialize(path = nil)
|
def initialize(path = nil)
|
||||||
@path = path || File.join(Inspec.config_dir, 'cache')
|
@path = path || File.join(Inspec.config_dir, "cache")
|
||||||
FileUtils.mkdir_p(@path) unless File.directory?(@path)
|
FileUtils.mkdir_p(@path) unless File.directory?(@path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'inspec/dependencies/requirement'
|
require "inspec/dependencies/requirement"
|
||||||
require 'inspec/dependencies/resolver'
|
require "inspec/dependencies/resolver"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
#
|
#
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require 'yaml'
|
require "yaml"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
class Lockfile
|
class Lockfile
|
||||||
|
@ -8,15 +8,15 @@ module Inspec
|
||||||
|
|
||||||
def self.from_dependency_set(dep_set)
|
def self.from_dependency_set(dep_set)
|
||||||
lockfile_content = {
|
lockfile_content = {
|
||||||
'lockfile_version' => CURRENT_LOCKFILE_VERSION,
|
"lockfile_version" => CURRENT_LOCKFILE_VERSION,
|
||||||
'depends' => dep_set.to_array,
|
"depends" => dep_set.to_array,
|
||||||
}
|
}
|
||||||
new(lockfile_content)
|
new(lockfile_content)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.from_content(content)
|
def self.from_content(content)
|
||||||
parsed_content = YAML.load(content)
|
parsed_content = YAML.load(content)
|
||||||
version = parsed_content['lockfile_version']
|
version = parsed_content["lockfile_version"]
|
||||||
raise "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)
|
validate_lockfile_version!(version.to_i)
|
||||||
new(parsed_content)
|
new(parsed_content)
|
||||||
|
@ -50,15 +50,15 @@ module Inspec
|
||||||
|
|
||||||
attr_reader :version, :deps
|
attr_reader :version, :deps
|
||||||
def initialize(lockfile_content_hash)
|
def initialize(lockfile_content_hash)
|
||||||
version = lockfile_content_hash['lockfile_version']
|
version = lockfile_content_hash["lockfile_version"]
|
||||||
@version = version.to_i
|
@version = version.to_i
|
||||||
parse_content_hash(lockfile_content_hash)
|
parse_content_hash(lockfile_content_hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_yaml
|
def to_yaml
|
||||||
{
|
{
|
||||||
'lockfile_version' => CURRENT_LOCKFILE_VERSION,
|
"lockfile_version" => CURRENT_LOCKFILE_VERSION,
|
||||||
'depends' => @deps.map { |i| stringify_keys(i) },
|
"depends" => @deps.map { |i| stringify_keys(i) },
|
||||||
}.to_yaml
|
}.to_yaml
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ module Inspec
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_content_hash_1(lockfile_content_hash)
|
def parse_content_hash_1(lockfile_content_hash)
|
||||||
@deps = lockfile_content_hash['depends']&.map { |i| symbolize_keys(i) }
|
@deps = lockfile_content_hash["depends"]&.map { |i| symbolize_keys(i) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def mutate_hash_keys_with(hash, fun)
|
def mutate_hash_keys_with(hash, fun)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'inspec/cached_fetcher'
|
require "inspec/cached_fetcher"
|
||||||
require 'semverse'
|
require "semverse"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
#
|
#
|
||||||
|
@ -8,7 +8,7 @@ module Inspec
|
||||||
#
|
#
|
||||||
class Requirement
|
class Requirement
|
||||||
def self.from_metadata(dep, cache, opts)
|
def self.from_metadata(dep, cache, opts)
|
||||||
raise 'Cannot load empty dependency.' if dep.nil? || dep.empty?
|
raise "Cannot load empty dependency." if dep.nil? || dep.empty?
|
||||||
|
|
||||||
req_path = opts[:cwd]
|
req_path = opts[:cwd]
|
||||||
|
|
||||||
|
@ -81,13 +81,13 @@ module Inspec
|
||||||
|
|
||||||
def to_hash
|
def to_hash
|
||||||
h = {
|
h = {
|
||||||
'name' => name,
|
"name" => name,
|
||||||
'resolved_source' => resolved_source,
|
"resolved_source" => resolved_source,
|
||||||
'version_constraints' => version_constraints,
|
"version_constraints" => version_constraints,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dependencies.empty?
|
if !dependencies.empty?
|
||||||
h['dependencies'] = dependencies.map(&:to_hash)
|
h["dependencies"] = dependencies.map(&:to_hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
h
|
h
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'inspec/log'
|
require "inspec/log"
|
||||||
require 'inspec/errors'
|
require "inspec/errors"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
#
|
#
|
||||||
|
@ -35,7 +35,7 @@ module Inspec
|
||||||
deps.each do |dep|
|
deps.each do |dep|
|
||||||
if seen_items_local.include?(dep.name)
|
if seen_items_local.include?(dep.name)
|
||||||
problem_cookbook = if top_level
|
problem_cookbook = if top_level
|
||||||
'the inspec.yml for this profile.'
|
"the inspec.yml for this profile."
|
||||||
else
|
else
|
||||||
"the dependency information for #{path_string.split(' ').last}"
|
"the dependency information for #{path_string.split(' ').last}"
|
||||||
end
|
end
|
||||||
|
@ -47,7 +47,7 @@ module Inspec
|
||||||
end
|
end
|
||||||
|
|
||||||
# Here deps is an Array of Inspec::Requirement
|
# Here deps is an Array of Inspec::Requirement
|
||||||
def resolve(deps, top_level = true, seen_items = {}, path_string = '') # rubocop:disable Metrics/AbcSize
|
def resolve(deps, top_level = true, seen_items = {}, path_string = "") # rubocop:disable Metrics/AbcSize
|
||||||
graph = {}
|
graph = {}
|
||||||
if top_level
|
if top_level
|
||||||
Inspec::Log.debug("Starting traversal of dependencies #{deps.map(&:to_s)}")
|
Inspec::Log.debug("Starting traversal of dependencies #{deps.map(&:to_s)}")
|
||||||
|
@ -79,7 +79,7 @@ module Inspec
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Inspec::Log.debug('Dependency traversal complete.') if top_level
|
Inspec::Log.debug("Dependency traversal complete.") if top_level
|
||||||
graph
|
graph
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,11 +13,11 @@ module Inspec
|
||||||
def one(&block)
|
def one(&block)
|
||||||
return unless block_given?
|
return unless block_given?
|
||||||
instance_eval(&block)
|
instance_eval(&block)
|
||||||
@action.call('describe.one', @checks, nil)
|
@action.call("describe.one", @checks, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
def describe(*args, &block)
|
def describe(*args, &block)
|
||||||
@checks.push(['describe', args, block])
|
@checks.push(["describe", args, block])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,18 +3,18 @@
|
||||||
module Inspec
|
module Inspec
|
||||||
module Dist
|
module Dist
|
||||||
# When referencing a product directly, like InSpec
|
# When referencing a product directly, like InSpec
|
||||||
PRODUCT_NAME = 'Chef InSpec'
|
PRODUCT_NAME = "Chef InSpec"
|
||||||
|
|
||||||
# The inspec executable
|
# The inspec executable
|
||||||
EXEC_NAME = 'inspec'
|
EXEC_NAME = "inspec"
|
||||||
|
|
||||||
# The name of the server product
|
# The name of the server product
|
||||||
SERVER_PRODUCT_NAME = 'Chef Server'
|
SERVER_PRODUCT_NAME = "Chef Server"
|
||||||
|
|
||||||
# name of the automate product
|
# name of the automate product
|
||||||
AUTOMATE_PRODUCT_NAME = 'Chef Automate'
|
AUTOMATE_PRODUCT_NAME = "Chef Automate"
|
||||||
|
|
||||||
# name of the compliance product
|
# name of the compliance product
|
||||||
COMPLIANCE_PRODUCT_NAME = 'Chef Compliance'
|
COMPLIANCE_PRODUCT_NAME = "Chef Compliance"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# copyright: 2015, Dominik Richter
|
# copyright: 2015, Dominik Richter
|
||||||
require 'inspec/log'
|
require "inspec/log"
|
||||||
require 'inspec/plugin/v2'
|
require "inspec/plugin/v2"
|
||||||
|
|
||||||
module Inspec::DSL
|
module Inspec::DSL
|
||||||
def require_controls(id, &block)
|
def require_controls(id, &block)
|
||||||
|
@ -17,7 +17,7 @@ module Inspec::DSL
|
||||||
alias include_rules include_controls
|
alias include_rules include_controls
|
||||||
|
|
||||||
def require_resource(options = {})
|
def require_resource(options = {})
|
||||||
raise '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
|
from_profile = options[:profile] || profile_name
|
||||||
target_name = options[:as] || options[:resource]
|
target_name = options[:as] || options[:resource]
|
||||||
|
@ -81,7 +81,7 @@ module Inspec::DSL
|
||||||
# remove all rules that were not registered
|
# remove all rules that were not registered
|
||||||
context.all_rules.each do |r|
|
context.all_rules.each do |r|
|
||||||
id = Inspec::Rule.rule_id(r)
|
id = Inspec::Rule.rule_id(r)
|
||||||
fid = Inspec::Rule.profile_id(r) + '/' + id
|
fid = Inspec::Rule.profile_id(r) + "/" + id
|
||||||
unless include_ctx.rules[id] || include_ctx.rules[fid]
|
unless include_ctx.rules[id] || include_ctx.rules[fid]
|
||||||
context.remove_rule(fid)
|
context.remove_rule(fid)
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ module Inspec
|
||||||
alias __ruby_require require
|
alias __ruby_require require
|
||||||
|
|
||||||
def require(path)
|
def require(path)
|
||||||
rbpath = path + '.rb'
|
rbpath = path + ".rb"
|
||||||
return __ruby_require(path) if !@require_loader.exists?(rbpath)
|
return __ruby_require(path) if !@require_loader.exists?(rbpath)
|
||||||
return false if @require_loader.loaded?(rbpath)
|
return false if @require_loader.loaded?(rbpath)
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
require 'inspec/shell_detector'
|
require "inspec/shell_detector"
|
||||||
require 'erb'
|
require "erb"
|
||||||
require 'shellwords'
|
require "shellwords"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
class EnvPrinter
|
class EnvPrinter
|
||||||
attr_reader :shell
|
attr_reader :shell
|
||||||
|
|
||||||
EVAL_COMMANDS = {
|
EVAL_COMMANDS = {
|
||||||
'bash' => 'eval \"$(inspec env bash)\"',
|
"bash" => 'eval \"$(inspec env bash)\"',
|
||||||
'fish' => 'inspec env fish > ~/.config/fish/completions/inspec.fish',
|
"fish" => "inspec env fish > ~/.config/fish/completions/inspec.fish",
|
||||||
'zsh' => 'eval \"$(inspec env zsh)\"',
|
"zsh" => 'eval \"$(inspec env zsh)\"',
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
def initialize(command_class, shell = nil)
|
def initialize(command_class, shell = nil)
|
||||||
|
@ -35,7 +35,7 @@ module Inspec
|
||||||
private
|
private
|
||||||
|
|
||||||
def print_completion_for_shell
|
def print_completion_for_shell
|
||||||
erb = ERB.new(File.read(completion_template_path), nil, '-')
|
erb = ERB.new(File.read(completion_template_path), nil, "-")
|
||||||
puts erb.result(TemplateContext.new(@command_class).get_bindings)
|
puts erb.result(TemplateContext.new(@command_class).get_bindings)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ module Inspec
|
||||||
end
|
end
|
||||||
|
|
||||||
def completion_dir
|
def completion_dir
|
||||||
File.join(File.dirname(__FILE__), 'completions')
|
File.join(File.dirname(__FILE__), "completions")
|
||||||
end
|
end
|
||||||
|
|
||||||
def completion_template_path
|
def completion_template_path
|
||||||
|
@ -56,7 +56,7 @@ module Inspec
|
||||||
end
|
end
|
||||||
|
|
||||||
def shells_with_completions
|
def shells_with_completions
|
||||||
Dir.glob("#{completion_dir}/*.sh.erb").map { |f| File.basename(f, '.sh.erb') }
|
Dir.glob("#{completion_dir}/*.sh.erb").map { |f| File.basename(f, ".sh.erb") }
|
||||||
end
|
end
|
||||||
|
|
||||||
def print_usage_guidance
|
def print_usage_guidance
|
||||||
|
@ -90,7 +90,7 @@ module Inspec
|
||||||
|
|
||||||
def exit_no_shell
|
def exit_no_shell
|
||||||
if @detected
|
if @detected
|
||||||
$stderr.puts '# Unable to automatically detect shell and no shell was provided.'
|
$stderr.puts "# Unable to automatically detect shell and no shell was provided."
|
||||||
end
|
end
|
||||||
$stderr.puts <<~EOF
|
$stderr.puts <<~EOF
|
||||||
#
|
#
|
||||||
|
@ -108,7 +108,7 @@ module Inspec
|
||||||
@command_class = command_class
|
@command_class = command_class
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_bindings # rubocop:disable Style/AccessorMethodName
|
def get_bindings # rubocop:disable Naming/AccessorMethodName
|
||||||
binding
|
binding
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# copyright: 2016, Chef Software Inc.
|
# copyright: 2016, Chef Software Inc.
|
||||||
|
|
||||||
require 'rspec/expectations'
|
require "rspec/expectations"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
class Expect
|
class Expect
|
||||||
|
@ -22,11 +22,11 @@ module Inspec
|
||||||
def example_group
|
def example_group
|
||||||
that = self
|
that = self
|
||||||
|
|
||||||
opts = { 'caller' => calls[0][3] } # TODO: this needs overhaul. no magic #s
|
opts = { "caller" => calls[0][3] } # TODO: this needs overhaul. no magic #s
|
||||||
if !calls[0][3].nil? && !calls[0][3].empty? &&
|
if !calls[0][3].nil? && !calls[0][3].empty? &&
|
||||||
(m = calls[0][3][0].match(/^([^:]*):(\d+):/))
|
(m = calls[0][3][0].match(/^([^:]*):(\d+):/))
|
||||||
opts['file_path'] = m[0]
|
opts["file_path"] = m[0]
|
||||||
opts['line_number'] = m[1]
|
opts["line_number"] = m[1]
|
||||||
end
|
end
|
||||||
|
|
||||||
RSpec::Core::ExampleGroup.describe(that.value, opts) do
|
RSpec::Core::ExampleGroup.describe(that.value, opts) do
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require 'inspec/plugin/v1'
|
require "inspec/plugin/v1"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
class FetcherRegistry < PluginRegistry
|
class FetcherRegistry < PluginRegistry
|
||||||
|
@ -29,15 +29,16 @@ module Inspec
|
||||||
|
|
||||||
def self.fetcher(version)
|
def self.fetcher(version)
|
||||||
if version != 1
|
if version != 1
|
||||||
raise 'Only fetcher version 1 is supported!'
|
raise "Only fetcher version 1 is supported!"
|
||||||
end
|
end
|
||||||
Inspec::Plugins::Fetcher
|
Inspec::Plugins::Fetcher
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'fetchers/local'
|
# TODO: remove. require up, not down.
|
||||||
require 'fetchers/url'
|
require "fetchers/local"
|
||||||
require 'fetchers/git'
|
require "fetchers/url"
|
||||||
|
require "fetchers/git"
|
||||||
|
|
||||||
# TODO: Remove in 4.0 when Compliance fetcher plugin is created
|
# TODO: Remove in 4.0 when Compliance fetcher plugin is created
|
||||||
require 'plugins/inspec-compliance/lib/inspec-compliance/api'
|
require "plugins/inspec-compliance/lib/inspec-compliance/api"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
require 'rubygems/package'
|
require "rubygems/package"
|
||||||
require 'zlib'
|
require "pathname"
|
||||||
require 'zip'
|
require "zlib"
|
||||||
|
require "zip"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
class FileProvider
|
class FileProvider
|
||||||
|
@ -9,9 +10,9 @@ module Inspec
|
||||||
MockProvider.new(path)
|
MockProvider.new(path)
|
||||||
elsif File.directory?(path)
|
elsif File.directory?(path)
|
||||||
DirProvider.new(path)
|
DirProvider.new(path)
|
||||||
elsif File.exist?(path) && path.end_with?('.tar.gz', 'tgz')
|
elsif File.exist?(path) && path.end_with?(".tar.gz", "tgz")
|
||||||
TarProvider.new(path)
|
TarProvider.new(path)
|
||||||
elsif File.exist?(path) && path.end_with?('.zip')
|
elsif File.exist?(path) && path.end_with?(".zip")
|
||||||
ZipProvider.new(path)
|
ZipProvider.new(path)
|
||||||
elsif File.exist?(path)
|
elsif File.exist?(path)
|
||||||
DirProvider.new(path)
|
DirProvider.new(path)
|
||||||
|
@ -71,7 +72,7 @@ module Inspec
|
||||||
@files = if File.file?(path)
|
@files = if File.file?(path)
|
||||||
[path]
|
[path]
|
||||||
else
|
else
|
||||||
Dir[File.join(Shellwords.shellescape(path), '**', '*')]
|
Dir[File.join(Shellwords.shellescape(path), "**", "*")]
|
||||||
end
|
end
|
||||||
@path = path
|
@path = path
|
||||||
end
|
end
|
||||||
|
@ -98,13 +99,13 @@ module Inspec
|
||||||
@files = []
|
@files = []
|
||||||
walk_zip(@path) do |io|
|
walk_zip(@path) do |io|
|
||||||
while (entry = io.get_next_entry)
|
while (entry = io.get_next_entry)
|
||||||
name = entry.name.sub(%r{/+$}, '')
|
name = entry.name.sub(%r{/+$}, "")
|
||||||
@files.push(name) unless name.empty? || name.squeeze('/') =~ %r{\.{2}(?:/|\z)}
|
@files.push(name) unless name.empty? || name.squeeze("/") =~ %r{\.{2}(?:/|\z)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract(destination_path = '.')
|
def extract(destination_path = ".")
|
||||||
FileUtils.mkdir_p(destination_path)
|
FileUtils.mkdir_p(destination_path)
|
||||||
|
|
||||||
Zip::File.open(@path) do |archive|
|
Zip::File.open(@path) do |archive|
|
||||||
|
@ -155,17 +156,17 @@ module Inspec
|
||||||
@files = tar.find_all(&:file?)
|
@files = tar.find_all(&:file?)
|
||||||
|
|
||||||
# delete all entries with no name
|
# delete all entries with no name
|
||||||
@files = @files.find_all { |x| !x.full_name.empty? && x.full_name.squeeze('/') !~ %r{\.{2}(?:/|\z)} }
|
@files = @files.find_all { |x| !x.full_name.empty? && x.full_name.squeeze("/") !~ %r{\.{2}(?:/|\z)} }
|
||||||
|
|
||||||
# delete all entries that have a PaxHeader
|
# delete all entries that have a PaxHeader
|
||||||
@files = @files.delete_if { |x| x.full_name.include?('PaxHeader/') }
|
@files = @files.delete_if { |x| x.full_name.include?("PaxHeader/") }
|
||||||
|
|
||||||
# replace all items of the array simply with the relative filename of the file
|
# replace all items of the array simply with the relative filename of the file
|
||||||
@files.map! { |x| Pathname.new(x.full_name).relative_path_from(Pathname.new('.')).to_s }
|
@files.map! { |x| Pathname.new(x.full_name).relative_path_from(Pathname.new(".")).to_s }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def extract(destination_path = '.')
|
def extract(destination_path = ".")
|
||||||
FileUtils.mkdir_p(destination_path)
|
FileUtils.mkdir_p(destination_path)
|
||||||
|
|
||||||
walk_tar(@path) do |files|
|
walk_tar(@path) do |files|
|
||||||
|
@ -178,7 +179,7 @@ module Inspec
|
||||||
FileUtils.remove_entry(final_path) if File.exist?(final_path)
|
FileUtils.remove_entry(final_path) if File.exist?(final_path)
|
||||||
|
|
||||||
FileUtils.mkdir_p(File.dirname(final_path))
|
FileUtils.mkdir_p(File.dirname(final_path))
|
||||||
File.open(final_path, 'wb') { |f| f.write(file.read) }
|
File.open(final_path, "wb") { |f| f.write(file.read) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -213,8 +214,8 @@ module Inspec
|
||||||
|
|
||||||
class RelativeFileProvider
|
class RelativeFileProvider
|
||||||
BLACKLIST_FILES = [
|
BLACKLIST_FILES = [
|
||||||
'/pax_global_header',
|
"/pax_global_header",
|
||||||
'pax_global_header',
|
"pax_global_header",
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
attr_reader :files
|
attr_reader :files
|
||||||
|
@ -238,7 +239,7 @@ module Inspec
|
||||||
.map { |x| x[prefix.length..-1] }
|
.map { |x| x[prefix.length..-1] }
|
||||||
.map do |x|
|
.map do |x|
|
||||||
path = Pathname.new(x)
|
path = Pathname.new(x)
|
||||||
path.absolute? ? path.to_s : path.relative_path_from(Pathname.new('.')).to_s
|
path.absolute? ? path.to_s : path.relative_path_from(Pathname.new(".")).to_s
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -258,7 +259,7 @@ module Inspec
|
||||||
private
|
private
|
||||||
|
|
||||||
def get_prefix(fs)
|
def get_prefix(fs)
|
||||||
return '' if fs.empty?
|
return "" if fs.empty?
|
||||||
|
|
||||||
# filter backlisted files
|
# filter backlisted files
|
||||||
fs -= BLACKLIST_FILES
|
fs -= BLACKLIST_FILES
|
||||||
|
@ -287,15 +288,15 @@ module Inspec
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_files_prefix(fs)
|
def get_files_prefix(fs)
|
||||||
return '' if fs.empty?
|
return "" if fs.empty?
|
||||||
|
|
||||||
file = fs[0]
|
file = fs[0]
|
||||||
bn = File.basename(file)
|
bn = File.basename(file)
|
||||||
# no more prefixes
|
# no more prefixes
|
||||||
return '' if bn == file
|
return "" if bn == file
|
||||||
|
|
||||||
i = file.rindex(bn)
|
i = file.rindex(bn)
|
||||||
pre = file[0..i-1]
|
pre = file[0..i - 1]
|
||||||
|
|
||||||
rest = fs.find_all { |f| !f.start_with?(pre) }
|
rest = fs.find_all { |f| !f.start_with?(pre) }
|
||||||
return pre if rest.empty?
|
return pre if rest.empty?
|
||||||
|
@ -303,8 +304,8 @@ module Inspec
|
||||||
new_pre = get_prefix(rest)
|
new_pre = get_prefix(rest)
|
||||||
return new_pre if pre.start_with? new_pre
|
return new_pre if pre.start_with? new_pre
|
||||||
# edge case: completely different prefixes; retry prefix detection
|
# edge case: completely different prefixes; retry prefix detection
|
||||||
a = File.dirname(pre + 'a')
|
a = File.dirname(pre + "a")
|
||||||
b = File.dirname(new_pre + 'b')
|
b = File.dirname(new_pre + "b")
|
||||||
get_prefix([a, b])
|
get_prefix([a, b])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
require 'inspec/formatters/base'
|
require "inspec/formatters/base"
|
||||||
require 'inspec/formatters/json_rspec'
|
require "inspec/formatters/json_rspec"
|
||||||
require 'inspec/formatters/show_progress'
|
require "inspec/formatters/show_progress"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'rspec/core'
|
require "rspec/core"
|
||||||
require 'rspec/core/formatters/base_formatter'
|
require "rspec/core/formatters/base_formatter"
|
||||||
|
|
||||||
module Inspec::Formatters
|
module Inspec::Formatters
|
||||||
class Base < RSpec::Core::Formatters::BaseFormatter
|
class Base < RSpec::Core::Formatters::BaseFormatter
|
||||||
|
@ -43,7 +43,7 @@ module Inspec::Formatters
|
||||||
next unless e
|
next unless e
|
||||||
|
|
||||||
if example.metadata[:sensitive]
|
if example.metadata[:sensitive]
|
||||||
hash[:message] = '*** sensitive output suppressed ***'
|
hash[:message] = "*** sensitive output suppressed ***"
|
||||||
else
|
else
|
||||||
hash[:message] = exception_message(e)
|
hash[:message] = exception_message(e)
|
||||||
end
|
end
|
||||||
|
@ -101,9 +101,9 @@ module Inspec::Formatters
|
||||||
|
|
||||||
all_unique_controls.each do |control|
|
all_unique_controls.each do |control|
|
||||||
next unless control[:results]
|
next unless control[:results]
|
||||||
if control[:results].any? { |r| r[:status] == 'failed' }
|
if control[:results].any? { |r| r[:status] == "failed" }
|
||||||
failed += 1
|
failed += 1
|
||||||
elsif control[:results].any? { |r| r[:status] == 'skipped' }
|
elsif control[:results].any? { |r| r[:status] == "skipped" }
|
||||||
skipped += 1
|
skipped += 1
|
||||||
else
|
else
|
||||||
passed += 1
|
passed += 1
|
||||||
|
@ -162,8 +162,8 @@ module Inspec::Formatters
|
||||||
res[:profile_id] = pid
|
res[:profile_id] = pid
|
||||||
end
|
end
|
||||||
|
|
||||||
if res[:status] == 'pending'
|
if res[:status] == "pending"
|
||||||
res[:status] = 'skipped'
|
res[:status] = "skipped"
|
||||||
res[:skip_message] = example.metadata[:description]
|
res[:skip_message] = example.metadata[:description]
|
||||||
res[:resource] = example.metadata[:described_class].to_s
|
res[:resource] = example.metadata[:described_class].to_s
|
||||||
end
|
end
|
||||||
|
@ -173,7 +173,7 @@ module Inspec::Formatters
|
||||||
|
|
||||||
def format_expectation_message(example)
|
def format_expectation_message(example)
|
||||||
if (example.metadata[:example_group][:description_args].first == example.metadata[:example_group][:described_class]) ||
|
if (example.metadata[:example_group][:description_args].first == example.metadata[:example_group][:described_class]) ||
|
||||||
example.metadata[:example_group][:described_class].nil?
|
example.metadata[:example_group][:described_class].nil?
|
||||||
example.metadata[:description]
|
example.metadata[:description]
|
||||||
else
|
else
|
||||||
"#{example.metadata[:example_group][:description]} #{example.metadata[:description]}"
|
"#{example.metadata[:example_group][:description]} #{example.metadata[:description]}"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
module Inspec
|
module Inspec
|
||||||
def self.config_dir
|
def self.config_dir
|
||||||
ENV['INSPEC_CONFIG_DIR'] ? ENV['INSPEC_CONFIG_DIR'] : File.join(Dir.home, '.inspec')
|
ENV["INSPEC_CONFIG_DIR"] ? ENV["INSPEC_CONFIG_DIR"] : File.join(Dir.home, ".inspec")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.src_root
|
def self.src_root
|
||||||
File.expand_path(File.join(__FILE__, '..', '..', '..'))
|
File.expand_path(File.join(__FILE__, "..", "..", ".."))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
# Impact scores based off CVSS 3.0
|
# Impact scores based off CVSS 3.0
|
||||||
module Inspec::Impact
|
module Inspec::Impact
|
||||||
IMPACT_SCORES = {
|
IMPACT_SCORES = {
|
||||||
'none' => 0.0,
|
"none" => 0.0,
|
||||||
'low' => 0.1,
|
"low" => 0.1,
|
||||||
'medium' => 0.4,
|
"medium" => 0.4,
|
||||||
'high' => 0.7,
|
"high" => 0.7,
|
||||||
'critical' => 0.9,
|
"critical" => 0.9,
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
def self.impact_from_string(value)
|
def self.impact_from_string(value)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
require 'forwardable'
|
require "forwardable"
|
||||||
require 'singleton'
|
require "singleton"
|
||||||
require 'inspec/objects/input'
|
require "inspec/objects/input"
|
||||||
require 'inspec/secrets'
|
require "inspec/secrets"
|
||||||
require 'inspec/exceptions'
|
require "inspec/exceptions"
|
||||||
|
require "inspec/plugin/v2"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
# The InputRegistry's responsibilities include:
|
# The InputRegistry's responsibilities include:
|
||||||
|
@ -12,7 +13,7 @@ module Inspec
|
||||||
include Singleton
|
include Singleton
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
|
|
||||||
attr_reader :inputs_by_profile, :profile_aliases
|
attr_reader :inputs_by_profile, :profile_aliases, :plugins
|
||||||
def_delegator :inputs_by_profile, :each
|
def_delegator :inputs_by_profile, :each
|
||||||
def_delegator :inputs_by_profile, :[]
|
def_delegator :inputs_by_profile, :[]
|
||||||
def_delegator :inputs_by_profile, :key?, :profile_known?
|
def_delegator :inputs_by_profile, :key?, :profile_known?
|
||||||
|
@ -25,6 +26,14 @@ module Inspec
|
||||||
|
|
||||||
# this is a list of optional profile name overrides set in the inspec.yml
|
# this is a list of optional profile name overrides set in the inspec.yml
|
||||||
@profile_aliases = {}
|
@profile_aliases = {}
|
||||||
|
|
||||||
|
# Upon creation, activate all input plugins
|
||||||
|
activators = Inspec::Plugin::V2::Registry.instance.find_activators(plugin_type: :input)
|
||||||
|
|
||||||
|
@plugins = activators.map do |activator|
|
||||||
|
activator.activate!
|
||||||
|
activator.implementation_class.new
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#-------------------------------------------------------------#
|
#-------------------------------------------------------------#
|
||||||
|
@ -35,32 +44,58 @@ module Inspec
|
||||||
@profile_aliases[name] = alias_name
|
@profile_aliases[name] = alias_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns an Hash, name => Input that have actually been mentioned
|
||||||
def list_inputs_for_profile(profile)
|
def list_inputs_for_profile(profile)
|
||||||
inputs_by_profile[profile] = {} unless profile_known?(profile)
|
inputs_by_profile[profile] = {} unless profile_known?(profile)
|
||||||
inputs_by_profile[profile]
|
inputs_by_profile[profile]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns an Array of input names. This includes input names
|
||||||
|
# that plugins may be able to fetch, but have not actually been
|
||||||
|
# mentioned in the control code.
|
||||||
|
def list_potential_input_names_for_profile(profile_name)
|
||||||
|
input_names_from_dsl = inputs_by_profile[profile_name].keys
|
||||||
|
input_names_from_plugins = plugins.map { |plugin| plugin.list_inputs(profile_name) }
|
||||||
|
(input_names_from_dsl + input_names_from_plugins).flatten.uniq
|
||||||
|
end
|
||||||
|
|
||||||
#-------------------------------------------------------------#
|
#-------------------------------------------------------------#
|
||||||
# Support for Individual Inputs
|
# Support for Individual Inputs
|
||||||
#-------------------------------------------------------------#
|
#-------------------------------------------------------------#
|
||||||
|
|
||||||
def find_or_register_input(input_name, profile_name, options = {})
|
def find_or_register_input(input_name, profile_name, options = {})
|
||||||
if profile_alias?(profile_name)
|
if profile_alias?(profile_name) && !profile_aliases[profile_name].nil?
|
||||||
alias_name = profile_name
|
alias_name = profile_name
|
||||||
profile_name = profile_aliases[profile_name]
|
profile_name = profile_aliases[profile_name]
|
||||||
handle_late_arriving_alias(alias_name, profile_name) if profile_known?(alias_name)
|
handle_late_arriving_alias(alias_name, profile_name) if profile_known?(alias_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Find or create the input
|
||||||
inputs_by_profile[profile_name] ||= {}
|
inputs_by_profile[profile_name] ||= {}
|
||||||
if inputs_by_profile[profile_name].key?(input_name)
|
if inputs_by_profile[profile_name].key?(input_name)
|
||||||
inputs_by_profile[profile_name][input_name].update(options)
|
inputs_by_profile[profile_name][input_name].update(options)
|
||||||
else
|
else
|
||||||
inputs_by_profile[profile_name][input_name] = Inspec::Input.new(input_name, options)
|
inputs_by_profile[profile_name][input_name] = Inspec::Input.new(input_name, options)
|
||||||
|
poll_plugins_for_update(profile_name, input_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
inputs_by_profile[profile_name][input_name]
|
inputs_by_profile[profile_name][input_name]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def poll_plugins_for_update(profile_name, input_name)
|
||||||
|
plugins.each do |plugin|
|
||||||
|
response = plugin.fetch(profile_name, input_name)
|
||||||
|
evt = Inspec::Input::Event.new(
|
||||||
|
action: :fetch,
|
||||||
|
provider: plugin.class.plugin_name,
|
||||||
|
priority: plugin.default_priority,
|
||||||
|
hit: !response.nil?
|
||||||
|
)
|
||||||
|
evt.value = response unless response.nil?
|
||||||
|
inputs_by_profile[profile_name][input_name].events << evt
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# It is possible for a wrapper profile to create an input in metadata,
|
# It is possible for a wrapper profile to create an input in metadata,
|
||||||
# referring to the child profile by an alias that has not yet been registered.
|
# referring to the child profile by an alias that has not yet been registered.
|
||||||
# The registry will then store the inputs under the alias, as if the alias
|
# The registry will then store the inputs under the alias, as if the alias
|
||||||
|
@ -115,7 +150,7 @@ module Inspec
|
||||||
provider: :runner_api, # TODO: suss out if audit cookbook or kitchen-inspec or something unknown
|
provider: :runner_api, # TODO: suss out if audit cookbook or kitchen-inspec or something unknown
|
||||||
priority: 40,
|
priority: 40,
|
||||||
file: loc.path,
|
file: loc.path,
|
||||||
line: loc.lineno,
|
line: loc.lineno
|
||||||
)
|
)
|
||||||
find_or_register_input(input_name, profile_name, event: evt)
|
find_or_register_input(input_name, profile_name, event: evt)
|
||||||
end
|
end
|
||||||
|
@ -135,7 +170,7 @@ module Inspec
|
||||||
if data.nil?
|
if data.nil?
|
||||||
raise Inspec::Exceptions::SecretsBackendNotFound,
|
raise Inspec::Exceptions::SecretsBackendNotFound,
|
||||||
"Cannot find parser for inputs file '#{path}'. " \
|
"Cannot find parser for inputs file '#{path}'. " \
|
||||||
'Check to make sure file has the appropriate extension.'
|
"Check to make sure file has the appropriate extension."
|
||||||
end
|
end
|
||||||
|
|
||||||
next if data.inputs.nil?
|
next if data.inputs.nil?
|
||||||
|
@ -144,7 +179,7 @@ module Inspec
|
||||||
value: input_value,
|
value: input_value,
|
||||||
provider: :cli_files,
|
provider: :cli_files,
|
||||||
priority: 40,
|
priority: 40,
|
||||||
file: path,
|
file: path
|
||||||
# TODO: any way we could get a line number?
|
# TODO: any way we could get a line number?
|
||||||
)
|
)
|
||||||
find_or_register_input(input_name, profile_name, event: evt)
|
find_or_register_input(input_name, profile_name, event: evt)
|
||||||
|
@ -156,13 +191,13 @@ module Inspec
|
||||||
unless File.exist?(path)
|
unless File.exist?(path)
|
||||||
raise Inspec::Exceptions::InputsFileDoesNotExist,
|
raise Inspec::Exceptions::InputsFileDoesNotExist,
|
||||||
"Cannot find input file '#{path}'. " \
|
"Cannot find input file '#{path}'. " \
|
||||||
'Check to make sure file exists.'
|
"Check to make sure file exists."
|
||||||
end
|
end
|
||||||
|
|
||||||
unless File.readable?(path)
|
unless File.readable?(path)
|
||||||
raise Inspec::Exceptions::InputsFileNotReadable,
|
raise Inspec::Exceptions::InputsFileNotReadable,
|
||||||
"Cannot read input file '#{path}'. " \
|
"Cannot read input file '#{path}'. " \
|
||||||
'Check to make sure file is readable.'
|
"Check to make sure file is readable."
|
||||||
end
|
end
|
||||||
|
|
||||||
true
|
true
|
||||||
|
@ -170,31 +205,46 @@ module Inspec
|
||||||
|
|
||||||
def bind_inputs_from_metadata(profile_name, profile_metadata_obj)
|
def bind_inputs_from_metadata(profile_name, profile_metadata_obj)
|
||||||
# TODO: move this into a core plugin
|
# TODO: move this into a core plugin
|
||||||
# TODO: add deprecation stuff
|
|
||||||
return if profile_metadata_obj.nil? # Metadata files are technically optional
|
return if profile_metadata_obj.nil? # Metadata files are technically optional
|
||||||
|
|
||||||
if profile_metadata_obj.params.key?(:attributes) && profile_metadata_obj.params[:attributes].is_a?(Array)
|
if profile_metadata_obj.params.key?(:inputs)
|
||||||
profile_metadata_obj.params[:attributes].each do |input_orig|
|
raw_inputs = profile_metadata_obj.params[:inputs]
|
||||||
input_options = input_orig.dup
|
|
||||||
input_name = input_options.delete(:name)
|
|
||||||
input_options.merge!({ priority: 30, provider: :profile_metadata, file: File.join(profile_name, 'inspec.yml') })
|
|
||||||
evt = Inspec::Input.infer_event(input_options)
|
|
||||||
|
|
||||||
# Profile metadata may set inputs in other profiles by naming them.
|
|
||||||
if input_options[:profile]
|
|
||||||
profile_name = input_options[:profile] || profile_name
|
|
||||||
# Override priority to force this to win. Allow user to set their own priority.
|
|
||||||
evt.priority = input_orig[:priority] || 35
|
|
||||||
end
|
|
||||||
find_or_register_input(input_name,
|
|
||||||
profile_name,
|
|
||||||
type: input_options[:type],
|
|
||||||
required: input_options[:required],
|
|
||||||
event: evt)
|
|
||||||
end
|
|
||||||
elsif profile_metadata_obj.params.key?(:attributes)
|
elsif profile_metadata_obj.params.key?(:attributes)
|
||||||
Inspec::Log.warn 'Inputs must be defined as an Array. Skipping current definition.'
|
Inspec.deprecate(:attrs_rename_in_metadata, "Profile: '#{profile_name}'.")
|
||||||
|
raw_inputs = profile_metadata_obj.params[:attributes]
|
||||||
|
else
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
unless raw_inputs.is_a?(Array)
|
||||||
|
Inspec::Log.warn "Inputs must be defined as an Array in metadata files. Skipping definition from #{profile_name}."
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
raw_inputs.each { |i| handle_raw_input_from_metadata(i, profile_name) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_raw_input_from_metadata(input_orig, profile_name)
|
||||||
|
input_options = input_orig.dup
|
||||||
|
input_name = input_options.delete(:name)
|
||||||
|
input_options[:provider] = :profile_metadata
|
||||||
|
input_options[:file] = File.join(profile_name, "inspec.yml")
|
||||||
|
input_options[:priority] ||= 30
|
||||||
|
evt = Inspec::Input.infer_event(input_options)
|
||||||
|
|
||||||
|
# Profile metadata may set inputs in other profiles by naming them.
|
||||||
|
if input_options[:profile]
|
||||||
|
profile_name = input_options[:profile] || profile_name
|
||||||
|
# Override priority to force this to win. Allow user to set their own priority.
|
||||||
|
evt.priority = input_orig[:priority] || 35
|
||||||
|
end
|
||||||
|
find_or_register_input(
|
||||||
|
input_name,
|
||||||
|
profile_name,
|
||||||
|
type: input_options[:type],
|
||||||
|
required: input_options[:required],
|
||||||
|
event: evt
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
#-------------------------------------------------------------#
|
#-------------------------------------------------------------#
|
||||||
|
@ -214,6 +264,7 @@ module Inspec
|
||||||
:find_or_register_input,
|
:find_or_register_input,
|
||||||
:register_profile_alias,
|
:register_profile_alias,
|
||||||
:list_inputs_for_profile,
|
:list_inputs_for_profile,
|
||||||
|
:list_potential_input_names_for_profile,
|
||||||
:bind_profile_inputs,
|
:bind_profile_inputs,
|
||||||
].each do |meth|
|
].each do |meth|
|
||||||
define_singleton_method(meth) do |*args|
|
define_singleton_method(meth) do |*args|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
require 'inspec/plugin/v1/plugin_types/resource'
|
require "inspec/plugin/v1/plugin_types/resource"
|
||||||
require 'inspec/dsl_shared'
|
require "inspec/dsl_shared"
|
||||||
|
|
||||||
module Inspec
|
module Inspec
|
||||||
#
|
#
|
||||||
|
@ -48,7 +48,7 @@ module Inspec
|
||||||
# Provide the local binding for this context which is necessary for
|
# Provide the local binding for this context which is necessary for
|
||||||
# calls to `require` to create all dependent objects in the correct
|
# calls to `require` to create all dependent objects in the correct
|
||||||
# context.
|
# context.
|
||||||
res.instance_variable_set('@inspec_binding', res.instance_eval('binding'))
|
res.instance_variable_set("@inspec_binding", res.instance_eval("binding"))
|
||||||
res
|
res
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue