chef 18.1.0-x64-mingw-ucrt → 18.1.29-x64-mingw-ucrt
Sign up to get free protection for your applications and to get access to all the features.
- 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
|