puppet 7.7.0 → 7.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +2 -2
  3. data/Gemfile +2 -1
  4. data/Gemfile.lock +9 -9
  5. data/ext/osx/puppet.plist +2 -0
  6. data/lib/puppet/defaults.rb +3 -1
  7. data/lib/puppet/pops/types/p_sem_ver_type.rb +8 -2
  8. data/lib/puppet/pops/types/p_sensitive_type.rb +10 -0
  9. data/lib/puppet/provider/package/apt.rb +3 -3
  10. data/lib/puppet/provider/package/nim.rb +11 -6
  11. data/lib/puppet/provider/package/yum.rb +3 -3
  12. data/lib/puppet/provider/package/zypper.rb +3 -3
  13. data/lib/puppet/provider/service/freebsd.rb +1 -1
  14. data/lib/puppet/provider/service/systemd.rb +6 -1
  15. data/lib/puppet/provider/user/directoryservice.rb +24 -11
  16. data/lib/puppet/transaction/additional_resource_generator.rb +1 -1
  17. data/lib/puppet/type/service.rb +8 -9
  18. data/lib/puppet/type/user.rb +38 -20
  19. data/lib/puppet/version.rb +1 -1
  20. data/locales/puppet.pot +36 -40
  21. data/man/man5/puppet.conf.5 +5 -2
  22. data/man/man8/puppet-agent.8 +1 -1
  23. data/man/man8/puppet-apply.8 +1 -1
  24. data/man/man8/puppet-catalog.8 +1 -1
  25. data/man/man8/puppet-config.8 +1 -1
  26. data/man/man8/puppet-describe.8 +1 -1
  27. data/man/man8/puppet-device.8 +1 -1
  28. data/man/man8/puppet-doc.8 +1 -1
  29. data/man/man8/puppet-epp.8 +1 -1
  30. data/man/man8/puppet-facts.8 +1 -1
  31. data/man/man8/puppet-filebucket.8 +1 -1
  32. data/man/man8/puppet-generate.8 +1 -1
  33. data/man/man8/puppet-help.8 +1 -1
  34. data/man/man8/puppet-lookup.8 +1 -1
  35. data/man/man8/puppet-module.8 +1 -1
  36. data/man/man8/puppet-node.8 +1 -1
  37. data/man/man8/puppet-parser.8 +1 -1
  38. data/man/man8/puppet-plugin.8 +1 -1
  39. data/man/man8/puppet-report.8 +1 -1
  40. data/man/man8/puppet-resource.8 +1 -1
  41. data/man/man8/puppet-script.8 +1 -1
  42. data/man/man8/puppet-ssl.8 +1 -1
  43. data/man/man8/puppet.8 +2 -2
  44. data/spec/integration/application/resource_spec.rb +30 -0
  45. data/spec/unit/functions4_spec.rb +17 -8
  46. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +18 -0
  47. data/spec/unit/pops/types/p_sensitive_type_spec.rb +18 -0
  48. data/spec/unit/provider/package/nim_spec.rb +42 -0
  49. data/spec/unit/provider/service/freebsd_spec.rb +1 -1
  50. data/spec/unit/provider/service/systemd_spec.rb +12 -0
  51. data/spec/unit/provider/user/directoryservice_spec.rb +67 -35
  52. data/spec/unit/type/service_spec.rb +49 -34
  53. data/spec/unit/type/user_spec.rb +45 -0
  54. metadata +4 -2
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "PUPPET\-SSL" "8" "May 2021" "Puppet, Inc." "Puppet manual"
4
+ .TH "PUPPET\-SSL" "8" "June 2021" "Puppet, Inc." "Puppet manual"
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBpuppet\-ssl\fR \- Manage SSL keys and certificates for puppet SSL clients
data/man/man8/puppet.8 CHANGED
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "PUPPET" "8" "May 2021" "Puppet, Inc." "Puppet manual"
4
+ .TH "PUPPET" "8" "June 2021" "Puppet, Inc." "Puppet manual"
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBpuppet\fR
@@ -25,4 +25,4 @@ Specialized:
25
25
  catalog Compile, save, view, and convert catalogs\. describe Display help about resource types device Manage remote network devices doc Generate Puppet references epp Interact directly with the EPP template parser/renderer\. facts Retrieve and store facts\. filebucket Store and retrieve files in a filebucket generate Generates Puppet code from Ruby definitions\. node View and manage node definitions\. parser Interact directly with the parser\. plugin Interact with the Puppet plugin system\. script Run a puppet manifests as a script without compiling a catalog ssl Manage SSL keys and certificates for puppet SSL clients
26
26
  .
27
27
  .P
28
- See \'puppet help \fIsubcommand\fR \fIaction\fR\' for help on a specific subcommand action\. See \'puppet help \fIsubcommand\fR\' for help on a specific subcommand\. Puppet v7\.7\.0
28
+ See \'puppet help \fIsubcommand\fR \fIaction\fR\' for help on a specific subcommand action\. See \'puppet help \fIsubcommand\fR\' for help on a specific subcommand\. Puppet v7\.8\.0
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'puppet_spec/files'
3
+
4
+ describe "puppet resource", unless: Puppet::Util::Platform.jruby? do
5
+ include PuppetSpec::Files
6
+
7
+ let(:resource) { Puppet::Application[:resource] }
8
+
9
+ describe "when handling file and tidy types" do
10
+ let!(:dir) { dir_containing('testdir', 'testfile' => 'contents') }
11
+
12
+ it 'does not raise when generating file resources' do
13
+ resource.command_line.args = ['file', dir, 'ensure=directory', 'recurse=true']
14
+
15
+ expect {
16
+ resource.run
17
+ }.to output(/ensure.+=> 'directory'/).to_stdout
18
+ end
19
+
20
+ it 'correctly cleans up a given path' do
21
+ resource.command_line.args = ['tidy', dir, 'rmdirs=true', 'recurse=true']
22
+
23
+ expect {
24
+ resource.run
25
+ }.to output(/Notice: \/File\[#{dir}\]\/ensure: removed/).to_stdout
26
+
27
+ expect(Puppet::FileSystem.exist?(dir)).to be false
28
+ end
29
+ end
30
+ end
@@ -39,6 +39,15 @@ describe 'the 4x function api' do
39
39
 
40
40
  let(:loader) { FunctionAPISpecModule::TestFunctionLoader.new }
41
41
 
42
+ def parse_eval(code, here)
43
+ if here.respond_to?(:source_location)
44
+ eval(code, here, here.source_location[0], here.source_location[1])
45
+ else
46
+ # this can be removed when ruby < 2.6 is dropped
47
+ eval(code, here)
48
+ end
49
+ end
50
+
42
51
  it 'allows a simple function to be created without dispatch declaration' do
43
52
  f = Puppet::Functions.create_function('min') do
44
53
  def min(x,y)
@@ -484,7 +493,7 @@ describe 'the 4x function api' do
484
493
  the_loader = loader()
485
494
  here = get_binding(the_loader)
486
495
  expect do
487
- eval(<<-CODE, here)
496
+ parse_eval(<<-CODE, here)
488
497
  Puppet::Functions.create_function('testing::test') do
489
498
  local_types do
490
499
  type 'MyType += Array[Integer]'
@@ -505,7 +514,7 @@ describe 'the 4x function api' do
505
514
  the_loader = loader()
506
515
  here = get_binding(the_loader)
507
516
  expect do
508
- eval(<<-CODE, here)
517
+ parse_eval(<<-CODE, here)
509
518
  Puppet::Functions.create_function('testing::test') do
510
519
  dispatch :test do
511
520
  param 'Array[1+=1]', :x
@@ -525,7 +534,7 @@ describe 'the 4x function api' do
525
534
  it 'uses return_type to validate returned value' do
526
535
  the_loader = loader()
527
536
  here = get_binding(the_loader)
528
- fc = eval(<<-CODE, here)
537
+ fc = parse_eval(<<-CODE, here)
529
538
  Puppet::Functions.create_function('testing::test') do
530
539
  dispatch :test do
531
540
  param 'Integer', :x
@@ -547,7 +556,7 @@ describe 'the 4x function api' do
547
556
  the_loader = loader()
548
557
  the_loader.add_type('myalias', type_alias_t('MyAlias', 'Integer'))
549
558
  here = get_binding(the_loader)
550
- fc = eval(<<-CODE, here)
559
+ fc = parse_eval(<<-CODE, here)
551
560
  Puppet::Functions.create_function('testing::test') do
552
561
  dispatch :test do
553
562
  param 'MyAlias', :x
@@ -567,7 +576,7 @@ describe 'the 4x function api' do
567
576
  it 'reports a reference to an unresolved type' do
568
577
  the_loader = loader()
569
578
  here = get_binding(the_loader)
570
- fc = eval(<<-CODE, here)
579
+ fc = parse_eval(<<-CODE, here)
571
580
  Puppet::Functions.create_function('testing::test') do
572
581
  dispatch :test do
573
582
  param 'MyAlias', :x
@@ -586,7 +595,7 @@ describe 'the 4x function api' do
586
595
  it 'create local Type aliases' do
587
596
  the_loader = loader()
588
597
  here = get_binding(the_loader)
589
- fc = eval(<<-CODE, here)
598
+ fc = parse_eval(<<-CODE, here)
590
599
  Puppet::Functions.create_function('testing::test') do
591
600
  local_types do
592
601
  type 'MyType = Array[Integer]'
@@ -608,7 +617,7 @@ describe 'the 4x function api' do
608
617
  it 'create nested local Type aliases' do
609
618
  the_loader = loader()
610
619
  here = get_binding(the_loader)
611
- fc = eval(<<-CODE, here)
620
+ fc = parse_eval(<<-CODE, here)
612
621
  Puppet::Functions.create_function('testing::test') do
613
622
  local_types do
614
623
  type 'InnerType = Array[Integer]'
@@ -631,7 +640,7 @@ describe 'the 4x function api' do
631
640
  it 'create self referencing local Type aliases' do
632
641
  the_loader = loader()
633
642
  here = get_binding(the_loader)
634
- fc = eval(<<-CODE, here)
643
+ fc = parse_eval(<<-CODE, here)
635
644
  Puppet::Functions.create_function('testing::test') do
636
645
  local_types do
637
646
  type 'Tree = Hash[String,Variant[String,Tree]]'
@@ -125,6 +125,24 @@ describe 'Semantic Versions' do
125
125
  expect(eval_and_collect_notices(code)).to eql(['true', 'false'])
126
126
  end
127
127
 
128
+ it 'can be compared to another instance created from arguments' do
129
+ code = <<-CODE
130
+ $x = SemVer('1.2.3-rc4+5')
131
+ $y = SemVer(1, 2, 3, 'rc4', '5')
132
+ notice($x == $y)
133
+ CODE
134
+ expect(eval_and_collect_notices(code)).to eql(['true'])
135
+ end
136
+
137
+ it 'can be compared to another instance created from a hash' do
138
+ code = <<-CODE
139
+ $x = SemVer('1.2.3-rc4+5')
140
+ $y = SemVer(major => 1, minor => 2, patch => 3, prerelease => 'rc4', build => '5')
141
+ notice($x == $y)
142
+ CODE
143
+ expect(eval_and_collect_notices(code)).to eql(['true'])
144
+ end
145
+
128
146
  it 'can be compared to another instance for magnitude' do
129
147
  code = <<-CODE
130
148
  $x = SemVer('1.1.1')
@@ -113,6 +113,24 @@ describe 'Sensitive Type' do
113
113
  expect(eval_and_collect_notices(code)).to eq(['Sensitive[Integer] != Sensitive[String]'])
114
114
  end
115
115
 
116
+ it 'equals another instance with the same value' do
117
+ code =<<-CODE
118
+ $i = Sensitive('secret')
119
+ $o = Sensitive('secret')
120
+ notice($i == $o)
121
+ CODE
122
+ expect(eval_and_collect_notices(code)).to eq(['true'])
123
+ end
124
+
125
+ it 'has equal hash keys for same values' do
126
+ code =<<-CODE
127
+ $i = Sensitive('secret')
128
+ $o = Sensitive('secret')
129
+ notice({$i => 1} == {$o => 1})
130
+ CODE
131
+ expect(eval_and_collect_notices(code)).to eq(['true'])
132
+ end
133
+
116
134
  it 'can be created from another sensitive instance ' do
117
135
  code =<<-CODE
118
136
  $o = Sensitive("hunter2")
@@ -191,6 +191,27 @@ OUTPUT
191
191
  expect(versions[version]).to eq(:rpm)
192
192
  end
193
193
  end
194
+
195
+ it "should be able to parse RPM package listings with letters in version" do
196
+ showres_output = <<END
197
+ cairo ALL @@R:cairo _all_filesets
198
+ @@R:cairo-1.14.6-2waixX11 1.14.6-2waixX11
199
+ END
200
+ packages = subject.send(:parse_showres_output, showres_output)
201
+ expect(Set.new(packages.keys)).to eq(Set.new(['cairo']))
202
+ versions = packages['cairo']
203
+ expect(versions.has_key?('1.14.6-2waixX11')).to eq(true)
204
+ expect(versions['1.14.6-2waixX11']).to eq(:rpm)
205
+ end
206
+
207
+ it "should raise error when parsing invalid RPM package listings" do
208
+ showres_output = <<END
209
+ cairo ALL @@R:cairo _all_filesets
210
+ @@R:cairo-invalid_version invalid_version
211
+ END
212
+ expect{ subject.send(:parse_showres_output, showres_output) }.to raise_error(Puppet::Error,
213
+ /Unable to parse output from nimclient showres: package string does not match expected rpm package string format/)
214
+ end
194
215
  end
195
216
 
196
217
  context "#determine_latest_version" do
@@ -220,6 +241,27 @@ END
220
241
  it "should return :installp for installp/bff packages" do
221
242
  expect(subject.send(:determine_package_type, bff_showres_output, 'mypackage.foo', '1.2.3.4')).to eq(:installp)
222
243
  end
244
+
245
+ it "should return :installp for security updates" do
246
+ nimclient_showres_output = <<END
247
+ bos.net ALL @@S:bos.net _all_filesets
248
+ + 7.2.0.1 TCP/IP ntp Applications @@S:bos.net.tcp.ntp 7.2.0.1
249
+ + 7.2.0.2 TCP/IP ntp Applications @@S:bos.net.tcp.ntp 7.2.0.2
250
+
251
+ END
252
+ expect(subject.send(:determine_package_type, nimclient_showres_output, 'bos.net.tcp.ntp', '7.2.0.2')).to eq(:installp)
253
+ end
254
+
255
+ it "should raise error when invalid header format is given" do
256
+ nimclient_showres_output = <<END
257
+ bos.net ALL @@INVALID_TYPE:bos.net _all_filesets
258
+ + 7.2.0.1 TCP/IP ntp Applications @@INVALID_TYPE:bos.net.tcp.ntp 7.2.0.1
259
+ + 7.2.0.2 TCP/IP ntp Applications @@INVALID_TYPE:bos.net.tcp.ntp 7.2.0.2
260
+
261
+ END
262
+ expect{ subject.send(:determine_package_type, nimclient_showres_output, 'bos.net.tcp.ntp', '7.2.0.2') }.to raise_error(
263
+ Puppet::Error, /Unable to parse output from nimclient showres: line does not match expected package header format/)
264
+ end
223
265
  end
224
266
  end
225
267
  end
@@ -82,7 +82,7 @@ OUTPUT
82
82
  allow(Puppet::FileSystem).to receive(:exist?).with('/etc/rc.conf').and_return(true)
83
83
  allow(File).to receive(:read).with('/etc/rc.conf').and_return("openntpd_enable=\"NO\"\nntpd_enable=\"NO\"\n")
84
84
  fh = double('fh')
85
- allow(File).to receive(:open).with('/etc/rc.conf', File::WRONLY).and_yield(fh)
85
+ allow(Puppet::FileSystem).to receive(:replace_file).with('/etc/rc.conf').and_yield(fh)
86
86
  expect(fh).to receive(:<<).with("openntpd_enable=\"NO\"\nntpd_enable=\"YES\"\n")
87
87
  allow(Puppet::FileSystem).to receive(:exist?).with('/etc/rc.conf.local').and_return(false)
88
88
  allow(Puppet::FileSystem).to receive(:exist?).with('/etc/rc.conf.d/ntpd').and_return(false)
@@ -362,6 +362,9 @@ Jun 14 21:43:23 foo.example.com systemd[1]: sshd.service lacks both ExecStart= a
362
362
  describe "#mask" do
363
363
  it "should run systemctl to disable and mask a service" do
364
364
  provider = provider_class.new(Puppet::Type.type(:service).new(:name => 'sshd.service'))
365
+ expect(provider).to receive(:execute).
366
+ with(['/bin/systemctl','cat', '--', 'sshd.service'], :failonfail => false).
367
+ and_return(Puppet::Util::Execution::ProcessOutput.new("# /lib/systemd/system/sshd.service\n...", 0))
365
368
  # :disable is the only call in the provider that uses a symbol instead of
366
369
  # a string.
367
370
  # This should be made consistent in the future and all tests updated.
@@ -369,6 +372,15 @@ Jun 14 21:43:23 foo.example.com systemd[1]: sshd.service lacks both ExecStart= a
369
372
  expect(provider).to receive(:systemctl).with(:mask, '--', 'sshd.service')
370
373
  provider.mask
371
374
  end
375
+
376
+ it "masks a service that doesn't exist" do
377
+ provider = provider_class.new(Puppet::Type.type(:service).new(:name => 'doesnotexist.service'))
378
+ expect(provider).to receive(:execute).
379
+ with(['/bin/systemctl','cat', '--', 'doesnotexist.service'], :failonfail => false).
380
+ and_return(Puppet::Util::Execution::ProcessOutput.new("No files found for doesnotexist.service.\n", 1))
381
+ expect(provider).to receive(:systemctl).with(:mask, '--', 'doesnotexist.service')
382
+ provider.mask
383
+ end
372
384
  end
373
385
 
374
386
  # Note: systemd provider does not care about hasstatus or a custom status
@@ -925,28 +925,75 @@ end
925
925
  }
926
926
  end
927
927
 
928
- it 'should call set_salted_sha512 on 10.7 when given a salted-SHA512 password hash' do
929
- expect(provider).to receive(:get_users_plist).and_return(sample_users_plist)
930
- expect(provider).to receive(:get_shadow_hash_data).with(sample_users_plist).and_return(sha512_shadowhashdata)
931
- expect(provider.class).to receive(:get_os_version).and_return('10.7')
932
- expect(provider).to receive(:set_salted_sha512).with(sample_users_plist, sha512_shadowhashdata, sha512_password_hash)
933
- provider.write_password_to_users_plist(sha512_password_hash)
928
+ before do
929
+ allow(provider).to receive(:merge_attribute_with_dscl).with('Users', username, 'AuthenticationAuthority', any_args)
934
930
  end
935
931
 
936
- it 'should call set_salted_pbkdf2 on 10.8 when given a PBKDF2 password hash' do
937
- expect(provider).to receive(:get_users_plist).and_return(sample_users_plist)
938
- expect(provider).to receive(:get_shadow_hash_data).with(sample_users_plist).and_return(pbkdf2_shadowhashdata)
939
- expect(provider.class).to receive(:get_os_version).and_return('10.8')
940
- expect(provider).to receive(:set_salted_pbkdf2).with(sample_users_plist, pbkdf2_shadowhashdata, 'entropy', pbkdf2_password_hash)
941
- provider.write_password_to_users_plist(pbkdf2_password_hash)
932
+ describe 'when on macOS 11 (Big Sur) or greater' do
933
+ before do
934
+ allow(provider.class).to receive(:get_os_version).and_return('11.0.0')
935
+ end
936
+
937
+ it 'should add salted_sha512_pbkdf2 AuthenticationAuthority key if missing' do
938
+ expect(provider).to receive(:get_users_plist).and_return(sample_users_plist)
939
+ expect(provider).to receive(:get_shadow_hash_data).with(sample_users_plist).and_return(pbkdf2_shadowhashdata)
940
+ expect(provider).to receive(:set_salted_pbkdf2).with(sample_users_plist, pbkdf2_shadowhashdata, 'entropy', pbkdf2_password_hash)
941
+ expect(provider).to receive(:needs_sha512_pbkdf2_authentication_authority_to_be_added?).and_return(true)
942
+
943
+ expect(Puppet).to receive(:debug).with("Adding 'SALTED-SHA512-PBKDF2' AuthenticationAuthority key for ShadowHash to user 'nonexistent_user'")
944
+ provider.write_password_to_users_plist(pbkdf2_password_hash)
945
+ end
946
+
947
+ it 'should not add salted_sha512_pbkdf2 AuthenticationAuthority key if not missing' do
948
+ expect(provider).to receive(:get_users_plist).and_return(sample_users_plist)
949
+ expect(provider).to receive(:get_shadow_hash_data).with(sample_users_plist).and_return(pbkdf2_shadowhashdata)
950
+ expect(provider).to receive(:set_salted_pbkdf2).with(sample_users_plist, pbkdf2_shadowhashdata, 'entropy', pbkdf2_password_hash)
951
+ expect(provider).to receive(:needs_sha512_pbkdf2_authentication_authority_to_be_added?).and_return(false)
952
+
953
+ expect(Puppet).not_to receive(:debug).with("Adding 'SALTED-SHA512-PBKDF2' AuthenticationAuthority key for ShadowHash to user 'nonexistent_user'")
954
+ provider.write_password_to_users_plist(pbkdf2_password_hash)
955
+ end
942
956
  end
943
957
 
944
- it "should delete the SALTED-SHA512 key in the shadow_hash_data hash if it exists on a 10.8 system and write_password_to_users_plist has been called to set the user's password" do
945
- expect(provider).to receive(:get_users_plist).and_return('users_plist')
946
- expect(provider).to receive(:get_shadow_hash_data).with('users_plist').and_return(sha512_shadowhashdata)
947
- expect(provider.class).to receive(:get_os_version).and_return('10.8')
948
- expect(provider).to receive(:set_salted_pbkdf2).with('users_plist', {}, 'entropy', pbkdf2_password_hash)
949
- provider.write_password_to_users_plist(pbkdf2_password_hash)
958
+ describe 'when on macOS version lower than 11' do
959
+ before do
960
+ allow(provider.class).to receive(:get_os_version)
961
+ allow(provider).to receive(:needs_sha512_pbkdf2_authentication_authority_to_be_added?).and_return(false)
962
+ end
963
+
964
+ it 'should not add salted_sha512_pbkdf2 AuthenticationAuthority' do
965
+ expect(provider).to receive(:get_users_plist).and_return(sample_users_plist)
966
+ expect(provider).to receive(:get_shadow_hash_data).with(sample_users_plist).and_return(pbkdf2_shadowhashdata)
967
+ expect(provider).to receive(:set_salted_pbkdf2).with(sample_users_plist, pbkdf2_shadowhashdata, 'entropy', pbkdf2_password_hash)
968
+ expect(provider).to receive(:needs_sha512_pbkdf2_authentication_authority_to_be_added?).and_return(false)
969
+
970
+ expect(Puppet).not_to receive(:debug).with("Adding 'SALTED-SHA512-PBKDF2' AuthenticationAuthority key for ShadowHash to user 'nonexistent_user'")
971
+ provider.write_password_to_users_plist(pbkdf2_password_hash)
972
+ end
973
+
974
+ it 'should call set_salted_sha512 on 10.7 when given a salted-SHA512 password hash' do
975
+ expect(provider).to receive(:get_users_plist).and_return(sample_users_plist)
976
+ expect(provider).to receive(:get_shadow_hash_data).with(sample_users_plist).and_return(sha512_shadowhashdata)
977
+ expect(provider.class).to receive(:get_os_version).and_return('10.7')
978
+ expect(provider).to receive(:set_salted_sha512).with(sample_users_plist, sha512_shadowhashdata, sha512_password_hash)
979
+ provider.write_password_to_users_plist(sha512_password_hash)
980
+ end
981
+
982
+ it 'should call set_salted_pbkdf2 on 10.8 when given a PBKDF2 password hash' do
983
+ expect(provider).to receive(:get_users_plist).and_return(sample_users_plist)
984
+ expect(provider).to receive(:get_shadow_hash_data).with(sample_users_plist).and_return(pbkdf2_shadowhashdata)
985
+ expect(provider.class).to receive(:get_os_version).and_return('10.8')
986
+ expect(provider).to receive(:set_salted_pbkdf2).with(sample_users_plist, pbkdf2_shadowhashdata, 'entropy', pbkdf2_password_hash)
987
+ provider.write_password_to_users_plist(pbkdf2_password_hash)
988
+ end
989
+
990
+ it "should delete the SALTED-SHA512 key in the shadow_hash_data hash if it exists on a 10.8 system and write_password_to_users_plist has been called to set the user's password" do
991
+ expect(provider).to receive(:get_users_plist).and_return('users_plist')
992
+ expect(provider).to receive(:get_shadow_hash_data).with('users_plist').and_return(sha512_shadowhashdata)
993
+ expect(provider.class).to receive(:get_os_version).and_return('10.8')
994
+ expect(provider).to receive(:set_salted_pbkdf2).with('users_plist', {}, 'entropy', pbkdf2_password_hash)
995
+ provider.write_password_to_users_plist(pbkdf2_password_hash)
996
+ end
950
997
  end
951
998
  end
952
999
 
@@ -974,16 +1021,7 @@ end
974
1021
  describe '#set_shadow_hash_data' do
975
1022
  let(:users_plist) { {'ShadowHashData' => ['string_data'] } }
976
1023
 
977
- it 'should flush the plist data to disk on OS X < 10.15' do
978
- allow(provider.class).to receive(:get_os_version).and_return('10.12')
979
-
980
- expect(provider).to receive(:write_users_plist_to_disk)
981
- provider.set_shadow_hash_data(users_plist, pbkdf2_embedded_plist)
982
- end
983
-
984
- it 'should flush the plist data a temporary file on OS X >= 10.15' do
985
- allow(provider.class).to receive(:get_os_version).and_return('10.15')
986
-
1024
+ it 'should flush the plist data to a temporary file' do
987
1025
  expect(provider).to receive(:write_and_import_shadow_hash_data)
988
1026
  provider.set_shadow_hash_data(users_plist, pbkdf2_embedded_plist)
989
1027
  end
@@ -1033,13 +1071,6 @@ end
1033
1071
  end
1034
1072
  end
1035
1073
 
1036
- describe '#write_users_plist_to_disk' do
1037
- it 'should save the passed plist to disk and convert it to a binary plist' do
1038
- expect(Puppet::Util::Plist).to receive(:write_plist_file).with(user_plist_xml, "#{users_plist_dir}/nonexistent_user.plist", :binary)
1039
- provider.write_users_plist_to_disk(user_plist_xml)
1040
- end
1041
- end
1042
-
1043
1074
  describe '#write_and_import_shadow_hash_data' do
1044
1075
  it 'should save the passed plist to a temporary file and import it' do
1045
1076
  tmpfile = double('tempfile', :path => "/tmp/dsimport_#{username}", :flush => nil)
@@ -1203,6 +1234,7 @@ end
1203
1234
  before :each do
1204
1235
  allow(provider.class).to receive(:get_all_users).and_return(all_users_hash)
1205
1236
  allow(provider.class).to receive(:get_list_of_groups).and_return(group_plist_hash_guid)
1237
+ allow(provider).to receive(:merge_attribute_with_dscl).with('Users', username, 'AuthenticationAuthority', any_args)
1206
1238
  provider.class.prefetch({})
1207
1239
  end
1208
1240
 
@@ -72,50 +72,65 @@ describe test_title, "when validating attribute values" do
72
72
  allow(@provider.class).to receive(:supports_parameter?).and_return(true)
73
73
  end
74
74
 
75
- it "should support :true as a value" do
76
- srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :true)
77
- expect(srv.should(:enable)).to eq(:true)
78
- end
75
+ describe "for value without required features" do
76
+ before :each do
77
+ allow(@provider).to receive(:satisfies?)
78
+ end
79
79
 
80
- it "should support :false as a value" do
81
- srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :false)
82
- expect(srv.should(:enable)).to eq(:false)
83
- end
80
+ it "should not support :mask as a value" do
81
+ expect { Puppet::Type.type(:service).new(:name => "yay", :enable => :mask) }.to raise_error(
82
+ Puppet::ResourceError,
83
+ /Provider .+ must have features 'maskable' to set 'enable' to 'mask'/
84
+ )
85
+ end
84
86
 
85
- it "should support :mask as a value" do
86
- srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :mask)
87
- expect(srv.should(:enable)).to eq(:mask)
88
- end
87
+ it "should not support :manual as a value" do
88
+ expect { Puppet::Type.type(:service).new(:name => "yay", :enable => :manual) }.to raise_error(
89
+ Puppet::ResourceError,
90
+ /Provider .+ must have features 'manual_startable' to set 'enable' to 'manual'/
91
+ )
92
+ end
89
93
 
90
- it "should support :manual as a value on Windows" do
91
- allow(Puppet::Util::Platform).to receive(:windows?).and_return(true)
92
- srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :manual)
93
- expect(srv.should(:enable)).to eq(:manual)
94
+ it "should not support :mask as a value" do
95
+ expect { Puppet::Type.type(:service).new(:name => "yay", :enable => :delayed) }.to raise_error(
96
+ Puppet::ResourceError,
97
+ /Provider .+ must have features 'delayed_startable' to set 'enable' to 'delayed'/
98
+ )
99
+ end
94
100
  end
95
101
 
96
- it "should support :delayed as a value on Windows" do
97
- allow(Puppet::Util::Platform).to receive(:windows?).and_return(true)
102
+ describe "for value with required features" do
103
+ before :each do
104
+ allow(@provider).to receive(:satisfies?).and_return(:true)
105
+ end
106
+
107
+ it "should support :true as a value" do
108
+ srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :true)
109
+ expect(srv.should(:enable)).to eq(:true)
110
+ end
98
111
 
99
- srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :delayed)
100
- expect(srv.should(:enable)).to eq(:delayed)
101
- end
112
+ it "should support :false as a value" do
113
+ srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :false)
114
+ expect(srv.should(:enable)).to eq(:false)
115
+ end
102
116
 
103
- it "should not support :manual as a value when not on Windows" do
104
- allow(Puppet::Util::Platform).to receive(:windows?).and_return(false)
117
+ it "should support :mask as a value" do
118
+ srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :mask)
119
+ expect(srv.should(:enable)).to eq(:mask)
120
+ end
105
121
 
106
- expect { Puppet::Type.type(:service).new(:name => "yay", :enable => :manual) }.to raise_error(
107
- Puppet::Error,
108
- /Setting enable to manual is only supported on Microsoft Windows\./
109
- )
110
- end
122
+ it "should support :manual as a value on Windows" do
123
+ allow(Puppet::Util::Platform).to receive(:windows?).and_return(true)
124
+ srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :manual)
125
+ expect(srv.should(:enable)).to eq(:manual)
126
+ end
111
127
 
112
- it "should not support :delayed as a value when not on Windows" do
113
- allow(Puppet::Util::Platform).to receive(:windows?).and_return(false)
128
+ it "should support :delayed as a value on Windows" do
129
+ allow(Puppet::Util::Platform).to receive(:windows?).and_return(true)
114
130
 
115
- expect { Puppet::Type.type(:service).new(:name => "yay", :enable => :delayed) }.to raise_error(
116
- Puppet::Error,
117
- /Setting enable to delayed is only supported on Microsoft Windows\./
118
- )
131
+ srv = Puppet::Type.type(:service).new(:name => "yay", :enable => :delayed)
132
+ expect(srv.should(:enable)).to eq(:delayed)
133
+ end
119
134
  end
120
135
  end
121
136