chef 16.7.61 → 16.9.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -5
- data/README.md +2 -2
- data/chef.gemspec +12 -2
- data/lib/chef/application/base.rb +1 -1
- data/lib/chef/client.rb +3 -0
- data/lib/chef/compliance/default_attributes.rb +93 -0
- data/lib/chef/compliance/fetcher/automate.rb +69 -0
- data/lib/chef/compliance/fetcher/chef_server.rb +134 -0
- data/lib/chef/compliance/reporter/automate.rb +201 -0
- data/lib/chef/compliance/reporter/chef_server_automate.rb +94 -0
- data/lib/chef/compliance/reporter/compliance_enforcer.rb +20 -0
- data/lib/chef/compliance/reporter/json_file.rb +19 -0
- data/lib/chef/compliance/runner.rb +262 -0
- data/lib/chef/cookbook_manifest.rb +1 -0
- data/lib/chef/encrypted_data_bag_item/assertions.rb +1 -1
- data/lib/chef/exceptions.rb +4 -0
- data/lib/chef/http/ssl_policies.rb +33 -14
- data/lib/chef/knife/bootstrap/train_connector.rb +1 -1
- data/lib/chef/knife/core/formatting_options.rb +49 -0
- data/lib/chef/knife/core/node_presenter.rb +0 -25
- data/lib/chef/knife/core/status_presenter.rb +1 -26
- data/lib/chef/knife/core/ui.rb +4 -1
- data/lib/chef/knife/core/windows_bootstrap_context.rb +1 -1
- data/lib/chef/knife/node_show.rb +2 -1
- data/lib/chef/knife/search.rb +2 -1
- data/lib/chef/knife/ssh.rb +3 -1
- data/lib/chef/knife/status.rb +8 -11
- data/lib/chef/mixin/powershell_exec.rb +3 -1
- data/lib/chef/platform/query_helpers.rb +4 -4
- data/lib/chef/policy_builder/policyfile.rb +1 -1
- data/lib/chef/powershell.rb +2 -0
- data/lib/chef/provider/dsc_resource.rb +12 -24
- data/lib/chef/provider/dsc_script.rb +16 -20
- data/lib/chef/provider/git.rb +5 -5
- data/lib/chef/provider/package.rb +53 -19
- data/lib/chef/provider/package/dnf.rb +39 -12
- data/lib/chef/provider/package/dnf/dnf_helper.py +18 -5
- data/lib/chef/provider/package/dnf/python_helper.rb +6 -6
- data/lib/chef/provider/package/freebsd/pkgng.rb +3 -1
- data/lib/chef/provider/yum_repository.rb +2 -2
- data/lib/chef/resource/chef_client_config.rb +1 -1
- data/lib/chef/resource/chef_gem.rb +2 -2
- data/lib/chef/resource/cron/cron_d.rb +1 -0
- data/lib/chef/resource/dsc_script.rb +8 -1
- data/lib/chef/resource/file.rb +1 -1
- data/lib/chef/resource/gem_package.rb +2 -2
- data/lib/chef/resource/homebrew_cask.rb +3 -3
- data/lib/chef/resource/hostname.rb +3 -3
- data/lib/chef/resource/http_request.rb +1 -1
- data/lib/chef/resource/locale.rb +1 -1
- data/lib/chef/resource/mdadm.rb +2 -2
- data/lib/chef/resource/osx_profile.rb +7 -7
- data/lib/chef/resource/remote_directory.rb +1 -1
- data/lib/chef/resource/ruby.rb +1 -5
- data/lib/chef/resource/ruby_block.rb +1 -1
- data/lib/chef/resource/template.rb +2 -2
- data/lib/chef/resource/user/windows_user.rb +5 -0
- data/lib/chef/resource/windows_certificate.rb +9 -13
- data/lib/chef/resource/yum_repository.rb +5 -0
- data/lib/chef/resource_collection/resource_set.rb +1 -1
- data/lib/chef/util/dsc/configuration_generator.rb +52 -11
- data/lib/chef/util/dsc/lcm_output_parser.rb +3 -4
- data/lib/chef/util/dsc/local_configuration_manager.rb +17 -14
- data/lib/chef/util/dsc/resource_store.rb +5 -11
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api/file.rb +4 -0
- data/spec/data/rubygems.org/latest_specs.4.8.gz +0 -0
- data/spec/data/rubygems.org/nonexistent_gem +0 -0
- data/spec/data/rubygems.org/sexp_processor +0 -0
- data/spec/data/rubygems.org/sexp_processor-4.15.1.gemspec.rz +0 -0
- data/spec/data/ssl/binary/chef-rspec-der.cert +0 -0
- data/spec/data/ssl/binary/chef-rspec-der.key +0 -0
- data/spec/functional/resource/dnf_package_spec.rb +319 -16
- data/spec/functional/resource/dsc_script_spec.rb +3 -6
- data/spec/functional/resource/windows_certificate_spec.rb +204 -384
- data/spec/integration/client/client_spec.rb +2 -1
- data/spec/integration/compliance/compliance_spec.rb +81 -0
- data/spec/integration/recipes/recipe_dsl_spec.rb +1 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/client_spec.rb +1 -0
- data/spec/unit/compliance/fetcher/automate_spec.rb +134 -0
- data/spec/unit/compliance/fetcher/chef_server_spec.rb +93 -0
- data/spec/unit/compliance/reporter/automate_spec.rb +427 -0
- data/spec/unit/compliance/reporter/chef_server_automate_spec.rb +177 -0
- data/spec/unit/compliance/reporter/compliance_enforcer_spec.rb +48 -0
- data/spec/unit/compliance/runner_spec.rb +167 -0
- data/spec/unit/http/ssl_policies_spec.rb +107 -68
- data/spec/unit/knife/bootstrap_spec.rb +5 -17
- data/spec/unit/knife/core/node_editor_spec.rb +1 -1
- data/spec/unit/knife/core/status_presenter_spec.rb +54 -0
- data/spec/unit/mixin/openssl_helper_spec.rb +0 -7
- data/spec/unit/mixin/powershell_exec_spec.rb +1 -1
- data/spec/unit/platform/query_helpers_spec.rb +11 -12
- data/spec/unit/provider/dsc_resource_spec.rb +10 -27
- data/spec/unit/provider/dsc_script_spec.rb +1 -1
- data/spec/unit/provider/mount/windows_spec.rb +1 -0
- data/spec/unit/provider/package/freebsd/pkgng_spec.rb +1 -1
- data/spec/unit/provider/package/rubygems_spec.rb +39 -7
- data/spec/unit/provider/systemd_unit_spec.rb +1 -1
- data/spec/unit/resource/user/windows_user_spec.rb +36 -0
- data/spec/unit/resource/windows_certificate_spec.rb +12 -0
- data/spec/unit/util/dsc/configuration_generator_spec.rb +79 -0
- data/spec/unit/util/dsc/local_configuration_manager_spec.rb +27 -35
- metadata +55 -18
- data/lib/chef/util/powershell/cmdlet.rb +0 -169
- data/lib/chef/util/powershell/cmdlet_result.rb +0 -61
- data/spec/data/trusted_certs_empty/.gitkeep +0 -0
- data/spec/data/trusted_certs_empty/README.md +0 -1
- data/spec/functional/util/powershell/cmdlet_spec.rb +0 -111
- data/spec/scripts/ssl-serve.rb +0 -47
- data/spec/unit/util/powershell/cmdlet_spec.rb +0 -106
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative "automate"
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
module Compliance
|
5
|
+
module Reporter
|
6
|
+
#
|
7
|
+
# Used to send inspec reports to Chef Automate server via Chef Server
|
8
|
+
#
|
9
|
+
class ChefServerAutomate < Chef::Compliance::Reporter::Automate
|
10
|
+
attr_reader :url
|
11
|
+
|
12
|
+
def initialize(opts)
|
13
|
+
@entity_uuid = opts[:entity_uuid]
|
14
|
+
@run_id = opts[:run_id]
|
15
|
+
@node_name = opts[:node_info][:node]
|
16
|
+
@insecure = opts[:insecure]
|
17
|
+
@environment = opts[:node_info][:environment]
|
18
|
+
@roles = opts[:node_info][:roles]
|
19
|
+
@recipes = opts[:node_info][:recipes]
|
20
|
+
@url = opts[:url]
|
21
|
+
@chef_tags = opts[:node_info][:chef_tags]
|
22
|
+
@policy_group = opts[:node_info][:policy_group]
|
23
|
+
@policy_name = opts[:node_info][:policy_name]
|
24
|
+
@source_fqdn = opts[:node_info][:source_fqdn]
|
25
|
+
@organization_name = opts[:node_info][:organization_name]
|
26
|
+
@ipaddress = opts[:node_info][:ipaddress]
|
27
|
+
@fqdn = opts[:node_info][:fqdn]
|
28
|
+
@control_results_limit = opts[:control_results_limit]
|
29
|
+
@timestamp = opts.fetch(:timestamp) { Time.now }
|
30
|
+
end
|
31
|
+
|
32
|
+
def send_report(report)
|
33
|
+
unless @entity_uuid && @run_id
|
34
|
+
Chef::Log.error "entity_uuid(#{@entity_uuid}) or run_id(#{@run_id}) can't be nil, not sending report to #{ChefUtils::Dist::Automate::PRODUCT}"
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
|
38
|
+
automate_report = truncate_controls_results(enriched_report(report), @control_results_limit)
|
39
|
+
|
40
|
+
report_size = Chef::JSONCompat.to_json(automate_report, validate_utf8: false).bytesize
|
41
|
+
# this is set to slightly less than the oc_erchef limit
|
42
|
+
if report_size > 900 * 1024
|
43
|
+
Chef::Log.warn "Generated report size is #{(report_size / (1024 * 1024.0)).round(2)} MB. #{ChefUtils::Dist::Server::PRODUCT} < 13.0 defaults to a limit of ~1MB, 13.0+ defaults to a limit of ~2MB."
|
44
|
+
end
|
45
|
+
|
46
|
+
Chef::Log.info "Report to #{ChefUtils::Dist::Automate::PRODUCT} via #{ChefUtils::Dist::Server::PRODUCT}: #{@url}"
|
47
|
+
with_http_rescue do
|
48
|
+
http_client.post(@url, automate_report)
|
49
|
+
return true
|
50
|
+
end
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
def http_client
|
55
|
+
config = if @insecure
|
56
|
+
Chef::Config.merge(ssl_verify_mode: :verify_none)
|
57
|
+
else
|
58
|
+
Chef::Config
|
59
|
+
end
|
60
|
+
|
61
|
+
Chef::ServerAPI.new(@url, config)
|
62
|
+
end
|
63
|
+
|
64
|
+
def with_http_rescue
|
65
|
+
response = yield
|
66
|
+
if response.respond_to?(:code)
|
67
|
+
# handle non 200 error codes, they are not raised as Net::HTTPClientException
|
68
|
+
handle_http_error_code(response.code) if response.code.to_i >= 300
|
69
|
+
end
|
70
|
+
response
|
71
|
+
rescue Net::HTTPClientException => e
|
72
|
+
Chef::Log.error e
|
73
|
+
handle_http_error_code(e.response.code)
|
74
|
+
end
|
75
|
+
|
76
|
+
def handle_http_error_code(code)
|
77
|
+
case code
|
78
|
+
when /401|403/
|
79
|
+
Chef::Log.error "Auth issue: see the Compliance Phase troubleshooting documentation (http://docs.chef.io/chef_compliance_phase/#troubleshooting)."
|
80
|
+
when /404/
|
81
|
+
Chef::Log.error "Object does not exist on remote server."
|
82
|
+
when /413/
|
83
|
+
Chef::Log.error "You most likely hit the erchef request size in #{ChefUtils::Dist::Server::PRODUCT} that defaults to ~2MB. To increase this limit see the Compliance Phase troubleshooting documentation (http://docs.chef.io/chef_compliance_phase/#troubleshooting) or the Chef Infra Server configuration documentation (https://docs.chef.io/server/config_rb_server/)"
|
84
|
+
when /429/
|
85
|
+
Chef::Log.error "This error typically means the data sent was larger than #{ChefUtils::Dist::Automate::PRODUCT}'s limit (4 MB). Run InSpec locally to identify any controls producing large diffs."
|
86
|
+
end
|
87
|
+
msg = "Received HTTP error #{code}"
|
88
|
+
Chef::Log.error msg
|
89
|
+
raise msg
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Chef
|
2
|
+
module Compliance
|
3
|
+
module Reporter
|
4
|
+
class AuditEnforcer
|
5
|
+
class ControlFailure < StandardError; end
|
6
|
+
|
7
|
+
def send_report(report)
|
8
|
+
report.fetch(:profiles, []).each do |profile|
|
9
|
+
profile.fetch(:controls, []).each do |control|
|
10
|
+
control.fetch(:results, []).each do |result|
|
11
|
+
raise ControlFailure, "Audit #{control[:id]} has failed. Aborting #{ChefUtils::Dist::Infra::CLIENT} run." if result[:status] == "failed"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "../../json_compat"
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
module Compliance
|
5
|
+
module Reporter
|
6
|
+
class JsonFile
|
7
|
+
def initialize(opts)
|
8
|
+
@path = opts.fetch(:file)
|
9
|
+
end
|
10
|
+
|
11
|
+
def send_report(report)
|
12
|
+
FileUtils.mkdir_p(File.dirname(@path), mode: 0700)
|
13
|
+
|
14
|
+
File.write(@path, Chef::JSONCompat.to_json(report))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,262 @@
|
|
1
|
+
autoload :Inspec, "inspec"
|
2
|
+
|
3
|
+
require_relative "default_attributes"
|
4
|
+
require_relative "reporter/automate"
|
5
|
+
require_relative "reporter/chef_server_automate"
|
6
|
+
require_relative "reporter/compliance_enforcer"
|
7
|
+
require_relative "reporter/json_file"
|
8
|
+
|
9
|
+
class Chef
|
10
|
+
module Compliance
|
11
|
+
class Runner < EventDispatch::Base
|
12
|
+
extend Forwardable
|
13
|
+
|
14
|
+
attr_accessor :run_id
|
15
|
+
attr_reader :node
|
16
|
+
def_delegators :node, :logger
|
17
|
+
|
18
|
+
def enabled?
|
19
|
+
audit_cookbook_present = node["recipes"].include?("audit::default")
|
20
|
+
|
21
|
+
logger.info("#{self.class}##{__method__}: #{Inspec::Dist::PRODUCT_NAME} profiles? #{inspec_profiles.any?}")
|
22
|
+
logger.info("#{self.class}##{__method__}: audit cookbook? #{audit_cookbook_present}")
|
23
|
+
|
24
|
+
inspec_profiles.any? && !audit_cookbook_present
|
25
|
+
end
|
26
|
+
|
27
|
+
def node=(node)
|
28
|
+
@node = node
|
29
|
+
node.default["audit"] = Chef::Compliance::DEFAULT_ATTRIBUTES.merge(node.default["audit"])
|
30
|
+
end
|
31
|
+
|
32
|
+
def node_load_completed(node, _expanded_run_list, _config)
|
33
|
+
self.node = node
|
34
|
+
end
|
35
|
+
|
36
|
+
def run_started(run_status)
|
37
|
+
self.run_id = run_status.run_id
|
38
|
+
end
|
39
|
+
|
40
|
+
def run_completed(_node, _run_status)
|
41
|
+
return unless enabled?
|
42
|
+
|
43
|
+
logger.info("#{self.class}##{__method__}: enabling Compliance Phase")
|
44
|
+
|
45
|
+
report
|
46
|
+
end
|
47
|
+
|
48
|
+
def run_failed(_exception, _run_status)
|
49
|
+
return unless enabled?
|
50
|
+
|
51
|
+
logger.info("#{self.class}##{__method__}: enabling Compliance Phase")
|
52
|
+
|
53
|
+
report
|
54
|
+
end
|
55
|
+
|
56
|
+
### Below code adapted from audit cookbook's files/default/handler/audit_report.rb
|
57
|
+
|
58
|
+
DEPRECATED_CONFIG_VALUES = %w{
|
59
|
+
attributes_save
|
60
|
+
fail_if_not_present
|
61
|
+
inspec_gem_source
|
62
|
+
inspec_version
|
63
|
+
interval
|
64
|
+
owner
|
65
|
+
raise_if_unreachable
|
66
|
+
}.freeze
|
67
|
+
|
68
|
+
def warn_for_deprecated_config_values!
|
69
|
+
deprecated_config_values = (node["audit"].keys & DEPRECATED_CONFIG_VALUES)
|
70
|
+
|
71
|
+
if deprecated_config_values.any?
|
72
|
+
values = deprecated_config_values.sort.map { |v| "'#{v}'" }.join(", ")
|
73
|
+
logger.warn "audit cookbook config values #{values} are not supported in #{ChefUtils::Dist::Infra::PRODUCT}'s Compliance Phase."
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def report(report = generate_report)
|
78
|
+
warn_for_deprecated_config_values!
|
79
|
+
|
80
|
+
if report.empty?
|
81
|
+
logger.error "Compliance report was not generated properly, skipped reporting"
|
82
|
+
return
|
83
|
+
end
|
84
|
+
|
85
|
+
Array(node["audit"]["reporter"]).each do |reporter|
|
86
|
+
send_report(reporter, report)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def inspec_opts
|
91
|
+
inputs = node["audit"]["attributes"].to_h
|
92
|
+
if node["audit"]["chef_node_attribute_enabled"]
|
93
|
+
inputs["chef_node"] = node.to_h
|
94
|
+
inputs["chef_node"]["chef_environment"] = node.chef_environment
|
95
|
+
end
|
96
|
+
|
97
|
+
{
|
98
|
+
backend_cache: node["audit"]["inspec_backend_cache"],
|
99
|
+
inputs: inputs,
|
100
|
+
logger: logger,
|
101
|
+
output: node["audit"]["quiet"] ? ::File::NULL : STDOUT,
|
102
|
+
report: true,
|
103
|
+
reporter: ["json-automate"],
|
104
|
+
reporter_backtrace_inclusion: node["audit"]["result_include_backtrace"],
|
105
|
+
reporter_message_truncation: node["audit"]["result_message_limit"],
|
106
|
+
waiver_file: Array(node["audit"]["waiver_file"]),
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
def inspec_profiles
|
111
|
+
profiles = node["audit"]["profiles"]
|
112
|
+
|
113
|
+
# TODO: Custom exception class here?
|
114
|
+
unless profiles.respond_to?(:map) && profiles.all? { |_, p| p.respond_to?(:transform_keys) && p.respond_to?(:update) }
|
115
|
+
raise "#{Inspec::Dist::PRODUCT_NAME} profiles specified in an unrecognized format, expected a hash of hashes."
|
116
|
+
end
|
117
|
+
|
118
|
+
profiles.map do |name, profile|
|
119
|
+
profile.transform_keys(&:to_sym).update(name: name)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def load_fetchers!
|
124
|
+
case node["audit"]["fetcher"]
|
125
|
+
when "chef-automate"
|
126
|
+
require_relative "fetcher/automate"
|
127
|
+
when "chef-server"
|
128
|
+
require_relative "fetcher/chef_server"
|
129
|
+
when nil
|
130
|
+
# intentionally blank
|
131
|
+
else
|
132
|
+
raise "Invalid value specified for Compliance Phase's fetcher: '#{node["audit"]["fetcher"]}'. Valid values are 'chef-automate', 'chef-server', or nil."
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def generate_report(opts: inspec_opts, profiles: inspec_profiles)
|
137
|
+
load_fetchers!
|
138
|
+
|
139
|
+
logger.debug "Options are set to: #{opts}"
|
140
|
+
runner = ::Inspec::Runner.new(opts)
|
141
|
+
|
142
|
+
if profiles.empty?
|
143
|
+
failed_report("No #{Inspec::Dist::PRODUCT_NAME} profiles are defined.")
|
144
|
+
return
|
145
|
+
end
|
146
|
+
|
147
|
+
profiles.each { |target| runner.add_target(target) }
|
148
|
+
|
149
|
+
logger.info "Running profiles from: #{profiles.inspect}"
|
150
|
+
runner.run
|
151
|
+
runner.report.tap do |r|
|
152
|
+
logger.debug "Compliance Report #{r}"
|
153
|
+
end
|
154
|
+
rescue Inspec::FetcherFailure => e
|
155
|
+
failed_report("Cannot fetch all profiles: #{profiles}. Please make sure you're authenticated and the server is reachable. #{e.message}")
|
156
|
+
rescue => e
|
157
|
+
failed_report(e.message)
|
158
|
+
end
|
159
|
+
|
160
|
+
# In case InSpec raises a runtime exception without providing a valid report,
|
161
|
+
# we make one up and add two new fields to it: `status` and `status_message`
|
162
|
+
def failed_report(err)
|
163
|
+
logger.error "#{Inspec::Dist::PRODUCT_NAME} has raised a runtime exception. Generating a minimal failed report."
|
164
|
+
logger.error err
|
165
|
+
{
|
166
|
+
"platform": {
|
167
|
+
"name": "unknown",
|
168
|
+
"release": "unknown",
|
169
|
+
},
|
170
|
+
"profiles": [],
|
171
|
+
"statistics": {
|
172
|
+
"duration": 0.0000001,
|
173
|
+
},
|
174
|
+
"version": Inspec::VERSION,
|
175
|
+
"status": "failed",
|
176
|
+
"status_message": err,
|
177
|
+
}
|
178
|
+
end
|
179
|
+
|
180
|
+
# extracts relevant node data
|
181
|
+
def node_info
|
182
|
+
chef_server_uri = URI(Chef::Config[:chef_server_url])
|
183
|
+
|
184
|
+
runlist_roles = node.run_list.select { |item| item.type == :role }.map(&:name)
|
185
|
+
runlist_recipes = node.run_list.select { |item| item.type == :recipe }.map(&:name)
|
186
|
+
{
|
187
|
+
node: node.name,
|
188
|
+
os: {
|
189
|
+
release: node["platform_version"],
|
190
|
+
family: node["platform"],
|
191
|
+
},
|
192
|
+
environment: node.environment,
|
193
|
+
roles: runlist_roles,
|
194
|
+
recipes: runlist_recipes,
|
195
|
+
policy_name: node.policy_name || "",
|
196
|
+
policy_group: node.policy_group || "",
|
197
|
+
chef_tags: node.tags,
|
198
|
+
organization_name: chef_server_uri.path.split("/").last || "",
|
199
|
+
source_fqdn: chef_server_uri.host || "",
|
200
|
+
ipaddress: node["ipaddress"],
|
201
|
+
fqdn: node["fqdn"],
|
202
|
+
}
|
203
|
+
end
|
204
|
+
|
205
|
+
def send_report(reporter_type, report)
|
206
|
+
logger.info "Reporting to #{reporter_type}"
|
207
|
+
|
208
|
+
reporter = reporter(reporter_type)
|
209
|
+
|
210
|
+
reporter.send_report(report) if reporter
|
211
|
+
end
|
212
|
+
|
213
|
+
def reporter(reporter_type)
|
214
|
+
case reporter_type
|
215
|
+
when "chef-automate"
|
216
|
+
opts = {
|
217
|
+
control_results_limit: node["audit"]["control_results_limit"],
|
218
|
+
entity_uuid: node["chef_guid"],
|
219
|
+
insecure: node["audit"]["insecure"],
|
220
|
+
node_info: node_info,
|
221
|
+
run_id: run_id,
|
222
|
+
run_time_limit: node["audit"]["run_time_limit"],
|
223
|
+
}
|
224
|
+
Chef::Compliance::Reporter::Automate.new(opts)
|
225
|
+
when "chef-server-automate"
|
226
|
+
opts = {
|
227
|
+
control_results_limit: node["audit"]["control_results_limit"],
|
228
|
+
entity_uuid: node["chef_guid"],
|
229
|
+
insecure: node["audit"]["insecure"],
|
230
|
+
node_info: node_info,
|
231
|
+
run_id: run_id,
|
232
|
+
run_time_limit: node["audit"]["run_time_limit"],
|
233
|
+
url: chef_server_automate_url,
|
234
|
+
}
|
235
|
+
Chef::Compliance::Reporter::ChefServerAutomate.new(opts)
|
236
|
+
when "json-file"
|
237
|
+
path = node["audit"]["json_file"]["location"]
|
238
|
+
logger.info "Writing compliance report to #{path}"
|
239
|
+
Chef::Compliance::Reporter::JsonFile.new(file: path)
|
240
|
+
when "audit-enforcer"
|
241
|
+
Chef::Compliance::Reporter::ComplianceEnforcer.new
|
242
|
+
else
|
243
|
+
raise "'#{reporter_type}' is not a supported reporter for Compliance Phase."
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def chef_server_automate_url
|
248
|
+
url = if node["audit"]["server"]
|
249
|
+
URI(node["audit"]["server"])
|
250
|
+
else
|
251
|
+
URI(Chef::Config[:chef_server_url]).tap do |u|
|
252
|
+
u.path = ""
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
org = Chef::Config[:chef_server_url].split("/").last
|
257
|
+
url.path = File.join(url.path, "organizations/#{org}/data-collector")
|
258
|
+
url
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
@@ -30,7 +30,7 @@ class Chef::EncryptedDataBagItem
|
|
30
30
|
unless format_version.is_a?(Integer) && format_version >= Chef::Config[:data_bag_decrypt_minimum_version]
|
31
31
|
raise UnacceptableEncryptedDataBagItemFormat,
|
32
32
|
"The encrypted data bag item has format version `#{format_version}', " +
|
33
|
-
|
33
|
+
"but the config setting 'data_bag_decrypt_minimum_version' requires version `#{Chef::Config[:data_bag_decrypt_minimum_version]}'"
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
data/lib/chef/exceptions.rb
CHANGED
@@ -84,11 +84,13 @@ class Chef
|
|
84
84
|
class InvalidPrivateKey < ArgumentError; end
|
85
85
|
class MissingKeyAttribute < ArgumentError; end
|
86
86
|
class KeyCommandInputError < ArgumentError; end
|
87
|
+
|
87
88
|
class BootstrapCommandInputError < ArgumentError
|
88
89
|
def initialize
|
89
90
|
super "You cannot pass both --json-attributes and --json-attribute-file. Please pass one or none."
|
90
91
|
end
|
91
92
|
end
|
93
|
+
|
92
94
|
class InvalidKeyArgument < ArgumentError; end
|
93
95
|
class InvalidKeyAttribute < ArgumentError; end
|
94
96
|
class InvalidUserAttribute < ArgumentError; end
|
@@ -195,6 +197,7 @@ class Chef
|
|
195
197
|
class IllegalVersionConstraint < NotImplementedError; end # rubocop:disable Lint/InheritException
|
196
198
|
|
197
199
|
class MetadataNotValid < StandardError; end
|
200
|
+
|
198
201
|
class MetadataNotFound < StandardError
|
199
202
|
attr_reader :install_path
|
200
203
|
attr_reader :cookbook_name
|
@@ -283,6 +286,7 @@ class Chef
|
|
283
286
|
end
|
284
287
|
|
285
288
|
end
|
289
|
+
|
286
290
|
# Exception class for collecting multiple failures. Used when running
|
287
291
|
# delayed notifications so that chef can process each delayed
|
288
292
|
# notification even if chef client or other notifications fail.
|
@@ -70,6 +70,12 @@ class Chef
|
|
70
70
|
end
|
71
71
|
|
72
72
|
http_client.ca_file = config[:ssl_ca_file]
|
73
|
+
elsif ENV["SSL_CERT_FILE"]
|
74
|
+
unless ::File.exist?(ENV["SSL_CERT_FILE"])
|
75
|
+
raise Chef::Exceptions::ConfigurationError, "The configured ssl_ca_file #{ENV["SSL_CERT_FILE"]} does not exist"
|
76
|
+
end
|
77
|
+
|
78
|
+
http_client.ca_file = ENV["SSL_CERT_FILE"]
|
73
79
|
end
|
74
80
|
end
|
75
81
|
|
@@ -79,28 +85,41 @@ class Chef
|
|
79
85
|
http_client.cert_store.set_default_paths
|
80
86
|
end
|
81
87
|
if config.trusted_certs_dir
|
82
|
-
certs = Dir.glob(File.join(Chef::Util::PathHelper.escape_glob_dir(config.trusted_certs_dir), "*.{crt,pem}"))
|
88
|
+
certs = Dir.glob(::File.join(Chef::Util::PathHelper.escape_glob_dir(config.trusted_certs_dir), "*.{crt,pem}"))
|
83
89
|
certs.each do |cert_file|
|
84
|
-
cert =
|
90
|
+
cert = begin
|
91
|
+
OpenSSL::X509::Certificate.new(::File.binread(cert_file))
|
92
|
+
rescue OpenSSL::X509::CertificateError => e
|
93
|
+
raise Chef::Exceptions::ConfigurationError, "Error reading cert file '#{cert_file}', original error '#{e.class}: #{e.message}'"
|
94
|
+
end
|
85
95
|
add_trusted_cert(cert)
|
86
96
|
end
|
87
97
|
end
|
88
98
|
end
|
89
99
|
|
90
100
|
def set_client_credentials
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
+
return unless config[:ssl_client_cert] || config[:ssl_client_key]
|
102
|
+
|
103
|
+
unless config[:ssl_client_cert] && config[:ssl_client_key]
|
104
|
+
raise Chef::Exceptions::ConfigurationError, "You must configure ssl_client_cert and ssl_client_key together"
|
105
|
+
end
|
106
|
+
unless ::File.exists?(config[:ssl_client_cert])
|
107
|
+
raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_cert #{config[:ssl_client_cert]} does not exist"
|
108
|
+
end
|
109
|
+
unless ::File.exists?(config[:ssl_client_key])
|
110
|
+
raise Chef::Exceptions::ConfigurationError, "The configured ssl_client_key #{config[:ssl_client_key]} does not exist"
|
111
|
+
end
|
112
|
+
|
113
|
+
begin
|
114
|
+
http_client.cert = OpenSSL::X509::Certificate.new(::File.binread(config[:ssl_client_cert]))
|
115
|
+
rescue OpenSSL::X509::CertificateError => e
|
116
|
+
raise Chef::Exceptions::ConfigurationError, "Error reading cert file '#{config[:ssl_client_cert]}', original error '#{e.class}: #{e.message}'"
|
117
|
+
end
|
101
118
|
|
102
|
-
|
103
|
-
http_client.key = OpenSSL::PKey::RSA.new(::File.
|
119
|
+
begin
|
120
|
+
http_client.key = OpenSSL::PKey::RSA.new(::File.binread(config[:ssl_client_key]))
|
121
|
+
rescue OpenSSL::PKey::RSAError => e
|
122
|
+
raise Chef::Exceptions::ConfigurationError, "Error reading key file '#{config[:ssl_client_key]}', original error '#{e.class}: #{e.message}'"
|
104
123
|
end
|
105
124
|
end
|
106
125
|
|