chef 17.4.38-universal-mingw32 → 17.5.22-universal-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/chef.gemspec +2 -0
- data/lib/chef/application/base.rb +11 -1
- data/lib/chef/client.rb +1 -2
- data/lib/chef/compliance/input.rb +115 -0
- data/lib/chef/compliance/input_collection.rb +139 -0
- data/lib/chef/compliance/profile.rb +122 -0
- data/lib/chef/compliance/profile_collection.rb +109 -0
- data/lib/chef/compliance/runner.rb +47 -5
- data/lib/chef/compliance/waiver.rb +115 -0
- data/lib/chef/compliance/waiver_collection.rb +143 -0
- data/lib/chef/dsl/compliance.rb +38 -0
- data/lib/chef/dsl/reader_helpers.rb +51 -0
- data/lib/chef/dsl/recipe.rb +4 -2
- data/lib/chef/dsl/secret.rb +2 -4
- data/lib/chef/dsl/universal.rb +2 -0
- data/lib/chef/event_dispatch/base.rb +44 -2
- data/lib/chef/formatters/doc.rb +46 -0
- data/lib/chef/http/basic_client.rb +15 -7
- data/lib/chef/http.rb +7 -3
- data/lib/chef/provider/file.rb +2 -0
- data/lib/chef/provider/link.rb +2 -2
- data/lib/chef/provider/registry_key.rb +3 -2
- data/lib/chef/provider/remote_file/http.rb +1 -1
- data/lib/chef/provider/template.rb +1 -1
- data/lib/chef/resource/archive_file.rb +17 -14
- data/lib/chef/resource/chef_client_scheduled_task.rb +45 -2
- data/lib/chef/resource/chocolatey_config.rb +13 -13
- data/lib/chef/resource/file/verification/json.rb +50 -0
- data/lib/chef/resource/file/verification/yaml.rb +52 -0
- data/lib/chef/resource/inspec_input.rb +128 -0
- data/lib/chef/resource/inspec_waiver.rb +185 -0
- data/lib/chef/resource/mount.rb +1 -1
- data/lib/chef/resource/registry_key.rb +36 -48
- data/lib/chef/resource/remote_file.rb +98 -2
- data/lib/chef/resource/timezone.rb +2 -2
- data/lib/chef/resource/user_ulimit.rb +1 -0
- data/lib/chef/resource/windows_printer.rb +1 -1
- data/lib/chef/resource/windows_uac.rb +3 -1
- data/lib/chef/resource/windows_user_privilege.rb +1 -1
- data/lib/chef/resources.rb +2 -0
- data/lib/chef/run_context/cookbook_compiler.rb +112 -28
- data/lib/chef/run_context.rb +31 -1
- data/lib/chef/secret_fetcher/akeyless_vault.rb +57 -0
- data/lib/chef/secret_fetcher/aws_secrets_manager.rb +1 -1
- data/lib/chef/secret_fetcher/azure_key_vault.rb +1 -1
- data/lib/chef/secret_fetcher/base.rb +1 -1
- data/lib/chef/secret_fetcher/hashi_vault.rb +100 -0
- data/lib/chef/secret_fetcher.rb +8 -2
- data/lib/chef/version.rb +1 -1
- data/spec/data/archive_file/test_archive.tar.gz +0 -0
- data/spec/functional/resource/archive_file_spec.rb +87 -0
- data/spec/functional/resource/group_spec.rb +5 -1
- data/spec/functional/resource/link_spec.rb +8 -0
- data/spec/integration/compliance/compliance_spec.rb +60 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/platform_helpers.rb +4 -0
- data/spec/support/ruby_installer.rb +51 -0
- data/spec/unit/compliance/input_spec.rb +104 -0
- data/spec/unit/compliance/profile_spec.rb +120 -0
- data/spec/unit/compliance/waiver_spec.rb +104 -0
- data/spec/unit/http/basic_client_spec.rb +30 -0
- data/spec/unit/http_spec.rb +8 -2
- data/spec/unit/provider/link_spec.rb +13 -7
- data/spec/unit/provider/remote_file/http_spec.rb +10 -0
- data/spec/unit/provider/template_spec.rb +2 -2
- data/spec/unit/resource/archive_file_spec.rb +414 -3
- data/spec/unit/resource/chef_client_scheduled_task_spec.rb +69 -0
- data/spec/unit/resource/file/verification/json_spec.rb +72 -0
- data/spec/unit/resource/file/verification/yaml_spec.rb +67 -0
- data/spec/unit/resource/inspec_input_spec.rb +300 -0
- data/spec/unit/resource/inspec_waiver_spec.rb +312 -0
- data/spec/unit/resource/mount_spec.rb +10 -0
- data/spec/unit/resource/user_ulimit_spec.rb +14 -1
- data/spec/unit/secret_fetcher/akeyless_vault_spec.rb +37 -0
- data/spec/unit/secret_fetcher/hashi_vault_spec.rb +80 -0
- data/tasks/rspec.rb +2 -1
- metadata +60 -6
@@ -81,6 +81,11 @@ class Chef
|
|
81
81
|
description: "Should the resource overwrite the destination file contents if they already exist? If set to `:auto` the date stamp of files within the archive will be compared to those on disk and disk contents will be overwritten if they differ. This may cause unintended consequences if disk date stamps are changed between runs, which will result in the files being overwritten during each client run. Make sure to properly test any change to this property.",
|
82
82
|
default: false
|
83
83
|
|
84
|
+
property :strip_components, Integer,
|
85
|
+
description: "Remove the specified number of leading path elements. Pathnames with fewer elements will be silently skipped. This behaves similarly to tar's --strip-components command line argument.",
|
86
|
+
introduced: "17.5",
|
87
|
+
default: 0
|
88
|
+
|
84
89
|
# backwards compatibility for the legacy cookbook names
|
85
90
|
alias_method :extract_options, :options
|
86
91
|
alias_method :extract_to, :destination
|
@@ -117,7 +122,7 @@ class Chef
|
|
117
122
|
|
118
123
|
if new_resource.owner || new_resource.group
|
119
124
|
converge_by("set owner of files extracted in #{new_resource.destination} to #{new_resource.owner}:#{new_resource.group}") do
|
120
|
-
archive = Archive::Reader.open_filename(new_resource.path)
|
125
|
+
archive = Archive::Reader.open_filename(new_resource.path, nil, strip_components: new_resource.strip_components)
|
121
126
|
archive.each_entry do |e|
|
122
127
|
FileUtils.chown(new_resource.owner, new_resource.group, "#{new_resource.destination}/#{e.pathname}")
|
123
128
|
end
|
@@ -160,18 +165,16 @@ class Chef
|
|
160
165
|
# @return [Boolean]
|
161
166
|
def archive_differs_from_disk?(src, dest)
|
162
167
|
modified = false
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
modified = true
|
174
|
-
end
|
168
|
+
archive = Archive::Reader.open_filename(src, nil, strip_components: new_resource.strip_components)
|
169
|
+
Chef::Log.trace("Beginning the comparison of file mtime between contents of #{src} and #{dest}")
|
170
|
+
archive.each_entry do |e|
|
171
|
+
pathname = ::File.expand_path(e.pathname, dest)
|
172
|
+
if ::File.exist?(pathname)
|
173
|
+
Chef::Log.trace("#{pathname} mtime is #{::File.mtime(pathname)} and archive is #{e.mtime}")
|
174
|
+
modified = true unless ::File.mtime(pathname) == e.mtime
|
175
|
+
else
|
176
|
+
Chef::Log.trace("#{pathname} doesn't exist on disk, but exists in the archive")
|
177
|
+
modified = true
|
175
178
|
end
|
176
179
|
end
|
177
180
|
modified
|
@@ -189,7 +192,7 @@ class Chef
|
|
189
192
|
flags = [options].flatten.map { |option| extract_option_map[option] }.compact.reduce(:|)
|
190
193
|
|
191
194
|
Dir.chdir(dest) do
|
192
|
-
archive = Archive::Reader.open_filename(src)
|
195
|
+
archive = Archive::Reader.open_filename(src, nil, strip_components: new_resource.strip_components)
|
193
196
|
|
194
197
|
archive.each_entry do |e|
|
195
198
|
archive.extract(e, flags.to_i)
|
@@ -58,6 +58,14 @@ class Chef
|
|
58
58
|
daemon_options ['-n audit_only']
|
59
59
|
end
|
60
60
|
```
|
61
|
+
|
62
|
+
**Run #{ChefUtils::Dist::Infra::PRODUCT} with a persistent delay on every run calculated once, similar to how chef_client_cron resource works**:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
chef_client_scheduled_task 'Run chef-client with persistent splay' do
|
66
|
+
use_consistent_splay true
|
67
|
+
end
|
68
|
+
```
|
61
69
|
DOC
|
62
70
|
|
63
71
|
resource_name :chef_client_scheduled_task
|
@@ -104,6 +112,11 @@ class Chef
|
|
104
112
|
description: "A random number of seconds between 0 and X to add to interval so that all #{ChefUtils::Dist::Infra::CLIENT} commands don't execute at the same time.",
|
105
113
|
default: 300
|
106
114
|
|
115
|
+
property :use_consistent_splay, [true, false],
|
116
|
+
description: "Always use the same random splay amount for each node to ensure consistent frequencies between #{ChefUtils::Dist::Infra::CLIENT} execution.",
|
117
|
+
introduced: "17.5",
|
118
|
+
default: false
|
119
|
+
|
107
120
|
property :run_on_battery, [true, false],
|
108
121
|
description: "Run the #{ChefUtils::Dist::Infra::PRODUCT} task when the system is on batteries.",
|
109
122
|
default: true
|
@@ -129,6 +142,11 @@ class Chef
|
|
129
142
|
description: "An array of options to pass to the #{ChefUtils::Dist::Infra::CLIENT} command.",
|
130
143
|
default: []
|
131
144
|
|
145
|
+
property :priority, Integer,
|
146
|
+
description: "Use to set Priority Levels range from 0 to 10.",
|
147
|
+
introduced: "17.5",
|
148
|
+
default: 7, callbacks: { "should be in range of 0 to 10" => proc { |v| v >= 0 && v <= 10 } }
|
149
|
+
|
132
150
|
action :add, description: "Add a Windows Scheduled Task that runs #{ChefUtils::Dist::Infra::PRODUCT}." do
|
133
151
|
# TODO: Replace this with a :create_if_missing action on directory when that exists
|
134
152
|
unless Dir.exist?(new_resource.log_directory)
|
@@ -151,8 +169,9 @@ class Chef
|
|
151
169
|
frequency_modifier new_resource.frequency_modifier if frequency_supports_frequency_modifier?
|
152
170
|
start_time new_resource.start_time
|
153
171
|
start_day new_resource.start_date unless new_resource.start_date.nil?
|
154
|
-
random_delay new_resource.splay if frequency_supports_random_delay?
|
172
|
+
random_delay new_resource.splay if frequency_supports_random_delay? && !new_resource.use_consistent_splay
|
155
173
|
disallow_start_if_on_batteries new_resource.splay unless new_resource.run_on_battery
|
174
|
+
priority new_resource.priority
|
156
175
|
action %i{create enable}
|
157
176
|
end
|
158
177
|
end
|
@@ -173,7 +192,31 @@ class Chef
|
|
173
192
|
# Fetch path of cmd.exe through environment variable comspec
|
174
193
|
cmd_path = ENV["COMSPEC"]
|
175
194
|
|
176
|
-
"#{cmd_path} /c \"#{client_cmd}\""
|
195
|
+
"#{cmd_path} /c \"#{consistent_splay_command}#{client_cmd}\""
|
196
|
+
end
|
197
|
+
|
198
|
+
#
|
199
|
+
# Generate a uniformly distributed unique number to sleep from 0 to the splay time
|
200
|
+
#
|
201
|
+
# @param [Integer] splay The number of seconds to splay
|
202
|
+
#
|
203
|
+
# @return [Integer]
|
204
|
+
#
|
205
|
+
def splay_sleep_time(splay)
|
206
|
+
seed = node["shard_seed"] || Digest::MD5.hexdigest(node.name).to_s.hex
|
207
|
+
random = Random.new(seed.to_i)
|
208
|
+
random.rand(splay)
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# The consistent splay sleep time when use_consistent_splay is true.
|
213
|
+
#
|
214
|
+
# @return [NilClass,String] The prepended sleep command to run prior to executing the full command.
|
215
|
+
#
|
216
|
+
def consistent_splay_command
|
217
|
+
return unless new_resource.use_consistent_splay
|
218
|
+
|
219
|
+
"C:/windows/system32/windowspowershell/v1.0/powershell.exe Start-Sleep -s #{splay_sleep_time(new_resource.splay)} && "
|
177
220
|
end
|
178
221
|
|
179
222
|
#
|
@@ -24,22 +24,22 @@ class Chef
|
|
24
24
|
description "Use the **chocolatey_config** resource to add or remove Chocolatey configuration keys."
|
25
25
|
introduced "14.3"
|
26
26
|
examples <<~DOC
|
27
|
-
|
27
|
+
**Set the Chocolatey cacheLocation config**:
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
```ruby
|
30
|
+
chocolatey_config 'Set cacheLocation config' do
|
31
|
+
config_key 'cacheLocation'
|
32
|
+
value 'C:\\temp\\choco'
|
33
|
+
end
|
34
|
+
```
|
35
35
|
|
36
|
-
|
36
|
+
**Unset a Chocolatey config**:
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
```ruby
|
39
|
+
chocolatey_config 'BogusConfig' do
|
40
|
+
action :unset
|
41
|
+
end
|
42
|
+
```
|
43
43
|
DOC
|
44
44
|
|
45
45
|
property :config_key, String, name_property: true,
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Antony Thomas (<antonydeepak@gmail.com>)
|
3
|
+
# Copyright:: Copyright (c) Facebook, Inc. and its affiliates.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
class Chef
|
20
|
+
class Resource
|
21
|
+
class File
|
22
|
+
class Verification
|
23
|
+
|
24
|
+
#
|
25
|
+
# Extends File verification to provide Json verification
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# file 'foo.json' do
|
29
|
+
# content '{"foo": "bar"}'
|
30
|
+
# verify :json
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
#
|
34
|
+
|
35
|
+
class Json < Chef::Resource::File::Verification
|
36
|
+
|
37
|
+
provides :json
|
38
|
+
|
39
|
+
def verify(path, opts = {})
|
40
|
+
Chef::JSONCompat.parse(IO.read(path))
|
41
|
+
true
|
42
|
+
rescue Chef::Exceptions::JSON::ParseError => e
|
43
|
+
Chef::Log.error("Json syntax verify failed with : #{e.message}")
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Antony Thomas (<antonydeepak@gmail.com>)
|
3
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "psych" unless defined?(Psych)
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Resource
|
23
|
+
class File
|
24
|
+
class Verification
|
25
|
+
|
26
|
+
#
|
27
|
+
# Extends File verification to provide a Yaml verification
|
28
|
+
#
|
29
|
+
# Example:
|
30
|
+
# file 'foo.yaml' do
|
31
|
+
# content "--- foo: 'foo-"
|
32
|
+
# verify :yaml
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
#
|
36
|
+
|
37
|
+
class Yaml < Chef::Resource::File::Verification
|
38
|
+
|
39
|
+
provides :yaml
|
40
|
+
|
41
|
+
def verify(path, opts = {})
|
42
|
+
Psych.parse_file(path)
|
43
|
+
true
|
44
|
+
rescue Psych::SyntaxError => e
|
45
|
+
Chef::Log.error("Yaml syntax verify failed with : #{e.message}")
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require_relative "../resource"
|
18
|
+
|
19
|
+
class Chef
|
20
|
+
class Resource
|
21
|
+
class InspecInput < Chef::Resource
|
22
|
+
provides :inspec_input
|
23
|
+
unified_mode true
|
24
|
+
|
25
|
+
description "Use the **inspec_input** resource to add an input to the Compliance Phase."
|
26
|
+
introduced "17.5"
|
27
|
+
examples <<~DOC
|
28
|
+
|
29
|
+
**Activate the default input in the openssh cookbook's compliance segment**:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
inspec_input 'openssh' do
|
33
|
+
action :add
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
**Activate all inputs in the openssh cookbook's compliance segment**:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
inspec_input 'openssh::.*' do
|
41
|
+
action :add
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
**Add an InSpec input to the Compliance Phase from a hash**:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
inspec_input { ssh_custom_path: '/whatever2' }
|
49
|
+
```
|
50
|
+
|
51
|
+
**Add an InSpec input to the Compliance Phase using the 'name' property to identify the input**:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
inspec_input "setting my input" do
|
55
|
+
source( { ssh_custom_path: '/whatever2' })
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
**Add an InSpec input to the Compliance Phase using a TOML, JSON or YAML file**:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
inspec_input "/path/to/my/input.yml"
|
63
|
+
```
|
64
|
+
|
65
|
+
**Add an InSpec input to the Compliance Phase using a TOML, JSON or YAML file, using the 'name' property**:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
inspec_input "setting my input" do
|
69
|
+
source "/path/to/my/input.yml"
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
Note that the inspec_input resource does not update and will not fire notifications (similar to the log resource). This is done to preserve the ability to use
|
74
|
+
the resource while not causing the updated resource count to be larger than zero. Since the resource does not update the state of the node being managed this
|
75
|
+
behavior is still consistent with the configuration management model. Events should be used to observe configuration changes for the compliance phase. It is
|
76
|
+
possible to use the `notify_group` resource to chain notifications of the two resources, but notifications are the wrong model to use and pure ruby conditionals
|
77
|
+
should be used instead. Compliance configuration should be independent of other resources and should only be made conditional based on state/attributes not
|
78
|
+
on other resources.
|
79
|
+
DOC
|
80
|
+
|
81
|
+
property :name, [ Hash, String ]
|
82
|
+
|
83
|
+
property :input, [ Hash, String ],
|
84
|
+
name_property: true
|
85
|
+
|
86
|
+
property :source, [ Hash, String ],
|
87
|
+
name_property: true
|
88
|
+
|
89
|
+
action :add, description: "Add an input to the compliance phase" do
|
90
|
+
if run_context.input_collection.valid?(new_resource.input)
|
91
|
+
include_input(new_resource.input)
|
92
|
+
else
|
93
|
+
include_input(input_hash)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
action_class do
|
98
|
+
# If the source is nil and the input / name_property contains a file separator and is a string of a
|
99
|
+
# file that exists, then use that as the file (similar to the package provider automatic source property). Otherwise
|
100
|
+
# just return the source.
|
101
|
+
#
|
102
|
+
# @api private
|
103
|
+
def source
|
104
|
+
@source ||= build_source
|
105
|
+
end
|
106
|
+
|
107
|
+
def build_source
|
108
|
+
return new_resource.source unless new_resource.source.nil?
|
109
|
+
return nil unless new_resource.input.count(::File::SEPARATOR) > 0 || (::File::ALT_SEPARATOR && new_resource.input.count(::File::ALT_SEPARATOR) > 0 )
|
110
|
+
return nil unless ::File.exist?(new_resource.input)
|
111
|
+
|
112
|
+
new_resource.input
|
113
|
+
end
|
114
|
+
|
115
|
+
def input_hash
|
116
|
+
case source
|
117
|
+
when Hash
|
118
|
+
source
|
119
|
+
when String
|
120
|
+
parse_file(source)
|
121
|
+
when nil
|
122
|
+
raise Chef::Exceptions::ValidationFailed, "Could not find the input #{new_resource.input} in any cookbook segment."
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require_relative "../resource"
|
18
|
+
|
19
|
+
class Chef
|
20
|
+
class Resource
|
21
|
+
class InspecWaiver < Chef::Resource
|
22
|
+
provides :inspec_waiver
|
23
|
+
unified_mode true
|
24
|
+
|
25
|
+
description "Use the **inspec_waiver** resource to add a waiver to the Compliance Phase."
|
26
|
+
introduced "17.5"
|
27
|
+
examples <<~DOC
|
28
|
+
**Activate the default waiver in the openssh cookbook's compliance segment**:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
inspec_waiver 'openssh' do
|
32
|
+
action :add
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
**Activate all waivers in the openssh cookbook's compliance segment**:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
inspec_waiver 'openssh::.*' do
|
40
|
+
action :add
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
**Add an InSpec waiver to the Compliance Phase**:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
inspec_waiver 'Add waiver entry for control' do
|
48
|
+
control 'my_inspec_control_01'
|
49
|
+
run_test false
|
50
|
+
justification "The subject of this control is not managed by #{ChefUtils::Dist::Infra::PRODUCT} on the systems in policy group \#{node['policy_group']}"
|
51
|
+
expiration '2022-01-01'
|
52
|
+
action :add
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
**Add an InSpec waiver to the Compliance Phase using the 'name' property to identify the control**:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
inspec_waiver 'my_inspec_control_01' do
|
60
|
+
justification "The subject of this control is not managed by #{ChefUtils::Dist::Infra::PRODUCT} on the systems in policy group \#{node['policy_group']}"
|
61
|
+
action :add
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
**Add an InSpec waiver to the Compliance Phase using an arbitrary YAML, JSON or TOML file**:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
# files ending in .yml or .yaml that exist are parsed as YAML
|
69
|
+
inspec_waiver "/path/to/my/waiver.yml"
|
70
|
+
|
71
|
+
inspec_waiver "my-waiver-name" do
|
72
|
+
source "/path/to/my/waiver.yml"
|
73
|
+
end
|
74
|
+
|
75
|
+
# files ending in .json that exist are parsed as JSON
|
76
|
+
inspec_waiver "/path/to/my/waiver.json"
|
77
|
+
|
78
|
+
inspec_waiver "my-waiver-name" do
|
79
|
+
source "/path/to/my/waiver.json"
|
80
|
+
end
|
81
|
+
|
82
|
+
# files ending in .toml that exist are parsed as TOML
|
83
|
+
inspec_waiver "/path/to/my/waiver.toml"
|
84
|
+
|
85
|
+
inspec_waiver "my-waiver-name" do
|
86
|
+
source "/path/to/my/waiver.toml"
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
**Add an InSpec waiver to the Compliance Phase using a hash**:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
my_hash = { "ssh-01" => {
|
94
|
+
"expiration_date" => "2033-07-31",
|
95
|
+
"run" => false,
|
96
|
+
"justification" => "because"
|
97
|
+
} }
|
98
|
+
|
99
|
+
inspec_waiver "my-waiver-name" do
|
100
|
+
source my_hash
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
Note that the inspec_waiver resource does not update and will not fire notifications (similar to the log resource). This is done to preserve the ability to use
|
105
|
+
the resource while not causing the updated resource count to be larger than zero. Since the resource does not update the state of the node being managed this
|
106
|
+
behavior is still consistent with the configuration management model. Events should be used to observe configuration changes for the compliance phase. It is
|
107
|
+
possible to use the `notify_group` resource to chain notifications of the two resources, but notifications are the wrong model to use and pure ruby conditionals
|
108
|
+
should be used instead. Compliance configuration should be independent of other resources and should only be made conditional based on state/attributes not
|
109
|
+
on other resources.
|
110
|
+
DOC
|
111
|
+
|
112
|
+
property :control, String,
|
113
|
+
name_property: true,
|
114
|
+
description: "The name of the control being waived"
|
115
|
+
|
116
|
+
property :expiration, String,
|
117
|
+
description: "The expiration date of the waiver - provided in YYYY-MM-DD format",
|
118
|
+
callbacks: {
|
119
|
+
"Expiration date should be a valid calendar date and match the following format: YYYY-MM-DD" => proc { |e|
|
120
|
+
re = Regexp.new('\d{4}-\d{2}-\d{2}$').freeze
|
121
|
+
if re.match?(e)
|
122
|
+
Date.valid_date?(*e.split("-").map(&:to_i))
|
123
|
+
else
|
124
|
+
e.nil?
|
125
|
+
end
|
126
|
+
},
|
127
|
+
}
|
128
|
+
|
129
|
+
property :run_test, [true, false],
|
130
|
+
description: "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."
|
131
|
+
|
132
|
+
property :justification, String,
|
133
|
+
description: "Can be any text you want and might include a reason for the waiver as well as who signed off on the waiver."
|
134
|
+
|
135
|
+
property :source, [ Hash, String ]
|
136
|
+
|
137
|
+
action :add, description: "Add a waiver to the compliance phase" do
|
138
|
+
if run_context.waiver_collection.valid?(new_resource.control)
|
139
|
+
include_waiver(new_resource.control)
|
140
|
+
else
|
141
|
+
include_waiver(waiver_hash)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
action_class do
|
146
|
+
# If the source is nil and the control / name_property contains a file separator and is a string of a
|
147
|
+
# file that exists, then use that as the file (similar to the package provider automatic source property). Otherwise
|
148
|
+
# just return the source.
|
149
|
+
#
|
150
|
+
# @api private
|
151
|
+
def source
|
152
|
+
@source ||= build_source
|
153
|
+
end
|
154
|
+
|
155
|
+
def build_source
|
156
|
+
return new_resource.source unless new_resource.source.nil?
|
157
|
+
return nil unless new_resource.control.count(::File::SEPARATOR) > 0 || (::File::ALT_SEPARATOR && new_resource.control.count(::File::ALT_SEPARATOR) > 0 )
|
158
|
+
return nil unless ::File.exist?(new_resource.control)
|
159
|
+
|
160
|
+
new_resource.control
|
161
|
+
end
|
162
|
+
|
163
|
+
def waiver_hash
|
164
|
+
case source
|
165
|
+
when Hash
|
166
|
+
source
|
167
|
+
when String
|
168
|
+
parse_file(source)
|
169
|
+
when nil
|
170
|
+
if new_resource.justification.nil? || new_resource.justification == ""
|
171
|
+
raise Chef::Exceptions::ValidationFailed, "Entries for an InSpec waiver must have a justification given, this parameter must have a value."
|
172
|
+
end
|
173
|
+
|
174
|
+
control_hash = {}
|
175
|
+
control_hash["expiration_date"] = new_resource.expiration.to_s unless new_resource.expiration.nil?
|
176
|
+
control_hash["run"] = new_resource.run_test unless new_resource.run_test.nil?
|
177
|
+
control_hash["justification"] = new_resource.justification.to_s
|
178
|
+
|
179
|
+
{ new_resource.control => control_hash }
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
data/lib/chef/resource/mount.rb
CHANGED
@@ -42,7 +42,7 @@ class Chef
|
|
42
42
|
sensitive: true
|
43
43
|
|
44
44
|
property :mount_point, String, name_property: true,
|
45
|
-
coerce: proc { |arg| arg.chomp("/") }, # Removed "/" from the end of str, because it was causing idempotency issue.
|
45
|
+
coerce: proc { |arg| (arg == "/" || arg.match?(":/$")) ? arg : arg.chomp("/") }, # Removed "/" from the end of str, because it was causing idempotency issue.
|
46
46
|
description: "The directory (or path) in which the device is to be mounted. Defaults to the name of the resource block if not provided."
|
47
47
|
|
48
48
|
property :device, String, identity: true,
|