Skip to content

Commit

Permalink
Implement an 'audit' reporter that will terminate Chef Client ru… (#380)
Browse files Browse the repository at this point in the history
Implement an 'audit' reporter that will terminate Chef Client runs on profile failures
  • Loading branch information
clintoncwolfe authored Jul 24, 2019
2 parents 776aa9f + b9c09ca commit b4ca5c7
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 2 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,16 @@ the Chef log:
[2017-08-29T00:22:10+00:00] INFO: Report handlers complete
```

#### Enforce compliance with executed profiles

The `audit-enforcer` enables you to enforce compliance with executed profiles. If the system under test is determined to be non-compliant, this reporter will raise an error and fail the Chef Client run. To activate compliance enforcement, set the `reporter` attribute to 'audit-enforcer':

```ruby
default['audit']['reporter'] = 'audit-enforcer'
```

Note that detection of non-compliance will immediately terminate the Chef Client run. If you specify [multiple reporters](#multiple-reporters), place the `audit-enforcer` at the end of the list, allowing the other reporters to generate their output prior to run termination.

#### Multiple Reporters

To enable multiple reporters, simply define multiple reporters with all the necessary information
Expand Down
2 changes: 2 additions & 0 deletions files/default/handler/audit_report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ def send_report(reporter, server, user, source_location, report)
path = node['audit']['json_file']['location']
Chef::Log.info "Writing report to #{path}"
Reporter::JsonFile.new(file: path).send_report(report)
elsif reporter == 'audit-enforcer'
Reporter::AuditEnforcer.new.send_report(report)
else
Chef::Log.warn "#{reporter} is not a supported InSpec report collector"
end
Expand Down
22 changes: 22 additions & 0 deletions libraries/reporters/audit-enforcer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# encoding: utf-8

module Reporter
#
# Used to raise an error on conformance failure
#
class AuditEnforcer
def send_report(report)
# iterate over each profile and control
report[:profiles].each do |profile|
next if profile[:controls].nil?
profile[:controls].each do |control|
next if control[:results].nil?
control[:results].each do |result|
raise "Audit #{control[:id]} has failed. Aborting chef-client run." if result[:status] == 'failed'
end
end
end
true
end
end
end
4 changes: 2 additions & 2 deletions metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
maintainer 'Chef Software, Inc.'
maintainer_email 'cookbooks@chef.io'
license 'Apache-2.0'
description 'Allows for fetching and executing compliance profiles, and reporting its results'
description 'Allows for fetching and executing compliance profiles, and reporting their results'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '8.0.0'
version '8.1.0'

source_url 'https://github.com/chef-cookbooks/audit'
issues_url 'https://github.com/chef-cookbooks/audit/issues'
Expand Down
53 changes: 53 additions & 0 deletions spec/unit/libraries/audit_enforcer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#
# Cookbook Name:: audit
# Spec:: automate_spec
#
# Copyright 2016 Chef Software, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require 'spec_helper'
require_relative '../../../libraries/reporters/audit-enforcer'

describe 'Reporter::ChefAutomate methods' do
before :each do
@min_report = {
"profiles": [
{
"controls": [
{ "id": 'c1', "results": [{ "status": 'passed' }] },
{ "id": 'c2', "results": [{ "status": 'passed' }] },
],
},
],
}
@automate = Reporter::AuditEnforcer.new
end

it 'is not raising error for a successful InSpec report' do
expect(@automate.send_report(@min_report)).to eq(true)
end

it 'is not raising error for an InSpec report with no controls' do
expect(@automate.send_report({ "profiles": [{ "name": 'empty' }] })).to eq(true)
end

it 'is not raising error for an InSpec report with controls but no results' do
expect(@automate.send_report({ "profiles": [{ "controls": [{ "id": 'empty' }] }] })).to eq(true)
end

it 'raises an error for a failed InSpec report' do
@min_report[:profiles][0][:controls][1][:results][0][:status] = 'failed'
expect { @automate.send_report(@min_report) }.to raise_error('Audit c2 has failed. Aborting chef-client run.')
end
end

0 comments on commit b4ca5c7

Please sign in to comment.