mirror of
https://github.com/inspec/inspec
synced 2024-11-10 07:04:15 +00:00
Add support for multiple descriptions for controls (#3424)
* Add support for multiple descriptions for controls This adds the ability to specify multiple descriptions in controls. Example: ```ruby control 'my-control' do impact 1.0 title 'My control' desc 'A default description' desc 'rational', 'I need an example' describe file('/tmp') do it { should be_directory } end end ``` Many thanks to @jquick for helping me with the unit tests. * Remove unused `descriptions` method * Remove unused profile from test mocks * Respond to feedback Signed-off-by: Jerry Aldrich <jerryaldrichiii@gmail.com>
This commit is contained in:
parent
3b6bd808e9
commit
20776b363d
24 changed files with 156 additions and 65 deletions
|
@ -26,10 +26,8 @@ In various use cases like implementing IT compliance across different department
|
|||
control 'sshd-8' do
|
||||
impact 0.6
|
||||
title 'Server: Configure the service port'
|
||||
desc '
|
||||
Always specify which port the SSH server should listen to.
|
||||
Prevent unexpected settings.
|
||||
'
|
||||
desc 'Always specify which port the SSH server should listen.'
|
||||
desc 'rationale', 'This ensures that there are no unexpected settings'
|
||||
tag 'ssh','sshd','openssh-server'
|
||||
tag cce: 'CCE-27072-8'
|
||||
ref 'NSA-RH6-STIG - Section 3.5.2.1', url: 'https://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf'
|
||||
|
@ -44,6 +42,7 @@ where
|
|||
|
||||
* `'sshd-8'` is the name of the control
|
||||
* `impact`, `title`, and `desc` define metadata that fully describes the importance of the control, its purpose, with a succinct and complete description
|
||||
* `desc` when given only one argument it sets the default description. When given 2 arguments (see: `'rationale'`) it will use the first argument as a header when rendering in Automate
|
||||
* `impact` is an float that measures the importance of the compliance results and must be a value between `0.0` and `1.0`. The value ranges are:
|
||||
* `0.0 to <0.4` these are controls with minor criticality
|
||||
* `0.4 to <0.7` these are controls with major criticality
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
title '/tmp profile'
|
||||
|
||||
# you add controls here
|
||||
control "tmp-1.0" do # A unique ID for this control
|
||||
impact 0.7 # The criticality, if this control fails.
|
||||
title "Create /tmp directory" # A human-readable title
|
||||
desc "An optional description..." # Describe why this is needed
|
||||
tag data: "temp data" # A tag allows you to associate key information
|
||||
tag "security" # to the test
|
||||
ref "Document A-12", url: 'http://...' # Additional references
|
||||
control "tmp-1.0" do # A unique ID for this control
|
||||
impact 0.7 # The criticality, if this control fails.
|
||||
title "Create /tmp directory" # A human-readable title
|
||||
desc "An optional description..." # Describe why this is needed
|
||||
desc "label", "An optional description with a label" # Pair a part of the description with a label
|
||||
tag data: "temp data" # A tag allows you to associate key information
|
||||
tag "security" # to the test
|
||||
ref "Document A-12", url: 'http://...' # Additional references
|
||||
|
||||
describe file('/tmp') do # The actual test
|
||||
describe file('/tmp') do # The actual test
|
||||
it { should be_directory }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
module Inspec
|
||||
class Control
|
||||
attr_accessor :id, :title, :desc, :impact, :tests, :tags, :refs
|
||||
attr_accessor :id, :title, :descriptions, :impact, :tests, :tags, :refs
|
||||
def initialize
|
||||
@tests = []
|
||||
@tags = []
|
||||
@refs = []
|
||||
@descriptions = {}
|
||||
end
|
||||
|
||||
def add_test(t)
|
||||
|
@ -18,13 +19,27 @@ module Inspec
|
|||
end
|
||||
|
||||
def to_hash
|
||||
{ id: id, title: title, desc: desc, impact: impact, tests: tests.map(&:to_hash), tags: tags.map(&:to_hash) }
|
||||
{
|
||||
id: id,
|
||||
title: title,
|
||||
descriptions: descriptions,
|
||||
impact: impact,
|
||||
tests: tests.map(&:to_hash),
|
||||
tags: tags.map(&:to_hash),
|
||||
}
|
||||
end
|
||||
|
||||
def to_ruby # rubocop:disable Metrics/AbcSize
|
||||
res = ["control #{id.inspect} do"]
|
||||
res.push " title #{title.inspect}" unless title.to_s.empty?
|
||||
res.push " desc #{prettyprint_text(desc, 2)}" unless desc.to_s.empty?
|
||||
descriptions.each do |label, text|
|
||||
if label == :default
|
||||
next if text.nil? or text == '' # don't render empty/nil desc
|
||||
res.push " desc #{prettyprint_text(text, 2)}"
|
||||
else
|
||||
res.push " desc #{label.to_s.inspect}, #{prettyprint_text(text, 2)}"
|
||||
end
|
||||
end
|
||||
res.push " impact #{impact}" unless impact.nil?
|
||||
tags.each { |t| res.push(indent(t.to_ruby, 2)) }
|
||||
refs.each { |t| res.push(" ref #{print_ref(t)}") }
|
||||
|
|
|
@ -369,7 +369,7 @@ module Inspec
|
|||
error.call(sfile, sline, nil, id, 'Avoid controls with empty IDs') if id.nil? or id.empty?
|
||||
next if id.start_with? '(generated '
|
||||
warn.call(sfile, sline, nil, id, "Control #{id} has no title") if control[:title].to_s.empty?
|
||||
warn.call(sfile, sline, nil, id, "Control #{id} has no description") if control[:desc].to_s.empty?
|
||||
warn.call(sfile, sline, nil, id, "Control #{id} has no descriptions") if control[:descriptions][:default].to_s.empty?
|
||||
warn.call(sfile, sline, nil, id, "Control #{id} has impact > 1.0") if control[:impact].to_f > 1.0
|
||||
warn.call(sfile, sline, nil, id, "Control #{id} has impact < 0.0") if control[:impact].to_f < 0.0
|
||||
warn.call(sfile, sline, nil, id, "Control #{id} has no tests defined") if control[:checks].nil? or control[:checks].empty?
|
||||
|
@ -561,6 +561,7 @@ module Inspec
|
|||
controls[id] = {
|
||||
title: rule.title,
|
||||
desc: rule.desc,
|
||||
descriptions: rule.descriptions,
|
||||
impact: rule.impact,
|
||||
refs: rule.ref,
|
||||
tags: rule.tag,
|
||||
|
|
|
@ -60,7 +60,8 @@ module Inspec::Reporters
|
|||
control = {
|
||||
id: c[:id],
|
||||
title: c[:title],
|
||||
desc: c[:desc],
|
||||
desc: c.dig(:descriptions, :default),
|
||||
descriptions: convert_descriptions(c[:descriptions]),
|
||||
impact: c[:impact],
|
||||
refs: c[:refs],
|
||||
tags: c[:tags],
|
||||
|
@ -116,5 +117,14 @@ module Inspec::Reporters
|
|||
end
|
||||
profiles
|
||||
end
|
||||
|
||||
def convert_descriptions(data)
|
||||
return [] if data.nil?
|
||||
results = []
|
||||
data.each do |label, text|
|
||||
results.push({ label: label.to_s, data: text })
|
||||
end
|
||||
results
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,7 +32,7 @@ module Inspec
|
|||
def initialize(id, profile_id, opts, &block)
|
||||
@impact = nil
|
||||
@title = nil
|
||||
@desc = nil
|
||||
@descriptions = {}
|
||||
@refs = []
|
||||
@tags = {}
|
||||
|
||||
|
@ -89,9 +89,18 @@ module Inspec
|
|||
@title
|
||||
end
|
||||
|
||||
def desc(v = nil)
|
||||
@desc = unindent(v) unless v.nil?
|
||||
@desc
|
||||
def desc(v = nil, data = nil)
|
||||
return @descriptions[:default] if v.nil?
|
||||
if data.nil?
|
||||
@descriptions[:default] = unindent(v)
|
||||
else
|
||||
@descriptions[v.to_sym] = unindent(data)
|
||||
end
|
||||
end
|
||||
|
||||
def descriptions(description_hash = nil)
|
||||
return @descriptions if description_hash.nil?
|
||||
@descriptions.merge!(description_hash)
|
||||
end
|
||||
|
||||
def ref(ref = nil, opts = {})
|
||||
|
@ -221,11 +230,11 @@ module Inspec
|
|||
return
|
||||
end
|
||||
# merge all fields
|
||||
dst.impact(src.impact) unless src.impact.nil?
|
||||
dst.title(src.title) unless src.title.nil?
|
||||
dst.desc(src.desc) unless src.desc.nil?
|
||||
dst.tag(src.tag) unless src.tag.nil?
|
||||
dst.ref(src.ref) unless src.ref.nil?
|
||||
dst.impact(src.impact) unless src.impact.nil?
|
||||
dst.title(src.title) unless src.title.nil?
|
||||
dst.descriptions(src.descriptions) unless src.descriptions.nil?
|
||||
dst.tag(src.tag) unless src.tag.nil?
|
||||
dst.ref(src.ref) unless src.ref.nil?
|
||||
|
||||
# merge indirect fields
|
||||
# checks defined in the source will completely eliminate
|
||||
|
|
|
@ -167,7 +167,7 @@ module Inspec
|
|||
metadata[:profile_id] = ::Inspec::Rule.profile_id(rule)
|
||||
metadata[:impact] = rule.impact
|
||||
metadata[:title] = rule.title
|
||||
metadata[:desc] = rule.desc
|
||||
metadata[:descriptions] = rule.descriptions
|
||||
metadata[:code] = rule.instance_variable_get(:@__code)
|
||||
metadata[:source_location] = rule.instance_variable_get(:@__source_location)
|
||||
end
|
||||
|
|
|
@ -84,6 +84,7 @@ module Inspec
|
|||
'id' => { 'type' => 'string' },
|
||||
'title' => { 'type' => %w{string null} },
|
||||
'desc' => { 'type' => %w{string null} },
|
||||
'descriptions' => { 'type' => %w{array} },
|
||||
'impact' => { 'type' => 'number' },
|
||||
'refs' => REFS,
|
||||
'tags' => TAGS,
|
||||
|
|
|
@ -73,7 +73,7 @@ describe 'inspec exec with json formatter' do
|
|||
"license" => "Apache-2.0",
|
||||
"summary" => "Demonstrates the use of InSpec Compliance Profile",
|
||||
"version" => "1.0.0",
|
||||
"sha256" => "c2416865d6da8cdeb4610442d6eac18be2737453e010d028cb901103fefebf6a",
|
||||
"sha256" => "9ce86873d1e0c450ec739883dfe39828b481697f573304ad24c835885085b132",
|
||||
"supports" => [{"platform-family" => "unix"}, {"platform-family"=>"windows"}],
|
||||
"attributes" => []
|
||||
})
|
||||
|
@ -114,21 +114,14 @@ describe 'inspec exec with json formatter' do
|
|||
result['start_time'].wont_be :nil?
|
||||
|
||||
actual.must_equal({
|
||||
"id" => "tmp-1.0",
|
||||
"title" => "Create /tmp directory",
|
||||
"desc" => "An optional description...",
|
||||
"impact" => 0.7,
|
||||
"refs" => [
|
||||
{
|
||||
"url" => "http://...",
|
||||
"ref" => "Document A-12"
|
||||
}
|
||||
],
|
||||
"tags" => {
|
||||
"data" => "temp data",
|
||||
"security" => nil
|
||||
},
|
||||
"code" => "control \"tmp-1.0\" do # A unique ID for this control\n impact 0.7 # The criticality, if this control fails.\n title \"Create /tmp directory\" # A human-readable title\n desc \"An optional description...\" # Describe why this is needed\n tag data: \"temp data\" # A tag allows you to associate key information\n tag \"security\" # to the test\n ref \"Document A-12\", url: 'http://...' # Additional references\n\n describe file('/tmp') do # The actual test\n it { should be_directory }\n end\nend\n",
|
||||
"id"=>"tmp-1.0",
|
||||
"title"=>"Create /tmp directory",
|
||||
"desc"=>"An optional description...",
|
||||
"descriptions"=>[{"label"=>"default", "data"=>"An optional description..."}, {"label"=>"label", "data"=>"An optional description with a label"}],
|
||||
"impact"=>0.7,
|
||||
"refs"=>[{"url"=>"http://...", "ref"=>"Document A-12"}],
|
||||
"tags"=>{"data"=>"temp data", "security"=>nil},
|
||||
"code"=>"control \"tmp-1.0\" do # A unique ID for this control\n impact 0.7 # The criticality, if this control fails.\n title \"Create /tmp directory\" # A human-readable title\n desc \"An optional description...\" # Describe why this is needed\n desc \"label\", \"An optional description with a label\" # Pair a part of the description with a label\n tag data: \"temp data\" # A tag allows you to associate key information\n tag \"security\" # to the test\n ref \"Document A-12\", url: 'http://...' # Additional references\n\n describe file('/tmp') do # The actual test\n it { should be_directory }\n end\nend\n"
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -446,17 +446,28 @@ Test Summary: \e[38;5;41m2 successful\e[0m, 0 failures, 0 skipped\n"
|
|||
controls.count.must_equal 2
|
||||
|
||||
# check for json override
|
||||
assert = " control 'pro1-con2' do\n impact 0.999\n title 'Profile 1 - Control 2-updated'\n desc 'Profile 1 - Control 2 description-updated'\n tag 'password-updated'\n ref 'Section 3.5.2.1', url: 'https://example.com'\n describe file('/etc/passwd') do\n it { should exist }\n end\n end\n"
|
||||
override['code'].must_equal assert
|
||||
expected_value = " control 'pro1-con2' do\n impact 0.999\n title 'Profile 1 - Control 2-updated'\n desc 'Profile 1 - Control 2 description-updated'\n desc 'overwrite me', 'it is overwritten'\n desc 'new entry', 'this is appended to the description list'\n tag 'password-updated'\n ref 'Section 3.5.2.1', url: 'https://example.com'\n describe file('/etc/passwd') do\n it { should exist }\n end\n end\n"
|
||||
override['code'].must_equal expected_value
|
||||
override['impact'].must_equal 0.999
|
||||
override['descriptions'].must_equal([
|
||||
{ 'label' => 'default',
|
||||
'data' => 'Profile 1 - Control 2 description-updated'
|
||||
},
|
||||
{ 'label' => 'overwrite me',
|
||||
'data' => 'it is overwritten'
|
||||
},
|
||||
{ 'label' => 'new entry',
|
||||
'data' => 'this is appended to the description list'
|
||||
},
|
||||
])
|
||||
override['title'].must_equal "Profile 1 - Control 2-updated"
|
||||
tags_assert = {"password"=>nil, "password-updated"=>nil}
|
||||
override['tags'].must_equal tags_assert
|
||||
child_profile['parent_profile'].must_equal 'wrapper-override'
|
||||
|
||||
# check for original code on child profile
|
||||
assert = "control 'pro1-con2' do\n impact 0.9\n title 'Profile 1 - Control 2'\n desc 'Profile 1 - Control 2 description'\n tag 'password'\n describe file('/etc/passwdddddddddd') do\n it { should exist }\n end\nend\n"
|
||||
child_control['code'].must_equal assert
|
||||
expected_value = "control 'pro1-con2' do\n impact 0.9\n title 'Profile 1 - Control 2'\n desc 'Profile 1 - Control 2 description'\n desc 'overwrite me', 'overwrite this'\n tag 'password'\n describe file('/etc/passwdddddddddd') do\n it { should exist }\n end\nend\n"
|
||||
child_control['code'].must_equal expected_value
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -22,22 +22,42 @@ describe 'controls' do
|
|||
end
|
||||
|
||||
it 'adds a description' do
|
||||
load("desc #{rand_string.inspect}")[:desc].must_equal rand_string
|
||||
load("desc #{rand_string.inspect}")[:descriptions][:default].must_equal rand_string
|
||||
end
|
||||
|
||||
it 'allows multiple desc with keys and values' do
|
||||
lines = <<-DESC_EXAMPLES
|
||||
desc 'this is default'
|
||||
desc 'example', 'this is foo'
|
||||
desc 'a space', 'this label has a space'
|
||||
desc 'newline', 'this value has
|
||||
a newline'
|
||||
desc 'heredoc', <<-EOF
|
||||
This is a heredoc
|
||||
EOF
|
||||
DESC_EXAMPLES
|
||||
|
||||
result = load(lines)
|
||||
result[:descriptions][:default].must_equal('this is default')
|
||||
result[:descriptions][:example].must_equal('this is foo')
|
||||
result[:descriptions][:'a space'].must_equal('this label has a space')
|
||||
result[:descriptions][:newline].must_match(/this value has\n\s*a newline/)
|
||||
result[:descriptions][:heredoc].must_equal('This is a heredoc')
|
||||
end
|
||||
|
||||
it 'adds a multiline description' do
|
||||
t = rand_string + "\n" + rand_string
|
||||
load("desc #{t.inspect}")[:desc].must_equal t
|
||||
load("desc #{t.inspect}")[:descriptions][:default].must_equal t
|
||||
end
|
||||
|
||||
it 'strips empty lines and spaces in description at start and end' do
|
||||
t = " \n" + rand_string + "\n "
|
||||
load("desc #{t.inspect}")[:desc].must_equal rand_string
|
||||
load("desc #{t.inspect}")[:descriptions][:default].must_equal rand_string
|
||||
end
|
||||
|
||||
it 'unindents properly' do
|
||||
t = "\n #{rand_string}\n \n\t\t #{rand_string}\n "
|
||||
load("desc #{t.inspect}")[:desc].must_equal "#{rand_string}\n \n #{rand_string}"
|
||||
load("desc #{t.inspect}")[:descriptions][:default].must_equal "#{rand_string}\n \n #{rand_string}"
|
||||
end
|
||||
|
||||
it 'works with empty refs' do
|
||||
|
|
|
@ -274,13 +274,19 @@ end
|
|||
control.add_test(obj1)
|
||||
control.id = 'sample.control.id'
|
||||
control.title = 'Sample Control Important Title'
|
||||
control.desc = 'The most critical control the world has ever seen'
|
||||
control.descriptions = {
|
||||
default: 'The most critical control the world has ever seen',
|
||||
rationale: 'It is needed to save the planet',
|
||||
'more info': 'Insert clever joke here',
|
||||
}
|
||||
control.refs = ['simple ref', {ref: 'title', url: 'my url'}]
|
||||
control.impact = 1.0
|
||||
control.to_ruby.must_equal '
|
||||
control "sample.control.id" do
|
||||
title "Sample Control Important Title"
|
||||
desc "The most critical control the world has ever seen"
|
||||
desc "rationale", "It is needed to save the planet"
|
||||
desc "more info", "Insert clever joke here"
|
||||
impact 1.0
|
||||
ref "simple ref"
|
||||
ref ({:ref=>"title", :url=>"my url"})
|
||||
|
@ -293,7 +299,7 @@ end
|
|||
|
||||
it 'constructs a multiline desc in a control with indentation' do
|
||||
control = Inspec::Control.new
|
||||
control.desc = "Multiline\n control"
|
||||
control.descriptions[:default] = "Multiline\n control"
|
||||
control.to_ruby.must_equal '
|
||||
control nil do
|
||||
desc "
|
||||
|
@ -311,16 +317,16 @@ control nil do
|
|||
end
|
||||
'.strip
|
||||
|
||||
control.desc = ''
|
||||
control.descriptions[:default] = ''
|
||||
control.to_ruby.must_equal x
|
||||
|
||||
control.desc = nil
|
||||
control.descriptions[:default] = nil
|
||||
control.to_ruby.must_equal x
|
||||
end
|
||||
|
||||
it 'handles non-string descriptions' do
|
||||
control = Inspec::Control.new
|
||||
control.desc = 123
|
||||
control.descriptions[:default] = 123
|
||||
control.to_ruby.must_equal '
|
||||
control nil do
|
||||
desc "123"
|
||||
|
@ -352,7 +358,7 @@ end
|
|||
|
||||
control.id = 'variable.control.id'
|
||||
control.title = 'Variable Control Important Title'
|
||||
control.desc = 'The most variable control the world has ever seen'
|
||||
control.descriptions[:default] = 'The most variable control the world has ever seen'
|
||||
control.impact = 1.0
|
||||
control.to_ruby.must_equal '
|
||||
control "variable.control.id" do
|
||||
|
@ -441,7 +447,7 @@ end
|
|||
control_hash = {
|
||||
id:"tag.control.id",
|
||||
title: nil,
|
||||
desc: nil,
|
||||
descriptions: {},
|
||||
impact: nil,
|
||||
tests: [],
|
||||
tags:[{
|
||||
|
@ -459,7 +465,6 @@ end
|
|||
}]
|
||||
}
|
||||
control.to_hash.must_equal control_hash
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
13
test/unit/mock/profiles/control_metadata/controls/example.rb
Normal file
13
test/unit/mock/profiles/control_metadata/controls/example.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
# encoding: utf-8
|
||||
|
||||
control 'tmp-1.0' do
|
||||
impact 0.7
|
||||
title 'Create /tmp directory'
|
||||
description 'Default description'
|
||||
description rational: 'Rational for the metadata test control'
|
||||
description 'something else': 'Even more metadata for the test control'
|
||||
|
||||
describe 'a thing' do
|
||||
it { should cmp 'a thing' }
|
||||
end
|
||||
end
|
8
test/unit/mock/profiles/control_metadata/inspec.yml
Normal file
8
test/unit/mock/profiles/control_metadata/inspec.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
name: control_metadata
|
||||
title: InSpec Profile
|
||||
maintainer: The Authors
|
||||
copyright: The Authors
|
||||
copyright_email: you@example.com
|
||||
license: Apache-2.0
|
||||
summary: An InSpec Compliance Profile
|
||||
version: 0.1.0
|
|
@ -7,6 +7,8 @@ include_controls 'myprofile1' do
|
|||
impact 0.999
|
||||
title 'Profile 1 - Control 2-updated'
|
||||
desc 'Profile 1 - Control 2 description-updated'
|
||||
desc 'overwrite me', 'it is overwritten'
|
||||
desc 'new entry', 'this is appended to the description list'
|
||||
tag 'password-updated'
|
||||
ref 'Section 3.5.2.1', url: 'https://example.com'
|
||||
describe file('/etc/passwd') do
|
|
@ -8,4 +8,4 @@ summary: Profile that wraps other profiles
|
|||
version: 0.6.1
|
||||
depends:
|
||||
- name: myprofile1
|
||||
url: https://s3-eu-west-1.amazonaws.com/apop-bucket/profiles/myprofile1-1.0.0.tar.gz
|
||||
path: does_not_matter_check_vendor
|
||||
|
|
|
@ -13,6 +13,7 @@ control 'pro1-con2' do
|
|||
impact 0.9
|
||||
title 'Profile 1 - Control 2'
|
||||
desc 'Profile 1 - Control 2 description'
|
||||
desc 'overwrite me', 'overwrite this'
|
||||
tag 'password'
|
||||
describe file('/etc/passwdddddddddd') do
|
||||
it { should exist }
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"platform":{"name":"mac_os_x","release":"17.5.0"},"profiles":[{"name":"wrapper-override","version":"0.6.1","sha256":"7436aac31d44de7987419d5f2ffb822f265645f4fc3c5d2ab37d8fff4dd5cf61","title":"Linux Wrapper Child Profile","maintainer":"Demo, Inc.","summary":"Profile that wraps other profiles","license":"Apache-2.0","copyright":"Demo, Inc.","copyright_email":"support@example.com","supports":[],"attributes":[],"depends":[{"name":"myprofile1z","url":"https://s3-eu-west-1.amazonaws.com/apop-bucket/profiles/myprofile1-1.0.0.tar.gz"}],"groups":[{"id":"/Users/jquick/.inspec/cache/e39eb85366b272bae98e5eecdfac9f84c50a9ae9dd625fba2ce847268a6c3477/controls/profile1.rb","controls":["pro1-con1","pro1-con2","pro1-con4"]}],"controls":[{"id":"pro1-con1","title":"Profile 1 - Control 1","desc":"Profile 1 - Control 1 description","impact":0.8,"refs":[],"tags":{"hosts":null,"file":null,"cce":"CCE-27072-8"},"code":"control 'pro1-con1' do\n impact 0.8\n title 'Profile 1 - Control 1'\n desc 'Profile 1 - Control 1 description'\n tag 'hosts','file'\n tag cce: 'CCE-27072-8'\n describe file('/etc/hosts') do\n its('mode') { should eq 0644 }\n end\nend\n","source_location":{"line":1,"ref":"/Users/jquick/.inspec/cache/e39eb85366b272bae98e5eecdfac9f84c50a9ae9dd625fba2ce847268a6c3477/controls/profile1.rb"},"results":[{"status":"passed","code_desc":"File /etc/hosts mode should eq 420","run_time":0.031503,"start_time":"2018-07-30T08:56:41-04:00"}]},{"id":"pro1-con2","title":"Profile 1 - Control 2-updated","desc":"Profile 1 - Control 2 description-updated","impact":0.999,"refs":[{"ref":[{"url":"https://example.com","ref":"Section 3.5.2.1"}]}],"tags":{"password":null,"password-updated":null},"code":" control 'pro1-con2' do\n impact 0.999\n title 'Profile 1 - Control 2-updated'\n desc 'Profile 1 - Control 2 description-updated'\n tag 'password-updated'\n ref 'Section 3.5.2.1', url: 'https://example.com'\n describe file('/etc/passwd') do\n it { should exist }\n end\n end\n","source_location":{"line":6,"ref":"wrapper-override/controls/defaut.rb"},"results":[{"status":"passed","code_desc":"File /etc/passwd should exist","run_time":0.003954,"start_time":"2018-07-30T08:56:41-04:00"}]},{"id":"pro1-con4","title":"Profile 1 - Control 3 - useless","desc":"Profile 1 - Control 3 description","impact":1,"refs":[],"tags":{},"code":"control 'pro1-con4' do\n impact 1\n title 'Profile 1 - Control 3 - useless'\n desc 'Profile 1 - Control 3 description'\n only_if do\n 1.eql?(0)\n end\n describe file('/tmp5') do\n it { should exist }\n end\nend\n","source_location":{"line":31,"ref":"/Users/jquick/.inspec/cache/e39eb85366b272bae98e5eecdfac9f84c50a9ae9dd625fba2ce847268a6c3477/controls/profile1.rb"},"results":[{"status":"skipped","code_desc":"Operating System Detection","run_time":2.9e-05,"start_time":"2018-07-30T08:56:41-04:00","resource":"Operating System Detection","skip_message":"Skipped control due to only_if condition."}]}]}],"statistics":{"duration":0.039182},"version":"2.2.26"}
|
||||
{"platform":{"name":"mac_os_x","release":"17.5.0"},"profiles":[{"name":"wrapper-override","version":"0.6.1","sha256":"7436aac31d44de7987419d5f2ffb822f265645f4fc3c5d2ab37d8fff4dd5cf61","title":"Linux Wrapper Child Profile","maintainer":"Demo, Inc.","summary":"Profile that wraps other profiles","license":"Apache-2.0","copyright":"Demo, Inc.","copyright_email":"support@example.com","supports":[],"attributes":[],"depends":[{"name":"myprofile1z","url":"https://s3-eu-west-1.amazonaws.com/apop-bucket/profiles/myprofile1-1.0.0.tar.gz"}],"groups":[{"id":"/Users/jquick/.inspec/cache/e39eb85366b272bae98e5eecdfac9f84c50a9ae9dd625fba2ce847268a6c3477/controls/profile1.rb","controls":["pro1-con1","pro1-con2","pro1-con4"]}],"controls":[{"id":"pro1-con1","title":"Profile 1 - Control 1","desc":"Profile 1 - Control 1 description","descriptions":[{"label":"default","data":"Profile 1 - Control 1 description"}],"impact":0.8,"refs":[],"tags":{"hosts":null,"file":null,"cce":"CCE-27072-8"},"code":"control 'pro1-con1' do\n impact 0.8\n title 'Profile 1 - Control 1'\n desc 'Profile 1 - Control 1 description'\n tag 'hosts','file'\n tag cce: 'CCE-27072-8'\n describe file('/etc/hosts') do\n its('mode') { should eq 0644 }\n end\nend\n","source_location":{"line":1,"ref":"/Users/jquick/.inspec/cache/e39eb85366b272bae98e5eecdfac9f84c50a9ae9dd625fba2ce847268a6c3477/controls/profile1.rb"},"results":[{"status":"passed","code_desc":"File /etc/hosts mode should eq 420","run_time":0.031503,"start_time":"2018-07-30T08:56:41-04:00"}]},{"id":"pro1-con2","title":"Profile 1 - Control 2-updated","desc":"Profile 1 - Control 2 description-updated","descriptions":[{"label":"default","data":"Profile 1 - Control 2 description-updated"}],"impact":0.999,"refs":[{"ref":[{"url":"https://example.com","ref":"Section 3.5.2.1"}]}],"tags":{"password":null,"password-updated":null},"code":" control 'pro1-con2' do\n impact 0.999\n title 'Profile 1 - Control 2-updated'\n desc 'Profile 1 - Control 2 description-updated'\n tag 'password-updated'\n ref 'Section 3.5.2.1', url: 'https://example.com'\n describe file('/etc/passwd') do\n it { should exist }\n end\n end\n","source_location":{"line":6,"ref":"wrapper-override/controls/defaut.rb"},"results":[{"status":"passed","code_desc":"File /etc/passwd should exist","run_time":0.003954,"start_time":"2018-07-30T08:56:41-04:00"}]},{"id":"pro1-con4","title":"Profile 1 - Control 3 - useless","desc":"Profile 1 - Control 3 description","descriptions":[{"label":"default","data":"Profile 1 - Control 3 description"}],"impact":1,"refs":[],"tags":{},"code":"control 'pro1-con4' do\n impact 1\n title 'Profile 1 - Control 3 - useless'\n desc 'Profile 1 - Control 3 description'\n only_if do\n 1.eql?(0)\n end\n describe file('/tmp5') do\n it { should exist }\n end\nend\n","source_location":{"line":31,"ref":"/Users/jquick/.inspec/cache/e39eb85366b272bae98e5eecdfac9f84c50a9ae9dd625fba2ce847268a6c3477/controls/profile1.rb"},"results":[{"status":"skipped","code_desc":"Operating System Detection","run_time":2.9e-05,"start_time":"2018-07-30T08:56:41-04:00","resource":"Operating System Detection","skip_message":"Skipped control due to only_if condition."}]}]}],"statistics":{"duration":0.039182},"version":"2.2.26"}
|
|
@ -1 +1 @@
|
|||
{"platform":{"name":"mac_os_x","release":"17.2.0"},"profiles":[{"name":"long_commands","version":"0.1.0","sha256":"4f816f8cf18f165f05f1cf20936aaad06a15287de3f578891197647ca05c7df4","title":"InSpec Profile","maintainer":"The Authors","summary":"An InSpec Compliance Profile","license":"Apache-2.0","copyright":"The Authors","copyright_email":"you@example.com","supports":[{"os-family":"bds"},{"os-name":"mac_os_x","release":"17.*"}],"attributes":[],"groups":[{"id":"controls/example.rb","controls":["(generated from example.rb:7 871cd54043069c5c4f6e382fd5627830)","tmp-1.0","(generated from example.rb:21 2ff474c5357e7070f4c3efa932032dcb)"],"title":"sample section"},{"id":"controls/run_command.rb","controls":["(generated from run_command.rb:5 a411d4ded1530b2f48170840e1127584)"]}],"controls":[{"id":"(generated from example.rb:7 871cd54043069c5c4f6e382fd5627830)","title":null,"desc":null,"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"line":89,"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb"},"results":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.002058,"start_time":"2018-01-05 11:43:04 -0500"}]},{"id":"tmp-1.0","title":"Create /tmp directory","desc":"An optional description...","impact":0.7,"refs":[],"tags":{},"code":"control 'tmp-1.0' do # A unique ID for this control\n impact 0.7 # The criticality, if this control fails.\n title 'Create /tmp directory' # A human-readable title\n desc 'An optional description...'\n describe file('/tmp') do # The actual test\n it { should be_directory }\n end\nend\n","source_location":{"line":12,"ref":"../inspec-demo/_test/long_commands/controls/example.rb"},"results":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.000102,"start_time":"2018-01-05 11:43:04 -0500"}]},{"id":"(generated from example.rb:21 2ff474c5357e7070f4c3efa932032dcb)","title":null,"desc":null,"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"line":89,"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb"},"results":[{"status":"failed","code_desc":"gem package rubocop should be installed","run_time":0.000168,"start_time":"2018-01-05 11:43:04 -0500","message":"rubocop is not installed"}]},{"id":"(generated from run_command.rb:5 a411d4ded1530b2f48170840e1127584)","title":null,"desc":null,"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"line":89,"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb"},"results":[{"status":"passed","code_desc":"Command whoami stdout should eq \"jquick\\n\"","run_time":0.034938,"start_time":"2018-01-05 11:43:04 -0500"}]}]}],"statistics":{"duration":0.039182},"version":"1.49.2"}
|
||||
{"platform":{"name":"mac_os_x","release":"17.2.0"},"profiles":[{"name":"long_commands","version":"0.1.0","sha256":"4f816f8cf18f165f05f1cf20936aaad06a15287de3f578891197647ca05c7df4","title":"InSpec Profile","maintainer":"The Authors","summary":"An InSpec Compliance Profile","license":"Apache-2.0","copyright":"The Authors","copyright_email":"you@example.com","supports":[{"os-family":"bds"},{"os-name":"mac_os_x","release":"17.*"}],"attributes":[],"groups":[{"id":"controls/example.rb","controls":["(generated from example.rb:7 871cd54043069c5c4f6e382fd5627830)","tmp-1.0","(generated from example.rb:21 2ff474c5357e7070f4c3efa932032dcb)"],"title":"sample section"},{"id":"controls/run_command.rb","controls":["(generated from run_command.rb:5 a411d4ded1530b2f48170840e1127584)"]}],"controls":[{"id":"(generated from example.rb:7 871cd54043069c5c4f6e382fd5627830)","title":null,"desc":null,"descriptions":[],"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"line":89,"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb"},"results":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.002058,"start_time":"2018-01-05 11:43:04 -0500"}]},{"id":"tmp-1.0","title":"Create /tmp directory","desc":"An optional description...","descriptions":[{"label":"default","data":"An optional description..."}],"impact":0.7,"refs":[],"tags":{},"code":"control 'tmp-1.0' do # A unique ID for this control\n impact 0.7 # The criticality, if this control fails.\n title 'Create /tmp directory' # A human-readable title\n desc 'An optional description...'\n describe file('/tmp') do # The actual test\n it { should be_directory }\n end\nend\n","source_location":{"line":12,"ref":"../inspec-demo/_test/long_commands/controls/example.rb"},"results":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.000102,"start_time":"2018-01-05 11:43:04 -0500"}]},{"id":"(generated from example.rb:21 2ff474c5357e7070f4c3efa932032dcb)","title":null,"desc":null,"descriptions":[],"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"line":89,"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb"},"results":[{"status":"failed","code_desc":"gem package rubocop should be installed","run_time":0.000168,"start_time":"2018-01-05 11:43:04 -0500","message":"rubocop is not installed"}]},{"id":"(generated from run_command.rb:5 a411d4ded1530b2f48170840e1127584)","title":null,"desc":null,"descriptions":[],"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"line":89,"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb"},"results":[{"status":"passed","code_desc":"Command whoami stdout should eq \"jquick\\n\"","run_time":0.034938,"start_time":"2018-01-05 11:43:04 -0500"}]}]}],"statistics":{"duration":0.039182},"version":"1.49.2"}
|
|
@ -1 +1 @@
|
|||
{"controls":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.002058,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"File /tmp","expectation_message":"should be directory"},{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.000102,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"File /tmp","expectation_message":"should be directory"},{"status":"passed","code_desc":"gem package rubocop should be installed","run_time":0.000168,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"gem package rubocop","expectation_message":"should be installed"},{"status":"passed","code_desc":"Command whoami stdout should eq \"jquick\\n\"","run_time":0.034938,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"stdout","expectation_message":"stdout should eq \"jquick\\n\""}],"other_checks":[],"profiles":[{"name":"long_commands","title":"InSpec Profile","maintainer":"The Authors","copyright":"The Authors","copyright_email":"you@example.com","license":"Apache-2.0","summary":"An InSpec Compliance Profile","version":"0.1.0","supports":[{"os-family":"bds"},{"os-name":"mac_os_x","release":"17.*"}],"controls":[{"title":null,"desc":null,"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb","line":89},"id":"(generated from example.rb:7 871cd54043069c5c4f6e382fd5627830)","results":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.002058,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"File /tmp","expectation_message":"should be directory"}]},{"title":"Create /tmp directory","desc":"An optional description...","impact":0.7,"refs":[],"tags":{},"code":"control 'tmp-1.0' do # A unique ID for this control\n impact 0.7 # The criticality, if this control fails.\n title 'Create /tmp directory' # A human-readable title\n desc 'An optional description...'\n describe file('/tmp') do # The actual test\n it { should be_directory }\n end\nend\n","source_location":{"ref":"../inspec-demo/_test/long_commands/controls/example.rb","line":12},"id":"tmp-1.0","results":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.000102,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"File /tmp","expectation_message":"should be directory"}]},{"title":null,"desc":null,"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb","line":89},"id":"(generated from example.rb:21 2ff474c5357e7070f4c3efa932032dcb)","results":[{"status":"failed","message":"rubocop is not installed","code_desc":"gem package rubocop should be installed","run_time":0.000168,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"gem package rubocop","expectation_message":"should be installed"}]},{"title":null,"desc":null,"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb","line":89},"id":"(generated from run_command.rb:5 a411d4ded1530b2f48170840e1127584)","results":[{"status":"passed","code_desc":"Command whoami stdout should eq \"jquick\\n\"","run_time":0.034938,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"stdout","expectation_message":"stdout should eq \"jquick\\n\""}]}],"groups":[{"title":"sample section","controls":["(generated from example.rb:7 871cd54043069c5c4f6e382fd5627830)","tmp-1.0","(generated from example.rb:21 2ff474c5357e7070f4c3efa932032dcb)"],"id":"controls/example.rb"},{"title":null,"controls":["(generated from run_command.rb:5 a411d4ded1530b2f48170840e1127584)"],"id":"controls/run_command.rb"}],"attributes":[],"sha256":"4f816f8cf18f165f05f1cf20936aaad06a15287de3f578891197647ca05c7df4"}],"platform":{"name":"mac_os_x","release":"17.2.0","target":"local://"},"version":"1.49.2","statistics":{"duration":0.039182}}
|
||||
{"controls":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.002058,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"File /tmp","expectation_message":"should be directory"},{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.000102,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"File /tmp","expectation_message":"should be directory"},{"status":"passed","code_desc":"gem package rubocop should be installed","run_time":0.000168,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"gem package rubocop","expectation_message":"should be installed"},{"status":"passed","code_desc":"Command whoami stdout should eq \"jquick\\n\"","run_time":0.034938,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"stdout","expectation_message":"stdout should eq \"jquick\\n\""}],"other_checks":[],"profiles":[{"name":"long_commands","title":"InSpec Profile","maintainer":"The Authors","copyright":"The Authors","copyright_email":"you@example.com","license":"Apache-2.0","summary":"An InSpec Compliance Profile","version":"0.1.0","supports":[{"os-family":"bds"},{"os-name":"mac_os_x","release":"17.*"}],"controls":[{"title":null,"desc":null,"descriptions":{},"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb","line":89},"id":"(generated from example.rb:7 871cd54043069c5c4f6e382fd5627830)","results":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.002058,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"File /tmp","expectation_message":"should be directory"}]},{"title":"Create /tmp directory","desc":"An optional description...","descriptions": { "default": "An optional description..."},"impact":0.7,"refs":[],"tags":{},"code":"control 'tmp-1.0' do # A unique ID for this control\n impact 0.7 # The criticality, if this control fails.\n title 'Create /tmp directory' # A human-readable title\n desc 'An optional description...'\n describe file('/tmp') do # The actual test\n it { should be_directory }\n end\nend\n","source_location":{"ref":"../inspec-demo/_test/long_commands/controls/example.rb","line":12},"id":"tmp-1.0","results":[{"status":"passed","code_desc":"File /tmp should be directory","run_time":0.000102,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"File /tmp","expectation_message":"should be directory"}]},{"title":null,"desc":null,"descriptions":{},"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb","line":89},"id":"(generated from example.rb:21 2ff474c5357e7070f4c3efa932032dcb)","results":[{"status":"failed","message":"rubocop is not installed","code_desc":"gem package rubocop should be installed","run_time":0.000168,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"gem package rubocop","expectation_message":"should be installed"}]},{"title":null,"desc":null,"descriptions":{},"impact":0.5,"refs":[],"tags":{},"code":"","source_location":{"ref":"/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb","line":89},"id":"(generated from run_command.rb:5 a411d4ded1530b2f48170840e1127584)","results":[{"status":"passed","code_desc":"Command whoami stdout should eq \"jquick\\n\"","run_time":0.034938,"start_time":"2018-01-05 11:43:04 -0500","resource_title":"stdout","expectation_message":"stdout should eq \"jquick\\n\""}]}],"groups":[{"title":"sample section","controls":["(generated from example.rb:7 871cd54043069c5c4f6e382fd5627830)","tmp-1.0","(generated from example.rb:21 2ff474c5357e7070f4c3efa932032dcb)"],"id":"controls/example.rb"},{"title":null,"controls":["(generated from run_command.rb:5 a411d4ded1530b2f48170840e1127584)"],"id":"controls/run_command.rb"}],"attributes":[],"sha256":"4f816f8cf18f165f05f1cf20936aaad06a15287de3f578891197647ca05c7df4"}],"platform":{"name":"mac_os_x","release":"17.2.0","target":"local://"},"version":"1.49.2","statistics":{"duration":0.039182}}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -16,6 +16,7 @@
|
|||
- :id: "(generated from t.rb:1 0aa70d93be7b0cf41b97a1363bb5e8b8)"
|
||||
:title:
|
||||
:desc:
|
||||
:descriptions: []
|
||||
:impact: 0.5
|
||||
:refs: []
|
||||
:tags: {}
|
||||
|
|
|
@ -15,7 +15,7 @@ describe Inspec::Reporters::Automate do
|
|||
'job_uuid' => "22ad2f99-f84f-5456-95a0-jobuuid12345",
|
||||
}
|
||||
end
|
||||
let(:report) do
|
||||
let(:report) do
|
||||
data = JSON.parse(File.read(path + '/../mock/reporters/run_data.json'), symbolize_names: true)
|
||||
options.merge!({ run_data: data })
|
||||
Inspec::Reporters::Automate.new(options)
|
||||
|
|
|
@ -84,6 +84,7 @@ describe Inspec::Reporters::Json do
|
|||
id: '(generated from example.rb:7 871cd54043069c5c4f6e382fd5627830)',
|
||||
title: nil,
|
||||
desc: nil,
|
||||
descriptions: [],
|
||||
impact: 0.5,
|
||||
refs: [],
|
||||
tags: {},
|
||||
|
|
Loading…
Reference in a new issue