summaryrefslogtreecommitdiff
path: root/lib/chef
diff options
context:
space:
mode:
authorTim Smith <tsmith@chef.io>2018-09-21 15:04:09 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2019-03-11 12:20:20 -0700
commitdf23dbbda7d4eb621804f004ff85181d83a11641 (patch)
treedc4ac3d354e5b9eb3229ed9be56d5447cc9a1d85 /lib/chef
parentb870d8c578a6424e405ec2083d5f47d331f09d14 (diff)
downloadchef-df23dbbda7d4eb621804f004ff85181d83a11641.tar.gz
WIP: Remove audit mode from chef-client
This just gives us a line count to the change and perhaps a starting point for when we do this in Chef 15 Signed-off-by: Tim Smith <tsmith@chef.io> Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
Diffstat (limited to 'lib/chef')
-rw-r--r--lib/chef/application/client.rb23
-rw-r--r--lib/chef/application/exit_code.rb10
-rw-r--r--lib/chef/application/solo.rb3
-rw-r--r--lib/chef/audit/audit_event_proxy.rb93
-rw-r--r--lib/chef/audit/audit_reporter.rb176
-rw-r--r--lib/chef/audit/control_group_data.rb145
-rw-r--r--lib/chef/audit/logger.rb36
-rw-r--r--lib/chef/audit/rspec_formatter.rb37
-rw-r--r--lib/chef/audit/runner.rb196
-rw-r--r--lib/chef/client.rb107
-rw-r--r--lib/chef/dsl/audit.rb51
-rw-r--r--lib/chef/dsl/recipe.rb2
-rw-r--r--lib/chef/event_dispatch/base.rb31
-rw-r--r--lib/chef/exceptions.rb21
-rw-r--r--lib/chef/formatters/doc.rb48
-rw-r--r--lib/chef/mixin/properties.rb5
-rw-r--r--lib/chef/run_context.rb8
17 files changed, 14 insertions, 978 deletions
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index 0e5584ded3..cdeb376f96 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -272,11 +272,6 @@ class Chef::Application::Client < Chef::Application
boolean: true
end
- option :audit_mode,
- long: "--audit-mode MODE",
- description: "Enable audit-mode with `enabled`. Disable audit-mode with `disabled`. Skip converge and only perform audits with `audit-only`",
- proc: lambda { |mo| mo.tr("-", "_").to_sym }
-
option :minimal_ohai,
long: "--minimal-ohai",
description: "Only run the bare minimum ohai plugins chef needs to function",
@@ -374,13 +369,6 @@ class Chef::Application::Client < Chef::Application
config_fetcher = Chef::ConfigFetcher.new(Chef::Config[:json_attribs])
@chef_client_json = config_fetcher.fetch_json
end
-
- if mode = config[:audit_mode] || Chef::Config[:audit_mode]
- expected_modes = [:enabled, :disabled, :audit_only]
- unless expected_modes.include?(mode)
- Chef::Application.fatal!(unrecognized_audit_mode(mode))
- end
- end
end
def load_config_file
@@ -521,17 +509,6 @@ class Chef::Application::Client < Chef::Application
"\nEnable chef-client interval runs by setting `:client_fork = true` in your config file or adding `--fork` to your command line options."
end
- def audit_mode_settings_explanation
- "\n* To enable audit mode after converge, use command line option `--audit-mode enabled` or set `audit_mode :enabled` in your config file." +
- "\n* To disable audit mode, use command line option `--audit-mode disabled` or set `audit_mode :disabled` in your config file." +
- "\n* To only run audit mode, use command line option `--audit-mode audit-only` or set `audit_mode :audit_only` in your config file." +
- "\nAudit mode is disabled by default."
- end
-
- def unrecognized_audit_mode(mode)
- "Unrecognized setting #{mode} for audit mode." + audit_mode_settings_explanation
- end
-
def fetch_recipe_tarball(url, path)
Chef::Log.trace("Download recipes tarball from #{url} to #{path}")
if File.exist?(url)
diff --git a/lib/chef/application/exit_code.rb b/lib/chef/application/exit_code.rb
index c87592f06b..6c9618fcb4 100644
--- a/lib/chef/application/exit_code.rb
+++ b/lib/chef/application/exit_code.rb
@@ -34,7 +34,7 @@ class Chef
REBOOT_SCHEDULED: 35,
REBOOT_NEEDED: 37,
REBOOT_FAILED: 41,
- AUDIT_MODE_FAILURE: 42,
+ # 42 was used by audit mode and should not be reused
CLIENT_UPGRADED: 213,
}.freeze
@@ -78,8 +78,6 @@ class Chef
VALID_RFC_062_EXIT_CODES[:REBOOT_NEEDED]
elsif reboot_failed?(exception)
VALID_RFC_062_EXIT_CODES[:REBOOT_FAILED]
- elsif audit_failure?(exception)
- VALID_RFC_062_EXIT_CODES[:AUDIT_MODE_FAILURE]
elsif client_upgraded?(exception)
VALID_RFC_062_EXIT_CODES[:CLIENT_UPGRADED]
else
@@ -105,12 +103,6 @@ class Chef
end
end
- def audit_failure?(exception)
- resolve_exception_array(exception).any? do |e|
- e.is_a? Chef::Exceptions::AuditError
- end
- end
-
def client_upgraded?(exception)
resolve_exception_array(exception).any? do |e|
e.is_a? Chef::Exceptions::ClientUpgraded
diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb
index 763d52226a..148e7720a5 100644
--- a/lib/chef/application/solo.rb
+++ b/lib/chef/application/solo.rb
@@ -288,9 +288,6 @@ class Chef::Application::Solo < Chef::Application
config_fetcher = Chef::ConfigFetcher.new(Chef::Config[:json_attribs])
@chef_client_json = config_fetcher.fetch_json
end
-
- # Disable auditing for solo
- Chef::Config[:audit_mode] = :disabled
end
def setup_application
diff --git a/lib/chef/audit/audit_event_proxy.rb b/lib/chef/audit/audit_event_proxy.rb
deleted file mode 100644
index 1cb8545d28..0000000000
--- a/lib/chef/audit/audit_event_proxy.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-#
-# Author:: Tyler Ball (<tball@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
-# License:: Apache License, Version 2.0
-#
-# 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.
-#
-
-RSpec::Support.require_rspec_core "formatters/base_text_formatter"
-
-class Chef
- class Audit
- class AuditEventProxy < ::RSpec::Core::Formatters::BaseFormatter
- ::RSpec::Core::Formatters.register self, :stop, :example_group_started
-
- # TODO I don't like this, but I don't see another way to pass this in
- # see rspec files configuration.rb#L671 and formatters.rb#L129
- def self.events=(events)
- @@events = events
- end
-
- def events
- @@events
- end
-
- def example_group_started(notification)
- if notification.group.parent_groups.size == 1
- # top level `control_group` block
- desc = notification.group.description
- Chef::Log.trace("Entered `control_group` block named #{desc}")
- events.control_group_started(desc)
- end
- end
-
- def stop(notification)
- Chef::Log.info("Successfully executed all `control_group` blocks and contained examples")
- notification.examples.each do |example|
- control_group_name, control_data = build_control_from(example)
- e = example.exception
- if e
- events.control_example_failure(control_group_name, control_data, e)
- else
- events.control_example_success(control_group_name, control_data)
- end
- end
- end
-
- private
-
- def build_control_from(example)
- described_class = example.metadata[:described_class]
- if described_class
- resource_type = described_class.class.name.split(":")[-1]
- resource_name = described_class.name
- end
-
- # The following code builds up the context - the list of wrapping `describe` or `control` blocks
- describe_groups = []
- group = example.metadata[:example_group]
- # If the innermost block has a resource instead of a string, don't include it in context
- describe_groups.unshift(group[:description]) if described_class.nil?
- group = group[:parent_example_group]
- until group.nil?
- describe_groups.unshift(group[:description])
- group = group[:parent_example_group]
- end
-
- # We know all of our examples each live in a top-level `control_group` block - get this name now
- outermost_group_desc = describe_groups.shift
-
- [outermost_group_desc, {
- name: example.description,
- desc: example.full_description,
- resource_type: resource_type,
- resource_name: resource_name,
- context: describe_groups,
- line_number: example.metadata[:line_number],
- }]
- end
-
- end
- end
-end
diff --git a/lib/chef/audit/audit_reporter.rb b/lib/chef/audit/audit_reporter.rb
deleted file mode 100644
index 40f1f9ffd7..0000000000
--- a/lib/chef/audit/audit_reporter.rb
+++ /dev/null
@@ -1,176 +0,0 @@
-#
-# Author:: Tyler Ball (<tball@chef.io>)
-#
-# Copyright:: Copyright 2014-2018, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# 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 "chef/event_dispatch/base"
-require "chef/audit/control_group_data"
-require "time"
-
-class Chef
- class Audit
- class AuditReporter < EventDispatch::Base
-
- attr_reader :rest_client, :audit_data, :ordered_control_groups, :run_status
- private :rest_client, :audit_data, :ordered_control_groups, :run_status
-
- PROTOCOL_VERSION = "0.1.1".freeze
-
- def initialize(rest_client)
- @rest_client = rest_client
- # Ruby 1.9.3 and above "enumerate their values in the order that the corresponding keys were inserted."
- @ordered_control_groups = Hash.new
- @audit_phase_error = nil
- end
-
- def run_context
- run_status.run_context
- end
-
- def audit_phase_start(run_status)
- Chef::Log.trace("Audit Reporter starting")
- @audit_data = AuditData.new(run_status.node.name, run_status.run_id)
- @run_status = run_status
- end
-
- def audit_phase_complete(audit_output)
- Chef::Log.trace("Audit Reporter completed successfully without errors.")
- ordered_control_groups.each_value do |control_group|
- audit_data.add_control_group(control_group)
- end
- end
-
- # If the audit phase failed, its because there was some kind of error in the framework
- # that runs tests - normal errors are interpreted as EXAMPLE failures and captured.
- # We still want to send available audit information to the server so we process the
- # known control groups.
- def audit_phase_failed(error, audit_output)
- # The stacktrace information has already been logged elsewhere
- @audit_phase_error = error
- Chef::Log.trace("Audit Reporter failed.")
- ordered_control_groups.each_value do |control_group|
- audit_data.add_control_group(control_group)
- end
- end
-
- def run_completed(node)
- post_auditing_data
- end
-
- def run_failed(error)
- # Audit phase errors are captured when audit_phase_failed gets called.
- # The error passed here isn't relevant to auditing, so we ignore it.
- post_auditing_data
- end
-
- def control_group_started(name)
- if ordered_control_groups.key?(name)
- raise Chef::Exceptions::AuditControlGroupDuplicate.new(name)
- end
- metadata = run_context.audits[name].metadata
- ordered_control_groups.store(name, ControlGroupData.new(name, metadata))
- end
-
- def control_example_success(control_group_name, example_data)
- control_group = ordered_control_groups[control_group_name]
- control_group.example_success(example_data)
- end
-
- def control_example_failure(control_group_name, example_data, error)
- control_group = ordered_control_groups[control_group_name]
- control_group.example_failure(example_data, error.message)
- end
-
- # If @audit_enabled is nil or true, we want to run audits
- def auditing_enabled?
- Chef::Config[:audit_mode] != :disabled
- end
-
- private
-
- def post_auditing_data
- unless auditing_enabled?
- Chef::Log.trace("Audit Reports are disabled. Skipping sending reports.")
- return
- end
-
- unless run_status
- Chef::Log.trace("Run failed before audit mode was initialized, not sending audit report to server")
- return
- end
-
- audit_data.start_time = iso8601ify(run_status.start_time)
- audit_data.end_time = iso8601ify(run_status.end_time)
-
- audit_history_url = "controls"
- Chef::Log.trace("Sending audit report (run-id: #{audit_data.run_id})")
- run_data = audit_data.to_h
-
- if @audit_phase_error
- error_info = "#{@audit_phase_error.class}: #{@audit_phase_error.message}"
- error_info << "\n#{@audit_phase_error.backtrace.join("\n")}" if @audit_phase_error.backtrace
- run_data[:error] = error_info
- end
-
- Chef::Log.trace "Audit Report:\n#{Chef::JSONCompat.to_json_pretty(run_data)}"
- begin
- rest_client.post(audit_history_url, run_data, headers)
- rescue StandardError => e
- if e.respond_to? :response
- # 404 error code is OK. This means the version of server we're running against doesn't support
- # audit reporting. Don't alarm failure in this case.
- if e.response.code == "404"
- Chef::Log.trace("Server doesn't support audit reporting. Skipping report.")
- return
- else
- # Save the audit report to local disk
- error_file = "failed-audit-data.json"
- Chef::FileCache.store(error_file, Chef::JSONCompat.to_json_pretty(run_data), 0640)
- if Chef::Config.chef_zero.enabled
- Chef::Log.trace("Saving audit report to #{Chef::FileCache.load(error_file, false)}")
- else
- Chef::Log.error("Failed to post audit report to server. Saving report to #{Chef::FileCache.load(error_file, false)}")
- end
- end
- else
- Chef::Log.error("Failed to post audit report to server (#{e})")
- end
-
- if Chef::Config[:enable_reporting_url_fatals]
- Chef::Log.error("Reporting fatals enabled. Aborting run.")
- raise
- end
- end
- end
-
- def headers(additional_headers = {})
- options = { "X-Ops-Audit-Report-Protocol-Version" => PROTOCOL_VERSION }
- options.merge(additional_headers)
- end
-
- def encode_gzip(data)
- "".tap do |out|
- Zlib::GzipWriter.wrap(StringIO.new(out)) { |gz| gz << data }
- end
- end
-
- def iso8601ify(time)
- time.utc.iso8601.to_s
- end
- end
- end
-end
diff --git a/lib/chef/audit/control_group_data.rb b/lib/chef/audit/control_group_data.rb
deleted file mode 100644
index 63f301da02..0000000000
--- a/lib/chef/audit/control_group_data.rb
+++ /dev/null
@@ -1,145 +0,0 @@
-#
-# Author:: Tyler Ball (<tball@chef.io>)
-#
-# Copyright:: Copyright 2014-2018, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# 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 "securerandom"
-
-class Chef
- class Audit
- class AuditData
- attr_reader :node_name, :run_id, :control_groups
- attr_accessor :start_time, :end_time
-
- def initialize(node_name, run_id)
- @node_name = node_name
- @run_id = run_id
- @control_groups = []
- end
-
- def add_control_group(control_group)
- control_groups << control_group
- end
-
- def to_h
- {
- node_name: node_name,
- run_id: run_id,
- start_time: start_time,
- end_time: end_time,
- control_groups: control_groups.collect { |c| c.to_h },
- }
- end
-
- alias_method :to_hash, :to_h
- end
-
- class ControlGroupData
- attr_reader :name, :status, :number_succeeded, :number_failed, :controls, :metadata
-
- def initialize(name, metadata = {})
- @status = "success"
- @controls = []
- @number_succeeded = 0
- @number_failed = 0
- @name = name
- @metadata = metadata
- end
-
- def example_success(control_data)
- @number_succeeded += 1
- control = create_control(control_data)
- control.status = "success"
- controls << control
- control
- end
-
- def example_failure(control_data, details)
- @number_failed += 1
- @status = "failure"
- control = create_control(control_data)
- control.details = details if details
- control.status = "failure"
- controls << control
- control
- end
-
- def to_h
- # We sort it so the examples appear in the output in the same order
- # they appeared in the recipe
- controls.sort! { |x, y| x.line_number <=> y.line_number }
- h = {
- name: name,
- status: status,
- number_succeeded: number_succeeded,
- number_failed: number_failed,
- controls: controls.collect { |c| c.to_h },
- }
- # If there is a duplicate key, metadata will overwrite it
- add_display_only_data(h).merge(metadata)
- end
-
- alias_method :to_hash, :to_h
-
- private
-
- def create_control(control_data)
- ControlData.new(control_data)
- end
-
- # The id and control sequence number are ephemeral data - they are not needed
- # to be persisted and can be regenerated at will. They are only needed
- # for display purposes.
- def add_display_only_data(group)
- group[:id] = SecureRandom.uuid
- group[:controls].collect!.with_index do |c, i|
- # i is zero-indexed, and we want the display one-indexed
- c[:sequence_number] = i + 1
- c
- end
- group
- end
-
- end
-
- class ControlData
- attr_reader :name, :resource_type, :resource_name, :context, :line_number
- attr_accessor :status, :details
-
- def initialize(control_data = {})
- control_data.each do |k, v|
- instance_variable_set("@#{k}", v)
- end
- end
-
- def to_h
- h = {
- name: name,
- status: status,
- details: details,
- resource_type: resource_type,
- resource_name: resource_name,
- }
- h[:context] = context || []
- h
- end
-
- alias_method :to_hash, :to_h
- end
-
- end
-end
diff --git a/lib/chef/audit/logger.rb b/lib/chef/audit/logger.rb
deleted file mode 100644
index 759683ccc8..0000000000
--- a/lib/chef/audit/logger.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
-# License:: Apache License, Version 2.0
-#
-# 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 "stringio"
-
-class Chef
- class Audit
- class Logger
- def self.puts(message = "")
- @buffer ||= StringIO.new
- @buffer.puts(message)
-
- Chef::Log.info(message)
- end
-
- def self.read_buffer
- return "" if @buffer.nil?
- @buffer.string
- end
- end
- end
-end
diff --git a/lib/chef/audit/rspec_formatter.rb b/lib/chef/audit/rspec_formatter.rb
deleted file mode 100644
index 234202b684..0000000000
--- a/lib/chef/audit/rspec_formatter.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Author:: Serdar Sutay (<serdar@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
-# License:: Apache License, Version 2.0
-#
-# 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 "rspec/core"
-
-class Chef
- class Audit
- class RspecFormatter < RSpec::Core::Formatters::DocumentationFormatter
- RSpec::Core::Formatters.register self, :close
-
- # @api public
- #
- # Invoked at the very end, `close` allows the formatter to clean
- # up resources, e.g. open streams, etc.
- #
- # @param _notification [NullNotification] (Ignored)
- def close(_notification)
- # Normally Rspec closes the streams it's given. We don't want it for Chef.
- end
- end
- end
-end
diff --git a/lib/chef/audit/runner.rb b/lib/chef/audit/runner.rb
deleted file mode 100644
index 847d5efbd5..0000000000
--- a/lib/chef/audit/runner.rb
+++ /dev/null
@@ -1,196 +0,0 @@
-#
-# Author:: Claire McQuin (<claire@chef.io>)
-# Copyright:: Copyright 2014-2018, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# 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 "chef/audit/logger"
-
-class Chef
- class Audit
- class Runner
-
- attr_reader :run_context
- private :run_context
-
- def initialize(run_context)
- @run_context = run_context
- end
-
- def run
- setup
- register_control_groups
- do_run
- end
-
- def failed?
- RSpec.world.reporter.failed_examples.size > 0
- end
-
- def num_failed
- RSpec.world.reporter.failed_examples.size
- end
-
- def num_total
- RSpec.world.reporter.examples.size
- end
-
- def exclusion_pattern
- Regexp.new(".+[\\\/]lib[\\\/]chef[\\\/]")
- end
-
- private
-
- # Prepare to run audits:
- # - Require files
- # - Configure RSpec
- # - Configure Specinfra/Serverspec
- def setup
- require_deps
- configure_rspec
- configure_specinfra
- end
-
- # RSpec uses a global configuration object, RSpec.configuration. We found
- # there was interference between the configuration for audit-mode and
- # the configuration for our own spec tests in these cases:
- # 1. Specinfra and Serverspec modify RSpec.configuration when loading.
- # 2. Setting output/error streams.
- # 3. Adding formatters.
- # 4. Defining example group aliases.
- #
- # Moreover, Serverspec loads its DSL methods into the global namespace,
- # which causes conflicts with the Chef namespace for resources and packages.
- #
- # We wait until we're in the audit-phase of the chef-client run to load
- # these files. This helps with the namespacing problems we saw, and
- # prevents Specinfra and Serverspec from modifying the RSpec configuration
- # used by our spec tests.
- def require_deps
- require "rspec"
- require "rspec/its"
- require "specinfra"
- require "specinfra/helper"
- require "specinfra/helper/set"
- require "serverspec/helper"
- require "serverspec/matcher"
- require "serverspec/subject"
- require "chef/audit/audit_event_proxy"
- require "chef/audit/rspec_formatter"
-
- Specinfra::Backend::Cmd.send(:include, Specinfra::Helper::Set)
- end
-
- # Configure RSpec just the way we like it:
- # - Set location of error and output streams
- # - Add custom audit-mode formatters
- # - Explicitly disable :should syntax
- # - Set :color option according to chef config
- # - Disable exposure of global DSL
- def configure_rspec
- set_streams
- add_formatters
- disable_should_syntax
-
- RSpec.configure do |c|
- c.color = Chef::Config[:color]
- c.expose_dsl_globally = false
- c.project_source_dirs = Array(Chef::Config[:cookbook_path])
- c.backtrace_exclusion_patterns << exclusion_pattern
- end
- end
-
- # Set the error and output streams which audit-mode will use to report
- # human-readable audit information.
- #
- # This should always be called before #add_formatters. RSpec won't allow
- # the output stream to be changed for a formatter once the formatter has
- # been added.
- def set_streams
- RSpec.configuration.output_stream = Chef::Audit::Logger
- RSpec.configuration.error_stream = Chef::Audit::Logger
- end
-
- # Add formatters which we use to
- # 1. Output human-readable data to the output stream,
- # 2. Collect JSON data to send back to the analytics server.
- def add_formatters
- RSpec.configuration.add_formatter(Chef::Audit::AuditEventProxy)
- RSpec.configuration.add_formatter(Chef::Audit::RspecFormatter)
- Chef::Audit::AuditEventProxy.events = run_context.events
- end
-
- # Audit-mode uses RSpec 3. :should syntax is deprecated by default in
- # RSpec 3, so we explicitly disable it here.
- #
- # This can be removed once :should is removed from RSpec.
- def disable_should_syntax
- RSpec.configure do |config|
- config.expect_with :rspec do |c|
- c.syntax = :expect
- end
- end
- end
-
- # Set up the backend for Specinfra/Serverspec. :exec is the local system; on Windows, it is :cmd
- def configure_specinfra
- if Chef::Platform.windows?
- Specinfra.configuration.backend = :cmd
- Specinfra.configuration.os = { family: "windows" }
- else
- Specinfra.configuration.backend = :exec
- end
- end
-
- # Iterates through the control groups registered to this run_context, builds an
- # example group (RSpec::Core::ExampleGroup) object per control group, and
- # registers the group with the RSpec.world.
- #
- # We could just store an array of example groups and not use RSpec.world,
- # but it may be useful later if we decide to apply our own ordering scheme
- # or use example group filters.
- def register_control_groups
- add_example_group_methods
- run_context.audits.each do |name, group| # rubocop:disable Performance/HashEachMethods
- ctl_grp = RSpec::Core::ExampleGroup.__control_group__(*group.args, &group.block)
- RSpec.world.record(ctl_grp)
- end
- end
-
- # Add example group method aliases to RSpec.
- #
- # __control_group__: Used internally to create example groups from the control
- # groups saved in the run_context.
- # control: Used within the context of a control group block, like RSpec's
- # describe or context.
- def add_example_group_methods
- RSpec::Core::ExampleGroup.define_example_group_method :__control_group__
- RSpec::Core::ExampleGroup.define_example_group_method :control
- end
-
- # Run the audits!
- def do_run
- # RSpec::Core::Runner wants to be initialized with an
- # RSpec::Core::ConfigurationOptions object, which is used to process
- # command line configuration arguments. We directly fiddle with the
- # internal RSpec configuration object, so we give nil here and let
- # RSpec pick up its own configuration and world.
- runner = RSpec::Core::Runner.new(nil)
- runner.run_specs(RSpec.world.ordered_example_groups)
- end
-
- end
- end
-end
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index 0dd6b2666f..3c1921e8dc 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -26,7 +26,6 @@ require "chef/deprecated"
require "chef/server_api"
require "chef/api_client"
require "chef/api_client/registration"
-require "chef/audit/runner"
require "chef/node"
require "chef/role"
require "chef/file_cache"
@@ -48,7 +47,6 @@ require "chef/version"
require "chef/action_collection"
require "chef/resource_reporter"
require "chef/data_collector"
-require "chef/audit/audit_reporter"
require "chef/run_lock"
require "chef/policy_builder"
require "chef/request_id"
@@ -219,23 +217,6 @@ class Chef
# @see #converge_and_save
# @see Chef::Runner
#
- # Phase 4: Audit
- # --------------
- # Runs 'control_group' audits in recipes. This entire section can be enabled or disabled with config.
- #
- # 1. 'control_group' DSL collects audits during Phase 2
- # 2. Audits are run using RSpec
- # 3. Errors are collected and reported using the formatters
- #
- # @see #run_audits
- # @see Chef::Audit::Runner#run
- #
- # @raise [Chef::Exceptions::RunFailedWrappingError] If converge or audit failed.
- #
- # @see Chef::Config#enforce_path_sanity
- # @see Chef::Config#solo
- # @see Chef::Config#audit_mode
- #
# @return Always returns true.
#
def run
@@ -284,16 +265,7 @@ class Chef
load_required_recipe(@rest, run_context) unless Chef::Config[:solo_legacy_mode]
- if Chef::Config[:audit_mode] != :audit_only
- converge_error = converge_and_save(run_context)
- end
-
- if Chef::Config[:why_run] == true
- # why_run should probably be renamed to why_converge
- logger.debug("Not running controls in 'why-run' mode - this mode is used to see potential converge changes")
- elsif Chef::Config[:audit_mode] != :disabled
- audit_error = run_audits(run_context)
- end
+ converge_error = converge_and_save(run_context)
# Raise converge_error so run_failed reporters/events are processed.
raise converge_error if converge_error
@@ -324,22 +296,11 @@ class Chef
runlock.release
end
- # Raise audit, converge, and other errors here so that we exit
+ # Raise converge, and other errors here so that we exit
# with the proper exit status code and everything gets raised
# as a RunFailedWrappingError
- if run_error || converge_error || audit_error
- error = if Chef::Config[:audit_mode] == :disabled
- run_error || converge_error
- else
- e = if run_error == converge_error
- Chef::Exceptions::RunFailedWrappingError.new(converge_error, audit_error)
- else
- Chef::Exceptions::RunFailedWrappingError.new(run_error, converge_error, audit_error)
- end
- e.fill_backtrace
- e
- end
-
+ if run_error || converge_error
+ error = run_error || converge_error
Chef::Application.debug_stacktrace(error)
raise error
end
@@ -349,7 +310,7 @@ class Chef
#
# Private API
- # TODO make this stuff protected or private
+ # @todo make this stuff protected or private
#
# @api private
@@ -417,8 +378,7 @@ class Chef
# @api private
def register_reporters
[
- Chef::ResourceReporter.new(rest_clean),
- Chef::Audit::AuditReporter.new(rest_clean),
+ Chef::ResourceReporter.new(rest_clean)
].each do |r|
events.register(r)
end
@@ -695,14 +655,9 @@ class Chef
#
# @param run_context The run context.
#
- # @return The thrown exception, if we are in audit mode. `nil` means the
- # converge was successful or ended early.
- #
- # @raise Any converge exception, unless we are in audit mode, in which case
- # we *return* the exception.
+ # @raise Any converge exception
#
# @see Chef::Runner#converge
- # @see Chef::Config#audit_mode
# @see Chef::EventDispatch#converge_start
# @see Chef::EventDispatch#converge_complete
# @see Chef::EventDispatch#converge_failed
@@ -720,7 +675,6 @@ class Chef
events.converge_complete
rescue Exception => e
events.converge_failed(e)
- raise e if Chef::Config[:audit_mode] == :disabled
converge_exception = e
end
end
@@ -732,15 +686,10 @@ class Chef
#
# @param run_context The run context.
#
- # @return The thrown exception, if we are in audit mode. `nil` means the
- # converge was successful or ended early.
- #
- # @raise Any converge or node save exception, unless we are in audit mode,
- # in which case we *return* the exception.
+ # @raise Any converge or node save exception
#
# @see #converge
# @see #save_updated_mode
- # @see Chef::Config#audit_mode
#
# @api private
#
@@ -755,51 +704,13 @@ class Chef
begin
save_updated_node
rescue Exception => e
- raise e if Chef::Config[:audit_mode] == :disabled
- converge_exception = e
+ raise e
end
end
converge_exception
end
#
- # Run the audit phase.
- #
- # Triggers the audit_phase_start, audit_phase_complete and
- # audit_phase_failed events.
- #
- # @param run_context The run context.
- #
- # @return Any thrown exceptions. `nil` if successful.
- #
- # @see Chef::Audit::Runner#run
- # @see Chef::EventDispatch#audit_phase_start
- # @see Chef::EventDispatch#audit_phase_complete
- # @see Chef::EventDispatch#audit_phase_failed
- #
- # @api private
- #
- def run_audits(run_context)
- begin
- events.audit_phase_start(run_status)
- logger.info("Starting audit phase")
- auditor = Chef::Audit::Runner.new(run_context)
- auditor.run
- if auditor.failed?
- audit_exception = Chef::Exceptions::AuditsFailed.new(auditor.num_failed, auditor.num_total)
- @events.audit_phase_failed(audit_exception, Chef::Audit::Logger.read_buffer)
- else
- @events.audit_phase_complete(Chef::Audit::Logger.read_buffer)
- end
- rescue Exception => e
- logger.error("Audit phase failed with error message: #{e.message}")
- @events.audit_phase_failed(e, Chef::Audit::Logger.read_buffer)
- audit_exception = e
- end
- audit_exception
- end
-
- #
# Expands the run list.
#
# @return [Chef::RunListExpansion] The expanded run list.
diff --git a/lib/chef/dsl/audit.rb b/lib/chef/dsl/audit.rb
deleted file mode 100644
index 927523e976..0000000000
--- a/lib/chef/dsl/audit.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Author:: Tyler Ball (<tball@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# 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 "chef/exceptions"
-
-class Chef
- module DSL
- module Audit
-
- # Can encompass tests in a `control` block or `describe` block
- # Adds the controls group and block (containing controls to execute) to the runner's list of pending examples
- def control_group(*args, &block)
- raise Chef::Exceptions::NoAuditsProvided unless block
-
- name = args[0]
- if name.nil? || name.empty?
- raise Chef::Exceptions::AuditNameMissing
- elsif run_context.audits.key?(name)
- raise Chef::Exceptions::AuditControlGroupDuplicate.new(name)
- end
-
- # This DSL will only work in the Recipe class because that exposes the cookbook_name
- cookbook_name = self.cookbook_name
- metadata = {
- cookbook_name: cookbook_name,
- cookbook_version: run_context.cookbook_collection[cookbook_name].version,
- recipe_name: recipe_name,
- line_number: block.source_location[1],
- }
-
- run_context.audits[name] = Struct.new(:args, :block, :metadata).new(args, block, metadata)
- end
-
- end
- end
-end
diff --git a/lib/chef/dsl/recipe.rb b/lib/chef/dsl/recipe.rb
index 9da812cec0..4d68a36a81 100644
--- a/lib/chef/dsl/recipe.rb
+++ b/lib/chef/dsl/recipe.rb
@@ -24,7 +24,6 @@ require "chef/dsl/data_query"
require "chef/dsl/include_recipe"
require "chef/dsl/registry_helper"
require "chef/dsl/reboot_pending"
-require "chef/dsl/audit"
require "chef/dsl/powershell"
require "chef/dsl/core"
require "chef/mixin/lazy_module_include"
@@ -55,7 +54,6 @@ class Chef
include Chef::DSL::IncludeRecipe
include Chef::DSL::RegistryHelper
include Chef::DSL::RebootPending
- include Chef::DSL::Audit
include Chef::DSL::Powershell
include Chef::DSL::Resources
include Chef::DSL::Definitions
diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb
index 3b0b70c9b9..be51cf362f 100644
--- a/lib/chef/event_dispatch/base.rb
+++ b/lib/chef/event_dispatch/base.rb
@@ -292,37 +292,6 @@ class Chef
def converge_failed(exception)
end
- ##################################
- # Audit Mode Events
- # This phase is currently experimental and these event APIs are subject to change
- ##################################
-
- # Called before audit phase starts
- def audit_phase_start(run_status)
- end
-
- # Called when audit phase successfully finishes
- def audit_phase_complete(audit_output)
- end
-
- # Called if there is an uncaught exception during the audit phase. The audit runner should
- # be catching and handling errors from the examples, so this is only uncaught errors (like
- # bugs in our handling code)
- def audit_phase_failed(exception, audit_output)
- end
-
- # Signifies the start of a `control_group` block with a defined name
- def control_group_started(name)
- end
-
- # An example in a `control_group` block completed successfully
- def control_example_success(control_group_name, example_data)
- end
-
- # An example in a `control_group` block failed with the provided error
- def control_example_failure(control_group_name, example_data, error)
- end
-
# TODO: need events for notification resolve?
# def notifications_resolved
# end
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb
index 41e0cdb33e..0a6c7dc635 100644
--- a/lib/chef/exceptions.rb
+++ b/lib/chef/exceptions.rb
@@ -443,26 +443,7 @@ class Chef
end
end
- class AuditError < RuntimeError; end
-
- class AuditControlGroupDuplicate < AuditError
- def initialize(name)
- super "Control group with name '#{name}' has already been defined"
- end
- end
- class AuditNameMissing < AuditError; end
- class NoAuditsProvided < AuditError
- def initialize
- super "You must provide a block with controls"
- end
- end
- class AuditsFailed < AuditError
- def initialize(num_failed, num_total)
- super "Audit phase found failures - #{num_failed}/#{num_total} controls failed"
- end
- end
-
- # If a converge or audit fails, we want to wrap the output from those errors into 1 error so we can
+ # If a converge fails, we want to wrap the output from those errors into 1 error so we can
# see both issues in the output. It is possible that nil will be provided. You must call `fill_backtrace`
# to correctly populate the backtrace with the wrapped backtraces.
class RunFailedWrappingError < RuntimeError
diff --git a/lib/chef/formatters/doc.rb b/lib/chef/formatters/doc.rb
index 936738f147..0b0a589d56 100644
--- a/lib/chef/formatters/doc.rb
+++ b/lib/chef/formatters/doc.rb
@@ -8,8 +8,7 @@ class Chef
# show context.
class Doc < Formatters::Base
- attr_reader :start_time, :end_time, :successful_audits, :failed_audits
- private :successful_audits, :failed_audits
+ attr_reader :start_time, :end_time
cli_name(:doc)
@@ -18,8 +17,6 @@ class Chef
@updated_resources = 0
@up_to_date_resources = 0
- @successful_audits = 0
- @failed_audits = 0
@start_time = Time.now
@end_time = @start_time
@skipped_resources = 0
@@ -51,10 +48,6 @@ class Chef
@up_to_date_resources + @updated_resources + @skipped_resources
end
- def total_audits
- successful_audits + failed_audits
- end
-
def run_completed(node)
@end_time = Time.now
# Print out deprecations.
@@ -85,9 +78,6 @@ class Chef
puts_line "Chef Client finished, #{@updated_resources}/#{total_resources} resources would have been updated"
else
puts_line "Chef Client finished, #{@updated_resources}/#{total_resources} resources updated in #{pretty_elapsed_time}"
- if total_audits > 0
- puts_line " #{successful_audits}/#{total_audits} controls succeeded"
- end
end
end
@@ -97,9 +87,6 @@ class Chef
puts_line "Chef Client failed. #{@updated_resources} resources would have been updated"
else
puts_line "Chef Client failed. #{@updated_resources} resources updated in #{pretty_elapsed_time}"
- if total_audits > 0
- puts_line " #{successful_audits} controls succeeded"
- end
end
end
@@ -239,37 +226,6 @@ class Chef
converge_complete
end
- # Called before audit phase starts
- def audit_phase_start(run_status)
- puts_line "Starting audit phase"
- end
-
- def audit_phase_complete(audit_output)
- puts_line audit_output
- puts_line "Auditing complete"
- end
-
- def audit_phase_failed(error, audit_output)
- puts_line audit_output
- puts_line ""
- puts_line "Audit phase exception:"
- indent
- puts_line (error.message).to_s
- if error.backtrace
- error.backtrace.each do |l|
- puts_line l
- end
- end
- end
-
- def control_example_success(control_group_name, example_data)
- @successful_audits += 1
- end
-
- def control_example_failure(control_group_name, example_data, error)
- @failed_audits += 1
- end
-
# Called before action is executed on a resource.
def resource_action_start(resource, action, notification_type = nil, notifier = nil)
if resource.cookbook_name && resource.recipe_name
@@ -284,7 +240,7 @@ class Chef
@current_recipe = resource_recipe
indent
end
- # TODO: info about notifies
+ # @todo info about notifies
start_line "* #{resource} action #{action}", stream: resource
indent
end
diff --git a/lib/chef/mixin/properties.rb b/lib/chef/mixin/properties.rb
index f72a22db2d..e0b32d2b9d 100644
--- a/lib/chef/mixin/properties.rb
+++ b/lib/chef/mixin/properties.rb
@@ -83,7 +83,7 @@ class Chef
# is part of object identity. Defaults to `false`.
# @option options [Boolean] :sensitive `true` if this property could
# contain sensitive information and whose value should be redacted
- # in any resource reporting / auditing output. Defaults to `false`.
+ # in any resource reporting output. Defaults to `false`.
#
# @example Bare property
# property :x
@@ -176,9 +176,6 @@ class Chef
# by providing additional options for a package manager to use when
# installing a package.
#
- # This list is used by the Chef client auditing system to extract
- # information from resources to describe changes made to the system.
- #
# This method is unnecessary when declaring properties with `property`;
# properties are added to state_properties by default, and can be turned off
# with `desired_state: false`.
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index e407a0e7be..bba109360d 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -106,11 +106,6 @@ class Chef
attr_accessor :action_collection
#
- # The list of control groups to execute during the audit phase
- #
- attr_reader :audits
-
- #
# Pointer back to the Chef::Runner that created this
#
attr_accessor :runner
@@ -204,7 +199,6 @@ class Chef
# Initialize state that applies to both Chef::RunContext and Chef::ChildRunContext
#
def initialize_child_state
- @audits = {}
@resource_collection = Chef::ResourceCollection.new(self)
@before_notification_collection = Hash.new { |h, k| h[k] = [] }
@immediate_notification_collection = Hash.new { |h, k| h[k] = [] }
@@ -645,8 +639,6 @@ class Chef
end
CHILD_STATE = %w{
- audits
- audits=
create_child
add_delayed_action
delayed_actions