chef 18.1.0-x64-mingw-ucrt → 18.1.29-x64-mingw-ucrt
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +0 -3
- data/chef.gemspec +3 -2
- data/lib/chef/application/base.rb +18 -2
- data/lib/chef/client.rb +23 -6
- data/lib/chef/http/authenticator.rb +117 -34
- data/lib/chef/mixin/proxified_socket.rb +1 -1
- data/lib/chef/resource/apt_repository.rb +20 -2
- data/lib/chef/resource/bash.rb +13 -0
- data/lib/chef/resource/dsc_script.rb +1 -1
- data/lib/chef/resource/launchd.rb +2 -2
- data/lib/chef/resource/rhsm_register.rb +1 -1
- data/lib/chef/resource/selinux_fcontext.rb +1 -1
- data/lib/chef/resource/selinux_permissive.rb +1 -1
- data/lib/chef/resource/selinux_port.rb +1 -1
- data/lib/chef/resource/selinux_state.rb +1 -1
- data/lib/chef/resource/service.rb +1 -1
- data/lib/chef/resource/user.rb +2 -2
- data/lib/chef/resource/windows_user_privilege.rb +14 -10
- data/lib/chef/version.rb +1 -1
- data/spec/integration/client/client_spec.rb +22 -16
- data/spec/spec_helper.rb +3 -3
- data/spec/unit/client_spec.rb +26 -2
- data/spec/unit/compliance/runner_spec.rb +8 -0
- data/spec/unit/http/authenticator_spec.rb +64 -11
- data/spec/unit/provider/apt_repository_spec.rb +26 -5
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 937611f440a583a253b01525212c4d6214da8f25aee63891ab928b9a3d53de67
|
4
|
+
data.tar.gz: 7d69aeb9e4df6f13d76b464c08178f9935bc9be01eed136539d5d123315f0fea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bc789e6367a7ba5277f905d460f7b5390854f62c98f0ba07270e6659e7e70bb92b2d4fc64c8d87e524a972da75657f64022d3f01305558e00f90348f8d6811a
|
7
|
+
data.tar.gz: dea177b817a903ef86d7b8bacef0aca894ca778c26615339a041186276da976eb23abede8c47c1a3b9ee459a392961ff75fbc8532475186a1d21d77a1a528fde
|
data/Gemfile
CHANGED
@@ -37,9 +37,6 @@ group(:omnibus_package, :pry) do
|
|
37
37
|
gem "pry-stack_explorer"
|
38
38
|
end
|
39
39
|
|
40
|
-
# proxifier gem is busted on ruby 3.1 and seems abandoned so use git fork of gem
|
41
|
-
gem "proxifier", git: "https://github.com/chef/ruby-proxifier", branch: "lcg/ruby-3"
|
42
|
-
|
43
40
|
# Everything except AIX and Windows
|
44
41
|
group(:ruby_shadow) do
|
45
42
|
# if ruby-shadow does a release that supports ruby-3.0 this can be removed
|
data/chef.gemspec
CHANGED
@@ -49,7 +49,8 @@ Gem::Specification.new do |s|
|
|
49
49
|
s.add_dependency "net-ftp" # remote_file resource
|
50
50
|
s.add_dependency "erubis", "~> 2.7" # template resource / cookbook syntax check
|
51
51
|
s.add_dependency "diff-lcs", ">= 1.2.4", "!= 1.4.0", "< 1.6.0" # 1.4 breaks output. Used in lib/chef/util/diff
|
52
|
-
s.add_dependency "ffi-libarchive", "~> 1.0", ">= 1.0.3" # archive_file resource
|
52
|
+
# s.add_dependency "ffi-libarchive", "~> 1.0", ">= 1.0.3" # archive_file resource
|
53
|
+
s.add_dependency "ffi-libarchive", "~> 1.1", ">= 1.1.3"
|
53
54
|
s.add_dependency "chef-zero", ">= 14.0.11"
|
54
55
|
s.add_dependency "chef-vault" # chef-vault resources and helpers
|
55
56
|
|
@@ -61,7 +62,7 @@ Gem::Specification.new do |s|
|
|
61
62
|
s.add_dependency "unf_ext", ">= 0.0.8.2" # This is ruby31 compatible ucrt gem version
|
62
63
|
s.add_dependency "corefoundation", "~> 0.3.4" # macos_userdefaults resource
|
63
64
|
|
64
|
-
s.add_dependency "
|
65
|
+
s.add_dependency "proxifier2", "~> 1.1"
|
65
66
|
|
66
67
|
s.add_dependency "aws-sdk-s3", "~> 1.91" # s3 recipe-url support
|
67
68
|
s.add_dependency "aws-sdk-secretsmanager", "~> 1.46"
|
@@ -386,8 +386,10 @@ class Chef::Application::Base < Chef::Application
|
|
386
386
|
elsif uri.scheme == "s3"
|
387
387
|
require "aws-sdk-s3" unless defined?(Aws::S3)
|
388
388
|
|
389
|
-
|
390
|
-
|
389
|
+
bucket_name = uri.hostname
|
390
|
+
s3 = Aws::S3::Client.new(region: s3_bucket_location(bucket_name))
|
391
|
+
|
392
|
+
object = s3.get_object(bucket: bucket_name, key: uri.path[1..-1])
|
391
393
|
File.open(path, "wb") do |f|
|
392
394
|
f.write(object.body.read)
|
393
395
|
end
|
@@ -403,6 +405,20 @@ class Chef::Application::Base < Chef::Application
|
|
403
405
|
end
|
404
406
|
end
|
405
407
|
|
408
|
+
def s3_bucket_location(bucket_name)
|
409
|
+
s3 = Aws::S3::Client.new(region: aws_api_region)
|
410
|
+
|
411
|
+
resp = s3.get_bucket_location(bucket: bucket_name)
|
412
|
+
resp.location_constraint
|
413
|
+
rescue Aws::S3::Errors::AccessDenied => _e
|
414
|
+
Chef::Log.warn("Missing s3:GetBucketLocation privilege, trying currently configured region #{aws_api_region}")
|
415
|
+
aws_api_region
|
416
|
+
end
|
417
|
+
|
418
|
+
def aws_api_region
|
419
|
+
ENV["AWS_REGION"] || Aws.shared_config.region || Aws::EC2Metadata.new.get("/latest/meta-data/placement/region")
|
420
|
+
end
|
421
|
+
|
406
422
|
def interval_run_chef_client
|
407
423
|
if Chef::Config[:daemonize]
|
408
424
|
Chef::Daemon.daemonize(ChefUtils::Dist::Infra::PRODUCT)
|
data/lib/chef/client.rb
CHANGED
@@ -66,6 +66,15 @@ class Chef
|
|
66
66
|
class Client
|
67
67
|
CRYPT_EXPORTABLE = 0x00000001
|
68
68
|
|
69
|
+
# adding these
|
70
|
+
# certstore 65536 == 0x00010000 == CurrentUser
|
71
|
+
# certstore 131072 == 0x00020000 == LocalMachine
|
72
|
+
# Reference: https://github.com/chef/win32-certstore/blob/main/lib/win32/certstore/mixin/crypto.rb#L90
|
73
|
+
CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000
|
74
|
+
CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000
|
75
|
+
CERT_SYSTEM_STORE_SERVICES = 0x00050000
|
76
|
+
CERT_SYSTEM_STORE_USERS = 0x00060000
|
77
|
+
|
69
78
|
attr_reader :local_context
|
70
79
|
|
71
80
|
extend Chef::Mixin::Deprecation
|
@@ -674,9 +683,15 @@ class Chef
|
|
674
683
|
|
675
684
|
# In the brave new world of No Certs On Disk, we want to put the pem file into Keychain or the Certstore
|
676
685
|
# But is it already there?
|
686
|
+
# We're solving the multi-user scenario where both a system/admin user can run on the box but also someone without
|
687
|
+
# admin rights can also run correctly locally.
|
677
688
|
def check_certstore_for_key(cert_name)
|
678
689
|
require "win32-certstore"
|
679
|
-
|
690
|
+
if Chef::Config[:auth_key_registry_type] == "user"
|
691
|
+
win32certstore = ::Win32::Certstore.open("MY", store_location: CERT_SYSTEM_STORE_CURRENT_USER)
|
692
|
+
else
|
693
|
+
win32certstore = ::Win32::Certstore.open("MY")
|
694
|
+
end
|
680
695
|
win32certstore.search("#{cert_name}")
|
681
696
|
end
|
682
697
|
|
@@ -783,8 +798,6 @@ class Chef
|
|
783
798
|
require "time" unless defined?(Time)
|
784
799
|
autoload :URI, "uri"
|
785
800
|
|
786
|
-
# KeyMigration.instance.key_migrated = true
|
787
|
-
|
788
801
|
node = Chef::Config[:node_name]
|
789
802
|
d = Time.now
|
790
803
|
if d.month == 10 || d.month == 11 || d.month == 12
|
@@ -818,9 +831,13 @@ class Chef
|
|
818
831
|
require "win32-certstore"
|
819
832
|
tempfile = Tempfile.new("#{Chef::Config[:node_name]}.pfx")
|
820
833
|
File.open(tempfile, "wb") { |f| f.print new_pfx.to_der }
|
821
|
-
|
822
|
-
|
823
|
-
|
834
|
+
# Need to determine where to store the key
|
835
|
+
if Chef::Config[:auth_key_registry_type] == "user"
|
836
|
+
win32certstore = ::Win32::Certstore.open("MY", store_location: CERT_SYSTEM_STORE_CURRENT_USER)
|
837
|
+
else
|
838
|
+
win32certstore = ::Win32::Certstore.open("MY")
|
839
|
+
end
|
840
|
+
win32certstore.add_pfx(tempfile, password, CRYPT_EXPORTABLE)
|
824
841
|
tempfile.unlink
|
825
842
|
end
|
826
843
|
|
@@ -102,12 +102,12 @@ class Chef
|
|
102
102
|
self.class.get_cert_password
|
103
103
|
end
|
104
104
|
|
105
|
-
def
|
106
|
-
self.class.
|
105
|
+
def encrypt_pfx_pass_with_vector
|
106
|
+
self.class.encrypt_pfx_pass_with_vector
|
107
107
|
end
|
108
108
|
|
109
|
-
def
|
110
|
-
self.class.
|
109
|
+
def decrypt_pfx_pass_with_vector
|
110
|
+
self.class.decrypt_pfx_pass_with_vector
|
111
111
|
end
|
112
112
|
|
113
113
|
# Detects if a private key exists in a certificate repository like Keychain (macOS) or Certificate Store (Windows)
|
@@ -123,9 +123,18 @@ class Chef
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
+
def self.get_cert_user
|
127
|
+
Chef::Config[:auth_key_registry_type] == "user" ? store = "CurrentUser" : store = "LocalMachine"
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.get_registry_user
|
131
|
+
Chef::Config[:auth_key_registry_type] == "user" ? store = "HKEY_CURRENT_USER" : store = "HKEY_LOCAL_MACHINE"
|
132
|
+
end
|
133
|
+
|
126
134
|
def self.check_certstore_for_key(client_name)
|
135
|
+
store = get_cert_user
|
127
136
|
powershell_code = <<~CODE
|
128
|
-
$cert = Get-ChildItem -path cert
|
137
|
+
$cert = Get-ChildItem -path cert:\\#{store}\\My -Recurse -Force | Where-Object { $_.Subject -Match "chef-#{client_name}" } -ErrorAction Stop
|
129
138
|
if (($cert.HasPrivateKey -eq $true) -and ($cert.PrivateKey.Key.ExportPolicy -ne "NonExportable")) {
|
130
139
|
return $true
|
131
140
|
}
|
@@ -164,49 +173,86 @@ class Chef
|
|
164
173
|
end
|
165
174
|
|
166
175
|
def self.get_cert_password
|
176
|
+
store = get_registry_user
|
167
177
|
@win32registry = Chef::Win32::Registry.new
|
168
|
-
path = "
|
178
|
+
path = "#{store}\\Software\\Progress\\Authentication"
|
169
179
|
# does the registry key even exist?
|
170
|
-
|
171
|
-
|
180
|
+
# password_blob should be an array of hashes
|
181
|
+
password_blob = @win32registry.get_values(path)
|
182
|
+
if password_blob.nil? || password_blob.empty?
|
172
183
|
raise Chef::Exceptions::Win32RegKeyMissing
|
173
184
|
end
|
174
185
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
186
|
+
# Did someone have just the password stored in the registry?
|
187
|
+
raw_data = password_blob.map { |x| x[:data] }
|
188
|
+
vector = raw_data[2]
|
189
|
+
if !!vector
|
190
|
+
decrypted_password = decrypt_pfx_pass_with_vector(password_blob)
|
191
|
+
else
|
192
|
+
decrypted_password = decrypt_pfx_pass_with_password(password_blob)
|
193
|
+
if !!decrypted_password
|
194
|
+
migrate_pass_to_use_vector(decrypted_password)
|
195
|
+
else
|
196
|
+
Chef::Log.error("Failed to retrieve certificate password")
|
179
197
|
end
|
180
198
|
end
|
181
|
-
|
182
|
-
raise Chef::Exceptions::Win32RegKeyMissing
|
183
|
-
|
199
|
+
decrypted_password
|
184
200
|
rescue Chef::Exceptions::Win32RegKeyMissing
|
185
201
|
# if we don't have a password, log that and generate one
|
186
|
-
|
187
|
-
new_path = "
|
202
|
+
store = get_registry_user
|
203
|
+
new_path = "#{store}\\Software\\Progress\\Authentication"
|
188
204
|
unless @win32registry.key_exists?(new_path)
|
189
205
|
@win32registry.create_key(new_path, true)
|
190
206
|
end
|
191
|
-
|
192
|
-
size = 14
|
193
|
-
password = SecureRandom.alphanumeric(size)
|
194
|
-
encrypted_pass = encrypt_pfx_pass(password)
|
195
|
-
values = { name: "PfxPass", type: :string, data: encrypted_pass }
|
196
|
-
@win32registry.set_value(new_path, values)
|
197
|
-
password
|
207
|
+
create_and_store_new_password
|
198
208
|
end
|
199
209
|
|
200
|
-
def self.
|
210
|
+
def self.encrypt_pfx_pass_with_vector(password)
|
201
211
|
powershell_code = <<~CODE
|
202
|
-
$
|
203
|
-
$
|
204
|
-
|
212
|
+
$AES = [System.Security.Cryptography.Aes]::Create()
|
213
|
+
$key_temp = [System.Convert]::ToBase64String($AES.Key)
|
214
|
+
$iv_temp = [System.Convert]::ToBase64String($AES.IV)
|
215
|
+
$encryptor = $AES.CreateEncryptor()
|
216
|
+
[System.Byte[]]$Bytes = [System.Text.Encoding]::Unicode.GetBytes("#{password}")
|
217
|
+
$EncryptedBytes = $encryptor.TransformFinalBlock($Bytes,0,$Bytes.Length)
|
218
|
+
$EncryptedBase64String = [System.Convert]::ToBase64String($EncryptedBytes)
|
219
|
+
# create array of encrypted pass, key, iv
|
220
|
+
$password_blob = @($EncryptedBase64String, $key_temp, $iv_temp)
|
221
|
+
return $password_blob
|
205
222
|
CODE
|
206
223
|
powershell_exec!(powershell_code).result
|
207
224
|
end
|
208
225
|
|
209
|
-
def self.
|
226
|
+
def self.decrypt_pfx_pass_with_vector(password_blob)
|
227
|
+
raw_data = password_blob.map { |x| x[:data] }
|
228
|
+
password = raw_data[0]
|
229
|
+
key = raw_data[1]
|
230
|
+
vector = raw_data[2]
|
231
|
+
|
232
|
+
powershell_code = <<~CODE
|
233
|
+
$KeyBytes = [System.Convert]::FromBase64String("#{key}")
|
234
|
+
$IVBytes = [System.Convert]::FromBase64String("#{vector}")
|
235
|
+
$aes = [System.Security.Cryptography.Aes]::Create()
|
236
|
+
$aes.Key = $KeyBytes
|
237
|
+
$aes.IV = $IVBytes
|
238
|
+
$EncryptedBytes = [System.Convert]::FromBase64String("#{password}")
|
239
|
+
$Decryptor = $aes.CreateDecryptor()
|
240
|
+
$DecryptedBytes = $Decryptor.TransformFinalBlock($EncryptedBytes,0,$EncryptedBytes.Length)
|
241
|
+
$DecryptedString = [System.Text.Encoding]::Unicode.GetString($DecryptedBytes)
|
242
|
+
return $DecryptedString
|
243
|
+
CODE
|
244
|
+
results = powershell_exec!(powershell_code).result
|
245
|
+
end
|
246
|
+
|
247
|
+
def self.decrypt_pfx_pass_with_password(password_blob)
|
248
|
+
password = ""
|
249
|
+
password_blob.each do |secret|
|
250
|
+
if secret[:name] == "PfxPass"
|
251
|
+
password = secret[:data]
|
252
|
+
else
|
253
|
+
Chef::Log.error("Failed to retrieve a password for the private key")
|
254
|
+
end
|
255
|
+
end
|
210
256
|
powershell_code = <<~CODE
|
211
257
|
$secure_string = "#{password}" | ConvertTo-SecureString
|
212
258
|
$string = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((($secure_string))))
|
@@ -215,14 +261,49 @@ class Chef
|
|
215
261
|
powershell_exec!(powershell_code).result
|
216
262
|
end
|
217
263
|
|
218
|
-
def self.
|
219
|
-
|
264
|
+
def self.migrate_pass_to_use_vector(password)
|
265
|
+
store = get_cert_user
|
266
|
+
corrected_store = (store == "CurrentUser" ? "HKCU" : "HKLM")
|
267
|
+
powershell_code = <<~CODE
|
268
|
+
Remove-ItemProperty -Path "#{corrected_store}:\\Software\\Progress\\Authentication" -Name "PfXPass"
|
269
|
+
CODE
|
270
|
+
powershell_exec!(powershell_code)
|
271
|
+
create_and_store_new_password(password)
|
272
|
+
end
|
220
273
|
|
274
|
+
# This method name is a bit of a misnomer. We call it to legit create a new password using the vector format.
|
275
|
+
# But we also call it with a password that needs to be migrated to use the vector format too.
|
276
|
+
def self.create_and_store_new_password(password = nil)
|
277
|
+
@win32registry = Chef::Win32::Registry.new
|
278
|
+
store = get_registry_user
|
279
|
+
path = "#{store}\\Software\\Progress\\Authentication"
|
280
|
+
if password.nil?
|
281
|
+
require "securerandom" unless defined?(SecureRandom)
|
282
|
+
size = 14
|
283
|
+
password = SecureRandom.alphanumeric(size)
|
284
|
+
end
|
285
|
+
encrypted_blob = encrypt_pfx_pass_with_vector(password)
|
286
|
+
encrypted_password = encrypted_blob[0]
|
287
|
+
key = encrypted_blob[1]
|
288
|
+
vector = encrypted_blob[2]
|
289
|
+
values = [
|
290
|
+
{ name: "PfxPass", type: :string, data: encrypted_password },
|
291
|
+
{ name: "PfxKey", type: :string, data: key },
|
292
|
+
{ name: "PfxIV", type: :string, data: vector },
|
293
|
+
]
|
294
|
+
values.each do |i|
|
295
|
+
@win32registry.set_value(path, i)
|
296
|
+
end
|
297
|
+
password
|
298
|
+
end
|
299
|
+
|
300
|
+
def self.retrieve_certificate_key(client_name)
|
221
301
|
if ChefUtils.windows?
|
302
|
+
require "openssl" unless defined?(OpenSSL)
|
222
303
|
password = get_cert_password
|
223
304
|
return false unless password
|
224
305
|
|
225
|
-
if check_certstore_for_key(client_name)
|
306
|
+
if !!check_certstore_for_key(client_name)
|
226
307
|
ps_blob = powershell_exec!(get_the_key_ps(client_name, password)).result
|
227
308
|
file_path = ps_blob["PSPath"].split("::")[1]
|
228
309
|
pkcs = OpenSSL::PKCS12.new(File.binread(file_path), password)
|
@@ -252,10 +333,11 @@ class Chef
|
|
252
333
|
end
|
253
334
|
|
254
335
|
def self.get_the_key_ps(client_name, password)
|
336
|
+
store = get_cert_user
|
255
337
|
powershell_code = <<~CODE
|
256
338
|
Try {
|
257
339
|
$my_pwd = ConvertTo-SecureString -String "#{password}" -Force -AsPlainText;
|
258
|
-
$cert = Get-ChildItem -path cert
|
340
|
+
$cert = Get-ChildItem -path cert:\\#{store}\\My -Recurse | Where-Object { $_.Subject -match "chef-#{client_name}$" } -ErrorAction Stop;
|
259
341
|
$tempfile = [System.IO.Path]::GetTempPath() + "export_pfx.pfx";
|
260
342
|
Export-PfxCertificate -Cert $cert -Password $my_pwd -FilePath $tempfile;
|
261
343
|
}
|
@@ -266,8 +348,9 @@ class Chef
|
|
266
348
|
end
|
267
349
|
|
268
350
|
def self.delete_old_key_ps(client_name)
|
351
|
+
store = get_cert_user
|
269
352
|
powershell_code = <<~CODE
|
270
|
-
Get-ChildItem -path cert
|
353
|
+
Get-ChildItem -path cert:\\#{store}\\My -Recurse | Where-Object { $_.Subject -match "chef-#{client_name}$" } | Remove-Item -ErrorAction Stop;
|
271
354
|
CODE
|
272
355
|
end
|
273
356
|
|
@@ -187,6 +187,24 @@ class Chef
|
|
187
187
|
end.compact
|
188
188
|
end
|
189
189
|
|
190
|
+
# run the specified command and extract the public key ids
|
191
|
+
# accepts the command so it can be used to extract both the current keys
|
192
|
+
# and the new keys
|
193
|
+
# @param [Array<String>] cmd the command to run
|
194
|
+
#
|
195
|
+
# @return [Array] an array of key ids
|
196
|
+
def extract_public_keys_from_cmd(*cmd)
|
197
|
+
so = shell_out(*cmd)
|
198
|
+
# Sample output
|
199
|
+
# pub:-:4096:1:D94AA3F0EFE21092:1336774248:::-:::scSC::::::23::0:
|
200
|
+
so.stdout.split(/\n/).map do |t|
|
201
|
+
if t.match(/^pub:/)
|
202
|
+
f = t.split(":")
|
203
|
+
f.slice(0, 6).join(":")
|
204
|
+
end
|
205
|
+
end.compact
|
206
|
+
end
|
207
|
+
|
190
208
|
# validate the key against the apt keystore to see if that version is expired
|
191
209
|
# @param [String] key
|
192
210
|
#
|
@@ -222,8 +240,8 @@ class Chef
|
|
222
240
|
def no_new_keys?(file)
|
223
241
|
# Now we are using the option --with-colons that works across old os versions
|
224
242
|
# as well as the latest (16.10). This for both `apt-key` and `gpg` commands
|
225
|
-
installed_keys =
|
226
|
-
proposed_keys =
|
243
|
+
installed_keys = extract_public_keys_from_cmd(*LIST_APT_KEY_FINGERPRINTS)
|
244
|
+
proposed_keys = extract_public_keys_from_cmd("gpg", "--with-fingerprint", "--with-colons", file)
|
227
245
|
(installed_keys & proposed_keys).sort == proposed_keys.sort
|
228
246
|
end
|
229
247
|
|
data/lib/chef/resource/bash.rb
CHANGED
@@ -43,6 +43,19 @@ class Chef
|
|
43
43
|
end
|
44
44
|
```
|
45
45
|
|
46
|
+
**Using escape characters in a string of code**
|
47
|
+
|
48
|
+
In the following example, the `find` command uses an escape character (`\`). Use a second escape character (`\\`) to preserve the escape character in the code string:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
bash 'delete some archives ' do
|
52
|
+
code <<-EOH
|
53
|
+
find ./ -name "*.tar.Z" -mtime +180 -exec rm -f {} \\;
|
54
|
+
EOH
|
55
|
+
ignore_failure true
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
46
59
|
**Install a file from a remote location**
|
47
60
|
|
48
61
|
The following is an example of how to install the foo123 module for Nginx. This module adds shell-style functionality to an Nginx configuration file and does the following:
|
@@ -34,7 +34,7 @@ class Chef
|
|
34
34
|
resource in #{ChefUtils::Dist::Infra::PRODUCT}, such as the Archive resource, a custom DSC resource, an existing DSC script that performs an important
|
35
35
|
task, and so on. Use the dsc_script resource to embed the code that defines a DSC configuration directly within a #{ChefUtils::Dist::Infra::PRODUCT} recipe.
|
36
36
|
|
37
|
-
Warning: The **dsc_script** resource
|
37
|
+
Warning: The **dsc_script** resource is only available on 64-bit Chef Infra Client.
|
38
38
|
DESC
|
39
39
|
|
40
40
|
default_action :run
|
@@ -21,7 +21,7 @@ require_relative "../resource"
|
|
21
21
|
class Chef
|
22
22
|
class Resource
|
23
23
|
class Launchd < Chef::Resource
|
24
|
-
provides :launchd
|
24
|
+
provides :launchd, os: "darwin"
|
25
25
|
|
26
26
|
description "Use the **launchd** resource to manage system-wide services (daemons) and per-user services (agents) on the macOS platform."
|
27
27
|
introduced "12.8"
|
@@ -129,7 +129,7 @@ class Chef
|
|
129
129
|
property :abandon_process_group, [ TrueClass, FalseClass ],
|
130
130
|
description: "If a job dies, all remaining processes with the same process ID may be kept running. Set to true to kill all remaining processes."
|
131
131
|
|
132
|
-
property :associated_bundle_identifiers,
|
132
|
+
property :associated_bundle_identifiers, Array,
|
133
133
|
description: "This optional key indicates which bundles the Login Items Added by Apps panel associates with the helper executable."
|
134
134
|
|
135
135
|
property :debug, [ TrueClass, FalseClass ],
|
@@ -92,7 +92,7 @@ class Chef
|
|
92
92
|
|
93
93
|
property :release,
|
94
94
|
[Float, String],
|
95
|
-
description: "Sets the operating system minor release to use for subscriptions for the system. Products and updates are limited to the specified minor release version. This is used with the `auto_attach`
|
95
|
+
description: "Sets the operating system minor release to use for subscriptions for the system. Products and updates are limited to the specified minor release version. This is used with the `auto_attach` or `activation_key` options. For example, `release '6.4'` will append `--release=6.4` to the register command.",
|
96
96
|
introduced: "17.8"
|
97
97
|
|
98
98
|
action :register, description: "Register the node with RHSM." do
|
@@ -22,7 +22,7 @@ class Chef
|
|
22
22
|
|
23
23
|
provides :selinux_fcontext
|
24
24
|
|
25
|
-
description "Use **selinux_fcontext** resource to set the SELinux context of files
|
25
|
+
description "Use the **selinux_fcontext** resource to set the SELinux context of files using the `semanage fcontext` command."
|
26
26
|
introduced "18.0"
|
27
27
|
examples <<~DOC
|
28
28
|
**Allow http servers (e.g. nginx/apache) to modify moodle files**:
|
@@ -20,7 +20,7 @@ class Chef
|
|
20
20
|
|
21
21
|
provides :selinux_permissive
|
22
22
|
|
23
|
-
description "Use **selinux_permissive** resource to
|
23
|
+
description "Use the **selinux_permissive** resource to allow some domains to misbehave without stopping them. This is not as good as setting specific policies, but better than disabling SELinux entirely."
|
24
24
|
introduced "18.0"
|
25
25
|
examples <<~DOC
|
26
26
|
**Disable enforcement on Apache**:
|
@@ -21,7 +21,7 @@ class Chef
|
|
21
21
|
|
22
22
|
provides :selinux_port
|
23
23
|
|
24
|
-
description "Use **selinux_port** resource to
|
24
|
+
description "Use the **selinux_port** resource to assign a network port to a specific SELinux context. For example, running a web server on a non-standard port."
|
25
25
|
introduced "18.0"
|
26
26
|
examples <<~DOC
|
27
27
|
**Allow nginx/apache to bind to port 5678 by giving it the http_port_t context**:
|
@@ -56,7 +56,7 @@ class Chef
|
|
56
56
|
|
57
57
|
property :persistent, [true, false],
|
58
58
|
default: true,
|
59
|
-
description: "
|
59
|
+
description: "Set the status update in the SELinux configuration file."
|
60
60
|
|
61
61
|
property :policy, String,
|
62
62
|
default: lazy { default_policy_platform },
|
@@ -81,7 +81,7 @@ class Chef
|
|
81
81
|
# specify overrides for the start_command, stop_command and
|
82
82
|
# restart_command properties.
|
83
83
|
property :init_command, String,
|
84
|
-
description: "The path to the init script that is associated with the service. Use init_command to prevent the need to specify overrides for the start_command
|
84
|
+
description: "The path to the init script that is associated with the service. Use `init_command` to prevent the need to specify overrides for the `start_command`, `stop_command`, and `restart_command` properties. When this property is not specified, the #{ChefUtils::Dist::Infra::PRODUCT} will use the default init command for the service provider being used.",
|
85
85
|
desired_state: false
|
86
86
|
|
87
87
|
# if the service is enabled or not
|
data/lib/chef/resource/user.rb
CHANGED
@@ -74,12 +74,12 @@ class Chef
|
|
74
74
|
alias_method :group, :gid
|
75
75
|
|
76
76
|
property :expire_date, [ String, NilClass ],
|
77
|
-
description: "(Linux) The date on which the user account will be disabled. The date is specified in
|
77
|
+
description: "(Linux) The date on which the user account will be disabled. The date is specified in YYYY-MM-DD format.",
|
78
78
|
introduced: "18.0",
|
79
79
|
desired_state: false
|
80
80
|
|
81
81
|
property :inactive, [ String, Integer, NilClass ],
|
82
|
-
description: "(Linux) The number of days after a password expires until the account is permanently disabled. A value of 0 disables the account as soon as the password has expired, and a value of
|
82
|
+
description: "(Linux) The number of days after a password expires until the account is permanently disabled. A value of `0` disables the account as soon as the password has expired, and a value of `-1` disables the feature.",
|
83
83
|
introduced: "18.0",
|
84
84
|
desired_state: false
|
85
85
|
end
|
@@ -23,12 +23,14 @@ class Chef
|
|
23
23
|
class WindowsUserPrivilege < Chef::Resource
|
24
24
|
|
25
25
|
provides :windows_user_privilege
|
26
|
-
description "
|
26
|
+
description "Use the **windows_user_privilege** resource to set privileges for a principal, user, or group.\n See [Microsoft's user rights assignment documentation](https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment) for more information."
|
27
27
|
|
28
28
|
introduced "16.0"
|
29
29
|
|
30
30
|
examples <<~DOC
|
31
|
-
**Set the SeNetworkLogonRight
|
31
|
+
**Set the SeNetworkLogonRight privilege for the Builtin Administrators and Authenticated Users groups**:
|
32
|
+
|
33
|
+
The `:set` action will add this privilege for these two groups and remove this privilege from all other groups or users.
|
32
34
|
|
33
35
|
```ruby
|
34
36
|
windows_user_privilege 'Network Logon Rights' do
|
@@ -38,7 +40,9 @@ class Chef
|
|
38
40
|
end
|
39
41
|
```
|
40
42
|
|
41
|
-
**
|
43
|
+
**Set the SeCreatePagefilePrivilege privilege for the Builtin Guests and Administrator groups**:
|
44
|
+
|
45
|
+
The `:set` action will add this privilege for these two groups and remove this privilege from all other groups or users.
|
42
46
|
|
43
47
|
```ruby
|
44
48
|
windows_user_privilege 'Create Pagefile' do
|
@@ -48,7 +52,7 @@ class Chef
|
|
48
52
|
end
|
49
53
|
```
|
50
54
|
|
51
|
-
**Add the SeDenyRemoteInteractiveLogonRight
|
55
|
+
**Add the SeDenyRemoteInteractiveLogonRight privilege to the 'Remote interactive logon' principal**:
|
52
56
|
|
53
57
|
```ruby
|
54
58
|
windows_user_privilege 'Remote interactive logon' do
|
@@ -57,7 +61,7 @@ class Chef
|
|
57
61
|
end
|
58
62
|
```
|
59
63
|
|
60
|
-
**Add to the Builtin Guests
|
64
|
+
**Add the SeCreatePageFilePrivilege privilege to the Builtin Guests group**:
|
61
65
|
|
62
66
|
```ruby
|
63
67
|
windows_user_privilege 'Guests add Create Pagefile' do
|
@@ -67,7 +71,7 @@ class Chef
|
|
67
71
|
end
|
68
72
|
```
|
69
73
|
|
70
|
-
**Remove the
|
74
|
+
**Remove the SeCreatePageFilePrivilege privilege from the Builtin Guests group**:
|
71
75
|
|
72
76
|
```ruby
|
73
77
|
windows_user_privilege 'Create Pagefile' do
|
@@ -77,7 +81,7 @@ class Chef
|
|
77
81
|
end
|
78
82
|
```
|
79
83
|
|
80
|
-
**Clear
|
84
|
+
**Clear the SeDenyNetworkLogonRight privilege from all users**:
|
81
85
|
|
82
86
|
```ruby
|
83
87
|
windows_user_privilege 'Allow any user the Network Logon right' do
|
@@ -135,15 +139,15 @@ class Chef
|
|
135
139
|
}.freeze
|
136
140
|
|
137
141
|
property :principal, String,
|
138
|
-
description: "An optional property to add the privilege for given principal. Use only with add and remove action. Principal can either be a
|
142
|
+
description: "An optional property to add the privilege for given principal. Use only with add and remove action. Principal can either be a user, group, or [special identity](https://docs.microsoft.com/en-us/windows/security/identity-protection/access-control/special-identities).",
|
139
143
|
name_property: true
|
140
144
|
|
141
145
|
property :users, [Array, String],
|
142
|
-
description: "An optional property to set the privilege for
|
146
|
+
description: "An optional property to set the privilege for the specified users. Use only with `:set` action",
|
143
147
|
coerce: proc { |v| Array(v) }
|
144
148
|
|
145
149
|
property :privilege, [Array, String],
|
146
|
-
description: "One or more privileges to set for principal or users/groups. For more information on what each privilege does
|
150
|
+
description: "One or more privileges to set for principal or users/groups. For more information, see [Microsoft's documentation on what each privilege does](https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment).",
|
147
151
|
required: true,
|
148
152
|
coerce: proc { |v| Array(v) },
|
149
153
|
callbacks: {
|
data/lib/chef/version.rb
CHANGED
@@ -35,14 +35,14 @@ describe "chef-client" do
|
|
35
35
|
@server = @api = nil
|
36
36
|
end
|
37
37
|
|
38
|
-
def install_certificate_in_store(client_name)
|
38
|
+
def install_certificate_in_store(client_name, store_location)
|
39
39
|
if ChefUtils.windows?
|
40
40
|
powershell_exec! <<~EOH
|
41
41
|
if (-not (($PSVersionTable.PSVersion.Major -ge 5) -and ($PSVersionTable.PSVersion.Build -ge 22000)) ) {
|
42
|
-
New-SelfSignedCertificate -CertStoreLocation Cert
|
42
|
+
New-SelfSignedCertificate -CertStoreLocation Cert:\\#{store_location}\\My -DnsName "#{client_name}"
|
43
43
|
}
|
44
44
|
else {
|
45
|
-
New-SelfSignedCertificate -CertStoreLocation Cert
|
45
|
+
New-SelfSignedCertificate -CertStoreLocation Cert:\\#{store_location}\\My -Subject "#{client_name}" -FriendlyName "#{client_name}" -KeyExportPolicy Exportable
|
46
46
|
}
|
47
47
|
EOH
|
48
48
|
end
|
@@ -50,14 +50,6 @@ describe "chef-client" do
|
|
50
50
|
|
51
51
|
def create_registry_key
|
52
52
|
::Chef::HTTP::Authenticator.get_cert_password
|
53
|
-
# @win32registry = Chef::Win32::Registry.new
|
54
|
-
# path = "HKEY_LOCAL_MACHINE\\Software\\Progress\\Authentication"
|
55
|
-
# unless @win32registry.key_exists?(path)
|
56
|
-
# @win32registry.create_key(path, true)
|
57
|
-
# end
|
58
|
-
# password = SOME_CHARS.sample(1 + rand(SOME_CHARS.count)).join[0...14]
|
59
|
-
# values = { name: "PfxPass", type: :string, data: password }
|
60
|
-
# @win32registry.set_value(path, values)
|
61
53
|
end
|
62
54
|
|
63
55
|
def remove_certificate_from_store
|
@@ -111,6 +103,9 @@ describe "chef-client" do
|
|
111
103
|
tempfile.close
|
112
104
|
@path = tempfile.path
|
113
105
|
Chef::Config.validation_key = @path
|
106
|
+
if ChefUtils.windows?
|
107
|
+
create_registry_key
|
108
|
+
end
|
114
109
|
|
115
110
|
file "config/client.rb", <<~EOM
|
116
111
|
local_mode true
|
@@ -201,17 +196,27 @@ describe "chef-client" do
|
|
201
196
|
|
202
197
|
if ChefUtils.windows?
|
203
198
|
context "and the private key is in the Windows CertStore" do
|
204
|
-
|
205
|
-
|
199
|
+
|
200
|
+
it "should verify that the cert is loaded in the \\LocalMachine\\My store" do
|
201
|
+
Chef::Config[:auth_key_registry_type] = "machine"
|
202
|
+
install_certificate_in_store(client_name, "LocalMachine")
|
206
203
|
create_registry_key
|
204
|
+
expect(Chef::HTTP::Authenticator.check_certstore_for_key(hostname)).to eq(true)
|
207
205
|
end
|
208
206
|
|
209
|
-
|
207
|
+
it "should verify that the export password for the pfx is loaded in the Registry" do
|
208
|
+
expect(verify_export_password_exists.result).to eq(true)
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should verify that a private key is returned to me" do
|
212
|
+
expect(Chef::HTTP::Authenticator.retrieve_certificate_key(client_name)).not_to be nil
|
210
213
|
remove_certificate_from_store
|
211
|
-
remove_registry_key
|
212
214
|
end
|
213
215
|
|
214
|
-
it "should verify that the cert is loaded in the
|
216
|
+
it "should verify that the cert is loaded in the \\CurrentUser\\My store" do
|
217
|
+
Chef::Config[:auth_key_registry_type] = "user"
|
218
|
+
install_certificate_in_store(client_name, "CurrentUser")
|
219
|
+
create_registry_key
|
215
220
|
expect(Chef::HTTP::Authenticator.check_certstore_for_key(hostname)).to eq(true)
|
216
221
|
end
|
217
222
|
|
@@ -221,6 +226,7 @@ describe "chef-client" do
|
|
221
226
|
|
222
227
|
it "should verify that a private key is returned to me" do
|
223
228
|
expect(Chef::HTTP::Authenticator.retrieve_certificate_key(client_name)).not_to be nil
|
229
|
+
remove_certificate_from_store
|
224
230
|
end
|
225
231
|
end
|
226
232
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -138,9 +138,9 @@ RSpec.configure do |config|
|
|
138
138
|
|
139
139
|
config.filter_run_excluding skip_buildkite: true if ENV["BUILDKITE"]
|
140
140
|
|
141
|
-
config.filter_run_excluding fips_mode: !fips_mode_build?
|
142
|
-
#
|
143
|
-
config.filter_run_excluding :fips_mode if
|
141
|
+
config.filter_run_excluding fips_mode: !fips_mode_build?
|
142
|
+
# Skip fips on windows
|
143
|
+
# config.filter_run_excluding :fips_mode if windows?
|
144
144
|
|
145
145
|
config.filter_run_excluding windows_only: true unless windows?
|
146
146
|
config.filter_run_excluding not_supported_on_windows: true if windows?
|
data/spec/unit/client_spec.rb
CHANGED
@@ -310,25 +310,49 @@ describe Chef::Client, :windows_only do
|
|
310
310
|
end
|
311
311
|
|
312
312
|
context "when the client intially boots the first time" do
|
313
|
-
it "verfies that a certificate was correctly created and exists in the Cert Store" do
|
313
|
+
it "verfies that a certificate was correctly created and exists in the LocalMachine Cert Store" do
|
314
|
+
Chef::Config[:node_name] = "test"
|
314
315
|
new_pfx = my_client.generate_pfx_package(cert_name, end_date)
|
315
316
|
my_client.import_pfx_to_store(new_pfx)
|
316
317
|
expect(my_client.check_certstore_for_key(cert_name)).not_to be false
|
318
|
+
delete_certificate(cert_name)
|
317
319
|
end
|
318
320
|
|
319
321
|
it "correctly returns a new Publc Key" do
|
320
322
|
new_pfx = my_client.generate_pfx_package(cert_name, end_date)
|
321
323
|
cert_object = new_pfx.certificate.public_key.to_pem
|
322
324
|
expect(cert_object.to_s).to match(/PUBLIC KEY/)
|
325
|
+
delete_certificate(cert_name)
|
326
|
+
end
|
327
|
+
|
328
|
+
end
|
329
|
+
|
330
|
+
context "when the client intially boots the first time and auth_key_registry_type is set to 'user' " do
|
331
|
+
it "verfies that a certificate was correctly created and exists in the CurrentUser Cert Store" do
|
332
|
+
Chef::Config[:node_name] = "test"
|
333
|
+
Chef::Config[:auth_key_registry_type] = "user"
|
334
|
+
new_pfx = my_client.generate_pfx_package(cert_name, end_date)
|
335
|
+
my_client.import_pfx_to_store(new_pfx)
|
336
|
+
expect(my_client.check_certstore_for_key(cert_name)).not_to be false
|
337
|
+
delete_certificate(cert_name)
|
338
|
+
end
|
339
|
+
|
340
|
+
it "correctly returns a new Publc Key" do
|
341
|
+
Chef::Config[:auth_key_registry_type] = "user"
|
342
|
+
new_pfx = my_client.generate_pfx_package(cert_name, end_date)
|
343
|
+
cert_object = new_pfx.certificate.public_key.to_pem
|
344
|
+
expect(cert_object.to_s).to match(/PUBLIC KEY/)
|
345
|
+
delete_certificate(cert_name)
|
323
346
|
end
|
324
347
|
|
325
348
|
end
|
326
349
|
|
327
350
|
def delete_certificate(cert_name)
|
351
|
+
Chef::Config[:auth_key_registry_type] == "user" ? store = "CurrentUser" : store = "LocalMachine"
|
328
352
|
require "chef/mixin/powershell_exec"
|
329
353
|
extend Chef::Mixin::PowershellExec
|
330
354
|
powershell_code = <<~CODE
|
331
|
-
Get-ChildItem -path cert
|
355
|
+
Get-ChildItem -path cert:\\#{store}\\My -Recurse -Force | Where-Object { $_.Subject -Match "#{cert_name}" } | Remove-item
|
332
356
|
CODE
|
333
357
|
powershell_exec!(powershell_code)
|
334
358
|
end
|
@@ -49,6 +49,14 @@ describe Chef::Compliance::Runner do
|
|
49
49
|
expect(runner).not_to be_enabled
|
50
50
|
end
|
51
51
|
|
52
|
+
it "is false if the node attributes have audit profiles and the audit cookbook is present, and the complince mode attribute is false" do
|
53
|
+
stub_const("::Reporter::ChefAutomate", true)
|
54
|
+
node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }
|
55
|
+
node.normal["audit"]["compliance_phase"] = false
|
56
|
+
|
57
|
+
expect(runner).not_to be_enabled
|
58
|
+
end
|
59
|
+
|
52
60
|
it "is true if the node attributes have audit profiles and the audit cookbook is present, and the complince mode attribute is true" do
|
53
61
|
stub_const("::Reporter::ChefAutomate", true)
|
54
62
|
node.normal["audit"]["profiles"]["ssh"] = { 'compliance': "base/ssh" }
|
@@ -18,6 +18,9 @@
|
|
18
18
|
|
19
19
|
require "spec_helper"
|
20
20
|
require "chef/http/authenticator"
|
21
|
+
require "chef/mixin/powershell_exec"
|
22
|
+
|
23
|
+
require_relative "../../../lib/chef/win32/registry"
|
21
24
|
|
22
25
|
describe Chef::HTTP::Authenticator, :windows_only do
|
23
26
|
let(:class_instance) { Chef::HTTP::Authenticator.new(client_name: "test") }
|
@@ -28,7 +31,7 @@ describe Chef::HTTP::Authenticator, :windows_only do
|
|
28
31
|
let(:node_name) { "test" }
|
29
32
|
let(:passwrd) { "some_insecure_password" }
|
30
33
|
|
31
|
-
before do
|
34
|
+
before(:each) do
|
32
35
|
Chef::Config[:node_name] = node_name
|
33
36
|
cert_name = "chef-#{node_name}"
|
34
37
|
d = Time.now
|
@@ -36,6 +39,7 @@ describe Chef::HTTP::Authenticator, :windows_only do
|
|
36
39
|
end_date = end_date.utc.iso8601
|
37
40
|
|
38
41
|
my_client = Chef::Client.new
|
42
|
+
class_instance.get_cert_password
|
39
43
|
pfx = my_client.generate_pfx_package(cert_name, end_date)
|
40
44
|
my_client.import_pfx_to_store(pfx)
|
41
45
|
end
|
@@ -47,10 +51,21 @@ describe Chef::HTTP::Authenticator, :windows_only do
|
|
47
51
|
delete_certificate(cert_name)
|
48
52
|
end
|
49
53
|
|
50
|
-
context "when retrieving a certificate from the certificate store" do
|
54
|
+
context "when retrieving a certificate from the certificate store it" do
|
55
|
+
it "properly creates the password hive in the registry when it doesn't exist" do
|
56
|
+
delete_registry_hive
|
57
|
+
class_instance.get_cert_password
|
58
|
+
win32registry = Chef::Win32::Registry.new
|
59
|
+
expected_path = "HKEY_LOCAL_MACHINE\\Software\\Progress\\Authentication"
|
60
|
+
path_created = win32registry.key_exists?(expected_path)
|
61
|
+
expect(path_created).to be(true)
|
62
|
+
end
|
63
|
+
|
51
64
|
it "retrieves a certificate password from the registry when the hive does not already exist" do
|
52
65
|
delete_registry_hive
|
66
|
+
password = class_instance.get_cert_password
|
53
67
|
expect { class_instance.get_cert_password }.not_to raise_error
|
68
|
+
expect(password).not_to be(nil)
|
54
69
|
end
|
55
70
|
|
56
71
|
it "should return a password of at least 14 characters in length" do
|
@@ -58,7 +73,27 @@ describe Chef::HTTP::Authenticator, :windows_only do
|
|
58
73
|
expect(password.length).to eql(14)
|
59
74
|
end
|
60
75
|
|
61
|
-
it "
|
76
|
+
it "will retrieve a password from a partial registry hive and upgrades it while using the old decryptor" do
|
77
|
+
delete_registry_hive
|
78
|
+
load_partial_registry_hive
|
79
|
+
password = class_instance.get_cert_password
|
80
|
+
expect(password).to eql(passwrd)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "verifies that the new password is now using a vector" do
|
84
|
+
win32registry = Chef::Win32::Registry.new
|
85
|
+
path = "HKEY_LOCAL_MACHINE\\Software\\Progress\\Authentication"
|
86
|
+
password_blob = win32registry.get_values(path)
|
87
|
+
if password_blob.nil? || password_blob.empty?
|
88
|
+
raise Chef::Exceptions::Win32RegKeyMissing
|
89
|
+
end
|
90
|
+
|
91
|
+
raw_data = password_blob.map { |x| x[:data] }
|
92
|
+
vector = raw_data[2]
|
93
|
+
expect(vector).not_to be(nil)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "correctly retrieves a valid certificate in pem format from the LocalMachine certstore" do
|
62
97
|
require "openssl"
|
63
98
|
certificate = class_instance.retrieve_certificate_key(node_name)
|
64
99
|
cert_object = OpenSSL::PKey::RSA.new(certificate)
|
@@ -66,21 +101,39 @@ describe Chef::HTTP::Authenticator, :windows_only do
|
|
66
101
|
end
|
67
102
|
end
|
68
103
|
|
69
|
-
def
|
104
|
+
def load_partial_registry_hive
|
105
|
+
extend Chef::Mixin::PowershellExec
|
106
|
+
password = "some_insecure_password"
|
70
107
|
powershell_code = <<~CODE
|
71
|
-
|
108
|
+
$encrypted_string = ConvertTo-SecureString "#{password}" -AsPlainText -Force
|
109
|
+
$secure_string = ConvertFrom-SecureString $encrypted_string
|
110
|
+
return $secure_string
|
72
111
|
CODE
|
73
|
-
powershell_exec!(powershell_code)
|
112
|
+
encrypted_pass = powershell_exec!(powershell_code).result
|
113
|
+
Chef::Config[:auth_key_registry_type] == "user" ? store = "HKEY_CURRENT_USER" : store = "HKEY_LOCAL_MACHINE"
|
114
|
+
hive_path = "#{store}\\Software\\Progress\\Authentication"
|
115
|
+
win32registry = Chef::Win32::Registry.new
|
116
|
+
unless win32registry.key_exists?(hive_path)
|
117
|
+
win32registry.create_key(hive_path, true)
|
118
|
+
end
|
119
|
+
values = { name: "PfxPass", type: :string, data: encrypted_pass }
|
120
|
+
win32registry.set_value(hive_path, values)
|
74
121
|
end
|
75
122
|
|
76
123
|
def delete_registry_hive
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
@win32registry.delete_key(path, true)
|
124
|
+
win32registry = Chef::Win32::Registry.new
|
125
|
+
hive_path = "HKEY_LOCAL_MACHINE\\Software\\Progress"
|
126
|
+
if win32registry.key_exists?(hive_path)
|
127
|
+
win32registry.delete_key(hive_path, true)
|
82
128
|
end
|
83
129
|
end
|
130
|
+
|
131
|
+
def delete_certificate(cert_name)
|
132
|
+
powershell_code = <<~CODE
|
133
|
+
Get-ChildItem -path cert:\\LocalMachine\\My -Recurse -Force | Where-Object { $_.Subject -Match "#{cert_name}" } | Remove-item
|
134
|
+
CODE
|
135
|
+
powershell_exec!(powershell_code)
|
136
|
+
end
|
84
137
|
end
|
85
138
|
|
86
139
|
describe Chef::HTTP::Authenticator do
|
@@ -82,6 +82,15 @@ C5986B4F1257FFA86632CBA746181433FBB75451
|
|
82
82
|
843938DF228D22F7B3742BC0D94AA3F0EFE21092}
|
83
83
|
end
|
84
84
|
|
85
|
+
let(:apt_public_keys) do
|
86
|
+
%w{
|
87
|
+
pub:-:1024:17:40976EAF437D05B5:2004-09-12
|
88
|
+
pub:-:1024:17:46181433FBB75451:2004-12-30
|
89
|
+
pub:-:4096:1:3B4FE6ACC0B21F32:2012-05-11
|
90
|
+
pub:-:4096:1:D94AA3F0EFE21092:2012-05-11
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
85
94
|
it "responds to load_current_resource" do
|
86
95
|
expect(provider).to respond_to(:load_current_resource)
|
87
96
|
end
|
@@ -113,6 +122,18 @@ C5986B4F1257FFA86632CBA746181433FBB75451
|
|
113
122
|
end
|
114
123
|
end
|
115
124
|
|
125
|
+
describe "#extract_public_keys_from_cmd" do
|
126
|
+
it "runs the desired command" do
|
127
|
+
expect(provider).to receive(:shell_out).and_return(apt_key_finger)
|
128
|
+
provider.extract_public_keys_from_cmd(*apt_key_finger_cmd)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "returns a list of key fingerprints" do
|
132
|
+
expect(provider).to receive(:shell_out).and_return(apt_key_finger)
|
133
|
+
expect(provider.extract_public_keys_from_cmd(*apt_key_finger_cmd)).to eql(apt_public_keys)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
116
137
|
describe "#cookbook_name" do
|
117
138
|
it "returns 'test' when the cookbook property is set" do
|
118
139
|
new_resource.cookbook("test")
|
@@ -122,22 +143,22 @@ C5986B4F1257FFA86632CBA746181433FBB75451
|
|
122
143
|
|
123
144
|
describe "#no_new_keys?" do
|
124
145
|
before do
|
125
|
-
allow(provider).to receive(:
|
146
|
+
allow(provider).to receive(:extract_public_keys_from_cmd).with(*apt_key_finger_cmd).and_return(apt_public_keys)
|
126
147
|
end
|
127
148
|
|
128
149
|
let(:file) { "/tmp/remote-gpg-keyfile" }
|
129
150
|
|
130
151
|
it "matches a set of keys" do
|
131
|
-
allow(provider).to receive(:
|
152
|
+
allow(provider).to receive(:extract_public_keys_from_cmd)
|
132
153
|
.with("gpg", "--with-fingerprint", "--with-colons", file)
|
133
|
-
.and_return(
|
154
|
+
.and_return([apt_public_keys.first])
|
134
155
|
expect(provider.no_new_keys?(file)).to be_truthy
|
135
156
|
end
|
136
157
|
|
137
158
|
it "notices missing keys" do
|
138
|
-
allow(provider).to receive(:
|
159
|
+
allow(provider).to receive(:extract_public_keys_from_cmd)
|
139
160
|
.with("gpg", "--with-fingerprint", "--with-colons", file)
|
140
|
-
.and_return(%w{
|
161
|
+
.and_return(%w{pub:-:4096:1:871920D1991BC93C:1537196506})
|
141
162
|
expect(provider.no_new_keys?(file)).to be_falsey
|
142
163
|
end
|
143
164
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 18.1.
|
4
|
+
version: 18.1.29
|
5
5
|
platform: x64-mingw-ucrt
|
6
6
|
authors:
|
7
7
|
- Adam Jacob
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-config
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 18.1.
|
19
|
+
version: 18.1.29
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 18.1.
|
26
|
+
version: 18.1.29
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: chef-utils
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 18.1.
|
33
|
+
version: 18.1.29
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 18.1.
|
40
|
+
version: 18.1.29
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: train-core
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -336,20 +336,20 @@ dependencies:
|
|
336
336
|
requirements:
|
337
337
|
- - "~>"
|
338
338
|
- !ruby/object:Gem::Version
|
339
|
-
version: '1.
|
339
|
+
version: '1.1'
|
340
340
|
- - ">="
|
341
341
|
- !ruby/object:Gem::Version
|
342
|
-
version: 1.
|
342
|
+
version: 1.1.3
|
343
343
|
type: :runtime
|
344
344
|
prerelease: false
|
345
345
|
version_requirements: !ruby/object:Gem::Requirement
|
346
346
|
requirements:
|
347
347
|
- - "~>"
|
348
348
|
- !ruby/object:Gem::Version
|
349
|
-
version: '1.
|
349
|
+
version: '1.1'
|
350
350
|
- - ">="
|
351
351
|
- !ruby/object:Gem::Version
|
352
|
-
version: 1.
|
352
|
+
version: 1.1.3
|
353
353
|
- !ruby/object:Gem::Dependency
|
354
354
|
name: chef-zero
|
355
355
|
requirement: !ruby/object:Gem::Requirement
|
@@ -483,19 +483,19 @@ dependencies:
|
|
483
483
|
- !ruby/object:Gem::Version
|
484
484
|
version: 0.3.4
|
485
485
|
- !ruby/object:Gem::Dependency
|
486
|
-
name:
|
486
|
+
name: proxifier2
|
487
487
|
requirement: !ruby/object:Gem::Requirement
|
488
488
|
requirements:
|
489
489
|
- - "~>"
|
490
490
|
- !ruby/object:Gem::Version
|
491
|
-
version: '1.
|
491
|
+
version: '1.1'
|
492
492
|
type: :runtime
|
493
493
|
prerelease: false
|
494
494
|
version_requirements: !ruby/object:Gem::Requirement
|
495
495
|
requirements:
|
496
496
|
- - "~>"
|
497
497
|
- !ruby/object:Gem::Version
|
498
|
-
version: '1.
|
498
|
+
version: '1.1'
|
499
499
|
- !ruby/object:Gem::Dependency
|
500
500
|
name: aws-sdk-s3
|
501
501
|
requirement: !ruby/object:Gem::Requirement
|