chef 17.2.29-universal-mingw32 → 17.5.22-universal-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -5
  3. data/chef.gemspec +3 -0
  4. data/lib/chef/application/base.rb +11 -1
  5. data/lib/chef/application.rb +3 -1
  6. data/lib/chef/client.rb +2 -3
  7. data/lib/chef/compliance/default_attributes.rb +5 -3
  8. data/lib/chef/compliance/input.rb +115 -0
  9. data/lib/chef/compliance/input_collection.rb +139 -0
  10. data/lib/chef/compliance/profile.rb +122 -0
  11. data/lib/chef/compliance/profile_collection.rb +109 -0
  12. data/lib/chef/compliance/reporter/automate.rb +1 -1
  13. data/lib/chef/compliance/runner.rb +62 -6
  14. data/lib/chef/compliance/waiver.rb +115 -0
  15. data/lib/chef/compliance/waiver_collection.rb +143 -0
  16. data/lib/chef/data_bag.rb +1 -2
  17. data/lib/chef/data_bag_item.rb +1 -2
  18. data/lib/chef/deprecated.rb +10 -4
  19. data/lib/chef/dsl/compliance.rb +38 -0
  20. data/lib/chef/dsl/reader_helpers.rb +51 -0
  21. data/lib/chef/dsl/recipe.rb +4 -2
  22. data/lib/chef/dsl/render_helpers.rb +44 -0
  23. data/lib/chef/dsl/secret.rb +62 -0
  24. data/lib/chef/dsl/toml.rb +116 -0
  25. data/lib/chef/dsl/universal.rb +7 -0
  26. data/lib/chef/dsl.rb +1 -0
  27. data/lib/chef/event_dispatch/base.rb +44 -2
  28. data/lib/chef/exceptions.rb +20 -0
  29. data/lib/chef/formatters/doc.rb +60 -13
  30. data/lib/chef/formatters/error_mapper.rb +2 -2
  31. data/lib/chef/formatters/minimal.rb +6 -5
  32. data/lib/chef/handler/slow_report.rb +1 -1
  33. data/lib/chef/http/basic_client.rb +15 -7
  34. data/lib/chef/http.rb +12 -8
  35. data/lib/chef/json_compat.rb +1 -1
  36. data/lib/chef/policy_builder/policyfile.rb +88 -45
  37. data/lib/chef/provider/execute.rb +1 -1
  38. data/lib/chef/provider/file.rb +4 -2
  39. data/lib/chef/provider/group/dscl.rb +1 -1
  40. data/lib/chef/provider/launchd.rb +6 -6
  41. data/lib/chef/provider/link.rb +2 -2
  42. data/lib/chef/provider/lwrp_base.rb +1 -1
  43. data/lib/chef/provider/package/habitat.rb +168 -0
  44. data/lib/chef/provider/package/powershell.rb +5 -0
  45. data/lib/chef/provider/registry_key.rb +3 -2
  46. data/lib/chef/provider/remote_file/http.rb +1 -1
  47. data/lib/chef/provider/subversion.rb +4 -4
  48. data/lib/chef/provider/support/yum_repo.erb +1 -1
  49. data/lib/chef/provider/systemd_unit.rb +17 -16
  50. data/lib/chef/provider/template.rb +1 -1
  51. data/lib/chef/provider/user/mac.rb +3 -3
  52. data/lib/chef/provider/yum_repository.rb +27 -43
  53. data/lib/chef/provider/zypper_repository.rb +3 -3
  54. data/lib/chef/provider.rb +26 -1
  55. data/lib/chef/provider_resolver.rb +8 -2
  56. data/lib/chef/providers.rb +1 -0
  57. data/lib/chef/resource/archive_file.rb +17 -14
  58. data/lib/chef/resource/chef_client_config.rb +7 -2
  59. data/lib/chef/resource/chef_client_cron.rb +1 -1
  60. data/lib/chef/resource/chef_client_launchd.rb +1 -1
  61. data/lib/chef/resource/chef_client_scheduled_task.rb +46 -3
  62. data/lib/chef/resource/chef_client_systemd_timer.rb +1 -1
  63. data/lib/chef/resource/chef_client_trusted_certificate.rb +2 -2
  64. data/lib/chef/resource/chef_vault_secret.rb +2 -2
  65. data/lib/chef/resource/chocolatey_config.rb +13 -13
  66. data/lib/chef/resource/dsc_resource.rb +1 -1
  67. data/lib/chef/resource/execute.rb +5 -5
  68. data/lib/chef/resource/file/verification/json.rb +50 -0
  69. data/lib/chef/resource/file/verification/yaml.rb +52 -0
  70. data/lib/chef/resource/gem_package.rb +2 -1
  71. data/lib/chef/resource/habitat/_habitat_shared.rb +28 -0
  72. data/lib/chef/resource/habitat/habitat_package.rb +129 -0
  73. data/lib/chef/resource/habitat/habitat_sup.rb +329 -0
  74. data/lib/chef/resource/habitat/habitat_sup_systemd.rb +67 -0
  75. data/lib/chef/resource/habitat/habitat_sup_windows.rb +90 -0
  76. data/lib/chef/resource/habitat_config.rb +107 -0
  77. data/lib/chef/resource/habitat_install.rb +247 -0
  78. data/lib/chef/resource/habitat_service.rb +451 -0
  79. data/lib/chef/resource/habitat_user_toml.rb +92 -0
  80. data/lib/chef/resource/homebrew_cask.rb +1 -1
  81. data/lib/chef/resource/inspec_input.rb +128 -0
  82. data/lib/chef/resource/inspec_waiver.rb +185 -0
  83. data/lib/chef/resource/inspec_waiver_file_entry.rb +2 -2
  84. data/lib/chef/resource/launchd.rb +3 -3
  85. data/lib/chef/resource/lwrp_base.rb +1 -1
  86. data/lib/chef/resource/mount.rb +1 -1
  87. data/lib/chef/resource/registry_key.rb +36 -48
  88. data/lib/chef/resource/remote_file.rb +99 -3
  89. data/lib/chef/resource/rhsm_subscription.rb +5 -5
  90. data/lib/chef/resource/ruby_block.rb +100 -0
  91. data/lib/chef/resource/scm/subversion.rb +1 -1
  92. data/lib/chef/resource/support/HabService.dll.config.erb +19 -0
  93. data/lib/chef/resource/support/client.erb +8 -1
  94. data/lib/chef/resource/support/sup.toml.erb +179 -0
  95. data/lib/chef/resource/sysctl.rb +2 -2
  96. data/lib/chef/resource/systemd_unit.rb +3 -3
  97. data/lib/chef/resource/timezone.rb +2 -2
  98. data/lib/chef/resource/user_ulimit.rb +1 -0
  99. data/lib/chef/resource/windows_defender.rb +163 -0
  100. data/lib/chef/resource/windows_defender_exclusion.rb +125 -0
  101. data/lib/chef/resource/windows_printer.rb +78 -44
  102. data/lib/chef/resource/windows_printer_port.rb +1 -1
  103. data/lib/chef/resource/windows_uac.rb +3 -1
  104. data/lib/chef/resource/windows_update_settings.rb +259 -0
  105. data/lib/chef/resource/windows_user_privilege.rb +1 -1
  106. data/lib/chef/resource/yum_package.rb +1 -5
  107. data/lib/chef/resource.rb +13 -17
  108. data/lib/chef/resource_inspector.rb +6 -2
  109. data/lib/chef/resources.rb +14 -1
  110. data/lib/chef/run_context/cookbook_compiler.rb +112 -28
  111. data/lib/chef/run_context.rb +31 -1
  112. data/lib/chef/secret_fetcher/akeyless_vault.rb +57 -0
  113. data/lib/chef/secret_fetcher/aws_secrets_manager.rb +65 -0
  114. data/lib/chef/secret_fetcher/azure_key_vault.rb +78 -0
  115. data/lib/chef/secret_fetcher/base.rb +76 -0
  116. data/lib/chef/secret_fetcher/example.rb +46 -0
  117. data/lib/chef/secret_fetcher/hashi_vault.rb +100 -0
  118. data/lib/chef/secret_fetcher.rb +61 -0
  119. data/lib/chef/version.rb +1 -1
  120. data/spec/data/archive_file/test_archive.tar.gz +0 -0
  121. data/spec/functional/mixin/from_file_spec.rb +1 -1
  122. data/spec/functional/resource/archive_file_spec.rb +87 -0
  123. data/spec/functional/resource/group_spec.rb +5 -1
  124. data/spec/functional/resource/link_spec.rb +8 -0
  125. data/spec/integration/compliance/compliance_spec.rb +61 -0
  126. data/spec/integration/recipes/recipe_dsl_spec.rb +1 -1
  127. data/spec/integration/recipes/resource_action_spec.rb +6 -6
  128. data/spec/spec_helper.rb +3 -0
  129. data/spec/support/platform_helpers.rb +4 -0
  130. data/spec/support/ruby_installer.rb +51 -0
  131. data/spec/support/shared/unit/provider/file.rb +2 -8
  132. data/spec/unit/compliance/input_spec.rb +104 -0
  133. data/spec/unit/compliance/profile_spec.rb +120 -0
  134. data/spec/unit/compliance/runner_spec.rb +46 -2
  135. data/spec/unit/compliance/waiver_spec.rb +104 -0
  136. data/spec/unit/data_bag_item_spec.rb +2 -2
  137. data/spec/unit/data_bag_spec.rb +1 -1
  138. data/spec/unit/dsl/render_helpers_spec.rb +102 -0
  139. data/spec/unit/dsl/secret_spec.rb +71 -0
  140. data/spec/unit/formatters/doc_spec.rb +1 -1
  141. data/spec/unit/http/basic_client_spec.rb +30 -0
  142. data/spec/unit/http_spec.rb +8 -2
  143. data/spec/unit/policy_builder/dynamic_spec.rb +0 -5
  144. data/spec/unit/policy_builder/policyfile_spec.rb +144 -56
  145. data/spec/unit/provider/apt_update_spec.rb +3 -1
  146. data/spec/unit/provider/link_spec.rb +13 -7
  147. data/spec/unit/provider/mount/aix_spec.rb +1 -1
  148. data/spec/unit/provider/package/powershell_spec.rb +74 -12
  149. data/spec/unit/provider/remote_file/http_spec.rb +10 -0
  150. data/spec/unit/provider/template_spec.rb +2 -2
  151. data/spec/unit/provider_spec.rb +23 -0
  152. data/spec/unit/resource/archive_file_spec.rb +414 -3
  153. data/spec/unit/resource/chef_client_scheduled_task_spec.rb +69 -0
  154. data/spec/unit/resource/file/verification/json_spec.rb +72 -0
  155. data/spec/unit/resource/file/verification/yaml_spec.rb +67 -0
  156. data/spec/unit/resource/homebrew_cask_spec.rb +29 -11
  157. data/spec/unit/resource/inspec_input_spec.rb +300 -0
  158. data/spec/unit/resource/inspec_waiver_spec.rb +312 -0
  159. data/spec/unit/resource/mount_spec.rb +10 -0
  160. data/spec/unit/resource/rhsm_subscription_spec.rb +50 -3
  161. data/spec/unit/resource/systemd_unit_spec.rb +1 -1
  162. data/spec/unit/resource/user_ulimit_spec.rb +14 -1
  163. data/spec/unit/resource/windows_defender_exclusion_spec.rb +62 -0
  164. data/spec/unit/resource/windows_defender_spec.rb +71 -0
  165. data/spec/unit/resource/windows_update_settings_spec.rb +64 -0
  166. data/spec/unit/resource_spec.rb +19 -8
  167. data/spec/unit/secret_fetcher/akeyless_vault_spec.rb +37 -0
  168. data/spec/unit/secret_fetcher/aws_secrets_manager_spec.rb +70 -0
  169. data/spec/unit/secret_fetcher/azure_key_vault_spec.rb +70 -0
  170. data/spec/unit/secret_fetcher/hashi_vault_spec.rb +80 -0
  171. data/spec/unit/secret_fetcher_spec.rb +82 -0
  172. data/tasks/rspec.rb +2 -1
  173. metadata +106 -7
@@ -32,6 +32,7 @@ class Chef
32
32
  attr_reader :events
33
33
  attr_reader :run_list_expansion
34
34
  attr_reader :logger
35
+ attr_reader :run_context
35
36
 
36
37
  def initialize(run_context, run_list_expansion, events)
37
38
  @run_context = run_context
@@ -43,23 +44,51 @@ class Chef
43
44
 
44
45
  # Chef::Node object for the current run.
45
46
  def node
46
- @run_context.node
47
+ run_context.node
47
48
  end
48
49
 
49
50
  # Chef::CookbookCollection object for the current run
50
51
  def cookbook_collection
51
- @run_context.cookbook_collection
52
+ run_context.cookbook_collection
52
53
  end
53
54
 
54
55
  # Resource Definitions from the compiled cookbooks. This is populated by
55
56
  # calling #compile_resource_definitions (which is called by #compile)
56
57
  def definitions
57
- @run_context.definitions
58
+ run_context.definitions
59
+ end
60
+
61
+ # The global waiver_collection hanging off of the run_context, used by
62
+ # compile_compliance and the compliance phase that runs inspec
63
+ #
64
+ # @returns [Chef::Compliance::WaiverCollection]
65
+ #
66
+ def waiver_collection
67
+ run_context.waiver_collection
68
+ end
69
+
70
+ # The global input_collection hanging off of the run_context, used by
71
+ # compile_compliance and the compliance phase that runs inspec
72
+ #
73
+ # @returns [Chef::Compliance::inputCollection]
74
+ #
75
+ def input_collection
76
+ run_context.input_collection
77
+ end
78
+
79
+ # The global profile_collection hanging off of the run_context, used by
80
+ # compile_compliance and the compliance phase that runs inspec
81
+ #
82
+ # @returns [Chef::Compliance::ProfileCollection]
83
+ #
84
+ def profile_collection
85
+ run_context.profile_collection
58
86
  end
59
87
 
60
88
  # Run the compile phase of the chef run. Loads files in the following order:
61
89
  # * Libraries
62
90
  # * Ohai
91
+ # * Compliance Profiles/Waivers
63
92
  # * Attributes
64
93
  # * LWRPs
65
94
  # * Resource Definitions
@@ -73,6 +102,7 @@ class Chef
73
102
  def compile
74
103
  compile_libraries
75
104
  compile_ohai_plugins
105
+ compile_compliance
76
106
  compile_attributes
77
107
  compile_lwrps
78
108
  compile_resource_definitions
@@ -98,7 +128,7 @@ class Chef
98
128
 
99
129
  # Loads library files from cookbooks according to #cookbook_order.
100
130
  def compile_libraries
101
- @events.library_load_start(count_files_by_segment(:libraries))
131
+ events.library_load_start(count_files_by_segment(:libraries))
102
132
  cookbook_order.each do |cookbook|
103
133
  eager_load_libraries = cookbook_collection[cookbook].metadata.eager_load_libraries
104
134
  if eager_load_libraries == true # actually true, not truthy
@@ -110,14 +140,14 @@ class Chef
110
140
  end
111
141
  end
112
142
  end
113
- @events.library_load_complete
143
+ events.library_load_complete
114
144
  end
115
145
 
116
146
  # Loads Ohai Plugins from cookbooks, and ensure any old ones are
117
147
  # properly cleaned out
118
148
  def compile_ohai_plugins
119
149
  ohai_plugin_count = count_files_by_segment(:ohai)
120
- @events.ohai_plugin_load_start(ohai_plugin_count)
150
+ events.ohai_plugin_load_start(ohai_plugin_count)
121
151
  FileUtils.rm_rf(Chef::Config[:ohai_segment_plugin_path])
122
152
 
123
153
  cookbook_order.each do |cookbook|
@@ -131,57 +161,81 @@ class Chef
131
161
  node.consume_ohai_data(ohai)
132
162
  end
133
163
 
134
- @events.ohai_plugin_load_complete
164
+ events.ohai_plugin_load_complete
165
+ end
166
+
167
+ # Loads the compliance segment files from the cookbook into the collections
168
+ # hanging off of the run_context, for later use in the compliance phase
169
+ # inspec run.
170
+ #
171
+ def compile_compliance
172
+ events.compliance_load_start
173
+ events.profiles_load_start
174
+ cookbook_order.each do |cookbook|
175
+ load_profiles_from_cookbook(cookbook)
176
+ end
177
+ events.profiles_load_complete
178
+ events.inputs_load_start
179
+ cookbook_order.each do |cookbook|
180
+ load_inputs_from_cookbook(cookbook)
181
+ end
182
+ events.inputs_load_complete
183
+ events.waivers_load_start
184
+ cookbook_order.each do |cookbook|
185
+ load_waivers_from_cookbook(cookbook)
186
+ end
187
+ events.waivers_load_complete
188
+ events.compliance_load_complete
135
189
  end
136
190
 
137
191
  # Loads attributes files from cookbooks. Attributes files are loaded
138
192
  # according to #cookbook_order; within a cookbook, +default.rb+ is loaded
139
193
  # first, then the remaining attributes files in lexical sort order.
140
194
  def compile_attributes
141
- @events.attribute_load_start(count_files_by_segment(:attributes, "attributes.rb"))
195
+ events.attribute_load_start(count_files_by_segment(:attributes, "attributes.rb"))
142
196
  cookbook_order.each do |cookbook|
143
197
  load_attributes_from_cookbook(cookbook)
144
198
  end
145
- @events.attribute_load_complete
199
+ events.attribute_load_complete
146
200
  end
147
201
 
148
202
  # Loads LWRPs according to #cookbook_order. Providers are loaded before
149
203
  # resources on a cookbook-wise basis.
150
204
  def compile_lwrps
151
205
  lwrp_file_count = count_files_by_segment(:providers) + count_files_by_segment(:resources)
152
- @events.lwrp_load_start(lwrp_file_count)
206
+ events.lwrp_load_start(lwrp_file_count)
153
207
  cookbook_order.each do |cookbook|
154
208
  load_lwrps_from_cookbook(cookbook)
155
209
  end
156
- @events.lwrp_load_complete
210
+ events.lwrp_load_complete
157
211
  end
158
212
 
159
213
  # Loads resource definitions according to #cookbook_order
160
214
  def compile_resource_definitions
161
- @events.definition_load_start(count_files_by_segment(:definitions))
215
+ events.definition_load_start(count_files_by_segment(:definitions))
162
216
  cookbook_order.each do |cookbook|
163
217
  load_resource_definitions_from_cookbook(cookbook)
164
218
  end
165
- @events.definition_load_complete
219
+ events.definition_load_complete
166
220
  end
167
221
 
168
222
  # Iterates over the expanded run_list, loading each recipe in turn.
169
223
  def compile_recipes
170
- @events.recipe_load_start(run_list_expansion.recipes.size)
224
+ events.recipe_load_start(run_list_expansion.recipes.size)
171
225
  run_list_expansion.recipes.each do |recipe|
172
226
 
173
227
  path = resolve_recipe(recipe)
174
- @run_context.load_recipe(recipe)
175
- @events.recipe_file_loaded(path, recipe)
228
+ run_context.load_recipe(recipe)
229
+ events.recipe_file_loaded(path, recipe)
176
230
  rescue Chef::Exceptions::RecipeNotFound => e
177
- @events.recipe_not_found(e)
231
+ events.recipe_not_found(e)
178
232
  raise
179
233
  rescue Exception => e
180
- @events.recipe_file_load_failed(path, e, recipe)
234
+ events.recipe_file_load_failed(path, e, recipe)
181
235
  raise
182
236
 
183
237
  end
184
- @events.recipe_load_complete
238
+ events.recipe_load_complete
185
239
  end
186
240
 
187
241
  # Whether or not a cookbook is reachable from the set of cookbook given
@@ -225,7 +279,7 @@ class Chef
225
279
  attr_file_basename = ::File.basename(filename, ".rb")
226
280
  node.include_attribute("#{cookbook_name}::#{attr_file_basename}")
227
281
  rescue Exception => e
228
- @events.attribute_file_load_failed(filename, e)
282
+ events.attribute_file_load_failed(filename, e)
229
283
  raise
230
284
  end
231
285
 
@@ -234,9 +288,9 @@ class Chef
234
288
 
235
289
  logger.trace("Loading cookbook #{cookbook_name}'s library file: #{filename}")
236
290
  Kernel.require(filename)
237
- @events.library_file_loaded(filename)
291
+ events.library_file_loaded(filename)
238
292
  rescue Exception => e
239
- @events.library_file_load_failed(filename, e)
293
+ events.library_file_load_failed(filename, e)
240
294
  raise
241
295
 
242
296
  end
@@ -260,18 +314,18 @@ class Chef
260
314
  def load_lwrp_provider(cookbook_name, filename)
261
315
  logger.trace("Loading cookbook #{cookbook_name}'s providers from #{filename}")
262
316
  Chef::Provider::LWRPBase.build_from_file(cookbook_name, filename, self)
263
- @events.lwrp_file_loaded(filename)
317
+ events.lwrp_file_loaded(filename)
264
318
  rescue Exception => e
265
- @events.lwrp_file_load_failed(filename, e)
319
+ events.lwrp_file_load_failed(filename, e)
266
320
  raise
267
321
  end
268
322
 
269
323
  def load_lwrp_resource(cookbook_name, filename)
270
324
  logger.trace("Loading cookbook #{cookbook_name}'s resources from #{filename}")
271
325
  Chef::Resource::LWRPBase.build_from_file(cookbook_name, filename, self)
272
- @events.lwrp_file_loaded(filename)
326
+ events.lwrp_file_loaded(filename)
273
327
  rescue Exception => e
274
- @events.lwrp_file_load_failed(filename, e)
328
+ events.lwrp_file_load_failed(filename, e)
275
329
  raise
276
330
  end
277
331
 
@@ -288,6 +342,36 @@ class Chef
288
342
  end
289
343
  end
290
344
 
345
+ # Load the compliance segment files from a single cookbook
346
+ #
347
+ def load_profiles_from_cookbook(cookbook_name)
348
+ # This identifies profiles by their inspec.yml file, we recurse into subdirs so the profiles may be deeply
349
+ # nested in a subdir structure for organization. You could have profiles inside of profiles but
350
+ # since that is not coherently defined, you should not.
351
+ #
352
+ each_file_in_cookbook_by_segment(cookbook_name, :compliance, [ "profiles/**/inspec.{yml,yaml}" ]) do |filename|
353
+ profile_collection.from_file(filename, cookbook_name)
354
+ end
355
+ end
356
+
357
+ def load_waivers_from_cookbook(cookbook_name)
358
+ # This identifies waiver files as any yaml files under the waivers subdir. We recurse into subdirs as well
359
+ # so that waivers may be nested in subdirs for organization. Any other files are ignored.
360
+ #
361
+ each_file_in_cookbook_by_segment(cookbook_name, :compliance, [ "waivers/**/*.{yml,yaml}" ]) do |filename|
362
+ waiver_collection.from_file(filename, cookbook_name)
363
+ end
364
+ end
365
+
366
+ def load_inputs_from_cookbook(cookbook_name)
367
+ # This identifies input files as any yaml files under the inputs subdir. We recurse into subdirs as well
368
+ # so that inputs may be nested in subdirs for organization. Any other files are ignored.
369
+ #
370
+ each_file_in_cookbook_by_segment(cookbook_name, :compliance, [ "inputs/**/*.{yml,yaml}" ]) do |filename|
371
+ input_collection.from_file(filename, cookbook_name)
372
+ end
373
+ end
374
+
291
375
  def load_resource_definitions_from_cookbook(cookbook_name)
292
376
  files_in_cookbook_by_segment(cookbook_name, :definitions).each do |filename|
293
377
  next unless File.extname(filename) == ".rb"
@@ -300,9 +384,9 @@ class Chef
300
384
  logger.info("Overriding duplicate definition #{key}, new definition found in #{filename}")
301
385
  newval
302
386
  end
303
- @events.definition_file_loaded(filename)
387
+ events.definition_file_loaded(filename)
304
388
  rescue Exception => e
305
- @events.definition_file_load_failed(filename, e)
389
+ events.definition_file_load_failed(filename, e)
306
390
  raise
307
391
  end
308
392
  end
@@ -25,6 +25,9 @@ require_relative "log"
25
25
  require_relative "recipe"
26
26
  require_relative "run_context/cookbook_compiler"
27
27
  require_relative "event_dispatch/events_output_stream"
28
+ require_relative "compliance/input_collection"
29
+ require_relative "compliance/waiver_collection"
30
+ require_relative "compliance/profile_collection"
28
31
  require_relative "train_transport"
29
32
  require_relative "exceptions"
30
33
  require "forwardable" unless defined?(Forwardable)
@@ -120,10 +123,28 @@ class Chef
120
123
 
121
124
  # Handle to the global action_collection of executed actions for reporting / data_collector /etc
122
125
  #
123
- # @return [Chef::ActionCollection
126
+ # @return [Chef::ActionCollection]
124
127
  #
125
128
  attr_accessor :action_collection
126
129
 
130
+ # Handle to the global profile_collection of inspec profiles for the compliance phase
131
+ #
132
+ # @return [Chef::Compliance::ProfileCollection]
133
+ #
134
+ attr_accessor :profile_collection
135
+
136
+ # Handle to the global waiver_collection of inspec waiver files for the compliance phase
137
+ #
138
+ # @return [Chef::Compliance::WaiverCollection]
139
+ #
140
+ attr_accessor :waiver_collection
141
+
142
+ # Handle to the global input_collection of inspec input files for the compliance phase
143
+ #
144
+ # @return [Chef::Compliance::inputCollection]
145
+ #
146
+ attr_accessor :input_collection
147
+
127
148
  # Pointer back to the Chef::Runner that created this
128
149
  #
129
150
  attr_accessor :runner
@@ -198,6 +219,9 @@ class Chef
198
219
  @loaded_attributes_hash = {}
199
220
  @reboot_info = {}
200
221
  @cookbook_compiler = nil
222
+ @input_collection = Chef::Compliance::InputCollection.new(events)
223
+ @waiver_collection = Chef::Compliance::WaiverCollection.new(events)
224
+ @profile_collection = Chef::Compliance::ProfileCollection.new(events)
201
225
 
202
226
  initialize_child_state
203
227
  end
@@ -674,6 +698,8 @@ class Chef
674
698
  events=
675
699
  has_cookbook_file_in_cookbook?
676
700
  has_template_in_cookbook?
701
+ input_collection
702
+ input_collection=
677
703
  load
678
704
  loaded_attribute
679
705
  loaded_attributes
@@ -688,6 +714,8 @@ class Chef
688
714
  node
689
715
  node=
690
716
  open_stream
717
+ profile_collection
718
+ profile_collection=
691
719
  reboot_info
692
720
  reboot_info=
693
721
  reboot_requested?
@@ -700,6 +728,8 @@ class Chef
700
728
  transport
701
729
  transport_connection
702
730
  unreachable_cookbook?
731
+ waiver_collection
732
+ waiver_collection=
703
733
  }
704
734
 
705
735
  def initialize(parent_run_context)
@@ -0,0 +1,57 @@
1
+ #
2
+ # Author:: Marc Paradise (<marc@chef.io>)
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_relative "base"
20
+ require_relative "hashi_vault"
21
+
22
+ class Chef
23
+ class SecretFetcher
24
+ # == Chef::SecretFetcher::AKeylessVault
25
+ # A fetcher that fetches a secret from AKeyless Vault. Initial implementation is
26
+ # based on HashiVault , because AKeyless provides a compatibility layer that makes this possible.
27
+ # Future revisions will use native akeyless authentication.
28
+ #
29
+ # Required config:
30
+ # :access_id - the access id of the API key
31
+ # :access_key - the access key of the API key
32
+ #
33
+ #
34
+ # @example
35
+ #
36
+ # fetcher = SecretFetcher.for_service(:akeyless_vault, { access_id: "my-access-id", access_key: "my-access-key" }, run_context )
37
+ # fetcher.fetch("/secret/data/secretkey1")
38
+ #
39
+ AKEYLESS_VAULT_PROXY_ADDR = "https://hvp.akeyless.io".freeze
40
+ class AKeylessVault < HashiVault
41
+ def validate!
42
+ if config[:access_key].nil?
43
+ raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide the secret access key in the configuration as :secret_access_key")
44
+ end
45
+ if config[:access_id].nil?
46
+ raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide the access key id in the configuration as :access_key_id")
47
+ end
48
+
49
+ config[:vault_addr] ||= AKEYLESS_VAULT_PROXY_ADDR
50
+ config[:auth_method] = :token
51
+ config[:token] = "#{config[:access_id]}..#{config[:access_key]}"
52
+ super
53
+ end
54
+ end
55
+ end
56
+ end
57
+
@@ -0,0 +1,65 @@
1
+ #
2
+ # Author:: Marc Paradise (<marc@chef.io>)
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_relative "base"
20
+ require "aws-sdk-core"
21
+ require "aws-sdk-secretsmanager"
22
+
23
+ class Chef
24
+ # == Chef::SecretFetcher::AWSSecretsManager
25
+ # A fetcher that fetches a secret from AWS Secrets Manager
26
+ # In this initial iteration it defaults to authentication via instance profile.
27
+ # It is possible to pass options that configure it to use alternative credentials.
28
+ # This implementation supports fetching with version.
29
+ #
30
+ # @note ':region' is required configuration. If it is not explicitly provided,
31
+ # and it is not available via global AWS config, we will pull it from node ohai data by default.
32
+ # If this isn't correct, you will need to explicitly override it.
33
+ # If it is not available via ohai data either (such as if you have the AWS plugin disabled)
34
+ # then the converge will fail with an error.
35
+ #
36
+ # @note: This does not yet support automatic retries, which the AWS client does by default.
37
+ #
38
+ # For configuration options see https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/SecretsManager/Client.html#initialize-instance_method
39
+ #
40
+ #
41
+ # Usage Example:
42
+ #
43
+ # fetcher = SecretFetcher.for_service(:aws_secrets_manager)
44
+ # fetcher.fetch("secretkey1", "v1")
45
+ class SecretFetcher
46
+ class AWSSecretsManager < Base
47
+ def validate!
48
+ config[:region] = config[:region] || Aws.config[:region] || run_context.node.dig("ec2", "region")
49
+ if config[:region].nil?
50
+ raise Chef::Exceptions::Secret::ConfigurationInvalid.new("Missing required config for AWS secret fetcher: :region")
51
+ end
52
+ end
53
+
54
+ # @param identifier [String] the secret_id
55
+ # @param version [String] the secret version.
56
+ # @return Aws::SecretsManager::Types::GetSecretValueResponse
57
+ def do_fetch(identifier, version)
58
+ client = Aws::SecretsManager::Client.new(config)
59
+ result = client.get_secret_value(secret_id: identifier, version_stage: version)
60
+ # These fields are mutually exclusive
61
+ result.secret_string || result.secret_binary
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,78 @@
1
+ require_relative "base"
2
+
3
+ class Chef
4
+ class SecretFetcher
5
+ # == Chef::SecretFetcher::AzureKeyVault
6
+ # A fetcher that fetches a secret from Azure Key Vault. Supports fetching with version.
7
+ #
8
+ # In this initial iteration this authenticates via token obtained from the OAuth2 /token
9
+ # endpoint.
10
+ #
11
+ # Validation of required configuration (vault name) is not performed until
12
+ # `fetch` time, to allow for embedding the vault name in with the secret
13
+ # name, such as "my_vault/secretkey1".
14
+ #
15
+ # @example
16
+ #
17
+ # fetcher = SecretFetcher.for_service(:azure_key_vault, { vault: "my_vault" }, run_context )
18
+ # fetcher.fetch("secretkey1", "v1")
19
+ #
20
+ # @example
21
+ #
22
+ # fetcher = SecretFetcher.for_service(:azure_key_vault, {}, run_context )
23
+ # fetcher.fetch("my_vault/secretkey1", "v1")
24
+ class AzureKeyVault < Base
25
+
26
+ def do_fetch(name, version)
27
+ token = fetch_token
28
+ vault, name = resolve_vault_and_secret_name(name)
29
+ if vault.nil?
30
+ raise Chef::Exceptions::Secret::ConfigurationInvalid.new("You must provide a vault name to fetcher options as vault: 'vault_name' or in the secret name as 'vault_name/secret_name'")
31
+ end
32
+
33
+ # Note that `version` is optional after the final `/`. If nil/"", the latest secret version will be fetched.
34
+ secret_uri = URI.parse("https://#{vault}.vault.azure.net/secrets/#{name}/#{version}?api-version=7.2")
35
+ http = Net::HTTP.new(secret_uri.host, secret_uri.port)
36
+ http.use_ssl = true
37
+
38
+ response = http.get(secret_uri, { "Authorization" => "Bearer #{token}",
39
+ "Content-Type" => "application/json" })
40
+
41
+ # If an exception is not raised, we can be reasonably confident of the
42
+ # shape of the result.
43
+ result = JSON.parse(response.body)
44
+ if result.key? "value"
45
+ result["value"]
46
+ else
47
+ raise Chef::Exceptions::Secret::FetchFailed.new("#{result["error"]["code"]}: #{result["error"]["message"]}")
48
+ end
49
+ end
50
+
51
+ # Determine the vault name and secret name from the provided name.
52
+ # If it is not in the provided name in the form "vault_name/secret_name"
53
+ # it will determine the vault name from `config[:vault]`.
54
+ # @param name [String] the secret name or vault and secret name in the form "vault_name/secret_name"
55
+ # @return Array[String, String] vault and secret name respectively
56
+ def resolve_vault_and_secret_name(name)
57
+ # We support a simplified approach where the vault name is not passed i
58
+ # into configuration, but
59
+ if name.include?("/")
60
+ name.split("/", 2)
61
+ else
62
+ [config[:vault], name]
63
+ end
64
+ end
65
+
66
+ def fetch_token
67
+ token_uri = URI.parse("http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fvault.azure.net")
68
+ http = Net::HTTP.new(token_uri.host, token_uri.port)
69
+ response = http.get(token_uri, { "Metadata" => "true" })
70
+ body = JSON.parse(response.body)
71
+ body["access_token"]
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+
78
+
@@ -0,0 +1,76 @@
1
+ #
2
+ # Author:: Marc Paradise (<marc@chef.io>)
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_relative "../exceptions"
20
+
21
+ class Chef
22
+ # == Chef::SecretFetcher
23
+ # An abstract base class that defines the methods required to implement
24
+ # a Secret Fetcher.
25
+ class SecretFetcher
26
+ class Base
27
+ attr_reader :config
28
+ # Note that this is only available in the context of a recipe.
29
+ # Since that's the only place it's intended to be used, that's probably OK.
30
+ attr_reader :run_context
31
+
32
+ # Initialize a new SecretFetcher::Base
33
+ #
34
+ # @param config [Hash] Configuration hash. Expected configuration keys and values
35
+ # will vary based on implementation, and are validated in `validate!`.
36
+ def initialize(config, run_context)
37
+ @config = config
38
+ @run_context = run_context
39
+ end
40
+
41
+ # Fetch the named secret by invoking implementation-specific [Chef::SecretFetcher::Base#do_fetch]
42
+ #
43
+ # @param name [Object] the name or identifier of the secret.
44
+ # @param version [Object] Optional version of the secret to fetch.
45
+ # @note - the name parameter will probably see a narrowing of type as we learn more about different integrations.
46
+ # @return [Object] the fetched secret
47
+ # @raise [Chef::Exceptions::Secret::MissingSecretName] when secret name is not provided
48
+ # @raise [Chef::Exceptions::Secret::FetchFailed] when the underlying attempt to fetch the secret fails.
49
+ def fetch(name, version = nil)
50
+ raise Chef::Exceptions::Secret::MissingSecretName.new if name.to_s == ""
51
+
52
+ do_fetch(name, version)
53
+ end
54
+
55
+ # Validate that the instance is correctly configured.
56
+ # @raise [Chef::Exceptions::Secret::ConfigurationInvalid] if it is not.
57
+ def validate!; end
58
+
59
+ # Called to fetch the secret identified by 'identifier'. Implementations
60
+ # should expect that `validate!` has been invoked before `do_fetch`.
61
+ #
62
+ # @param identifier [Object] Unique identifier of the secret to be retrieved.
63
+ # When invoked via DSL, this is pre-verified to be not nil/not empty string.
64
+ # The expected data type and form can vary by implementation.
65
+ # @param version [Object] Optional version of the secret to be retrieved. If not
66
+ # provided, implementations are expected to fetch the most recent version of the
67
+ # secret by default.
68
+ #
69
+ # @return [Object] The secret as returned from the implementation. The data type
70
+ # will vary implementation.
71
+ #
72
+ # @raise [Chef::Exceptions::Secret::FetchFailed] if the secret could not be fetched
73
+ def do_fetch(identifier, version); raise NotImplementedError.new; end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,46 @@
1
+ #
2
+ # Author:: Marc Paradise (<marc@chef.io>)
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_relative "base"
20
+
21
+ class Chef
22
+ # == Chef::SecretFetcher::Example
23
+ # A simple implementation of a secrets fetcher.
24
+ # It expects to be initialized with a hash of
25
+ # keys and secret values.
26
+ #
27
+ # Usage Example:
28
+ #
29
+ # fetcher = SecretFetcher.for_service(:example, "secretkey1" => { "secret" => "lives here" })
30
+ # fetcher.fetch("secretkey1")
31
+ class SecretFetcher
32
+ class Example < Base
33
+ def validate!
34
+ if config.class != Hash
35
+ raise Chef::Exceptions::Secret::ConfigurationInvalid.new("The Example fetcher requires a hash of secrets")
36
+ end
37
+ end
38
+
39
+ def do_fetch(identifier, version)
40
+ raise Chef::Exceptions::Secret::FetchFailed.new("Secret #{identifier}) not found.") unless config.key?(identifier)
41
+
42
+ config[identifier]
43
+ end
44
+ end
45
+ end
46
+ end