chef 17.0.242-universal-mingw32 → 17.1.35-universal-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +0 -12
- data/Rakefile +2 -2
- data/chef.gemspec +9 -20
- data/lib/chef/chef_fs/file_pattern.rb +2 -2
- data/lib/chef/compliance/default_attributes.rb +1 -1
- data/lib/chef/compliance/reporter/automate.rb +1 -1
- data/lib/chef/compliance/runner.rb +2 -2
- data/lib/chef/cookbook/cookbook_version_loader.rb +3 -3
- data/lib/chef/cookbook/gem_installer.rb +5 -1
- data/lib/chef/dsl/declare_resource.rb +5 -10
- data/lib/chef/formatters/doc.rb +2 -1
- data/lib/chef/node.rb +1 -1
- data/lib/chef/provider/directory.rb +6 -6
- data/lib/chef/provider/link.rb +1 -1
- data/lib/chef/provider/package/dnf/dnf_helper.py +11 -10
- data/lib/chef/provider/package/dnf/python_helper.rb +9 -8
- data/lib/chef/provider/package/yum.rb +1 -4
- data/lib/chef/provider/package/yum/python_helper.rb +15 -10
- data/lib/chef/provider/package/yum/yum_helper.py +46 -62
- data/lib/chef/provider/registry_key.rb +1 -1
- data/lib/chef/provider/service/systemd.rb +1 -1
- data/lib/chef/provider/systemd_unit.rb +1 -1
- data/lib/chef/provider/template/content.rb +1 -1
- data/lib/chef/provider/windows_script.rb +1 -1
- data/lib/chef/resource.rb +6 -7
- data/lib/chef/resource/execute.rb +2 -2
- data/lib/chef/resource/inspec_waiver_file_entry.rb +155 -0
- data/lib/chef/resource/lwrp_base.rb +17 -2
- data/lib/chef/resource/remote_file.rb +2 -2
- data/lib/chef/resource/windows_env.rb +1 -1
- data/lib/chef/resource/windows_font.rb +1 -1
- data/lib/chef/resource/windows_pagefile.rb +2 -2
- data/lib/chef/resource/windows_path.rb +2 -2
- data/lib/chef/resource/windows_security_policy.rb +5 -2
- data/lib/chef/resource/windows_task.rb +1 -1
- data/lib/chef/resource_builder.rb +8 -2
- data/lib/chef/resources.rb +1 -0
- data/lib/chef/run_lock.rb +1 -1
- data/lib/chef/runner.rb +1 -1
- data/lib/chef/shell/ext.rb +3 -3
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api.rb +9 -2
- data/spec/data/knife-home/.chef/plugins/knife/example_home_subcommand.rb +0 -0
- data/spec/data/knife-site-subcommands/plugins/knife/example_subcommand.rb +0 -0
- data/spec/data/knife_subcommand/test_explicit_category.rb +7 -0
- data/spec/data/knife_subcommand/test_name_mapping.rb +4 -0
- data/spec/data/knife_subcommand/test_yourself.rb +21 -0
- data/spec/functional/resource/dnf_package_spec.rb +857 -537
- data/spec/functional/resource/group_spec.rb +1 -1
- data/spec/functional/resource/link_spec.rb +1 -1
- data/spec/functional/resource/remote_file_spec.rb +1 -1
- data/spec/functional/resource/windows_env_spec.rb +2 -2
- data/spec/functional/resource/yum_package_spec.rb +495 -428
- data/spec/integration/client/client_spec.rb +0 -20
- data/spec/integration/recipes/unified_mode_spec.rb +70 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/chef_helpers.rb +1 -1
- data/spec/support/shared/functional/execute_resource.rb +1 -1
- data/spec/support/shared/functional/knife.rb +37 -0
- data/spec/support/shared/integration/knife_support.rb +192 -0
- data/spec/support/shared/unit/knife_shared.rb +39 -0
- data/spec/support/shared/unit/provider/file.rb +1 -1
- data/spec/unit/chef_fs/file_system/repository/directory_spec.rb +1 -1
- data/spec/unit/compliance/runner_spec.rb +1 -1
- data/spec/unit/provider/link_spec.rb +1 -1
- data/spec/unit/provider/package/dnf/python_helper_spec.rb +1 -0
- data/spec/unit/provider/package/yum/python_helper_spec.rb +1 -0
- data/spec/unit/provider/service/systemd_service_spec.rb +2 -2
- data/spec/unit/provider/systemd_unit_spec.rb +2 -2
- data/spec/unit/resource/inspec_waiver_file_entry_spec.rb +80 -0
- data/tasks/rspec.rb +4 -9
- metadata +16 -160
- data/lib/chef/provider/package/yum/simplejson/LICENSE.txt +0 -79
- data/lib/chef/provider/package/yum/simplejson/__init__.py +0 -318
- data/lib/chef/provider/package/yum/simplejson/__init__.pyc +0 -0
- data/lib/chef/provider/package/yum/simplejson/decoder.py +0 -354
- data/lib/chef/provider/package/yum/simplejson/decoder.pyc +0 -0
- data/lib/chef/provider/package/yum/simplejson/encoder.py +0 -440
- data/lib/chef/provider/package/yum/simplejson/encoder.pyc +0 -0
- data/lib/chef/provider/package/yum/simplejson/scanner.py +0 -65
- data/lib/chef/provider/package/yum/simplejson/scanner.pyc +0 -0
- data/lib/chef/provider/package/yum/simplejson/tool.py +0 -37
@@ -2,45 +2,26 @@
|
|
2
2
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
3
3
|
|
4
4
|
#
|
5
|
-
# NOTE: this actually needs to run under python2.
|
6
|
-
# please manually test changes on
|
5
|
+
# NOTE: this actually needs to run under python2.7 and centos 6.x through python3 and centos 7.x
|
6
|
+
# please manually test changes on centos6 boxes or you will almost certainly break things.
|
7
7
|
#
|
8
8
|
|
9
9
|
import sys
|
10
10
|
import yum
|
11
11
|
import signal
|
12
12
|
import os
|
13
|
-
|
14
|
-
|
15
|
-
except ImportError: import simplejson as json
|
13
|
+
import fcntl
|
14
|
+
import json
|
16
15
|
import re
|
17
16
|
from rpmUtils.miscutils import stringToVersion,compareEVR
|
18
17
|
from rpmUtils.arch import getBaseArch, getArchList
|
19
|
-
|
20
|
-
|
21
|
-
try: from yum.misc import string_to_prco_tuple
|
22
|
-
except ImportError:
|
23
|
-
# RHEL5 compat
|
24
|
-
def string_to_prco_tuple(prcoString):
|
25
|
-
prco_split = prcoString.split()
|
26
|
-
n, f, v = prco_split
|
27
|
-
(prco_e, prco_v, prco_r) = stringToVersion(v)
|
28
|
-
return (n, f, (prco_e, prco_v, prco_r))
|
18
|
+
from yum.misc import string_to_prco_tuple
|
29
19
|
|
30
20
|
# hack to work around https://github.com/chef/chef/issues/7126
|
31
21
|
# see https://bugzilla.redhat.com/show_bug.cgi?id=1396248
|
32
22
|
if not hasattr(yum.packages.FakeRepository, 'compare_providers_priority'):
|
33
23
|
yum.packages.FakeRepository.compare_providers_priority = 99
|
34
24
|
|
35
|
-
base = None
|
36
|
-
|
37
|
-
def get_base():
|
38
|
-
global base
|
39
|
-
if base is None:
|
40
|
-
base = yum.YumBase()
|
41
|
-
setup_exit_handler()
|
42
|
-
return base
|
43
|
-
|
44
25
|
def versioncompare(versions):
|
45
26
|
arch_list = getArchList()
|
46
27
|
candidate_arch1 = versions[0].split(".")[-1]
|
@@ -51,9 +32,9 @@ def versioncompare(versions):
|
|
51
32
|
# then we'll chop the arch component (assuming it *is* a valid one) from the first version string
|
52
33
|
# so we're only comparing the evr portions.
|
53
34
|
if (candidate_arch2 not in arch_list) and (candidate_arch1 in arch_list):
|
54
|
-
|
35
|
+
final_version1 = versions[0].replace("." + candidate_arch1,"")
|
55
36
|
else:
|
56
|
-
|
37
|
+
final_version1 = versions[0]
|
57
38
|
|
58
39
|
final_version2 = versions[1]
|
59
40
|
|
@@ -64,37 +45,24 @@ def versioncompare(versions):
|
|
64
45
|
outpipe.write("%(e)s\n" % { 'e': evr_comparison })
|
65
46
|
outpipe.flush()
|
66
47
|
|
67
|
-
def install_only_packages(name):
|
68
|
-
base = get_base()
|
48
|
+
def install_only_packages(base, name):
|
69
49
|
if name in base.conf.installonlypkgs:
|
70
|
-
|
50
|
+
outpipe.write('True\n')
|
71
51
|
else:
|
72
|
-
|
52
|
+
outpipe.write('False\n')
|
73
53
|
outpipe.flush()
|
74
54
|
|
75
|
-
|
76
|
-
try:
|
77
|
-
any
|
78
|
-
except NameError:
|
79
|
-
def any(s):
|
80
|
-
for v in s:
|
81
|
-
if v:
|
82
|
-
return True
|
83
|
-
return False
|
84
|
-
|
85
|
-
def query(command):
|
86
|
-
base = get_base()
|
87
|
-
|
55
|
+
def query(base, command):
|
88
56
|
enabled_repos = base.repos.listEnabled()
|
89
57
|
|
90
58
|
# Handle any repocontrols passed in with our options
|
91
59
|
|
92
60
|
if 'repos' in command:
|
93
|
-
|
94
|
-
|
95
|
-
|
61
|
+
for repo in command['repos']:
|
62
|
+
if 'enable' in repo:
|
63
|
+
base.repos.enableRepo(repo['enable'])
|
96
64
|
if 'disable' in repo:
|
97
|
-
|
65
|
+
base.repos.disableRepo(repo['disable'])
|
98
66
|
|
99
67
|
args = { 'name': command['provides'] }
|
100
68
|
do_nevra = False
|
@@ -136,7 +104,7 @@ def query(command):
|
|
136
104
|
# returnPackages and searchProvides and then apply the Nevra filters to those results.
|
137
105
|
pkgs = obj.searchNevra(**args)
|
138
106
|
if (command['action'] == "whatinstalled") and (not pkgs):
|
139
|
-
|
107
|
+
pkgs = obj.searchNevra(name=args['name'], arch=desired_arch)
|
140
108
|
else:
|
141
109
|
pats = [command['provides']]
|
142
110
|
pkgs = obj.returnPackages(patterns=pats)
|
@@ -157,13 +125,13 @@ def query(command):
|
|
157
125
|
|
158
126
|
# Reset any repos we were passed in enablerepo/disablerepo to the original state in enabled_repos
|
159
127
|
if 'repos' in command:
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
128
|
+
for repo in command['repos']:
|
129
|
+
if 'enable' in repo:
|
130
|
+
if base.repos.getRepo(repo['enable']) not in enabled_repos:
|
131
|
+
base.repos.disableRepo(repo['enable'])
|
164
132
|
if 'disable' in repo:
|
165
|
-
|
166
|
-
|
133
|
+
if base.repos.getRepo(repo['disable']) in enabled_repos:
|
134
|
+
base.repos.enableRepo(repo['disable'])
|
167
135
|
|
168
136
|
# the design of this helper is that it should try to be 'brittle' and fail hard and exit in order
|
169
137
|
# to keep process tables clean. additional error handling should probably be added to the retry loop
|
@@ -179,21 +147,29 @@ def setup_exit_handler():
|
|
179
147
|
signal.signal(signal.SIGPIPE, exit_handler)
|
180
148
|
signal.signal(signal.SIGQUIT, exit_handler)
|
181
149
|
|
150
|
+
def set_blocking(fd):
|
151
|
+
old_flags = fcntl.fcntl(fd, fcntl.F_GETFL)
|
152
|
+
fcntl.fcntl(fd, fcntl.F_SETFL, old_flags & ~os.O_NONBLOCK)
|
153
|
+
|
154
|
+
base = None
|
155
|
+
|
182
156
|
if len(sys.argv) < 3:
|
183
|
-
|
184
|
-
|
157
|
+
inpipe = sys.stdin
|
158
|
+
outpipe = sys.stdout
|
185
159
|
else:
|
186
|
-
|
187
|
-
|
160
|
+
set_blocking(int(sys.argv[1]))
|
161
|
+
set_blocking(int(sys.argv[2]))
|
162
|
+
inpipe = os.fdopen(int(sys.argv[1]), "r")
|
163
|
+
outpipe = os.fdopen(int(sys.argv[2]), "w")
|
188
164
|
|
189
165
|
try:
|
166
|
+
setup_exit_handler()
|
190
167
|
while 1:
|
191
168
|
# stop the process if the parent proc goes away
|
192
169
|
ppid = os.getppid()
|
193
170
|
if ppid == 1:
|
194
171
|
raise RuntimeError("orphaned")
|
195
172
|
|
196
|
-
setup_exit_handler()
|
197
173
|
line = inpipe.readline()
|
198
174
|
|
199
175
|
# only way to detect EOF in python
|
@@ -205,14 +181,22 @@ try:
|
|
205
181
|
except ValueError, e:
|
206
182
|
raise RuntimeError("bad json parse")
|
207
183
|
|
184
|
+
if base is None:
|
185
|
+
base = yum.YumBase()
|
186
|
+
|
208
187
|
if command['action'] == "whatinstalled":
|
209
|
-
query(command)
|
188
|
+
query(base, command)
|
210
189
|
elif command['action'] == "whatavailable":
|
211
|
-
query(command)
|
190
|
+
query(base, command)
|
212
191
|
elif command['action'] == "versioncompare":
|
213
192
|
versioncompare(command['versions'])
|
214
193
|
elif command['action'] == "installonlypkgs":
|
215
|
-
|
194
|
+
install_only_packages(base, command['package'])
|
195
|
+
elif command['action'] == "close_rpmdb":
|
196
|
+
base.closeRpmDB()
|
197
|
+
base = None
|
198
|
+
outpipe.write('nil nil nil\n')
|
199
|
+
outpipe.flush()
|
216
200
|
else:
|
217
201
|
raise RuntimeError("bad command")
|
218
202
|
finally:
|
@@ -78,7 +78,7 @@ class Chef
|
|
78
78
|
def define_resource_requirements
|
79
79
|
requirements.assert(:create, :create_if_missing, :delete, :delete_key) do |a|
|
80
80
|
a.assertion { registry.hive_exists?(new_resource.key) }
|
81
|
-
a.failure_message(Chef::Exceptions::Win32RegHiveMissing, "Hive #{new_resource.key.split(
|
81
|
+
a.failure_message(Chef::Exceptions::Win32RegHiveMissing, "Hive #{new_resource.key.split("\\").shift} does not exist")
|
82
82
|
end
|
83
83
|
|
84
84
|
requirements.assert(:create) do |a|
|
@@ -80,7 +80,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
|
|
80
80
|
@systemd_service_status ||= begin
|
81
81
|
# Collect all the status information for a service and returns it at once
|
82
82
|
options, args = get_systemctl_options_args
|
83
|
-
s = shell_out!(systemctl_path, args, "show", "-p", "UnitFileState", "-p", "ActiveState", new_resource.service_name, options)
|
83
|
+
s = shell_out!(systemctl_path, args, "show", "-p", "UnitFileState", "-p", "ActiveState", new_resource.service_name, **options)
|
84
84
|
# e.g. /bin/systemctl --system show -p UnitFileState -p ActiveState sshd.service
|
85
85
|
# Returns something like:
|
86
86
|
# ActiveState=active
|
@@ -60,7 +60,7 @@ class Chef
|
|
60
60
|
# Collect all the status information for a unit and return it at once
|
61
61
|
# This may fail if we are managing a template unit (e.g. with '@'), in which case
|
62
62
|
# we just ignore the error because unit status is irrelevant in that case
|
63
|
-
s = shell_out(*systemctl_cmd, "show", "-p", "UnitFileState", "-p", "ActiveState", new_resource.unit_name, systemctl_opts)
|
63
|
+
s = shell_out(*systemctl_cmd, "show", "-p", "UnitFileState", "-p", "ActiveState", new_resource.unit_name, **systemctl_opts)
|
64
64
|
# e.g. /bin/systemctl --system show -p UnitFileState -p ActiveState syslog.socket
|
65
65
|
# Returns something like:
|
66
66
|
# ActiveState=inactive
|
@@ -63,7 +63,7 @@ class Chef
|
|
63
63
|
context[:template_finder] = template_finder
|
64
64
|
|
65
65
|
# helper variables
|
66
|
-
context[:cookbook_name] = new_resource.cookbook_name unless context.keys.include?(:
|
66
|
+
context[:cookbook_name] = new_resource.cookbook_name unless context.keys.include?(:cookbook_name)
|
67
67
|
context[:recipe_name] = new_resource.recipe_name unless context.keys.include?(:recipe_name)
|
68
68
|
context[:recipe_line_string] = new_resource.source_line unless context.keys.include?(:recipe_line_string)
|
69
69
|
context[:recipe_path] = new_resource.source_line_file unless context.keys.include?(:recipe_path)
|
@@ -83,7 +83,7 @@ class Chef
|
|
83
83
|
username = new_resource.user
|
84
84
|
|
85
85
|
if new_resource.domain
|
86
|
-
username = new_resource.domain +
|
86
|
+
username = new_resource.domain + "\\" + new_resource.user
|
87
87
|
end
|
88
88
|
|
89
89
|
# Create an ACE that allows the alternate user read access to the script
|
data/lib/chef/resource.rb
CHANGED
@@ -42,6 +42,7 @@ require_relative "mixin/deprecation"
|
|
42
42
|
require_relative "mixin/properties"
|
43
43
|
require_relative "mixin/provides"
|
44
44
|
require_relative "dsl/universal"
|
45
|
+
require_relative "constants"
|
45
46
|
|
46
47
|
class Chef
|
47
48
|
class Resource
|
@@ -1362,8 +1363,9 @@ class Chef
|
|
1362
1363
|
#
|
1363
1364
|
# @param arg [String] version constraint to match against (e.g. "> 14")
|
1364
1365
|
#
|
1365
|
-
def self.chef_version_for_provides(constraint)
|
1366
|
-
@chef_version_for_provides = constraint
|
1366
|
+
def self.chef_version_for_provides(constraint = NOT_PASSED)
|
1367
|
+
@chef_version_for_provides = constraint unless constraint == NOT_PASSED
|
1368
|
+
@chef_version_for_provides ||= nil
|
1367
1369
|
end
|
1368
1370
|
|
1369
1371
|
# Mark this resource as providing particular DSL.
|
@@ -1376,14 +1378,11 @@ class Chef
|
|
1376
1378
|
def self.provides(name, **options, &block)
|
1377
1379
|
name = name.to_sym
|
1378
1380
|
|
1379
|
-
# quell warnings
|
1380
|
-
@chef_version_for_provides = nil unless defined?(@chef_version_for_provides)
|
1381
|
-
|
1382
1381
|
# deliberately do not go through the accessor here
|
1383
1382
|
@resource_name = name if resource_name.nil?
|
1384
1383
|
|
1385
|
-
if
|
1386
|
-
options[:chef_version] =
|
1384
|
+
if chef_version_for_provides && !options.include?(:chef_version)
|
1385
|
+
options[:chef_version] = chef_version_for_provides
|
1387
1386
|
end
|
1388
1387
|
|
1389
1388
|
result = Chef.resource_handler_map.set(name, self, **options, &block)
|
@@ -633,13 +633,13 @@ class Chef
|
|
633
633
|
end
|
634
634
|
|
635
635
|
# if domain is provided in both username and domain
|
636
|
-
if specified_user.is_a?(String) && ((specified_user.include?
|
636
|
+
if specified_user.is_a?(String) && ((specified_user.include? "\\") || (specified_user.include? "@")) && specified_domain
|
637
637
|
raise ArgumentError, "The domain is provided twice. Username: `#{specified_user}`, Domain: `#{specified_domain}`. Please specify domain only once."
|
638
638
|
end
|
639
639
|
|
640
640
|
if specified_user.is_a?(String) && specified_domain.nil?
|
641
641
|
# Splitting username of format: Domain\Username
|
642
|
-
domain_and_user = user.split(
|
642
|
+
domain_and_user = user.split("\\")
|
643
643
|
|
644
644
|
if domain_and_user.length == 2
|
645
645
|
domain = domain_and_user[0]
|
@@ -0,0 +1,155 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Davin Taddeo (<davin@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require_relative "../resource"
|
19
|
+
require "yaml"
|
20
|
+
require "date"
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Resource
|
24
|
+
class InspecWaiverFileEntry < Chef::Resource
|
25
|
+
provides :inspec_waiver_file_entry
|
26
|
+
unified_mode true
|
27
|
+
|
28
|
+
description "Use the **inspec_waiver_file_entry** resource to add or remove entries from an InSpec waiver file. This can be used in conjunction with the Compliance Phase."
|
29
|
+
introduced "17.1"
|
30
|
+
examples <<~DOC
|
31
|
+
**Add an InSpec waiver entry to a given waiver file**:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
inspec_waiver_file_entry 'Add waiver entry for control' do
|
35
|
+
file_path 'C:\\chef\\inspec_waiver_file.yml'
|
36
|
+
control 'my_inspec_control_01'
|
37
|
+
run_test false
|
38
|
+
justification "The subject of this control is not managed by Chef on the systems in policy group \#{node['policy_group']}"
|
39
|
+
expiration '2022-01-01'
|
40
|
+
action :add
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
**Add an InSpec waiver entry to a given waiver file using the 'name' property to identify the control**:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
inspec_waiver_file_entry 'my_inspec_control_01' do
|
48
|
+
justification "The subject of this control is not managed by Chef on the systems in policy group \#{node['policy_group']}"
|
49
|
+
action :add
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
**Remove an InSpec waiver entry to a given waiver file**:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
inspec_waiver_file_entry "my_inspec_control_01" do
|
57
|
+
action :remove
|
58
|
+
end
|
59
|
+
```
|
60
|
+
DOC
|
61
|
+
|
62
|
+
property :control, String,
|
63
|
+
name_property: true,
|
64
|
+
description: "The name of the control being added or removed to the waiver file"
|
65
|
+
|
66
|
+
property :file_path, String,
|
67
|
+
required: true,
|
68
|
+
description: "The path to the waiver file being modified",
|
69
|
+
default: "#{ChefConfig::Config.etc_chef_dir}/inspec_waivers.yml",
|
70
|
+
default_description: "`/etc/chef/inspec_waivers.yml` on Linux/Unix and `C:\\chef\\inspec_waivers.yml` on Windows"
|
71
|
+
|
72
|
+
property :expiration, String,
|
73
|
+
description: "The expiration date of the given waiver - provided in YYYY-MM-DD format",
|
74
|
+
callbacks: {
|
75
|
+
"Expiration date should be a valid calendar date and match the following format: YYYY-MM-DD" => proc { |e|
|
76
|
+
re = Regexp.new('\d{4}-\d{2}-\d{2}$').freeze
|
77
|
+
if re.match?(e)
|
78
|
+
Date.valid_date?(*e.split("-").map(&:to_i))
|
79
|
+
else
|
80
|
+
e.nil?
|
81
|
+
end
|
82
|
+
},
|
83
|
+
}
|
84
|
+
|
85
|
+
property :run_test, [true, false],
|
86
|
+
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."
|
87
|
+
|
88
|
+
property :justification, String,
|
89
|
+
description: "Can be any text you want and might include a reason for the waiver as well as who signed off on the waiver."
|
90
|
+
|
91
|
+
property :backup, [false, Integer],
|
92
|
+
description: "The number of backups to be kept in /var/chef/backup (for UNIX- and Linux-based platforms) or C:/chef/backup (for the Microsoft Windows platform). Set to false to prevent backups from being kept.",
|
93
|
+
default: false
|
94
|
+
|
95
|
+
action :add do
|
96
|
+
if new_resource.justification.nil? || new_resource.justification == ""
|
97
|
+
raise Chef::Exceptions::ValidationFailed, "Entries in the InSpec waiver file must have a justification given, this parameter must have a value."
|
98
|
+
end
|
99
|
+
|
100
|
+
filename = new_resource.file_path
|
101
|
+
waiver_hash = load_waiver_file_to_hash(filename)
|
102
|
+
control_hash = {}
|
103
|
+
control_hash["expiration_date"] = new_resource.expiration.to_s unless new_resource.expiration.nil?
|
104
|
+
control_hash["run"] = new_resource.run_test unless new_resource.run_test.nil?
|
105
|
+
control_hash["justification"] = new_resource.justification.to_s
|
106
|
+
|
107
|
+
unless waiver_hash[new_resource.control] == control_hash
|
108
|
+
waiver_hash[new_resource.control] = control_hash
|
109
|
+
waiver_hash = waiver_hash.sort.to_h
|
110
|
+
|
111
|
+
file "Update Waiver File #{new_resource.file_path} to update waiver for control #{new_resource.control}" do
|
112
|
+
path new_resource.file_path
|
113
|
+
content waiver_hash.to_yaml
|
114
|
+
backup new_resource.backup
|
115
|
+
action :create
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
action :remove do
|
121
|
+
filename = new_resource.file_path
|
122
|
+
waiver_hash = load_waiver_file_to_hash(filename)
|
123
|
+
if waiver_hash.key?(new_resource.control)
|
124
|
+
waiver_hash.delete(new_resource.control)
|
125
|
+
waiver_hash = waiver_hash.sort.to_h
|
126
|
+
file "Update Waiver File #{new_resource.file_path} to remove waiver for control #{new_resource.control}" do
|
127
|
+
path new_resource.file_path
|
128
|
+
content waiver_hash.to_yaml
|
129
|
+
backup new_resource.backup
|
130
|
+
action :create
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
action_class do
|
136
|
+
def load_waiver_file_to_hash(file_name)
|
137
|
+
if file_name =~ %r{(/|C:\\).*(.yaml|.yml)}i
|
138
|
+
if ::File.exist?(file_name)
|
139
|
+
hash = ::YAML.load_file(file_name)
|
140
|
+
if hash == false || hash.nil? || hash == ""
|
141
|
+
{}
|
142
|
+
else
|
143
|
+
::YAML.load_file(file_name)
|
144
|
+
end
|
145
|
+
else
|
146
|
+
{}
|
147
|
+
end
|
148
|
+
else
|
149
|
+
raise "Waiver files needs to be a YAML file which should have a .yaml or .yml extension -\"#{file_name}\" does not have an appropriate extension"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|