From b0ab35d941f2d641d08ecd347b9ae0619266ad41 Mon Sep 17 00:00:00 2001 From: Christoph Hartmann Date: Thu, 18 May 2017 14:20:10 +0200 Subject: [PATCH] throw an error during inspec check if the version is not correct Signed-off-by: Christoph Hartmann --- inspec.gemspec | 1 + lib/inspec/metadata.rb | 14 +++++ .../mock/profiles/invalid-version/inspec.yml | 8 +++ test/unit/profiles/metadata_test.rb | 14 +++++ test/unit/profiles/profile_test.rb | 51 +++++++++++++++++++ 5 files changed, 88 insertions(+) create mode 100644 test/unit/mock/profiles/invalid-version/inspec.yml diff --git a/inspec.gemspec b/inspec.gemspec index 6e32a7b10..d09cb627b 100644 --- a/inspec.gemspec +++ b/inspec.gemspec @@ -43,4 +43,5 @@ Gem::Specification.new do |spec| spec.add_dependency 'toml', '~> 0.1' spec.add_dependency 'addressable', '~> 2.4' spec.add_dependency 'parslet', '~> 1.5' + spec.add_dependency 'semverse' end diff --git a/lib/inspec/metadata.rb b/lib/inspec/metadata.rb index 52a765eaf..903cad356 100644 --- a/lib/inspec/metadata.rb +++ b/lib/inspec/metadata.rb @@ -6,6 +6,7 @@ require 'logger' require 'rubygems/version' require 'rubygems/requirement' +require 'semverse' module Inspec # Extract metadata.rb information @@ -109,6 +110,12 @@ module Inspec next unless params[field.to_sym].nil? errors.push("Missing profile #{field} in #{ref}") end + + # if version is set, ensure it is correct + if !params[:version].nil? && !valid_version?(params[:version]) + errors.push('Version needs to be in SemVer format') + end + %w{ title summary maintainer copyright }.each do |field| next unless params[field.to_sym].nil? warnings.push("Missing profile #{field} in #{ref}") @@ -123,6 +130,13 @@ module Inspec errors.empty? && unsupported.empty? end + def valid_version?(value) + Semverse::Version.new(value) + true + rescue Semverse::InvalidVersionFormat + false + end + def method_missing(sth, *args) @logger.warn "#{ref} doesn't support: #{sth} #{args}" @missing_methods.push(sth) diff --git a/test/unit/mock/profiles/invalid-version/inspec.yml b/test/unit/mock/profiles/invalid-version/inspec.yml new file mode 100644 index 000000000..75001b6b9 --- /dev/null +++ b/test/unit/mock/profiles/invalid-version/inspec.yml @@ -0,0 +1,8 @@ +name: invalid-version +title: InSpec Profile +maintainer: The Authors +copyright: The Authors +copyright_email: you@example.com +license: All Rights Reserved +summary: An InSpec Compliance Profile +version: 0.1.0.999 diff --git a/test/unit/profiles/metadata_test.rb b/test/unit/profiles/metadata_test.rb index 6bba9e815..ff816946c 100644 --- a/test/unit/profiles/metadata_test.rb +++ b/test/unit/profiles/metadata_test.rb @@ -39,6 +39,20 @@ describe 'metadata with supported operating systems' do res.params[:name].must_equal('mock') end + it 'reads the version from metadata' do + res = Inspec::Metadata.from_yaml('mock', "---\nversion: '1.1.0'", nil) + Inspec::Metadata.finalize(res, 'mock', empty_options) + res.params[:version].must_equal('1.1.0') + res.valid_version?(res.params[:version]).must_equal(true) + end + + it 'does not accept invalid version from metadata' do + res = Inspec::Metadata.from_yaml('mock', "---\nversion: '1.1.0.1'", nil) + Inspec::Metadata.finalize(res, 'mock', empty_options) + res.params[:version].must_equal('1.1.0.1') + res.valid_version?(res.params[:version]).must_equal(false) + end + it 'finalizes a loaded metadata by turning strings into symbols' do res = Inspec::Metadata.from_yaml('mock', "---\nauthor: world", nil) Inspec::Metadata.finalize(res, 'mock', empty_options) diff --git a/test/unit/profiles/profile_test.rb b/test/unit/profiles/profile_test.rb index a4a34ab00..d56b49813 100644 --- a/test/unit/profiles/profile_test.rb +++ b/test/unit/profiles/profile_test.rb @@ -282,5 +282,56 @@ describe Inspec::Profile do result[:warnings].length.must_equal 0 end end + + describe 'a complete metadata profile with controls in zipfile' do + let(:profile_id) { 'complete-profile' } + let(:profile_path) { MockLoader.profile_zip(profile_id) } + let(:profile) { MockLoader.load_profile(profile_path, {logger: logger}) } + + it 'prints ok messages and counts the controls' do + logger.expect :info, nil, ["Checking profile in #{home}/mock/profiles/#{profile_id}"] + logger.expect :info, nil, ['Metadata OK.'] + logger.expect :info, nil, ['Found 1 controls.'] + logger.expect :info, nil, ['Control definitions OK.'] + + result = MockLoader.load_profile(profile_id, {logger: logger}).check + # verify logger output + logger.verify + + # verify hash result + result[:summary][:valid].must_equal true + result[:summary][:location].must_equal "#{home}/mock/profiles/#{profile_id}" + result[:summary][:profile].must_equal 'complete' + result[:summary][:controls].must_equal 1 + result[:errors].length.must_equal 0 + result[:warnings].length.must_equal 0 + end + end + + describe 'shows error if version is invalid' do + let(:profile_id) { 'invalid-version' } + let(:profile_path) { MockLoader.profile_zip(profile_id) } + let(:profile) { MockLoader.load_profile(profile_path, {logger: logger}) } + + it 'prints ok messages and counts the controls' do + logger.expect :info, nil, ["Checking profile in #{home}/mock/profiles/#{profile_id}"] + logger.expect :warn, nil, ['No controls or tests were defined.'] + logger.expect :error, nil, ['Version needs to be in SemVer format'] + + result = MockLoader.load_profile(profile_id, {logger: logger}).check + + # verify logger output + logger.verify + + # verify hash result + result[:summary][:valid].must_equal false + result[:summary][:location].must_equal "#{home}/mock/profiles/#{profile_id}" + result[:summary][:profile].must_equal 'invalid-version' + + result[:summary][:controls].must_equal 0 + result[:errors].length.must_equal 1 + result[:warnings].length.must_equal 1 + end + end end end