chef 17.3.48-universal-mingw32 → 17.6.15-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.
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
@@ -21,7 +21,7 @@ require_relative "exceptions"
21
21
  class Chef
22
22
  class SecretFetcher
23
23
 
24
- SECRET_FETCHERS = %i{example aws_secrets_manager azure_key_vault}.freeze
24
+ SECRET_FETCHERS = %i{example aws_secrets_manager azure_key_vault hashi_vault akeyless_vault}.freeze
25
25
 
26
26
  # Returns a configured and validated instance
27
27
  # of a [Chef::SecretFetcher::Base] for the given
@@ -30,21 +30,28 @@ class Chef
30
30
  # @param service [Symbol] the identifier for the service that will support this request. Must be in
31
31
  # SECRET_FETCHERS
32
32
  # @param config [Hash] configuration that the secrets service requires
33
- def self.for_service(service, config)
33
+ # @param run_context [Chef::RunContext] the run context this is being invoked from
34
+ def self.for_service(service, config, run_context)
34
35
  fetcher = case service
35
36
  when :example
36
37
  require_relative "secret_fetcher/example"
37
- Chef::SecretFetcher::Example.new(config)
38
+ Chef::SecretFetcher::Example.new(config, run_context)
38
39
  when :aws_secrets_manager
39
40
  require_relative "secret_fetcher/aws_secrets_manager"
40
- Chef::SecretFetcher::AWSSecretsManager.new(config)
41
+ Chef::SecretFetcher::AWSSecretsManager.new(config, run_context)
41
42
  when :azure_key_vault
42
43
  require_relative "secret_fetcher/azure_key_vault"
43
- Chef::SecretFetcher::AzureKeyVault.new(config)
44
+ Chef::SecretFetcher::AzureKeyVault.new(config, run_context)
45
+ when :hashi_vault
46
+ require_relative "secret_fetcher/hashi_vault"
47
+ Chef::SecretFetcher::HashiVault.new(config, run_context)
48
+ when :akeyless_vault
49
+ require_relative "secret_fetcher/akeyless_vault"
50
+ Chef::SecretFetcher::AKeylessVault.new(config, run_context)
44
51
  when nil, ""
45
52
  raise Chef::Exceptions::Secret::MissingFetcher.new(SECRET_FETCHERS)
46
53
  else
47
- raise Chef::Exceptions::Secret::InvalidFetcherService.new("Unsupported secret service: #{service}", SECRET_FETCHERS)
54
+ raise Chef::Exceptions::Secret::InvalidFetcherService.new("Unsupported secret service: '#{service}'", SECRET_FETCHERS)
48
55
  end
49
56
  fetcher.validate!
50
57
  fetcher
data/lib/chef/version.rb CHANGED
@@ -23,7 +23,7 @@ require_relative "version_string"
23
23
 
24
24
  class Chef
25
25
  CHEF_ROOT = File.expand_path("..", __dir__)
26
- VERSION = Chef::VersionString.new("17.3.48")
26
+ VERSION = Chef::VersionString.new("17.6.15")
27
27
  end
28
28
 
29
29
  #
@@ -49,7 +49,8 @@ class Chef
49
49
  private_class_method :method_name_from_marketing_name
50
50
 
51
51
  WIN_VERSIONS = {
52
- "Windows Server 2019" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number >= 17763 } },
52
+ "Windows Server 2022" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number >= 20348 } },
53
+ "Windows Server 2019" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number >= 17763 && build_number < 20348 } },
53
54
  "Windows 10" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type == VER_NT_WORKSTATION } },
54
55
  "Windows Server 2016" => { major: 10, minor: 0, callable: lambda { |product_type, suite_mask, build_number| product_type != VER_NT_WORKSTATION && build_number <= 14393 } },
55
56
  "Windows 8.1" => { major: 6, minor: 3, callable: lambda { |product_type, suite_mask, build_number| product_type == VER_NT_WORKSTATION } },
@@ -0,0 +1,87 @@
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 "spec_helper"
19
+ require "tmpdir"
20
+
21
+ # Exclude this test on platforms where ffi-libarchive loading is broken
22
+ describe Chef::Resource::ArchiveFile, :libarchive_loading_broken do
23
+ include RecipeDSLHelper
24
+
25
+ let(:tmp_path) { Dir.mktmpdir }
26
+ let(:extract_destination) { "#{tmp_path}/extract_here" }
27
+ let(:test_archive_path) { File.expand_path("archive_file/test_archive.tar.gz", CHEF_SPEC_DATA) }
28
+
29
+ after do
30
+ FileUtils.remove_entry_secure(extract_destination) if File.exist?(extract_destination)
31
+ end
32
+
33
+ context "when strip_components is 0" do
34
+ it "extracts archive to destination" do
35
+ af = archive_file test_archive_path do
36
+ destination extract_destination
37
+ end
38
+ af.should_be_updated
39
+
40
+ expect(af.strip_components).to eq(0) # Validate defaults haven't changed here
41
+ expect(Dir.glob("#{extract_destination}/**/*").length).to eq(4)
42
+ expect(Dir.exist?("#{extract_destination}/folder-1")).to eq(true)
43
+ expect(File.exist?("#{extract_destination}/folder-1/file-1.txt")).to eq(true)
44
+ expect(Dir.exist?("#{extract_destination}/folder-1/folder-2")).to eq(true)
45
+ expect(File.exist?("#{extract_destination}/folder-1/folder-2/file-2.txt")).to eq(true)
46
+ end
47
+ end
48
+
49
+ context "when strip_components is 1" do
50
+ it "extracts archive to destination, with 1 component stripped" do
51
+ archive_file test_archive_path do
52
+ destination extract_destination
53
+ strip_components 1
54
+ end.should_be_updated
55
+
56
+ expect(Dir.exist?("#{extract_destination}/folder-1")).to eq(false)
57
+ expect(File.exist?("#{extract_destination}/folder-1/file-1.txt")).to eq(false)
58
+ expect(Dir.exist?("#{extract_destination}/folder-1/folder-2")).to eq(false)
59
+ expect(File.exist?("#{extract_destination}/folder-1/folder-2/file-2.txt")).to eq(false)
60
+
61
+ expect(Dir.glob("#{extract_destination}/**/*").length).to eq(3)
62
+ expect(File.exist?("#{extract_destination}/file-1.txt")).to eq(true)
63
+ expect(Dir.exist?("#{extract_destination}/folder-2")).to eq(true)
64
+ expect(File.exist?("#{extract_destination}/folder-2/file-2.txt")).to eq(true)
65
+ end
66
+ end
67
+
68
+ context "when strip_components is 2" do
69
+ it "extracts archive to destination, with 2 components stripped" do
70
+ archive_file test_archive_path do
71
+ destination extract_destination
72
+ strip_components 2
73
+ end.should_be_updated
74
+
75
+ expect(Dir.exist?("#{extract_destination}/folder-1")).to eq(false)
76
+ expect(File.exist?("#{extract_destination}/folder-1/file-1.txt")).to eq(false)
77
+ expect(Dir.exist?("#{extract_destination}/folder-1/folder-2")).to eq(false)
78
+ expect(File.exist?("#{extract_destination}/folder-1/folder-2/file-2.txt")).to eq(false)
79
+ expect(File.exist?("#{extract_destination}/file-1.txt")).to eq(false)
80
+ expect(Dir.exist?("#{extract_destination}/folder-2")).to eq(false)
81
+ expect(File.exist?("#{extract_destination}/folder-2/file-2.txt")).to eq(false)
82
+
83
+ expect(Dir.glob("#{extract_destination}/**/*").length).to eq(1)
84
+ expect(File.exist?("#{extract_destination}/file-2.txt")).to eq(true)
85
+ end
86
+ end
87
+ end
@@ -44,6 +44,10 @@ describe Chef::Resource::Group, :requires_root_or_running_windows do
44
44
  members.shift # Get rid of GroupMembership: string
45
45
  members.include?(user)
46
46
  else
47
+ # TODO For some reason our temporary AIX 7.2 system does not correctly report group membership immediately after changes have been made.
48
+ # Adding a 2 second delay for this platform is enough to get correct results.
49
+ # We hope to remove this delay after we get more permanent AIX 7.2 systems in our CI pipeline. reference: https://github.com/chef/release-engineering/issues/1617
50
+ sleep 2 if aix? && (ohai[:platform_version] == "7.2")
47
51
  Etc.getgrnam(group_name).mem.include?(user)
48
52
  end
49
53
  end
@@ -181,7 +185,7 @@ describe Chef::Resource::Group, :requires_root_or_running_windows do
181
185
 
182
186
  describe "when the users exist" do
183
187
  before do
184
- high_uid = 30000
188
+ high_uid = 40000
185
189
  (spec_members).each do |member|
186
190
  remove_user(member)
187
191
  create_user(member, high_uid)
@@ -345,9 +345,17 @@ describe Chef::Resource::Link do
345
345
  let(:test_user) { "test-link-user" }
346
346
  before do
347
347
  user(test_user).run_action(:create)
348
+ # TODO For some reason our temporary AIX 7.2 system does not correctly report user existence immediately after changes have been made.
349
+ # Adding a 2 second delay for this platform is enough to get correct results.
350
+ # We hope to remove this delay after we get more permanent AIX 7.2 systems in our CI pipeline. reference: https://github.com/chef/release-engineering/issues/1617
351
+ sleep 2 if aix? && (ohai[:platform_version] == "7.2")
348
352
  end
349
353
  after do
350
354
  user(test_user).run_action(:remove)
355
+ # TODO For some reason our temporary AIX 7.2 system does not correctly report user existence immediately after changes have been made.
356
+ # Adding a 2 second delay for this platform is enough to get correct results.
357
+ # We hope to remove this delay after we get more permanent AIX 7.2 systems in our CI pipeline. reference: https://github.com/chef/release-engineering/issues/1617
358
+ sleep 2 if aix? && (ohai[:platform_version] == "7.2")
351
359
  end
352
360
  before(:each) do
353
361
  resource.owner(test_user)
@@ -22,7 +22,7 @@ describe Chef::Resource::PowershellPackageSource, :windows_gte_10 do
22
22
  include Chef::Mixin::PowershellExec
23
23
 
24
24
  let(:source_name) { "fake" }
25
- let(:url) { "https://www.nuget.org/api/v2" }
25
+ let(:source_location) { "https://www.nuget.org/api/v2" }
26
26
  let(:trusted) { true }
27
27
 
28
28
  let(:run_context) do
@@ -32,7 +32,7 @@ describe Chef::Resource::PowershellPackageSource, :windows_gte_10 do
32
32
  subject do
33
33
  new_resource = Chef::Resource::PowershellPackageSource.new("test powershell package source", run_context)
34
34
  new_resource.source_name source_name
35
- new_resource.url url
35
+ new_resource.source_location source_location
36
36
  new_resource.trusted trusted
37
37
  new_resource.provider_name provider_name
38
38
  new_resource
@@ -61,7 +61,7 @@ describe Chef::Resource::PowershellPackageSource, :windows_gte_10 do
61
61
  it "updates an existing package source if changed" do
62
62
  subject.run_action(:register)
63
63
  subject.trusted !trusted
64
- subject.run_action(:register)
64
+ subject.run_action(:set)
65
65
  expect(subject).to be_updated_by_last_action
66
66
  end
67
67
  end
@@ -73,9 +73,8 @@ describe Chef::Resource::PowershellPackageSource, :windows_gte_10 do
73
73
  expect(get_installed_package_source_name).to be_empty
74
74
  end
75
75
 
76
- it "does not unregister the package source if not already installed" do
77
- subject.run_action(:unregister)
78
- expect(subject).not_to be_updated_by_last_action
76
+ it "does not unregister the package source if not installed" do
77
+ expect { subject.run_action(:unregister) }.to_not raise_error
79
78
  end
80
79
  end
81
80
  end
@@ -47,6 +47,7 @@ describe "chef-client with compliance phase" do
47
47
  {
48
48
  "audit": {
49
49
  "compliance_phase": true,
50
+ "reporter": "json-file",
50
51
  "json_file": {
51
52
  "location": "#{report_file}"
52
53
  },
@@ -79,4 +80,64 @@ describe "chef-client with compliance phase" do
79
80
  expect(result["status"]).to eq("passed")
80
81
  end
81
82
  end
83
+
84
+ when_the_repository "has a compliance segment" do
85
+ let(:report_file) { path_to("report_file.json") }
86
+
87
+ before do
88
+ directory "cookbooks/x" do
89
+ directory "compliance" do
90
+ directory "profiles/my_profile" do
91
+ file "inspec.yml", <<~FILE
92
+ ---
93
+ name: my-profile
94
+ FILE
95
+
96
+ directory "controls" do
97
+ file "my_control.rb", <<~FILE
98
+ control "my control" do
99
+ describe Dir.home do
100
+ it { should be_kind_of String }
101
+ end
102
+ end
103
+ FILE
104
+ end
105
+ end
106
+ end
107
+ file "attributes/default.rb", <<~FILE
108
+ default['audit']['reporter'] = "json-file"
109
+ default['audit']['json_file'] = {
110
+ "location" => "#{report_file}"
111
+ }
112
+ FILE
113
+ file "recipes/default.rb", <<~FILE
114
+ include_profile ".*::.*"
115
+ FILE
116
+ end
117
+ file "config/client.rb", <<~EOM
118
+ local_mode true
119
+ cookbook_path "#{path_to("cookbooks")}"
120
+ log_level :warn
121
+ EOM
122
+ end
123
+
124
+ it "should complete with success" do
125
+ result = shell_out!("#{chef_client} -c \"#{path_to("config/client.rb")}\" -r 'recipe[x]'", cwd: chef_dir)
126
+ result.error!
127
+
128
+ inspec_report = JSON.parse(File.read(report_file))
129
+ expect(inspec_report["profiles"].length).to eq(1)
130
+
131
+ profile = inspec_report["profiles"].first
132
+ expect(profile["name"]).to eq("my-profile")
133
+ expect(profile["controls"].length).to eq(1)
134
+
135
+ control = profile["controls"].first
136
+ expect(control["id"]).to eq("my control")
137
+ expect(control["results"].length).to eq(1)
138
+
139
+ result = control["results"].first
140
+ expect(result["status"]).to eq("passed")
141
+ end
142
+ end
82
143
  end
@@ -354,8 +354,8 @@ module ResourceActionSpec
354
354
  end
355
355
 
356
356
  it "allows overridden action to have a description separate from the action defined in the base resource" do
357
- expect(ActionJackson.action_description(:test1)).to eql "Original description"
358
- expect(ActionJackalope.action_description(:test1)).to eql "An old action with a new description"
357
+ expect(ActionJackson.new("ActionJackson", nil).action_description(:test1)).to eql "Original description"
358
+ expect(ActionJackalope.new("ActionJackalope", nil).action_description(:test1)).to eql "An old action with a new description"
359
359
  end
360
360
 
361
361
  it "non-overridden actions run and can access overridden and non-overridden variables (but not necessarily new ones)" do
data/spec/spec_helper.rb CHANGED
@@ -68,6 +68,7 @@ end
68
68
  require "spec/support/local_gems" if File.exist?(File.join(File.dirname(__FILE__), "support", "local_gems.rb"))
69
69
 
70
70
  # Explicitly require spec helpers that need to load first
71
+ require "spec/support/ruby_installer"
71
72
  require "spec/support/platform_helpers"
72
73
  require "spec/support/shared/unit/mock_shellout"
73
74
 
@@ -186,6 +187,8 @@ RSpec.configure do |config|
186
187
  config.filter_run_excluding not_rhel7: true if rhel7?
187
188
  config.filter_run_excluding not_intel_64bit: true if intel_64bit?
188
189
 
190
+ config.filter_run_excluding libarchive_loading_broken: true if aix? || amazon_linux? || rhel7?
191
+
189
192
  # these let us use chef: ">= 13" or ruby: "~> 2.0.0" or any other Gem::Dependency-style constraint
190
193
  config.filter_run_excluding chef: DependencyProc.with(Chef::VERSION)
191
194
  config.filter_run_excluding ruby: DependencyProc.with(RUBY_VERSION)
@@ -163,6 +163,10 @@ def aix?
163
163
  RUBY_PLATFORM.include?("aix")
164
164
  end
165
165
 
166
+ def amazon_linux?
167
+ ohai[:platform_family] == "amazon"
168
+ end
169
+
166
170
  def wpar?
167
171
  !((ohai[:virtualization] || {})[:wpar_no].nil?)
168
172
  end
@@ -0,0 +1,51 @@
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
+ def add_libarchive_dll_directory
18
+ require "ruby_installer"
19
+ libarchive_paths = Dir.glob("{#{Gem.dir},C:/hab}/**/libarchive.dll").map { |f| File.expand_path(f) }
20
+ if libarchive_paths.empty?
21
+ $stderr.puts <<~EOL
22
+ !!!!
23
+ We couldn't find a libarchive.dll in #{Gem.dir} or C:/hab
24
+
25
+ If this is running in a CI/CD environment, this may end up causing failures
26
+ in the tests for archive_file. If this is not running in a CI/CD
27
+ environment then it may be safe to ignore this. That is especially true if
28
+ you're not using the Ruby Installer as your Ruby runtime.
29
+ !!!!
30
+ EOL
31
+ return
32
+ end
33
+
34
+ $stderr.puts "\nFound the following libarchive paths:\n\n#{libarchive_paths.map { |f| "- #{f}\n" }.join}\n\n"
35
+ libarchive_path = libarchive_paths.first
36
+ libarchive_dir = File.dirname(libarchive_path)
37
+
38
+ if defined?(RubyInstaller::Build) && RubyInstaller::Build.methods.include?(:add_dll_directory)
39
+ $stderr.puts "Adding #{libarchive_dir} as a DLL load path using RubyInstaller::Build#add_dll_directory"
40
+ RubyInstaller::Build.add_dll_directory(libarchive_dir)
41
+ elsif defined?(RubyInstaller::Runtime) && RubyInstaller::Runtime.methods.include?(:add_dll_directory)
42
+ $stderr.puts "Adding #{libarchive_dir} as a DLL load path using RubyInstaller::Runtime#add_dll_directory"
43
+ RubyInstaller::Runtime.add_dll_directory(libarchive_dir)
44
+ else
45
+ $stderr.puts "Unable to find the right namespace to call #add_dll_directory! Please raise an issue on [GitHub](https://github.com/chef/chef/issues/new/choose)."
46
+ end
47
+ rescue LoadError
48
+ $stderr.puts "Failed to load ruby_installer. Assuming Ruby Installer is not being used."
49
+ end
50
+
51
+ add_libarchive_dll_directory if RUBY_PLATFORM =~ /mswin|mingw32|windows/
@@ -0,0 +1,104 @@
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 "spec_helper"
19
+ require "tempfile"
20
+
21
+ describe Chef::Compliance::Input do
22
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
23
+ let(:data) { { "ssh-01" => { "expiration_date" => Date.jd(2463810), "justification" => "waived, yo", "run" => false } } }
24
+ let(:path) { "/var/chef/cache/cookbooks/acme_compliance/compliance/inputs/default.yml" }
25
+ let(:cookbook_name) { "acme_compliance" }
26
+ let(:input) { Chef::Compliance::Input.new(events, data, path, cookbook_name) }
27
+
28
+ it "has a cookbook_name" do
29
+ expect(input.cookbook_name).to eql(cookbook_name)
30
+ end
31
+
32
+ it "has a path" do
33
+ expect(input.path).to eql(path)
34
+ end
35
+
36
+ it "has a pathname based on the path" do
37
+ expect(input.pathname).to eql("default")
38
+ end
39
+
40
+ it "is disabled" do
41
+ expect(input.enabled).to eql(false)
42
+ expect(input.enabled?).to eql(false)
43
+ end
44
+
45
+ it "has an event handler" do
46
+ expect(input.events).to eql(events)
47
+ end
48
+
49
+ it "can be enabled by enable!" do
50
+ input.enable!
51
+ expect(input.enabled).to eql(true)
52
+ expect(input.enabled?).to eql(true)
53
+ end
54
+
55
+ it "enabling sends an event" do
56
+ expect(events).to receive(:compliance_input_enabled).with(input)
57
+ input.enable!
58
+ end
59
+
60
+ it "can be disabled by disable!" do
61
+ input.enable!
62
+ input.disable!
63
+ expect(input.enabled).to eql(false)
64
+ expect(input.enabled?).to eql(false)
65
+ end
66
+
67
+ it "has a #inspec_data method that renders the data" do
68
+ expect(input.inspec_data).to eql(data)
69
+ end
70
+
71
+ it "doesn't render the events in the inspect output" do
72
+ expect(input.inspect).not_to include("events")
73
+ end
74
+
75
+ it "inflates objects from YAML" do
76
+ string = <<~EOH
77
+ ssh-01:
78
+ expiration_date: 2033-07-31
79
+ run: false
80
+ justification: "waived, yo"
81
+ EOH
82
+ newinput = Chef::Compliance::Input.from_yaml(events, string, path, cookbook_name)
83
+ expect(newinput.data).to eql(data)
84
+ end
85
+
86
+ it "inflates objects from files" do
87
+ string = <<~EOH
88
+ ssh-01:
89
+ expiration_date: 2033-07-31
90
+ run: false
91
+ justification: "waived, yo"
92
+ EOH
93
+ tempfile = Tempfile.new("chef-compliance-test")
94
+ tempfile.write string
95
+ tempfile.close
96
+ newinput = Chef::Compliance::Input.from_file(events, tempfile.path, cookbook_name)
97
+ expect(newinput.data).to eql(data)
98
+ end
99
+
100
+ it "inflates objects from hashes" do
101
+ newinput = Chef::Compliance::Input.from_hash(events, data, path, cookbook_name)
102
+ expect(newinput.data).to eql(data)
103
+ end
104
+ end
@@ -0,0 +1,120 @@
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 "spec_helper"
19
+ require "tempfile"
20
+
21
+ describe Chef::Compliance::Profile do
22
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
23
+ let(:data) { { "copyright" => "DevSec Hardening Framework Team", "copyright_email" => "hello@dev-sec.io", "license" => "Apache-2.0", "maintainer" => "DevSec Hardening Framework Team", "name" => "ssh-baseline", "summary" => "Test-suite for best-practice SSH hardening", "supports" => [{ "os-family" => "unix" }], "title" => "DevSec SSH Baseline", "version" => "2.6.4" } }
24
+ let(:path) { "/var/chef/cache/cookbooks/acme_compliance/compliance/profiles/thisdirectoryisnotthename/inspec.yml" }
25
+ let(:cookbook_name) { "acme_compliance" }
26
+ let(:profile) { Chef::Compliance::Profile.new(events, data, path, cookbook_name) }
27
+
28
+ it "has a cookbook_name" do
29
+ expect(profile.cookbook_name).to eql(cookbook_name)
30
+ end
31
+
32
+ it "has a path" do
33
+ expect(profile.path).to eql(path)
34
+ end
35
+
36
+ it "has a name based on the yml" do
37
+ expect(profile.name).to eql("ssh-baseline")
38
+ end
39
+
40
+ it "has a pathname based on the path" do
41
+ expect(profile.pathname).to eql("thisdirectoryisnotthename")
42
+ end
43
+
44
+ it "is disabled" do
45
+ expect(profile.enabled).to eql(false)
46
+ expect(profile.enabled?).to eql(false)
47
+ end
48
+
49
+ it "has an event handler" do
50
+ expect(profile.events).to eql(events)
51
+ end
52
+
53
+ it "can be enabled by enable!" do
54
+ profile.enable!
55
+ expect(profile.enabled).to eql(true)
56
+ expect(profile.enabled?).to eql(true)
57
+ end
58
+
59
+ it "enabling sends an event" do
60
+ expect(events).to receive(:compliance_profile_enabled).with(profile)
61
+ profile.enable!
62
+ end
63
+
64
+ it "can be disabled by disable!" do
65
+ profile.enable!
66
+ profile.disable!
67
+ expect(profile.enabled).to eql(false)
68
+ expect(profile.enabled?).to eql(false)
69
+ end
70
+
71
+ it "has a #inspec_data method that renders the path" do
72
+ expect(profile.inspec_data).to eql( { name: "ssh-baseline", path: "/var/chef/cache/cookbooks/acme_compliance/compliance/profiles/thisdirectoryisnotthename" } )
73
+ end
74
+
75
+ it "doesn't render the events in the inspect output" do
76
+ expect(profile.inspect).not_to include("events")
77
+ end
78
+
79
+ it "inflates objects from YAML" do
80
+ string = <<~EOH
81
+ name: ssh-baseline#{" "}
82
+ title: DevSec SSH Baseline#{" "}
83
+ maintainer: DevSec Hardening Framework Team#{" "}
84
+ copyright: DevSec Hardening Framework Team#{" "}
85
+ copyright_email: hello@dev-sec.io#{" "}
86
+ license: Apache-2.0#{" "}
87
+ summary: Test-suite for best-practice SSH hardening#{" "}
88
+ version: 2.6.4#{" "}
89
+ supports:#{" "}
90
+ - os-family: unix
91
+ EOH
92
+ newprofile = Chef::Compliance::Profile.from_yaml(events, string, path, cookbook_name)
93
+ expect(newprofile.data).to eql(data)
94
+ end
95
+
96
+ it "inflates objects from files" do
97
+ string = <<~EOH
98
+ name: ssh-baseline#{" "}
99
+ title: DevSec SSH Baseline#{" "}
100
+ maintainer: DevSec Hardening Framework Team#{" "}
101
+ copyright: DevSec Hardening Framework Team#{" "}
102
+ copyright_email: hello@dev-sec.io#{" "}
103
+ license: Apache-2.0#{" "}
104
+ summary: Test-suite for best-practice SSH hardening#{" "}
105
+ version: 2.6.4#{" "}
106
+ supports:#{" "}
107
+ - os-family: unix
108
+ EOH
109
+ tempfile = Tempfile.new("chef-compliance-test")
110
+ tempfile.write string
111
+ tempfile.close
112
+ newprofile = Chef::Compliance::Profile.from_file(events, tempfile.path, cookbook_name)
113
+ expect(newprofile.data).to eql(data)
114
+ end
115
+
116
+ it "inflates objects from hashes" do
117
+ newprofile = Chef::Compliance::Profile.from_hash(events, data, path, cookbook_name)
118
+ expect(newprofile.data).to eql(data)
119
+ end
120
+ end