chef 17.3.48-universal-mingw32 → 17.6.15-universal-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -2
  3. data/chef.gemspec +2 -0
  4. data/lib/chef/application/base.rb +11 -1
  5. data/lib/chef/application.rb +3 -1
  6. data/lib/chef/client.rb +1 -2
  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/dsl/compliance.rb +38 -0
  17. data/lib/chef/dsl/reader_helpers.rb +51 -0
  18. data/lib/chef/dsl/recipe.rb +4 -2
  19. data/lib/chef/dsl/secret.rb +5 -7
  20. data/lib/chef/dsl/universal.rb +2 -0
  21. data/lib/chef/event_dispatch/base.rb +44 -2
  22. data/lib/chef/exceptions.rb +0 -2
  23. data/lib/chef/formatters/doc.rb +60 -13
  24. data/lib/chef/formatters/error_mapper.rb +2 -2
  25. data/lib/chef/formatters/minimal.rb +6 -5
  26. data/lib/chef/http/basic_client.rb +15 -7
  27. data/lib/chef/http.rb +12 -8
  28. data/lib/chef/provider/execute.rb +1 -1
  29. data/lib/chef/provider/file.rb +2 -0
  30. data/lib/chef/provider/group/dscl.rb +1 -1
  31. data/lib/chef/provider/launchd.rb +6 -6
  32. data/lib/chef/provider/link.rb +2 -2
  33. data/lib/chef/provider/registry_key.rb +3 -2
  34. data/lib/chef/provider/remote_file/http.rb +1 -1
  35. data/lib/chef/provider/subversion.rb +4 -4
  36. data/lib/chef/provider/support/yum_repo.erb +1 -1
  37. data/lib/chef/provider/systemd_unit.rb +17 -16
  38. data/lib/chef/provider/template.rb +1 -1
  39. data/lib/chef/provider/user/mac.rb +3 -3
  40. data/lib/chef/provider/yum_repository.rb +27 -43
  41. data/lib/chef/provider/zypper_repository.rb +3 -3
  42. data/lib/chef/provider.rb +26 -1
  43. data/lib/chef/provider_resolver.rb +8 -2
  44. data/lib/chef/resource/archive_file.rb +17 -14
  45. data/lib/chef/resource/chef_client_scheduled_task.rb +45 -2
  46. data/lib/chef/resource/chocolatey_config.rb +13 -13
  47. data/lib/chef/resource/execute.rb +2 -2
  48. data/lib/chef/resource/file/verification/json.rb +50 -0
  49. data/lib/chef/resource/file/verification/yaml.rb +52 -0
  50. data/lib/chef/resource/homebrew_cask.rb +1 -1
  51. data/lib/chef/resource/inspec_input.rb +127 -0
  52. data/lib/chef/resource/inspec_waiver.rb +184 -0
  53. data/lib/chef/resource/inspec_waiver_file_entry.rb +2 -2
  54. data/lib/chef/resource/launchd.rb +3 -3
  55. data/lib/chef/resource/mount.rb +1 -1
  56. data/lib/chef/resource/openssl_x509_certificate.rb +1 -1
  57. data/lib/chef/resource/powershell_package_source.rb +234 -70
  58. data/lib/chef/resource/registry_key.rb +36 -48
  59. data/lib/chef/resource/remote_file.rb +99 -3
  60. data/lib/chef/resource/rhsm_subscription.rb +5 -5
  61. data/lib/chef/resource/ruby_block.rb +100 -0
  62. data/lib/chef/resource/scm/subversion.rb +1 -1
  63. data/lib/chef/resource/sysctl.rb +2 -2
  64. data/lib/chef/resource/systemd_unit.rb +3 -3
  65. data/lib/chef/resource/timezone.rb +2 -2
  66. data/lib/chef/resource/user_ulimit.rb +1 -0
  67. data/lib/chef/resource/windows_printer.rb +1 -1
  68. data/lib/chef/resource/windows_uac.rb +3 -1
  69. data/lib/chef/resource/windows_user_privilege.rb +1 -1
  70. data/lib/chef/resource/yum_package.rb +1 -5
  71. data/lib/chef/resource.rb +13 -17
  72. data/lib/chef/resource_inspector.rb +6 -2
  73. data/lib/chef/resources.rb +2 -0
  74. data/lib/chef/run_context/cookbook_compiler.rb +112 -28
  75. data/lib/chef/run_context.rb +31 -1
  76. data/lib/chef/secret_fetcher/akeyless_vault.rb +57 -0
  77. data/lib/chef/secret_fetcher/aws_secrets_manager.rb +17 -5
  78. data/lib/chef/secret_fetcher/azure_key_vault.rb +32 -10
  79. data/lib/chef/secret_fetcher/base.rb +6 -2
  80. data/lib/chef/secret_fetcher/hashi_vault.rb +100 -0
  81. data/lib/chef/secret_fetcher.rb +13 -6
  82. data/lib/chef/version.rb +1 -1
  83. data/lib/chef/win32/version.rb +2 -1
  84. data/spec/data/archive_file/test_archive.tar.gz +0 -0
  85. data/spec/functional/resource/archive_file_spec.rb +87 -0
  86. data/spec/functional/resource/group_spec.rb +5 -1
  87. data/spec/functional/resource/link_spec.rb +8 -0
  88. data/spec/functional/resource/powershell_package_source_spec.rb +5 -6
  89. data/spec/integration/compliance/compliance_spec.rb +61 -0
  90. data/spec/integration/recipes/resource_action_spec.rb +2 -2
  91. data/spec/spec_helper.rb +3 -0
  92. data/spec/support/platform_helpers.rb +4 -0
  93. data/spec/support/ruby_installer.rb +51 -0
  94. data/spec/unit/compliance/input_spec.rb +104 -0
  95. data/spec/unit/compliance/profile_spec.rb +120 -0
  96. data/spec/unit/compliance/runner_spec.rb +46 -2
  97. data/spec/unit/compliance/waiver_spec.rb +104 -0
  98. data/spec/unit/dsl/secret_spec.rb +8 -2
  99. data/spec/unit/formatters/doc_spec.rb +1 -1
  100. data/spec/unit/http/basic_client_spec.rb +30 -0
  101. data/spec/unit/http_spec.rb +8 -2
  102. data/spec/unit/provider/link_spec.rb +13 -7
  103. data/spec/unit/provider/remote_file/http_spec.rb +10 -0
  104. data/spec/unit/provider/template_spec.rb +2 -2
  105. data/spec/unit/provider_spec.rb +23 -0
  106. data/spec/unit/resource/archive_file_spec.rb +414 -3
  107. data/spec/unit/resource/chef_client_scheduled_task_spec.rb +69 -0
  108. data/spec/unit/resource/file/verification/json_spec.rb +72 -0
  109. data/spec/unit/resource/file/verification/yaml_spec.rb +67 -0
  110. data/spec/unit/resource/homebrew_cask_spec.rb +29 -11
  111. data/spec/unit/resource/inspec_input_spec.rb +300 -0
  112. data/spec/unit/resource/inspec_waiver_spec.rb +312 -0
  113. data/spec/unit/resource/mount_spec.rb +10 -0
  114. data/spec/unit/resource/powershell_package_source_spec.rb +63 -62
  115. data/spec/unit/resource/rhsm_subscription_spec.rb +50 -3
  116. data/spec/unit/resource/systemd_unit_spec.rb +1 -1
  117. data/spec/unit/resource/user_ulimit_spec.rb +14 -1
  118. data/spec/unit/resource_spec.rb +19 -8
  119. data/spec/unit/secret_fetcher/akeyless_vault_spec.rb +37 -0
  120. data/spec/unit/secret_fetcher/aws_secrets_manager_spec.rb +70 -0
  121. data/spec/unit/secret_fetcher/azure_key_vault_spec.rb +23 -16
  122. data/spec/unit/secret_fetcher/hashi_vault_spec.rb +80 -0
  123. data/spec/unit/secret_fetcher_spec.rb +9 -9
  124. data/tasks/rspec.rb +2 -1
  125. metadata +61 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 203a5aa495fb3cbce86bd90e53bde981b7fe825dc5a02fb508342bfe24168736
4
- data.tar.gz: d5aee72a800a84a704acf217184ae04830405fe12fa66f69b2bf768885cfcfa0
3
+ metadata.gz: d1af2f5d07eb0aced716be1b85c74bc9a6599c7fb432e7ec6a46d10fdffbfc78
4
+ data.tar.gz: 335f5b9d300e0a2102247247262b4a579467df2ff50bd373ee9d2360d4e88c0e
5
5
  SHA512:
6
- metadata.gz: 9f0e89f09f3fa298a205b9094d042eb202d9992294b02cb332703e9a314bbe07414701713797eb1b3cd698e36b4e2de8f32b3ffbba913f42da33c86b98eacdbf
7
- data.tar.gz: 4fbe89ccc95d59001243fc39267f314e77ebd7eeece444267715f9e6fd8123af6409db3956bd60c76e1e4ce57dcf60428f4d865d998fe6ac98cf5bc5498c5e29
6
+ metadata.gz: 780e3a4d4b93171175ac1b19b8beb4f359c929f292a0f384f6c5783cadb0cc0af96339147b57baa3b83edd33def12b7de6126968a998df0b2a105dd2814cfde6
7
+ data.tar.gz: 65dd63d76bd8ea7cc3e04b60c995e5454e04a18af294d7722e9b739efdd75b6a5cbdc30c2624e204dc2909625bbf7fac4dfd8928d005d7b0604bb819ab584d02
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem "chef", path: "."
4
4
 
5
- gem "ohai", git: "https://github.com/chef/ohai.git", branch: "master"
5
+ gem "ohai", git: "https://github.com/chef/ohai.git", branch: "main"
6
6
 
7
7
  gem "chef-utils", path: File.expand_path("chef-utils", __dir__) if File.exist?(File.expand_path("chef-utils", __dir__))
8
8
  gem "chef-config", path: File.expand_path("chef-config", __dir__) if File.exist?(File.expand_path("chef-config", __dir__))
@@ -48,7 +48,7 @@ end
48
48
 
49
49
  group(:chefstyle) do
50
50
  # for testing new chefstyle rules
51
- gem "chefstyle", git: "https://github.com/chef/chefstyle.git", branch: "master"
51
+ gem "chefstyle", git: "https://github.com/chef/chefstyle.git", branch: "main"
52
52
  end
53
53
 
54
54
  instance_eval(ENV["GEMFILE_MOD"]) if ENV["GEMFILE_MOD"]
data/chef.gemspec CHANGED
@@ -55,7 +55,9 @@ Gem::Specification.new do |s|
55
55
 
56
56
  s.add_dependency "proxifier", "~> 1.0"
57
57
 
58
+ s.add_dependency "aws-sdk-s3", "~> 1.91" # s3 recipe-url support
58
59
  s.add_dependency "aws-sdk-secretsmanager", "~> 1.46"
60
+ s.add_dependency "vault", "~> 0.16" # hashi vault official client gem
59
61
  s.bindir = "bin"
60
62
  s.executables = %w{ }
61
63
 
@@ -378,9 +378,19 @@ class Chef::Application::Base < Chef::Application
378
378
 
379
379
  def fetch_recipe_tarball(url, path)
380
380
  require "open-uri" unless defined?(OpenURI)
381
+ uri = URI.parse(url)
382
+
381
383
  Chef::Log.trace("Download recipes tarball from #{url} to #{path}")
382
384
  if File.exist?(url)
383
385
  FileUtils.cp(url, path)
386
+ elsif uri.scheme == "s3"
387
+ require "aws-sdk-s3" unless defined?(Aws::S3)
388
+
389
+ s3 = Aws::S3::Client.new
390
+ object = s3.get_object(bucket: uri.hostname, key: uri.path[1..-1])
391
+ File.open(path, "wb") do |f|
392
+ f.write(object.body.read)
393
+ end
384
394
  elsif URI::DEFAULT_PARSER.make_regexp.match?(url)
385
395
  File.open(path, "wb") do |f|
386
396
  URI.open(url) do |r|
@@ -388,7 +398,7 @@ class Chef::Application::Base < Chef::Application
388
398
  end
389
399
  end
390
400
  else
391
- Chef::Application.fatal! "You specified --recipe-url but the value is neither a valid URL nor a path to a file that exists on disk." +
401
+ Chef::Application.fatal! "You specified --recipe-url but the value is neither a valid URL, an S3 bucket nor a path to a file that exists on disk." +
392
402
  "Please confirm the location of the tarball and try again."
393
403
  end
394
404
  end
@@ -377,7 +377,9 @@ class Chef
377
377
 
378
378
  Chef::FileCache.store("#{ChefUtils::Dist::Infra::SHORT}-stacktrace.out", chef_stacktrace_out)
379
379
  logger.fatal("Stacktrace dumped to #{Chef::FileCache.load("#{ChefUtils::Dist::Infra::SHORT}-stacktrace.out", false)}")
380
- logger.fatal("Please provide the contents of the stacktrace.out file if you file a bug report")
380
+ logger.fatal("---------------------------------------------------------------------------------------")
381
+ logger.fatal("PLEASE PROVIDE THE CONTENTS OF THE stacktrace.out FILE (above) IF YOU FILE A BUG REPORT")
382
+ logger.fatal("---------------------------------------------------------------------------------------")
381
383
  if Chef::Config[:always_dump_stacktrace]
382
384
  logger.fatal(message)
383
385
  else
data/lib/chef/client.rb CHANGED
@@ -241,8 +241,7 @@ class Chef
241
241
 
242
242
  run_status.run_id = request_id = Chef::RequestID.instance.request_id
243
243
 
244
- @run_context = Chef::RunContext.new
245
- run_context.events = events
244
+ @run_context = Chef::RunContext.new(nil, nil, events)
246
245
  run_status.run_context = run_context
247
246
 
248
247
  events.run_start(Chef::VERSION, run_status)
@@ -28,7 +28,7 @@ class Chef
28
28
  # Controls what is done with the resulting report after the Chef InSpec run.
29
29
  # Accepts a single string value or an array of multiple values.
30
30
  # Accepted values: 'chef-server-automate', 'chef-automate', 'json-file', 'audit-enforcer', 'cli'
31
- "reporter" => %w{json-file cli},
31
+ "reporter" => "cli",
32
32
 
33
33
  # Controls if Chef InSpec profiles should be fetched from Chef Automate or Chef Infra Server
34
34
  # in addition to the default fetch locations provided by Chef Inspec.
@@ -47,8 +47,10 @@ class Chef
47
47
  "profiles" => {},
48
48
 
49
49
  # Extra inputs passed to Chef InSpec to allow finer-grained control over behavior.
50
- # These are mapped to Chef InSpec's inputs, but are named attributes here for legacy reasons.
51
50
  # See Chef Inspec's documentation for more information: https://docs.chef.io/inspec/inputs/
51
+ "inputs" => {},
52
+
53
+ # Legacy alias for inputs
52
54
  "attributes" => {},
53
55
 
54
56
  # A string path or an array of paths to Chef InSpec waiver files.
@@ -88,7 +90,7 @@ class Chef
88
90
 
89
91
  # If enabled, a hash representation of the Chef Infra node object will be sent to Chef InSpec in an input
90
92
  # named `chef_node`.
91
- "chef_node_attribute_enabled" => false,
93
+ "chef_node_attribute_enabled" => true,
92
94
 
93
95
  # Should the built-in compliance phase run. True and false force the behavior. Nil does magic based on if you have
94
96
  # profiles defined but do not have the audit cookbook enabled.
@@ -0,0 +1,115 @@
1
+ #
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
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 "yaml"
19
+
20
+ class Chef
21
+ module Compliance
22
+ #
23
+ # Chef object that represents a single input file in the compliance segment
24
+ # of a cookbook.
25
+ #
26
+ class Input
27
+ # @return [Boolean] if the input has been enabled
28
+ attr_reader :enabled
29
+
30
+ # @return [String] The name of the cookbook that the input is in
31
+ attr_reader :cookbook_name
32
+
33
+ # @return [String] The full path on the host to the input yml file
34
+ attr_reader :path
35
+
36
+ # @return [String] the pathname in the cookbook
37
+ attr_reader :pathname
38
+
39
+ # Event dispatcher for this run.
40
+ #
41
+ # @return [Chef::EventDispatch::Dispatcher]
42
+ #
43
+ attr_reader :events
44
+
45
+ # @api private
46
+ attr_reader :data
47
+
48
+ def initialize(events, data, path, cookbook_name)
49
+ @events = events
50
+ @data = data
51
+ @cookbook_name = cookbook_name
52
+ @path = path
53
+ @pathname = File.basename(path, File.extname(path)) unless path.nil?
54
+ disable!
55
+ end
56
+
57
+ # @return [Boolean] if the input has been enabled
58
+ #
59
+ def enabled?
60
+ !!@enabled
61
+ end
62
+
63
+ # Set the input to being enabled
64
+ #
65
+ def enable!
66
+ events.compliance_input_enabled(self)
67
+ @enabled = true
68
+ end
69
+
70
+ # Set the input as being disabled
71
+ #
72
+ def disable!
73
+ @enabled = false
74
+ end
75
+
76
+ # Render the input in a way that it can be consumed by inspec
77
+ #
78
+ def inspec_data
79
+ data
80
+ end
81
+
82
+ HIDDEN_IVARS = [ :@events ].freeze
83
+
84
+ # Omit the event object from error output
85
+ #
86
+ def inspect
87
+ ivar_string = (instance_variables.map(&:to_sym) - HIDDEN_IVARS).map do |ivar|
88
+ "#{ivar}=#{instance_variable_get(ivar).inspect}"
89
+ end.join(", ")
90
+ "#<#{self.class}:#{object_id} #{ivar_string}>"
91
+ end
92
+
93
+ # Helper to construct a input object from a hash. Since the path and
94
+ # cookbook_name are required this is probably not externally useful.
95
+ #
96
+ def self.from_hash(events, hash, path = nil, cookbook_name = nil)
97
+ new(events, hash, path, cookbook_name)
98
+ end
99
+
100
+ # Helper to construct a input object from a yaml string. Since the path
101
+ # and cookbook_name are required this is probably not externally useful.
102
+ #
103
+ def self.from_yaml(events, string, path = nil, cookbook_name = nil)
104
+ from_hash(events, YAML.load(string), path, cookbook_name)
105
+ end
106
+
107
+ # @param filename [String] full path to the yml file in the cookbook
108
+ # @param cookbook_name [String] cookbook that the input is in
109
+ #
110
+ def self.from_file(events, filename, cookbook_name = nil)
111
+ from_yaml(events, IO.read(filename), filename, cookbook_name)
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,139 @@
1
+ # Copyright:: Copyright (c) Chef Software Inc.
2
+ # License:: Apache License, Version 2.0
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 "input"
18
+
19
+ class Chef
20
+ module Compliance
21
+ class InputCollection < Array
22
+
23
+ # Event dispatcher for this run.
24
+ #
25
+ # @return [Chef::EventDispatch::Dispatcher]
26
+ #
27
+ attr_reader :events
28
+
29
+ def initialize(events)
30
+ @events = events
31
+ end
32
+
33
+ # Add a input to the input collection. The cookbook_name needs to be determined by the
34
+ # caller and is used in the `include_input` API to match on. The path should be the complete
35
+ # path on the host of the yml file, including the filename.
36
+ #
37
+ # @param path [String]
38
+ # @param cookbook_name [String]
39
+ #
40
+ def from_file(filename, cookbook_name)
41
+ new_input = Input.from_file(events, filename, cookbook_name)
42
+ self << new_input
43
+ events.compliance_input_loaded(new_input)
44
+ end
45
+
46
+ # Add a input from a raw hash. This input will be enabled by default.
47
+ #
48
+ # @param path [String]
49
+ # @param cookbook_name [String]
50
+ #
51
+ def from_hash(hash)
52
+ new_input = Input.from_hash(events, hash)
53
+ new_input.enable!
54
+ self << new_input
55
+ end
56
+
57
+ # @return [Array<Input>] inspec inputs which are enabled in a form suitable to pass to inspec
58
+ #
59
+ def inspec_data
60
+ select(&:enabled?).each_with_object({}) { |input, hash| hash.merge(input.inspec_data) }
61
+ end
62
+
63
+ # DSL method to enable input files. This matches on the filename of the input file.
64
+ # If the specific input is omitted then it uses the default input. The string
65
+ # supports regular expression matching.
66
+ #
67
+ # @example Specific input file in a cookbook
68
+ #
69
+ # include_input "acme_cookbook::ssh-001"
70
+ #
71
+ # @example The compliance/inputs/default.yml input in a cookbook
72
+ #
73
+ # include_input "acme_cookbook"
74
+ #
75
+ # @example Every input file in a cookbook
76
+ #
77
+ # include_input "acme_cookbook::.*"
78
+ #
79
+ # @example Matching inputs by regexp in a cookbook
80
+ #
81
+ # include_input "acme_cookbook::ssh.*"
82
+ #
83
+ # @example Matching inputs by regexp in any cookbook in the cookbook collection
84
+ #
85
+ # include_input ".*::ssh.*"
86
+ #
87
+ # @example Adding an arbitrary hash of data (not from any file in a cookbook)
88
+ #
89
+ # include_input({ "ssh_custom_path": "/usr/local/bin" })
90
+ #
91
+ def include_input(arg)
92
+ raise "include_input was given a nil value" if arg.nil?
93
+
94
+ # if we're given a hash argument just shove it in the raw_hash
95
+ if arg.is_a?(Hash)
96
+ from_hash(arg)
97
+ return
98
+ end
99
+
100
+ matching_inputs(arg).each(&:enable!)
101
+ end
102
+
103
+ def valid?(arg)
104
+ !matching_inputs(arg).empty?
105
+ end
106
+
107
+ HIDDEN_IVARS = [ :@events ].freeze
108
+
109
+ # Omit the event object from error output
110
+ #
111
+ def inspect
112
+ ivar_string = (instance_variables.map(&:to_sym) - HIDDEN_IVARS).map do |ivar|
113
+ "#{ivar}=#{instance_variable_get(ivar).inspect}"
114
+ end.join(", ")
115
+ "#<#{self.class}:#{object_id} #{ivar_string}>"
116
+ end
117
+
118
+ private
119
+
120
+ def matching_inputs(arg, should_raise: false)
121
+ (cookbook_name, input_name) = arg.split("::")
122
+
123
+ input_name = "default" if input_name.nil?
124
+
125
+ inputs = select { |input| /^#{cookbook_name}$/.match?(input.cookbook_name) && /^#{input_name}$/.match?(input.pathname) }
126
+
127
+ if inputs.empty? && should_raise
128
+ raise "No inspec inputs matching '#{input_name}' found in cookbooks matching '#{cookbook_name}'"
129
+ end
130
+
131
+ inputs
132
+ end
133
+
134
+ def matching_inputs!(arg)
135
+ matching_inputs(arg, should_raise: true)
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,122 @@
1
+ #
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
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
+ class Chef
19
+ module Compliance
20
+ class Profile
21
+ # @return [Boolean] if the profile has been enabled
22
+ attr_accessor :enabled
23
+
24
+ # @return [String] The full path on the host to the profile inspec.yml
25
+ attr_reader :path
26
+
27
+ # @return [String] The name of the cookbook that the profile is in
28
+ attr_reader :cookbook_name
29
+
30
+ # @return [String] the pathname in the cookbook
31
+ attr_accessor :pathname
32
+
33
+ # @return [Chef::EventDispatch::Dispatcher] Event dispatcher for this run.
34
+ attr_reader :events
35
+
36
+ # @api private
37
+ attr_reader :data
38
+
39
+ def initialize(events, data, path, cookbook_name)
40
+ @events = events
41
+ @data = data
42
+ @path = path
43
+ @cookbook_name = cookbook_name
44
+ @pathname = File.basename(File.dirname(path))
45
+ disable!
46
+ validate!
47
+ end
48
+
49
+ # @return [String] name of the inspec profile from parsing the inspec.yml
50
+ def name
51
+ @data["name"]
52
+ end
53
+
54
+ # @return [String] version of the inspec profile from parsing the inspec.yml
55
+ def version
56
+ @data["version"]
57
+ end
58
+
59
+ # Raises if the inspec profile is not valid.
60
+ #
61
+ def validate!
62
+ raise "Inspec profile at #{path} has no name" unless name
63
+ end
64
+
65
+ # @return [Boolean] if the profile has been enabled
66
+ def enabled?
67
+ !!@enabled
68
+ end
69
+
70
+ # Set the profile to being enabled
71
+ #
72
+ def enable!
73
+ events.compliance_profile_enabled(self)
74
+ @enabled = true
75
+ end
76
+
77
+ # Set the profile as being disabled
78
+ #
79
+ def disable!
80
+ @enabled = false
81
+ end
82
+
83
+ # Render the profile in a way that it can be consumed by inspec
84
+ #
85
+ def inspec_data
86
+ { name: name, path: File.dirname(path) }
87
+ end
88
+
89
+ HIDDEN_IVARS = [ :@events ].freeze
90
+
91
+ # Omit the event object from error output
92
+ #
93
+ def inspect
94
+ ivar_string = (instance_variables.map(&:to_sym) - HIDDEN_IVARS).map do |ivar|
95
+ "#{ivar}=#{instance_variable_get(ivar).inspect}"
96
+ end.join(", ")
97
+ "#<#{self.class}:#{object_id} #{ivar_string}>"
98
+ end
99
+
100
+ # Helper to construct a profile object from a hash. Since the path and
101
+ # cookbook_name are required this is probably not externally useful.
102
+ #
103
+ def self.from_hash(events, hash, path, cookbook_name)
104
+ new(events, hash, path, cookbook_name)
105
+ end
106
+
107
+ # Helper to construct a profile object from a yaml string. Since the path
108
+ # and cookbook_name are required this is probably not externally useful.
109
+ #
110
+ def self.from_yaml(events, string, path, cookbook_name)
111
+ from_hash(events, YAML.load(string), path, cookbook_name)
112
+ end
113
+
114
+ # @param filename [String] full path to the inspec.yml file in the cookbook
115
+ # @param cookbook_name [String] cookbook that the profile is in
116
+ #
117
+ def self.from_file(events, filename, cookbook_name)
118
+ from_yaml(events, IO.read(filename), filename, cookbook_name)
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,109 @@
1
+ #
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
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 "profile"
19
+
20
+ class Chef
21
+ module Compliance
22
+ class ProfileCollection < Array
23
+
24
+ # Event dispatcher for this run.
25
+ #
26
+ # @return [Chef::EventDispatch::Dispatcher]
27
+ #
28
+ attr_reader :events
29
+
30
+ def initialize(events)
31
+ @events = events
32
+ end
33
+
34
+ # Add a profile to the profile collection. The cookbook_name needs to be determined by the
35
+ # caller and is used in the `include_profile` API to match on. The path should be the complete
36
+ # path on the host of the inspec.yml file, including the filename.
37
+ #
38
+ # @param path [String]
39
+ # @param cookbook_name [String]
40
+ #
41
+ def from_file(path, cookbook_name)
42
+ new_profile = Profile.from_file(events, path, cookbook_name)
43
+ self << new_profile
44
+ events.compliance_profile_loaded(new_profile)
45
+ end
46
+
47
+ # @return [Boolean] if any of the profiles are enabled
48
+ #
49
+ def using_profiles?
50
+ any?(&:enabled?)
51
+ end
52
+
53
+ # @return [Array<Profile>] inspec profiles which are enabled in a form suitable to pass to inspec
54
+ #
55
+ def inspec_data
56
+ select(&:enabled?).each_with_object([]) { |profile, arry| arry << profile.inspec_data }
57
+ end
58
+
59
+ # DSL method to enable profile files. This matches on the name of the profile being included it
60
+ # does not match on the filename of the input file. If the specific profile is omitted then
61
+ # it uses the default profile. The string supports regular expression matching.
62
+ #
63
+ # @example Specific profile in a cookbook
64
+ #
65
+ # include_profile "acme_cookbook::ssh-001"
66
+ #
67
+ # @example The profile named "default" in a cookbook
68
+ #
69
+ # include_profile "acme_cookbook"
70
+ #
71
+ # @example Every profile in a cookbook
72
+ #
73
+ # include_profile "acme_cookbook::.*"
74
+ #
75
+ # @example Matching profiles by regexp in a cookbook
76
+ #
77
+ # include_profile "acme_cookbook::ssh.*"
78
+ #
79
+ # @example Matching profiles by regexp in any cookbook in the cookbook collection
80
+ #
81
+ # include_profile ".*::ssh.*"
82
+ #
83
+ def include_profile(arg)
84
+ (cookbook_name, profile_name) = arg.split("::")
85
+
86
+ profile_name = "default" if profile_name.nil?
87
+
88
+ profiles = select { |profile| /^#{cookbook_name}$/.match?(profile.cookbook_name) && /^#{profile_name}$/.match?(profile.pathname) }
89
+
90
+ if profiles.empty?
91
+ raise "No inspec profiles matching '#{profile_name}' found in cookbooks matching '#{cookbook_name}'"
92
+ end
93
+
94
+ profiles.each(&:enable!)
95
+ end
96
+
97
+ HIDDEN_IVARS = [ :@events ].freeze
98
+
99
+ # Omit the event object from error output
100
+ #
101
+ def inspect
102
+ ivar_string = (instance_variables.map(&:to_sym) - HIDDEN_IVARS).map do |ivar|
103
+ "#{ivar}=#{instance_variable_get(ivar).inspect}"
104
+ end.join(", ")
105
+ "#<#{self.class}:#{object_id} #{ivar_string}>"
106
+ end
107
+ end
108
+ end
109
+ end
@@ -76,7 +76,7 @@ class Chef
76
76
 
77
77
  begin
78
78
  Chef::Log.info "Report to #{ChefUtils::Dist::Automate::PRODUCT}: #{@url}"
79
- Chef::Log.debug "Compliance Report: #{json_report}"
79
+ Chef::Log.debug "Compliance Phase report: #{json_report}"
80
80
  http_client.post(nil, json_report, headers)
81
81
  true
82
82
  rescue => e