Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inspec check and json to use vendored dependencies #1321

Merged
merged 3 commits into from
Nov 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/meta-profile/inspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ summary: InSpec Profile that is only consuming dependencies
version: 0.2.0
depends:
- name: hardening/ssh-hardening # defaults to supermarket
- git: https://github.com/dev-sec/ssl-benchmark.git
- url: https://github.com/dev-sec/ssl-benchmark
- name: windows-patch-benchmark
git: https://github.com/chris-rock/windows-patch-benchmark.git
url: https://github.com/chris-rock/windows-patch-benchmark
3 changes: 2 additions & 1 deletion lib/inspec/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
def json(target)
diagnose
o = opts.dup
configure_logger(o)
o[:ignore_supports] = true
o[:backend] = Inspec::Backend.create(target: 'mock://')

Expand All @@ -59,7 +60,7 @@ def json(target)
def check(path) # rubocop:disable Metrics/AbcSize
diagnose
o = opts.dup
# configure_logger(o) # we do not need a logger for check yet
configure_logger(o)
o[:ignore_supports] = true # we check for integrity only
o[:backend] = Inspec::Backend.create(target: 'mock://')

Expand Down
9 changes: 5 additions & 4 deletions lib/inspec/profile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@ module Inspec
class Profile # rubocop:disable Metrics/ClassLength
extend Forwardable

def self.resolve_target(target, cache = nil)
c = cache || Cache.new
Inspec::Log.debug "Resolve #{target} into cache #{c.path}"
Inspec::CachedFetcher.new(target, cache || Cache.new)
def self.resolve_target(target, cache)
Inspec::Log.debug "Resolve #{target} into cache #{cache.path}"
Inspec::CachedFetcher.new(target, cache)
end

# Check if the profile contains a vendored cache, move content into global cache
Expand Down Expand Up @@ -65,11 +64,13 @@ def self.for_path(path, opts)
end

def self.for_fetcher(fetcher, opts)
opts[:cache] = opts[:cache] || Cache.new
path, writable = fetcher.fetch
for_path(path, opts.merge(target: fetcher.target, writable: writable))
end

def self.for_target(target, opts = {})
opts[:cache] = opts[:cache] || Cache.new
fetcher = resolve_target(target, opts[:cache])
for_fetcher(fetcher, opts)
end
Expand Down
63 changes: 60 additions & 3 deletions test/functional/inspec_vendor_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
end

it 'can vendor profile dependencies from the profile path' do
# clean existing vendor directory
FileUtils.rm_r ("#{inheritance_path}/vendor")

# vendor all dependencies
out = inspec('vendor --overwrite', "cd #{inheritance_path} &&")
out.stdout.force_encoding(Encoding::UTF_8).must_include "Vendor dependencies of #{inheritance_path} into #{inheritance_path}/vendor"
out.stderr.must_equal ''
Expand All @@ -34,6 +38,10 @@
end

it 'ensure nothing is loaded from external source if vendored profile is used' do
# clean existing vendor directory
FileUtils.rm_r ("#{meta_path}/vendor")

# vendor all dependencies
out = inspec('vendor ' + meta_path + ' --overwrite')
out.exit_status.must_equal 0

Expand All @@ -44,19 +52,68 @@
File.exist?(lockfile).must_equal true

out = inspec('exec ' + meta_path + ' -l debug --no-create-lockfile')
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:url=>"https://github.com/dev-sec/tests-ssh-hardening/archive/master.tar.gz", :sha256=>"01414bd307ea2f7d4dc8cd141085ba7ad61d4c3b2606d57b2dae987c1c3954cb"'
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:git=>"https://github.com/dev-sec/ssl-benchmark.git", :ref=>"e17486c864434c818f96ca13edd2c5a420100a45"'
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:git=>"https://github.com/chris-rock/windows-patch-benchmark.git", :ref=>"c183d08eb25638e7f5eac97e521640ea314c8e3d"'
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:url=>"https://github.com/dev-sec/tests-ssh-hardening/archive/master.tar.gz"'
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:url=>"https://github.com/dev-sec/ssl-benchmark/archive/master.tar.gz"'
out.stdout.force_encoding(Encoding::UTF_8).must_include 'Using cached dependency for {:url=>"https://github.com/chris-rock/windows-patch-benchmark/archive/master.tar.gz"'
out.stdout.force_encoding(Encoding::UTF_8).index('Fetching URL:').must_be_nil
out.stdout.force_encoding(Encoding::UTF_8).index('Fetched archive moved to:').must_be_nil

out.stderr.must_equal ''
end

it 'ensure json command is not fetching remote profiles if vendored' do
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good test for this would be to check that the vendored profile(ex: 01414bd307ea2f7d4dc8cd141085ba7ad61d4c3b2606d57b2dae987c1c3954cb.tar.gz was copied in the cache) instead of a remote one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in length is 1 and that profile is 01414bd307ea2f7d4dc8cd141085ba7ad61d4c3b2606d57b2dae987c1c3954cb.tar.gz

# ensure the profile is vendored
out = inspec('vendor ' + meta_path + ' --overwrite')

# clean cache directory
FileUtils.rm_rf "#{Dir.home}/.inspec/cache"

# execute json command
out = inspec('json ' + meta_path + ' -l debug')
out.exit_status.must_equal 0

copies = out.stdout.scan(/Copy .* to cache directory/).length
copies.must_equal 3

length = out.stdout.scan(/Dependency does not exist in the cache/).length
length.must_equal 1
end

it 'ensure check command is not fetching remote profiles if vendored' do
# ensure the profile is vendored
out = inspec('vendor ' + meta_path + ' --overwrite')

# clean cache directory
FileUtils.rm_rf "#{Dir.home}/.inspec/cache"

# execute check command
out = inspec('check ' + meta_path + ' -l debug')
out.exit_status.must_equal 0

copies = out.stdout.scan(/Copy .* to cache directory/).length
copies.must_equal 3

length = out.stdout.scan(/Dependency does not exist in the cache/).length
length.must_equal 1
end

it 'ensure json command works for vendored profile' do
out = inspec('json ' + meta_path + ' --output ' + dst.path)
hm = JSON.load(File.read(dst.path))
hm['name'].must_equal 'meta-profile'
hm['controls'].length.must_equal 79
end

it 'can vendor profile dependencies from the profile path' do
out = inspec('vendor --overwrite', "cd #{inheritance_path} &&")
out.stdout.force_encoding(Encoding::UTF_8).must_include "Vendor dependencies of #{inheritance_path} into #{inheritance_path}/vendor"
out.stderr.must_equal ''
out.exit_status.must_equal 0

vendor_dir = File.join(inheritance_path, 'vendor')
File.exist?(vendor_dir).must_equal true

lockfile = File.join(inheritance_path, 'inspec.lock')
File.exist?(lockfile).must_equal true
end
end