mirror of
https://github.com/inspec/inspec
synced 2025-02-17 06:28:40 +00:00
Waivers Feedback - Per control reporting and other minor issues (#4567)
Waivers Feedback - Per control reporting and other minor issues
This commit is contained in:
commit
a04142d034
24 changed files with 278 additions and 70 deletions
|
@ -26,13 +26,13 @@ Waiver files are [input files](https://www.inspec.io/docs/reference/inputs/) wit
|
|||
```yaml
|
||||
control_id:
|
||||
expiration_date: YYYY-MM-DD
|
||||
skip: true
|
||||
run: false
|
||||
justification: "reason for waiving this control"
|
||||
```
|
||||
|
||||
+ `expiration_date` is optional. Absence means the waiver is permanent.
|
||||
+ `skip` is optional. Absence means the control will run and be
|
||||
reported, but failures in it won't make the overall run fail.
|
||||
+ `run` is optional. If present and true, the control will run and be
|
||||
reported, but failures in it won't make the overall run fail. If absent or false, the control will not be run. You may use any of yes, no, true or false.
|
||||
+ `justification` can be any text you want and might include a reason
|
||||
as well as who signed off on the waiver.
|
||||
|
||||
|
@ -46,5 +46,5 @@ waiver_control_1_2_3:
|
|||
xccdf_org.cisecurity.benchmarks_rule_1.1.1.4_Ensure_mounting_of_hfs_filesystems_is_disabled:
|
||||
expiry_date: 2020-03-01
|
||||
justification: "This might be a bug in the test. @qateam"
|
||||
skip_run: true
|
||||
run: false
|
||||
```
|
||||
|
|
|
@ -259,6 +259,11 @@ module Inspec::Formatters
|
|||
example.delete(:id)
|
||||
example.delete(:profile_id)
|
||||
control[:results].push(example)
|
||||
|
||||
# Waiver data, if available, is internally stored on a per-result
|
||||
# (that is, per-describe-block) basis, because that is the only granularity
|
||||
# available to us in the RSpec report data structure which we use as a vehicle.
|
||||
control[:waiver_data] ||= example[:waiver_data] || {}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,7 +40,6 @@ module Inspec::Reporters
|
|||
message: r[:message],
|
||||
exception: r[:exception],
|
||||
backtrace: r[:backtrace],
|
||||
waiver_data: r[:waiver_data],
|
||||
}.reject { |_k, v| v.nil? }
|
||||
}
|
||||
end
|
||||
|
@ -96,6 +95,7 @@ module Inspec::Reporters
|
|||
line: c[:source_location][:line],
|
||||
ref: c[:source_location][:ref],
|
||||
},
|
||||
waiver_data: c[:waiver_data] || {},
|
||||
results: profile_results(c),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -297,11 +297,11 @@ module Inspec
|
|||
__waiver_data["skipped_due_to_waiver"] = false
|
||||
__waiver_data["message"] = ""
|
||||
|
||||
# Waivers should have a hash value with keys possibly including skip and
|
||||
# expiration_date. We only care here if it has a skip key and it
|
||||
# is yes-like, since all non-skipped waiver operations are handled
|
||||
# Waivers should have a hash value with keys possibly including "run" and
|
||||
# expiration_date. We only care here if it has a "run" key and it
|
||||
# is false-like, since all non-skipped waiver operations are handled
|
||||
# during reporting phase.
|
||||
return unless __waiver_data.key?("skip") && __waiver_data["skip"]
|
||||
return unless __waiver_data.key?("run") && !__waiver_data["run"]
|
||||
|
||||
# OK, the intent is to skip. Does it have an expiration date, and
|
||||
# if so, is it in the future?
|
||||
|
|
|
@ -96,6 +96,16 @@ module Inspec
|
|||
},
|
||||
},
|
||||
"results" => { "type" => "array", "items" => RESULT },
|
||||
"waiver_data" => {
|
||||
"type" => "object",
|
||||
"properties" => {
|
||||
"skipped_due_to_waiver" => { "type" => "string" },
|
||||
"run" => { "type" => "boolean" },
|
||||
"message" => { "type" => "string" },
|
||||
"expiration_date" => { "type" => "string" },
|
||||
"justification" => { "type" => "string" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}.freeze
|
||||
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
require "functional/helper"
|
||||
require "json-schema"
|
||||
require "inspec/schema"
|
||||
|
||||
describe "inspec exec with json formatter" do
|
||||
include FunctionalHelper
|
||||
let(:schema) { Inspec::Schema.json("exec-json") }
|
||||
|
||||
parallelize_me!
|
||||
|
||||
it "can execute a simple file and validate the json schema" do
|
||||
out = inspec("exec " + example_control + " --reporter json --no-create-lockfile")
|
||||
|
||||
data = JSON.parse(out.stdout)
|
||||
sout = inspec("schema exec-json")
|
||||
schema = JSON.parse(sout.stdout)
|
||||
_(JSON::Validator.validate(schema, data)).wont_equal false
|
||||
|
||||
_(out.stderr).must_equal ""
|
||||
|
@ -22,10 +21,7 @@ describe "inspec exec with json formatter" do
|
|||
|
||||
it "can execute a profile and validate the json schema" do
|
||||
out = inspec("exec " + example_profile + " --reporter json --no-create-lockfile")
|
||||
|
||||
data = JSON.parse(out.stdout)
|
||||
sout = inspec("schema exec-json")
|
||||
schema = JSON.parse(sout.stdout)
|
||||
_(JSON::Validator.validate(schema, data)).wont_equal false
|
||||
|
||||
_(out.stderr).must_equal ""
|
||||
|
@ -36,8 +32,6 @@ describe "inspec exec with json formatter" do
|
|||
it "can execute a simple file while using end of options after reporter cli option" do
|
||||
out = inspec("exec --no-create-lockfile --reporter json -- " + example_control)
|
||||
data = JSON.parse(out.stdout)
|
||||
sout = inspec("schema exec-json")
|
||||
schema = JSON.parse(sout.stdout)
|
||||
_(JSON::Validator.validate(schema, data)).wont_equal false
|
||||
|
||||
_(out.stderr).must_equal ""
|
||||
|
@ -50,8 +44,6 @@ describe "inspec exec with json formatter" do
|
|||
out = inspec("exec " + example_profile + " --reporter json --no-create-lockfile --target-id 1d3e399f-4d71-4863-ac54-84d437fbc444")
|
||||
data = JSON.parse(out.stdout)
|
||||
_(data["platform"]["target_id"]).must_equal "1d3e399f-4d71-4863-ac54-84d437fbc444"
|
||||
sout = inspec("schema exec-json")
|
||||
schema = JSON.parse(sout.stdout)
|
||||
_(JSON::Validator.validate(schema, data)).wont_equal false
|
||||
|
||||
_(out.stderr).must_equal ""
|
||||
|
@ -224,6 +216,7 @@ describe "inspec exec with json formatter" do
|
|||
"refs" => [{ "url" => "http://...", "ref" => "Document A-12" }],
|
||||
"tags" => { "data" => "temp data", "security" => nil },
|
||||
"code" => example_rb_code,
|
||||
"waiver_data" => {},
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,7 +20,7 @@ describe "waivers" do
|
|||
end
|
||||
|
||||
def waiver_data(control_id)
|
||||
controls_by_id.dig(control_id, "results", 0, "waiver_data")
|
||||
controls_by_id.dig(control_id, "waiver_data")
|
||||
end
|
||||
|
||||
def assert_waiver_annotation(control_id)
|
||||
|
@ -30,24 +30,26 @@ describe "waivers" do
|
|||
expiry = !!(control_id !~ /no_expiry/)
|
||||
in_past = !!(control_id =~ /in_past/)
|
||||
in_future = !!(control_id =~ /in_future/)
|
||||
skipped = !!(control_id !~ /not_skipped/)
|
||||
ran = !!(control_id !~ /not_ran/)
|
||||
|
||||
# higher logic
|
||||
waived = (!expiry && skipped) || (expiry && skipped && in_future)
|
||||
waived = (!expiry && !ran) || (expiry && !ran && in_future)
|
||||
# TODO: wasn't message was originally specced as being optional?
|
||||
has_message = expiry && skipped && in_past
|
||||
has_message = expiry && !ran && in_past
|
||||
|
||||
assert_instance_of Hash, act
|
||||
|
||||
assert_stringy act["justification"] # TODO: optional?
|
||||
assert_equal skipped, act["skip"]
|
||||
assert_equal ran, act["run"]
|
||||
assert_equal waived, act["skipped_due_to_waiver"]
|
||||
assert_stringy act["message"] if has_message
|
||||
assert_equal "", act["message"] unless has_message
|
||||
end
|
||||
|
||||
def refute_waiver_annotation(control_id)
|
||||
assert_nil waiver_data control_id
|
||||
act = waiver_data control_id
|
||||
assert_instance_of Hash, act
|
||||
assert_empty act
|
||||
end
|
||||
|
||||
def assert_skip_message(yea, nay)
|
||||
|
@ -64,15 +66,15 @@ describe "waivers" do
|
|||
{
|
||||
"01_not_waivered_passes" => "passed",
|
||||
"02_not_waivered_fails" => "failed",
|
||||
"03_waivered_no_expiry_not_skipped_passes" => "passed",
|
||||
"04_waivered_no_expiry_not_skipped_fails" => "failed",
|
||||
"05_waivered_no_expiry_skipped" => "skipped",
|
||||
"06_waivered_expiry_in_past_not_skipped_passes" => "passed",
|
||||
"07_waivered_expiry_in_past_not_skipped_fails" => "failed",
|
||||
"08_waivered_expiry_in_past_skipped" => "passed",
|
||||
"09_waivered_expiry_in_future_not_skipped_passes" => "passed",
|
||||
"10_waivered_expiry_in_future_not_skipped_fails" => "failed",
|
||||
"11_waivered_expiry_in_future_skipped" => "skipped",
|
||||
"03_waivered_no_expiry_ran_passes" => "passed",
|
||||
"04_waivered_no_expiry_ran_fails" => "failed",
|
||||
"05_waivered_no_expiry_not_ran" => "skipped",
|
||||
"06_waivered_expiry_in_past_ran_passes" => "passed",
|
||||
"07_waivered_expiry_in_past_ran_fails" => "failed",
|
||||
"08_waivered_expiry_in_past_not_ran" => "passed",
|
||||
"09_waivered_expiry_in_future_ran_passes" => "passed",
|
||||
"10_waivered_expiry_in_future_ran_fails" => "failed",
|
||||
"11_waivered_expiry_in_future_not_ran" => "skipped",
|
||||
}.each do |control_id, expected|
|
||||
it "has all of the expected outcomes #{control_id}" do
|
||||
assert_test_outcome expected, control_id
|
||||
|
@ -86,7 +88,30 @@ describe "waivers" do
|
|||
end
|
||||
end
|
||||
|
||||
# describe "an inherited profile"
|
||||
describe "an inherited profile" do
|
||||
let(:profile_name) { "waiver-wrapper" }
|
||||
let(:waiver_file) { "waivers.yaml" }
|
||||
it "should set the data in the child but be empty in the wrapper" do
|
||||
json = run_result.payload.json
|
||||
child_profile = json["profiles"].detect { |p| p["name"] == "waiver-child" }
|
||||
child_waiver_data = child_profile.dig("controls", 0, "waiver_data")
|
||||
assert_instance_of Hash, child_waiver_data
|
||||
refute_empty child_waiver_data
|
||||
expected_child_waiver_data = {
|
||||
"run" => false,
|
||||
"justification" => "I said so",
|
||||
"skipped_due_to_waiver" => true,
|
||||
"message" => "",
|
||||
}
|
||||
assert_equal expected_child_waiver_data, child_waiver_data
|
||||
|
||||
wrapper_profile = json["profiles"].detect { |p| p["name"] == "waiver-wrapper" }
|
||||
wrapper_waiver_data = wrapper_profile.dig("controls", 0, "waiver_data")
|
||||
assert_instance_of Hash, wrapper_waiver_data
|
||||
assert_empty wrapper_waiver_data
|
||||
end
|
||||
end
|
||||
|
||||
# describe "a profile whose control ids require transformation"
|
||||
|
||||
describe "a waiver file with invalid dates" do
|
||||
|
|
|
@ -6,38 +6,38 @@ control "02_not_waivered_fails" do
|
|||
describe(true) { it { should eq false } }
|
||||
end
|
||||
|
||||
control "03_waivered_no_expiry_not_skipped_passes" do
|
||||
control "03_waivered_no_expiry_ran_passes" do
|
||||
describe(true) { it { should eq true } }
|
||||
end
|
||||
|
||||
control "04_waivered_no_expiry_not_skipped_fails" do
|
||||
control "04_waivered_no_expiry_ran_fails" do
|
||||
describe(true) { it { should eq false } }
|
||||
end
|
||||
|
||||
control "05_waivered_no_expiry_skipped" do
|
||||
control "05_waivered_no_expiry_not_ran" do
|
||||
describe(true) { it { should eq true } }
|
||||
end
|
||||
|
||||
control "06_waivered_expiry_in_past_not_skipped_passes" do
|
||||
control "06_waivered_expiry_in_past_ran_passes" do
|
||||
describe(true) { it { should eq true } }
|
||||
end
|
||||
|
||||
control "07_waivered_expiry_in_past_not_skipped_fails" do
|
||||
control "07_waivered_expiry_in_past_ran_fails" do
|
||||
describe(true) { it { should eq false } }
|
||||
end
|
||||
|
||||
control "08_waivered_expiry_in_past_skipped" do
|
||||
control "08_waivered_expiry_in_past_not_ran" do
|
||||
describe(true) { it { should eq true } }
|
||||
end
|
||||
|
||||
control "09_waivered_expiry_in_future_not_skipped_passes" do
|
||||
control "09_waivered_expiry_in_future_ran_passes" do
|
||||
describe(true) { it { should eq true } }
|
||||
end
|
||||
|
||||
control "10_waivered_expiry_in_future_not_skipped_fails" do
|
||||
control "10_waivered_expiry_in_future_ran_fails" do
|
||||
describe(true) { it { should eq false } }
|
||||
end
|
||||
|
||||
control "11_waivered_expiry_in_future_skipped" do
|
||||
control "11_waivered_expiry_in_future_not_ran" do
|
||||
describe(true) { it { should eq true } }
|
||||
end
|
||||
|
|
|
@ -1,41 +1,41 @@
|
|||
03_waivered_no_expiry_not_skipped_passes:
|
||||
03_waivered_no_expiry_ran_passes:
|
||||
justification: Sound reasoning
|
||||
skip: no
|
||||
run: true
|
||||
|
||||
04_waivered_no_expiry_not_skipped_fails:
|
||||
04_waivered_no_expiry_ran_fails:
|
||||
justification: Unassailable thinking
|
||||
skip: no
|
||||
run: true
|
||||
|
||||
05_waivered_no_expiry_skipped:
|
||||
05_waivered_no_expiry_not_ran:
|
||||
justification: Sheer cleverness
|
||||
skip: yes
|
||||
run: false
|
||||
|
||||
06_waivered_expiry_in_past_not_skipped_passes:
|
||||
06_waivered_expiry_in_past_ran_passes:
|
||||
expiration_date: 1977-06-01
|
||||
justification: Necessity
|
||||
skip: no
|
||||
run: true
|
||||
|
||||
07_waivered_expiry_in_past_not_skipped_fails:
|
||||
07_waivered_expiry_in_past_ran_fails:
|
||||
expiration_date: 1977-06-01
|
||||
justification: Whimsy
|
||||
skip: no
|
||||
run: true
|
||||
|
||||
08_waivered_expiry_in_past_skipped:
|
||||
08_waivered_expiry_in_past_not_ran:
|
||||
expiration_date: 1977-06-01
|
||||
justification: Contrariness
|
||||
skip: yes
|
||||
run: false
|
||||
|
||||
09_waivered_expiry_in_future_not_skipped_passes:
|
||||
09_waivered_expiry_in_future_ran_passes:
|
||||
expiration_date: 2077-06-01
|
||||
justification: Handwaving
|
||||
skip: no
|
||||
run: true
|
||||
|
||||
10_waivered_expiry_in_future_not_skipped_fails:
|
||||
10_waivered_expiry_in_future_ran_fails:
|
||||
expiration_date: 2077-06-01
|
||||
justification: Didn't feel like it
|
||||
skip: no
|
||||
run: true
|
||||
|
||||
11_waivered_expiry_in_future_skipped:
|
||||
11_waivered_expiry_in_future_not_ran:
|
||||
expiration_date: 2077-06-01
|
||||
justification: Lack of imagination
|
||||
skip: yes
|
||||
run: false
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
01_only_if:
|
||||
skip: true
|
||||
run: false
|
||||
justification: test_message_from_waiver
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
01_small:
|
||||
expiration_date: never
|
||||
skip: true
|
||||
run: false
|
||||
justification: Callous disregard
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
control "waiver-child-01" do
|
||||
describe true do
|
||||
it { should cmp true }
|
||||
end
|
||||
end
|
4
test/unit/mock/profiles/waivers/waiver-child/inspec.yml
Normal file
4
test/unit/mock/profiles/waivers/waiver-child/inspec.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
name: waiver-child
|
||||
version: 0.1.0
|
||||
supports:
|
||||
platform: os
|
|
@ -0,0 +1 @@
|
|||
include_controls "waiver-child"
|
|
@ -0,0 +1,3 @@
|
|||
waiver-child-01:
|
||||
run: no
|
||||
justification: I said so
|
|
@ -0,0 +1,9 @@
|
|||
name: waiver-wrapper
|
||||
license: Apache-2.0
|
||||
summary: Verify waiver behavior under inheritance
|
||||
version: 0.1.0
|
||||
supports:
|
||||
platform: os
|
||||
depends:
|
||||
- name: waiver-child
|
||||
path: ../waiver-child
|
|
@ -1 +1,145 @@
|
|||
{"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"}
|
||||
{
|
||||
"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"
|
||||
},
|
||||
"waiver_data": {},
|
||||
"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"
|
||||
},
|
||||
"waiver_data": {},
|
||||
"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"
|
||||
},
|
||||
"waiver_data": {},
|
||||
"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,"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"}
|
||||
{"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"},"waiver_data":{},"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","waiver_data":{},"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":"","waiver_data":{},"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":"","waiver_data":{},"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,"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}}
|
||||
{"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"}],"waiver_data":{}},{"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"}],"waiver_data":{}},{"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"}],"waiver_data":{}},{"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\""}],"waiver_data":{}}],"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}}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
:code_desc: File /tmp should exist
|
||||
:run_time: 0.001313935
|
||||
:start_time: '2018-05-31T16:22:19+05:30'
|
||||
:waiver_data: {}
|
||||
:statistics:
|
||||
:duration: 0.002678506
|
||||
:version: 2.1.83
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -24,6 +24,7 @@
|
|||
:source_location:
|
||||
:line: 89
|
||||
:ref: "/home/frezbo/git/work/ruby/inspec/lib/inspec/control_eval_context.rb"
|
||||
:waiver_data: {}
|
||||
:results:
|
||||
- :status: passed
|
||||
:code_desc: File /tmp should exist
|
||||
|
|
|
@ -2,6 +2,8 @@ require "helper"
|
|||
require "inspec/reporters"
|
||||
|
||||
describe Inspec::Reporters::JsonAutomate do
|
||||
make_my_diffs_pretty!
|
||||
|
||||
let(:path) { File.expand_path(File.dirname(__FILE__)) }
|
||||
let(:report) do
|
||||
data = JSON.parse(File.read(path + "/../mock/reporters/run_data_wrapper.json"), symbolize_names: true)
|
||||
|
@ -12,8 +14,12 @@ describe Inspec::Reporters::JsonAutomate do
|
|||
describe "#render" do
|
||||
it "confirms render output" do
|
||||
output = File.read(path + "/../mock/reporters/json_merged_output")
|
||||
output = JSON.parse(output, symbolize_names: true)
|
||||
report.render
|
||||
_(report.rendered_output).must_equal output
|
||||
|
||||
actual = JSON.parse(report.rendered_output, symbolize_names: true)
|
||||
|
||||
_(actual).must_equal output
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ describe Inspec::Reporters::Json do
|
|||
it "confirm render output" do
|
||||
output = File.read(path + "/../mock/reporters/json_output")
|
||||
report.render
|
||||
_(report.rendered_output).must_equal output
|
||||
_(JSON.parse(report.rendered_output)).must_equal JSON.parse(output)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -92,6 +92,7 @@ describe Inspec::Reporters::Json do
|
|||
line: 89,
|
||||
ref: "/Users/jquick/Chef/inspec/lib/inspec/control_eval_context.rb",
|
||||
},
|
||||
waiver_data: {},
|
||||
}
|
||||
control = report.send(:profile_controls, profile).first
|
||||
control.delete(:results)
|
||||
|
|
Loading…
Add table
Reference in a new issue