make check work again with new rule-tree

Signed-off-by: Dominik Richter <dominik@vulcanosec.com>
This commit is contained in:
Dominik Richter 2015-06-20 01:36:27 +02:00
parent 5e83779fb4
commit 83dc0a6425
2 changed files with 118 additions and 90 deletions

View file

@ -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?

View file

@ -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