mirror of
https://github.com/inspec/inspec
synced 2024-11-10 07:04:15 +00:00
make check work again with new rule-tree
Signed-off-by: Dominik Richter <dominik@vulcanosec.com>
This commit is contained in:
parent
5e83779fb4
commit
83dc0a6425
2 changed files with 118 additions and 90 deletions
|
@ -31,43 +31,42 @@ module Vulcano
|
|||
@log.ok "Valid directory"
|
||||
end
|
||||
|
||||
md = Metadata.for_path(path)
|
||||
@log.ok "vmetadata.rb" unless md.nil? or !md.valid?
|
||||
metadata = Metadata.for_path(path)
|
||||
@log.ok "vmetadata.rb" unless metadata.nil? or !metadata.valid?
|
||||
|
||||
specs = Dir["#{path}/spec/*_spec.rb"]
|
||||
if specs.empty?
|
||||
@log.warn "No tests found in #{path}"
|
||||
end
|
||||
specs.each{|s| valid_spec? s }
|
||||
specs.each{|s| valid_spec? s, metadata }
|
||||
end
|
||||
|
||||
def valid_spec? f
|
||||
def valid_spec? f, metadata
|
||||
return @log.error "Can't find spec file #{f}" unless File::file? f
|
||||
# validation tracking
|
||||
valid = true
|
||||
specs = SpecFile.from_file(f)
|
||||
meta = specs.vulcano_meta
|
||||
if meta['title'].nil?
|
||||
@log.error "Missing title in spec file #{f}"
|
||||
valid = false
|
||||
end
|
||||
if meta['copyright'].nil?
|
||||
@log.error "Missing copyright in spec file #{f}"
|
||||
valid = false
|
||||
end
|
||||
|
||||
raw = File::read(f)
|
||||
describe_lines = raw.split("\n").each_with_index.
|
||||
find_all{|line,idx| line =~ /^[^"#]*describe.*do(\s|$)/ }.
|
||||
map{|x| x[1]+1 }
|
||||
|
||||
unless meta['rules'][''].nil?
|
||||
@log.error "Please configure IDs for all rules."
|
||||
end
|
||||
|
||||
invalid = lambda {|msg|
|
||||
@log.error "#{msg} (#{File::basename f})"
|
||||
valid = false
|
||||
}
|
||||
# Load the spec file
|
||||
specs = SpecFile.from_file(f, metadata)
|
||||
# find all errors during parsing
|
||||
specs.errors.each do |err|
|
||||
invalid.(err)
|
||||
end
|
||||
# detect missing metadata
|
||||
meta = specs.metadata
|
||||
if meta['title'].nil?
|
||||
invalid.("Missing title in spec file")
|
||||
end
|
||||
if meta['copyright'].nil?
|
||||
invalid.("Missing copyright in spec file")
|
||||
end
|
||||
# detect empty rules
|
||||
unless meta['rules'][''].nil?
|
||||
invalid.("Please configure IDs for all rules.")
|
||||
end
|
||||
|
||||
meta['rules'].each do |k,v|
|
||||
if v['impact'].nil?
|
||||
|
|
|
@ -11,74 +11,36 @@ rescue LoadError
|
|||
end
|
||||
|
||||
module Vulcano
|
||||
class DummyVulcanoRule < VulcanoBaseRule
|
||||
include DummyServerspecTypes
|
||||
include DummyVulcanoTypes
|
||||
def method_missing(m, *a, &b)
|
||||
end
|
||||
end
|
||||
class DummyContext
|
||||
include Vulcano::DSL
|
||||
|
||||
class SpecFile
|
||||
include DummyServerspecTypes
|
||||
include DummyVulcanoTypes
|
||||
Log = ::Vulcano::Log.new()
|
||||
|
||||
def initialize path
|
||||
def initialize path, profile_id
|
||||
@path = path
|
||||
@rules = []
|
||||
@raw = File::read(path)
|
||||
@invalid_calls = []
|
||||
self.instance_eval(@raw, path, 1)
|
||||
@profile_id = profile_id
|
||||
@rules = {}
|
||||
@errors = []
|
||||
end
|
||||
|
||||
def vulcano_meta
|
||||
# helper methods (which we don't expose)
|
||||
def rule2dict(rule)
|
||||
d = nil
|
||||
d = rule.desc.gsub(/\s*\n\s*/, ' ').strip unless rule.desc.nil?
|
||||
{
|
||||
"impact" => rule.impact,
|
||||
"title" => rule.title,
|
||||
"desc" => d
|
||||
}
|
||||
# DSL methods
|
||||
def __register_rule r
|
||||
fid = VulcanoBaseRule.full_id r, @profile_id
|
||||
if @rules[fid].nil?
|
||||
@rules[fid] = r
|
||||
else
|
||||
@errors.push "Duplicate definition of rule #{fid}."
|
||||
end
|
||||
def rules2dict(rules)
|
||||
res = {}
|
||||
rules.map do |rule|
|
||||
nu = rule2dict(rule)
|
||||
if res[rule.id].nil?
|
||||
res[rule.id] = nu
|
||||
else
|
||||
Log.error(
|
||||
"Not redefining rule id #{rule.id}:\n"+
|
||||
"-- #{res[rule.id]}\n"+
|
||||
"++ #{nu}\n"
|
||||
)
|
||||
end
|
||||
end
|
||||
res
|
||||
end
|
||||
def __unregister_rule id
|
||||
fid = "#{@profile_id}/#{id}"
|
||||
if @rules.key? fid
|
||||
@rules.delete(fid)
|
||||
else
|
||||
@errors.push "Failed to skip rule #{fid}, it isn't defined."
|
||||
end
|
||||
def mOr(m, other)
|
||||
(m.nil? || m[1].nil?) ? other : m[1]
|
||||
end
|
||||
header = @raw.sub(/^[^#].*\Z/m,'')
|
||||
|
||||
{
|
||||
"title" => mOr(header.match(/^# title: (.*)$/), 'untitled'),
|
||||
"copyright" => mOr(header.match(/^# copyright: (.*)$/), 'All rights reserved'),
|
||||
"rules" => rules2dict(@rules)
|
||||
}
|
||||
end
|
||||
|
||||
def rule id, &block
|
||||
@rules.push(DummyVulcanoRule.new(id, &block))
|
||||
end
|
||||
|
||||
def method_missing sth, *args
|
||||
Log.warn "spec file doesn't support: #{sth} #{args.join(', ')}"
|
||||
@invalid_calls.push([sth, args])
|
||||
end
|
||||
|
||||
# redefine require to find files in the context
|
||||
# of this profile
|
||||
def require sth
|
||||
# ignore vulcano includes, we already have those
|
||||
lib = File::expand_path( File.join @path, '..', '..', 'lib', "#{sth}.rb" )
|
||||
|
@ -87,12 +49,79 @@ module Vulcano
|
|||
end
|
||||
end
|
||||
|
||||
def self.from_file path
|
||||
if !File::file?(path)
|
||||
Log.error "Can't find spec file in #{path}"
|
||||
return nil
|
||||
end
|
||||
return SpecFile.new(path)
|
||||
def method_missing sth, *args
|
||||
@errors.push "Don't understand method #{sth} ( #{args} )."
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module Vulcano
|
||||
class SpecFile
|
||||
Log = ::Vulcano::Log.new()
|
||||
|
||||
attr_reader :errors, :rules
|
||||
def initialize path, metadata
|
||||
@rules = []
|
||||
@raw = File::read(path)
|
||||
@profile_id = metadata.dict['name']
|
||||
@invalid_calls = []
|
||||
|
||||
ctx = DummyContext.new(path, @profile_id)
|
||||
ctx.instance_eval(@raw, path, 1)
|
||||
@errors = ctx.instance_variable_get(:@errors)
|
||||
@rules = ctx.instance_variable_get(:@rules)
|
||||
end
|
||||
|
||||
def metadata
|
||||
header = @raw.sub(/^[^#].*\Z/m,'')
|
||||
{
|
||||
"title" => mOr(header.match(/^# title: (.*)$/), 'untitled'),
|
||||
"copyright" => mOr(header.match(/^# copyright: (.*)$/), 'All rights reserved'),
|
||||
"rules" => rules2dict(@rules)
|
||||
}
|
||||
end
|
||||
|
||||
def self.from_file path, metadata
|
||||
if !File::file?(path)
|
||||
Log.error "Can't find spec file in #{path}"
|
||||
return nil
|
||||
end
|
||||
return SpecFile.new(path, metadata)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def rule2dict(rule)
|
||||
d = nil
|
||||
d = rule.desc.gsub(/\s*\n\s*/, ' ').strip unless rule.desc.nil?
|
||||
{
|
||||
"impact" => rule.impact,
|
||||
"title" => rule.title,
|
||||
"desc" => d
|
||||
}
|
||||
end
|
||||
|
||||
def rules2dict(rules)
|
||||
res = {}
|
||||
rules.map do |id, rule|
|
||||
nu = rule2dict(rule)
|
||||
if res[id].nil?
|
||||
res[id] = nu
|
||||
else
|
||||
Log.error(
|
||||
"Not redefining rule id #{id}:\n"+
|
||||
"-- #{res[id]}\n"+
|
||||
"++ #{nu}\n"
|
||||
)
|
||||
end
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
def mOr(m, other)
|
||||
(m.nil? || m[1].nil?) ? other : m[1]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue