puppet 2.7.9 → 2.7.11
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.
- data/CHANGELOG +413 -0
- data/README_DEVELOPER.md +28 -0
- data/conf/redhat/puppet.spec +10 -1
- data/conf/solaris/pkginfo +1 -1
- data/conf/suse/puppet.spec +7 -4
- data/ext/envpuppet.bat +13 -0
- data/ext/rack/files/apache2.conf +4 -0
- data/install.rb +4 -8
- data/lib/puppet.rb +1 -1
- data/lib/puppet/agent.rb +7 -0
- data/lib/puppet/agent/disabler.rb +27 -0
- data/lib/puppet/agent/locker.rb +0 -10
- data/lib/puppet/application.rb +3 -0
- data/lib/puppet/application/agent.rb +13 -3
- data/lib/puppet/application/apply.rb +6 -6
- data/lib/puppet/application/cert.rb +5 -5
- data/lib/puppet/application/instrumentation_data.rb +4 -0
- data/lib/puppet/application/instrumentation_listener.rb +4 -0
- data/lib/puppet/application/instrumentation_probe.rb +4 -0
- data/lib/puppet/configurer.rb +3 -1
- data/lib/puppet/configurer/downloader.rb +4 -2
- data/lib/puppet/configurer/fact_handler.rb +0 -21
- data/lib/puppet/daemon.rb +3 -4
- data/lib/puppet/defaults.rb +2 -2
- data/lib/puppet/face/instrumentation_data.rb +28 -0
- data/lib/puppet/face/instrumentation_listener.rb +96 -0
- data/lib/puppet/face/instrumentation_probe.rb +77 -0
- data/lib/puppet/face/module/list.rb +64 -0
- data/lib/puppet/face/module/uninstall.rb +50 -0
- data/lib/puppet/face/node/clean.rb +1 -4
- data/lib/puppet/feature/base.rb +1 -0
- data/lib/puppet/file_serving/content.rb +1 -1
- data/lib/puppet/indirector/facts/facter.rb +20 -7
- data/lib/puppet/indirector/facts/inventory_active_record.rb +14 -11
- data/lib/puppet/indirector/indirection.rb +7 -0
- data/lib/puppet/indirector/instrumentation_data.rb +3 -0
- data/lib/puppet/indirector/instrumentation_data/local.rb +19 -0
- data/lib/puppet/indirector/instrumentation_data/rest.rb +5 -0
- data/lib/puppet/indirector/instrumentation_listener.rb +3 -0
- data/lib/puppet/indirector/instrumentation_listener/local.rb +23 -0
- data/lib/puppet/indirector/instrumentation_listener/rest.rb +5 -0
- data/lib/puppet/indirector/instrumentation_probe.rb +3 -0
- data/lib/puppet/indirector/instrumentation_probe/local.rb +24 -0
- data/lib/puppet/indirector/instrumentation_probe/rest.rb +5 -0
- data/lib/puppet/indirector/rest.rb +1 -1
- data/lib/puppet/module.rb +13 -17
- data/lib/puppet/module_tool/applications.rb +1 -0
- data/lib/puppet/module_tool/applications/uninstaller.rb +33 -0
- data/lib/puppet/module_tool/contents_description.rb +1 -1
- data/lib/puppet/network/server.rb +2 -3
- data/lib/puppet/node/environment.rb +16 -3
- data/lib/puppet/parser/ast/leaf.rb +1 -1
- data/lib/puppet/parser/functions/create_resources.rb +1 -1
- data/lib/puppet/parser/type_loader.rb +1 -1
- data/lib/puppet/property.rb +46 -14
- data/lib/puppet/provider.rb +13 -4
- data/lib/puppet/provider/augeas/augeas.rb +6 -4
- data/lib/puppet/provider/group/pw.rb +24 -10
- data/lib/puppet/provider/nameservice/directoryservice.rb +146 -37
- data/lib/puppet/provider/package/pip.rb +1 -1
- data/lib/puppet/provider/package/yum.rb +1 -2
- data/lib/puppet/provider/service/debian.rb +14 -0
- data/lib/puppet/provider/service/launchd.rb +1 -1
- data/lib/puppet/provider/service/smf.rb +2 -2
- data/lib/puppet/provider/user/pw.rb +56 -2
- data/lib/puppet/provider/user/user_role_add.rb +32 -22
- data/lib/puppet/provider/user/windows_adsi.rb +1 -0
- data/lib/puppet/rails/benchmark.rb +1 -1
- data/lib/puppet/reports/store.rb +8 -1
- data/lib/puppet/resource/catalog.rb +5 -1
- data/lib/puppet/simple_graph.rb +11 -14
- data/lib/puppet/transaction.rb +10 -4
- data/lib/puppet/transaction/report.rb +9 -3
- data/lib/puppet/type.rb +19 -7
- data/lib/puppet/type/exec.rb +1 -1
- data/lib/puppet/type/file.rb +4 -1
- data/lib/puppet/type/file/ensure.rb +5 -1
- data/lib/puppet/type/file/mode.rb +45 -10
- data/lib/puppet/type/file/source.rb +4 -0
- data/lib/puppet/type/host.rb +17 -3
- data/lib/puppet/type/k5login.rb +3 -2
- data/lib/puppet/type/schedule.rb +3 -2
- data/lib/puppet/util.rb +83 -27
- data/lib/puppet/util/anonymous_filelock.rb +36 -0
- data/lib/puppet/util/docs.rb +18 -2
- data/lib/puppet/util/instrumentation.rb +173 -0
- data/lib/puppet/util/instrumentation/data.rb +34 -0
- data/lib/puppet/util/instrumentation/indirection_probe.rb +29 -0
- data/lib/puppet/util/instrumentation/instrumentable.rb +143 -0
- data/lib/puppet/util/instrumentation/listener.rb +60 -0
- data/lib/puppet/util/instrumentation/listeners/log.rb +29 -0
- data/lib/puppet/util/instrumentation/listeners/performance.rb +30 -0
- data/lib/puppet/util/monkey_patches.rb +8 -0
- data/lib/puppet/util/pidlock.rb +21 -25
- data/lib/puppet/util/rdoc/parser.rb +2 -2
- data/lib/puppet/util/reference.rb +8 -23
- data/lib/puppet/util/retryaction.rb +48 -0
- data/lib/puppet/util/suidmanager.rb +70 -39
- data/lib/puppet/util/symbolic_file_mode.rb +140 -0
- data/spec/integration/configurer_spec.rb +5 -0
- data/spec/integration/indirector/direct_file_server_spec.rb +1 -1
- data/spec/integration/indirector/file_content/file_server_spec.rb +7 -7
- data/spec/integration/provider/package_spec.rb +7 -0
- data/spec/unit/agent/disabler_spec.rb +60 -0
- data/spec/unit/agent/locker_spec.rb +0 -12
- data/spec/unit/agent_spec.rb +8 -0
- data/spec/unit/application/agent_spec.rb +38 -1
- data/spec/unit/application/apply_spec.rb +34 -40
- data/spec/unit/application/cert_spec.rb +1 -1
- data/spec/unit/application_spec.rb +6 -0
- data/spec/unit/configurer/downloader_spec.rb +29 -10
- data/spec/unit/configurer/fact_handler_spec.rb +5 -29
- data/spec/unit/configurer_spec.rb +8 -8
- data/spec/unit/daemon_spec.rb +12 -26
- data/spec/unit/face/instrumentation_data.rb +7 -0
- data/spec/unit/face/instrumentation_listener.rb +38 -0
- data/spec/unit/face/instrumentation_probe.rb +21 -0
- data/spec/unit/face/node_spec.rb +111 -111
- data/spec/unit/file_serving/content_spec.rb +2 -2
- data/spec/unit/indirector/facts/facter_spec.rb +25 -3
- data/spec/unit/indirector/facts/inventory_active_record_spec.rb +14 -4
- data/spec/unit/indirector/instrumentation_data/local_spec.rb +52 -0
- data/spec/unit/indirector/instrumentation_data/rest_spec.rb +11 -0
- data/spec/unit/indirector/instrumentation_listener/local_spec.rb +65 -0
- data/spec/unit/indirector/instrumentation_listener/rest_spec.rb +11 -0
- data/spec/unit/indirector/instrumentation_probe/local_spec.rb +65 -0
- data/spec/unit/indirector/instrumentation_probe/rest_spec.rb +11 -0
- data/spec/unit/module_spec.rb +39 -125
- data/spec/unit/module_tool/uninstaller_spec.rb +44 -0
- data/spec/unit/network/server_spec.rb +2 -20
- data/spec/unit/node/environment_spec.rb +76 -58
- data/spec/unit/parser/ast/asthash_spec.rb +1 -2
- data/spec/unit/parser/ast/leaf_spec.rb +16 -0
- data/spec/unit/property/keyvalue_spec.rb +5 -2
- data/spec/unit/property_spec.rb +260 -159
- data/spec/unit/provider/augeas/augeas_spec.rb +2 -2
- data/spec/unit/provider/group/pw_spec.rb +81 -0
- data/spec/unit/provider/nameservice/directoryservice_spec.rb +102 -0
- data/spec/unit/provider/package/pip_spec.rb +7 -0
- data/spec/unit/provider/package/yum_spec.rb +45 -1
- data/spec/unit/provider/service/debian_spec.rb +15 -0
- data/spec/unit/provider/service/launchd_spec.rb +48 -43
- data/spec/unit/provider/service/smf_spec.rb +3 -3
- data/spec/unit/provider/user/pw_spec.rb +183 -0
- data/spec/unit/provider/user/user_role_add_spec.rb +46 -39
- data/spec/unit/provider/user/windows_adsi_spec.rb +1 -0
- data/spec/unit/provider_spec.rb +32 -0
- data/spec/unit/reports/store_spec.rb +19 -1
- data/spec/unit/simple_graph_spec.rb +34 -19
- data/spec/unit/ssl/certificate_factory_spec.rb +3 -3
- data/spec/unit/transaction/report_spec.rb +29 -1
- data/spec/unit/transaction_spec.rb +32 -46
- data/spec/unit/type/file/mode_spec.rb +1 -1
- data/spec/unit/type/file/source_spec.rb +28 -3
- data/spec/unit/type/file_spec.rb +17 -16
- data/spec/unit/type/host_spec.rb +527 -0
- data/spec/unit/type/k5login_spec.rb +115 -0
- data/spec/unit/type/schedule_spec.rb +6 -6
- data/spec/unit/type_spec.rb +51 -0
- data/spec/unit/util/anonymous_filelock_spec.rb +78 -0
- data/spec/unit/util/execution_stub_spec.rb +2 -1
- data/spec/unit/util/instrumentation/data_spec.rb +44 -0
- data/spec/unit/util/instrumentation/indirection_probe_spec.rb +19 -0
- data/spec/unit/util/instrumentation/instrumentable_spec.rb +186 -0
- data/spec/unit/util/instrumentation/listener_spec.rb +100 -0
- data/spec/unit/util/instrumentation/listeners/log_spec.rb +34 -0
- data/spec/unit/util/instrumentation/listeners/performance_spec.rb +36 -0
- data/spec/unit/util/instrumentation_spec.rb +181 -0
- data/spec/unit/util/pidlock_spec.rb +208 -0
- data/spec/unit/util/rdoc/parser_spec.rb +1 -1
- data/spec/unit/util/reference_spec.rb +16 -6
- data/spec/unit/util/retryaction_spec.rb +62 -0
- data/spec/unit/util/suidmanager_spec.rb +101 -83
- data/spec/unit/util/symbolic_file_mode_spec.rb +182 -0
- data/spec/unit/util_spec.rb +126 -0
- data/tasks/rake/apple.rake +176 -0
- data/tasks/rake/templates/prototype.plist.erb +38 -0
- metadata +61 -13
- data/lib/puppet/application/module.rb +0 -3
- data/lib/puppet/face/module.rb +0 -12
- data/spec/unit/face/module/build_spec.rb +0 -30
- data/spec/unit/face/module/changes_spec.rb +0 -30
- data/spec/unit/face/module/clean_spec.rb +0 -30
- data/spec/unit/face/module/generate_spec.rb +0 -30
- data/spec/unit/face/module/install_spec.rb +0 -75
- data/spec/unit/face/module/search_spec.rb +0 -40
- data/test/util/pidlock.rb +0 -126
@@ -17,10 +17,12 @@ require 'augeas' if Puppet.features.augeas?
|
|
17
17
|
require 'strscan'
|
18
18
|
require 'puppet/util'
|
19
19
|
require 'puppet/util/diff'
|
20
|
+
require 'puppet/util/package'
|
20
21
|
|
21
22
|
Puppet::Type.type(:augeas).provide(:augeas) do
|
22
23
|
include Puppet::Util
|
23
24
|
include Puppet::Util::Diff
|
25
|
+
include Puppet::Util::Package
|
24
26
|
|
25
27
|
confine :true => Puppet.features.augeas?
|
26
28
|
|
@@ -149,7 +151,7 @@ Puppet::Type.type(:augeas).provide(:augeas) do
|
|
149
151
|
debug("Opening augeas with root #{root}, lens path #{load_path}, flags #{flags}")
|
150
152
|
@aug = Augeas::open(root, load_path,flags)
|
151
153
|
|
152
|
-
debug("Augeas version #{get_augeas_version} is installed") if get_augeas_version
|
154
|
+
debug("Augeas version #{get_augeas_version} is installed") if versioncmp(get_augeas_version, "0.3.6") >= 0
|
153
155
|
|
154
156
|
if resource[:incl]
|
155
157
|
aug.set("/augeas/load/Xfm/lens", resource[:lens])
|
@@ -285,7 +287,7 @@ Puppet::Type.type(:augeas).provide(:augeas) do
|
|
285
287
|
# If we have a verison of augeas which is at least 0.3.6 then we
|
286
288
|
# can make the changes now, see if changes were made, and
|
287
289
|
# actually do the save.
|
288
|
-
if return_value and get_augeas_version
|
290
|
+
if return_value and versioncmp(get_augeas_version, "0.3.6") >= 0
|
289
291
|
debug("Will attempt to save and only run if files changed")
|
290
292
|
set_augeas_save_mode(SAVE_NEWFILE)
|
291
293
|
do_execute_changes
|
@@ -325,7 +327,7 @@ Puppet::Type.type(:augeas).provide(:augeas) do
|
|
325
327
|
begin
|
326
328
|
open_augeas
|
327
329
|
saved_files = @aug.match("/augeas/events/saved")
|
328
|
-
|
330
|
+
unless saved_files.empty?
|
329
331
|
saved_files.each do |key|
|
330
332
|
root = resource[:root].sub(/^\/$/, "")
|
331
333
|
saved_file = @aug.get(key).to_s.sub(/^\/files/, root)
|
@@ -337,7 +339,7 @@ Puppet::Type.type(:augeas).provide(:augeas) do
|
|
337
339
|
end
|
338
340
|
else
|
339
341
|
debug("No saved files, re-executing augeas")
|
340
|
-
set_augeas_save_mode(SAVE_OVERWRITE) if get_augeas_version
|
342
|
+
set_augeas_save_mode(SAVE_OVERWRITE) if versioncmp(get_augeas_version, "0.3.6") >= 0
|
341
343
|
do_execute_changes
|
342
344
|
success = @aug.save
|
343
345
|
fail("Save failed with return code #{success}") if success != true
|
@@ -1,34 +1,48 @@
|
|
1
1
|
require 'puppet/provider/nameservice/pw'
|
2
2
|
|
3
3
|
Puppet::Type.type(:group).provide :pw, :parent => Puppet::Provider::NameService::PW do
|
4
|
-
desc "Group management via `pw
|
4
|
+
desc "Group management via `pw` on FreeBSD."
|
5
5
|
|
6
|
-
|
6
|
+
commands :pw => "pw"
|
7
|
+
has_features :manages_members
|
7
8
|
|
8
|
-
"
|
9
|
-
|
10
|
-
commands :pw => "/usr/sbin/pw"
|
11
9
|
defaultfor :operatingsystem => :freebsd
|
12
10
|
|
11
|
+
options :members, :flag => "-M", :method => :mem
|
12
|
+
|
13
13
|
verify :gid, "GID must be an integer" do |value|
|
14
14
|
value.is_a? Integer
|
15
15
|
end
|
16
16
|
|
17
17
|
def addcmd
|
18
18
|
cmd = [command(:pw), "groupadd", @resource[:name]]
|
19
|
+
|
19
20
|
if gid = @resource.should(:gid)
|
20
21
|
unless gid == :absent
|
21
22
|
cmd << flag(:gid) << gid
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
if members = @resource.should(:members)
|
27
|
+
unless members == :absent
|
28
|
+
if members.is_a?(Array)
|
29
|
+
members = members.join(",")
|
30
|
+
end
|
31
|
+
cmd << "-M" << members
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
cmd << "-o" if @resource.allowdupe?
|
30
36
|
|
31
37
|
cmd
|
32
38
|
end
|
39
|
+
|
40
|
+
def modifycmd(param, value)
|
41
|
+
# members may be an array, need a comma separated list
|
42
|
+
if param == :members and value.is_a?(Array)
|
43
|
+
value = value.join(",")
|
44
|
+
end
|
45
|
+
super(param, value)
|
46
|
+
end
|
33
47
|
end
|
34
48
|
|
@@ -2,7 +2,7 @@ require 'puppet'
|
|
2
2
|
require 'puppet/provider/nameservice'
|
3
3
|
require 'facter/util/plist'
|
4
4
|
require 'cgi'
|
5
|
-
|
5
|
+
require 'fileutils'
|
6
6
|
|
7
7
|
class Puppet::Provider::NameService
|
8
8
|
class DirectoryService < Puppet::Provider::NameService
|
@@ -21,6 +21,7 @@ class DirectoryService < Puppet::Provider::NameService
|
|
21
21
|
commands :dscl => "/usr/bin/dscl"
|
22
22
|
commands :dseditgroup => "/usr/sbin/dseditgroup"
|
23
23
|
commands :sw_vers => "/usr/bin/sw_vers"
|
24
|
+
commands :plutil => '/usr/bin/plutil'
|
24
25
|
confine :operatingsystem => :darwin
|
25
26
|
defaultfor :operatingsystem => :darwin
|
26
27
|
|
@@ -60,6 +61,8 @@ class DirectoryService < Puppet::Provider::NameService
|
|
60
61
|
}
|
61
62
|
|
62
63
|
@@password_hash_dir = "/var/db/shadow/hash"
|
64
|
+
@@users_plist_dir = '/var/db/dslocal/nodes/Default/users'
|
65
|
+
|
63
66
|
|
64
67
|
def self.instances
|
65
68
|
# JJM Class method that provides an array of instance objects of this
|
@@ -193,7 +196,7 @@ class DirectoryService < Puppet::Provider::NameService
|
|
193
196
|
# stored in the user record. It is stored at a path that involves the
|
194
197
|
# UUID of the user record for non-Mobile local acccounts.
|
195
198
|
# Mobile Accounts are out of scope for this provider for now
|
196
|
-
attribute_hash[:password] = self.get_password(attribute_hash[:guid]) if @resource_type.validproperties.include?(:password) and Puppet.features.root?
|
199
|
+
attribute_hash[:password] = self.get_password(attribute_hash[:guid], attribute_hash[:name]) if @resource_type.validproperties.include?(:password) and Puppet.features.root?
|
197
200
|
attribute_hash
|
198
201
|
end
|
199
202
|
|
@@ -268,46 +271,144 @@ class DirectoryService < Puppet::Provider::NameService
|
|
268
271
|
end
|
269
272
|
|
270
273
|
def self.set_password(resource_name, guid, password_hash)
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
274
|
+
# Use Puppet::Util::Package.versioncmp() to catch the scenario where a
|
275
|
+
# version '10.10' would be < '10.7' with simple string comparison. This
|
276
|
+
# if-statement only executes if the current version is less-than 10.7
|
277
|
+
if (Puppet::Util::Package.versioncmp(get_macosx_version_major, '10.7') == -1)
|
278
|
+
password_hash_file = "#{@@password_hash_dir}/#{guid}"
|
279
|
+
begin
|
280
|
+
File.open(password_hash_file, 'w') { |f| f.write(password_hash)}
|
281
|
+
rescue Errno::EACCES => detail
|
282
|
+
fail("Could not write to password hash file: #{detail}")
|
283
|
+
end
|
284
|
+
|
285
|
+
# NBK: For shadow hashes, the user AuthenticationAuthority must contain a value of
|
286
|
+
# ";ShadowHash;". The LKDC in 10.5 makes this more interesting though as it
|
287
|
+
# will dynamically generate ;Kerberosv5;;username@LKDC:SHA1 attributes if
|
288
|
+
# missing. Thus we make sure we only set ;ShadowHash; if it is missing, and
|
289
|
+
# we can do this with the merge command. This allows people to continue to
|
290
|
+
# use other custom AuthenticationAuthority attributes without stomping on them.
|
291
|
+
#
|
292
|
+
# There is a potential problem here in that we're only doing this when setting
|
293
|
+
# the password, and the attribute could get modified at other times while the
|
294
|
+
# hash doesn't change and so this doesn't get called at all... but
|
295
|
+
# without switching all the other attributes to merge instead of create I can't
|
296
|
+
# see a simple enough solution for this that doesn't modify the user record
|
297
|
+
# every single time. This should be a rather rare edge case. (famous last words)
|
298
|
+
|
299
|
+
dscl_vector = self.get_exec_preamble("-merge", resource_name)
|
300
|
+
dscl_vector << "AuthenticationAuthority" << ";ShadowHash;"
|
301
|
+
begin
|
302
|
+
dscl_output = execute(dscl_vector)
|
303
|
+
rescue Puppet::ExecutionFailure => detail
|
304
|
+
fail("Could not set AuthenticationAuthority.")
|
305
|
+
end
|
306
|
+
else
|
307
|
+
# 10.7 uses salted SHA512 password hashes which are 128 characters plus
|
308
|
+
# an 8 character salt. Previous versions used a SHA1 hash padded with
|
309
|
+
# zeroes. If someone attempts to use a password hash that worked with
|
310
|
+
# a previous version of OX X, we will fail early and warn them.
|
311
|
+
if password_hash.length != 136
|
312
|
+
fail("OS X 10.7 requires a Salted SHA512 hash password of 136 characters. \
|
313
|
+
Please check your password and try again.")
|
314
|
+
end
|
315
|
+
|
316
|
+
if File.exists?("#{@@users_plist_dir}/#{resource_name}.plist")
|
317
|
+
# If a plist already exists in /var/db/dslocal/nodes/Default/users, then
|
318
|
+
# we will need to extract the binary plist from the 'ShadowHashData'
|
319
|
+
# key, log the new password into the resultant plist's 'SALTED-SHA512'
|
320
|
+
# key, and then save the entire structure back.
|
321
|
+
users_plist = Plist::parse_xml(plutil( '-convert', 'xml1', '-o', '/dev/stdout', \
|
322
|
+
"#{@@users_plist_dir}/#{resource_name}.plist"))
|
323
|
+
|
324
|
+
# users_plist['ShadowHashData'][0].string is actually a binary plist
|
325
|
+
# that's nested INSIDE the user's plist (which itself is a binary
|
326
|
+
# plist).
|
327
|
+
password_hash_plist = users_plist['ShadowHashData'][0].string
|
328
|
+
converted_hash_plist = convert_binary_to_xml(password_hash_plist)
|
329
|
+
|
330
|
+
# converted_hash_plist['SALTED-SHA512'].string expects a Base64 encoded
|
331
|
+
# string. The password_hash provided as a resource attribute is a
|
332
|
+
# hex value. We need to convert the provided hex value to a Base64
|
333
|
+
# encoded string to nest it in the converted hash plist.
|
334
|
+
converted_hash_plist['SALTED-SHA512'].string = \
|
335
|
+
password_hash.unpack('a2'*(password_hash.size/2)).collect { |i| i.hex.chr }.join
|
336
|
+
|
337
|
+
# Finally, we can convert the nested plist back to binary, embed it
|
338
|
+
# into the user's plist, and convert the resultant plist back to
|
339
|
+
# a binary plist.
|
340
|
+
changed_plist = convert_xml_to_binary(converted_hash_plist)
|
341
|
+
users_plist['ShadowHashData'][0].string = changed_plist
|
342
|
+
Plist::Emit.save_plist(users_plist, "#{@@users_plist_dir}/#{resource_name}.plist")
|
343
|
+
plutil('-convert', 'binary1', "#{@@users_plist_dir}/#{resource_name}.plist")
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
def self.get_password(guid, username)
|
349
|
+
# Use Puppet::Util::Package.versioncmp() to catch the scenario where a
|
350
|
+
# version '10.10' would be < '10.7' with simple string comparison. This
|
351
|
+
# if-statement only executes if the current version is less-than 10.7
|
352
|
+
if (Puppet::Util::Package.versioncmp(get_macosx_version_major, '10.7') == -1)
|
353
|
+
password_hash = nil
|
354
|
+
password_hash_file = "#{@@password_hash_dir}/#{guid}"
|
355
|
+
if File.exists?(password_hash_file) and File.file?(password_hash_file)
|
356
|
+
fail("Could not read password hash file at #{password_hash_file}") if not File.readable?(password_hash_file)
|
357
|
+
f = File.new(password_hash_file)
|
358
|
+
password_hash = f.read
|
359
|
+
f.close
|
360
|
+
end
|
361
|
+
password_hash
|
362
|
+
else
|
363
|
+
if File.exists?("#{@@users_plist_dir}/#{username}.plist")
|
364
|
+
# If a plist exists in /var/db/dslocal/nodes/Default/users, we will
|
365
|
+
# extract the binary plist from the 'ShadowHashData' key, decode the
|
366
|
+
# salted-SHA512 password hash, and then return it.
|
367
|
+
users_plist = Plist::parse_xml(plutil('-convert', 'xml1', '-o', '/dev/stdout', "#{@@users_plist_dir}/#{username}.plist"))
|
368
|
+
if users_plist['ShadowHashData']
|
369
|
+
# users_plist['ShadowHashData'][0].string is actually a binary plist
|
370
|
+
# that's nested INSIDE the user's plist (which itself is a binary
|
371
|
+
# plist).
|
372
|
+
password_hash_plist = users_plist['ShadowHashData'][0].string
|
373
|
+
converted_hash_plist = convert_binary_to_xml(password_hash_plist)
|
374
|
+
|
375
|
+
# converted_hash_plist['SALTED-SHA512'].string is a Base64 encoded
|
376
|
+
# string. The password_hash provided as a resource attribute is a
|
377
|
+
# hex value. We need to convert the Base64 encoded string to a
|
378
|
+
# hex value and provide it back to Puppet.
|
379
|
+
password_hash = converted_hash_plist['SALTED-SHA512'].string.unpack("H*")[0]
|
380
|
+
password_hash
|
381
|
+
end
|
382
|
+
end
|
276
383
|
end
|
384
|
+
end
|
277
385
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
# hash doesn't change and so this doesn't get called at all... but
|
288
|
-
# without switching all the other attributes to merge instead of create I can't
|
289
|
-
# see a simple enough solution for this that doesn't modify the user record
|
290
|
-
# every single time. This should be a rather rare edge case. (famous last words)
|
291
|
-
|
292
|
-
dscl_vector = self.get_exec_preamble("-merge", resource_name)
|
293
|
-
dscl_vector << "AuthenticationAuthority" << ";ShadowHash;"
|
294
|
-
begin
|
295
|
-
dscl_output = execute(dscl_vector)
|
296
|
-
rescue Puppet::ExecutionFailure => detail
|
297
|
-
fail("Could not set AuthenticationAuthority.")
|
386
|
+
# This method will accept a hash that has been returned from Plist::parse_xml
|
387
|
+
# and convert it to a binary plist (string value).
|
388
|
+
def self.convert_xml_to_binary(plist_data)
|
389
|
+
Puppet.debug('Converting XML plist to binary')
|
390
|
+
Puppet.debug('Executing: \'plutil -convert binary1 -o - -\'')
|
391
|
+
IO.popen('plutil -convert binary1 -o - -', mode='r+') do |io|
|
392
|
+
io.write plist_data.to_plist
|
393
|
+
io.close_write
|
394
|
+
@converted_plist = io.read
|
298
395
|
end
|
396
|
+
@converted_plist
|
299
397
|
end
|
300
398
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
399
|
+
# This method will accept a binary plist (as a string) and convert it to a
|
400
|
+
# hash via Plist::parse_xml.
|
401
|
+
def self.convert_binary_to_xml(plist_data)
|
402
|
+
Puppet.debug('Converting binary plist to XML')
|
403
|
+
Puppet.debug('Executing: \'plutil -convert xml1 -o - -\'')
|
404
|
+
IO.popen('plutil -convert xml1 -o - -', mode='r+') do |io|
|
405
|
+
io.write plist_data
|
406
|
+
io.close_write
|
407
|
+
@converted_plist = io.read
|
309
408
|
end
|
310
|
-
|
409
|
+
Puppet.debug('Converting XML values to a hash.')
|
410
|
+
@plist_hash = Plist::parse_xml(@converted_plist)
|
411
|
+
@plist_hash
|
311
412
|
end
|
312
413
|
|
313
414
|
# Unlike most other *nixes, OS X doesn't provide built in functionality
|
@@ -468,7 +569,14 @@ class DirectoryService < Puppet::Provider::NameService
|
|
468
569
|
begin
|
469
570
|
execute(cmd)
|
470
571
|
rescue Puppet::ExecutionFailure => detail
|
471
|
-
|
572
|
+
# TODO: We're falling back to removing the member using dscl due to rdar://8481241
|
573
|
+
# This bug causes dseditgroup to fail to remove a member if that member doesn't exist
|
574
|
+
cmd = [:dscl, ".", "-delete", "/Groups/#{@resource.name}", "GroupMembership", member]
|
575
|
+
begin
|
576
|
+
execute(cmd)
|
577
|
+
rescue Puppet::ExecutionFailure => detail
|
578
|
+
fail("Could not remove #{member} from group: #{@resource.name}, #{detail}")
|
579
|
+
end
|
472
580
|
end
|
473
581
|
end
|
474
582
|
end
|
@@ -535,3 +643,4 @@ class DirectoryService < Puppet::Provider::NameService
|
|
535
643
|
end
|
536
644
|
end
|
537
645
|
end
|
646
|
+
|
@@ -56,7 +56,6 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
|
56
56
|
wanted = @resource[:name]
|
57
57
|
operation = :install
|
58
58
|
|
59
|
-
# XXX: We don't actually deal with epochs here.
|
60
59
|
case should
|
61
60
|
when true, false, Symbol
|
62
61
|
# pass
|
@@ -87,7 +86,7 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
|
|
87
86
|
unless upd.nil?
|
88
87
|
# FIXME: there could be more than one update for a package
|
89
88
|
# because of multiarch
|
90
|
-
return "#{upd[:version]}-#{upd[:release]}"
|
89
|
+
return "#{upd[:epoch]}:#{upd[:version]}-#{upd[:release]}"
|
91
90
|
else
|
92
91
|
# Yum didn't find updates, pretend the current
|
93
92
|
# version is the latest
|
@@ -42,11 +42,25 @@ Puppet::Type.type(:service).provide :debian, :parent => :init do
|
|
42
42
|
# See x-man-page://invoke-rc.d
|
43
43
|
if [104, 106].include?($CHILD_STATUS.exitstatus)
|
44
44
|
return :true
|
45
|
+
elsif [105].include?($CHILD_STATUS.exitstatus)
|
46
|
+
# 105 is unknown, which generally means the the iniscript does not support query
|
47
|
+
# The debian policy states that the initscript should support methods of query
|
48
|
+
# For those that do not, peform the checks manually
|
49
|
+
# http://www.debian.org/doc/debian-policy/ch-opersys.html
|
50
|
+
if get_start_link_count >= 4
|
51
|
+
return :true
|
52
|
+
else
|
53
|
+
return :false
|
54
|
+
end
|
45
55
|
else
|
46
56
|
return :false
|
47
57
|
end
|
48
58
|
end
|
49
59
|
|
60
|
+
def get_start_link_count
|
61
|
+
Dir.glob("/etc/rc*.d/S*#{@resource[:name]}").length
|
62
|
+
end
|
63
|
+
|
50
64
|
def enable
|
51
65
|
update_rc "-f", @resource[:name], "remove"
|
52
66
|
update_rc @resource[:name], "defaults"
|
@@ -196,7 +196,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
|
|
196
196
|
did_enable_job = false
|
197
197
|
cmds = []
|
198
198
|
cmds << :launchctl << :load
|
199
|
-
if self.enabled? == :false # launchctl won't load disabled jobs
|
199
|
+
if self.enabled? == :false || self.status == :stopped # launchctl won't load disabled jobs
|
200
200
|
cmds << "-w"
|
201
201
|
did_enable_job = true
|
202
202
|
end
|
@@ -58,7 +58,7 @@ Puppet::Type.type(:service).provide :smf, :parent => :base do
|
|
58
58
|
when :maintenance
|
59
59
|
[command(:adm), :clear, @resource[:name]]
|
60
60
|
else
|
61
|
-
[command(:adm), :enable, @resource[:name]]
|
61
|
+
[command(:adm), :enable, "-s", @resource[:name]]
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -98,7 +98,7 @@ Puppet::Type.type(:service).provide :smf, :parent => :base do
|
|
98
98
|
end
|
99
99
|
|
100
100
|
def stopcmd
|
101
|
-
[command(:adm), :disable, @resource[:name]]
|
101
|
+
[command(:adm), :disable, "-s", @resource[:name]]
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -1,16 +1,18 @@
|
|
1
1
|
require 'puppet/provider/nameservice/pw'
|
2
|
+
require 'open3'
|
2
3
|
|
3
4
|
Puppet::Type.type(:user).provide :pw, :parent => Puppet::Provider::NameService::PW do
|
4
5
|
desc "User management via `pw` on FreeBSD."
|
5
6
|
|
6
7
|
commands :pw => "pw"
|
7
|
-
has_features :manages_homedir, :allows_duplicates
|
8
|
+
has_features :manages_homedir, :allows_duplicates, :manages_passwords, :manages_expiry
|
8
9
|
|
9
10
|
defaultfor :operatingsystem => :freebsd
|
10
11
|
|
11
12
|
options :home, :flag => "-d", :method => :dir
|
12
13
|
options :comment, :method => :gecos
|
13
14
|
options :groups, :flag => "-G"
|
15
|
+
options :expiry, :method => :expire
|
14
16
|
|
15
17
|
verify :gid, "GID must be an integer" do |value|
|
16
18
|
value.is_a? Integer
|
@@ -23,10 +25,14 @@ Puppet::Type.type(:user).provide :pw, :parent => Puppet::Provider::NameService::
|
|
23
25
|
def addcmd
|
24
26
|
cmd = [command(:pw), "useradd", @resource[:name]]
|
25
27
|
@resource.class.validproperties.each do |property|
|
26
|
-
next if property == :ensure
|
28
|
+
next if property == :ensure or property == :password
|
27
29
|
# the value needs to be quoted, mostly because -c might
|
28
30
|
# have spaces in it
|
29
31
|
if value = @resource.should(property) and value != ""
|
32
|
+
if property == :expiry
|
33
|
+
# FreeBSD uses DD-MM-YYYY rather than YYYY-MM-DD
|
34
|
+
value = value.split("-").reverse.join("-")
|
35
|
+
end
|
30
36
|
cmd << flag(property) << value
|
31
37
|
end
|
32
38
|
end
|
@@ -37,5 +43,53 @@ Puppet::Type.type(:user).provide :pw, :parent => Puppet::Provider::NameService::
|
|
37
43
|
|
38
44
|
cmd
|
39
45
|
end
|
46
|
+
|
47
|
+
def modifycmd(param, value)
|
48
|
+
if param == :expiry
|
49
|
+
# FreeBSD uses DD-MM-YYYY rather than YYYY-MM-DD
|
50
|
+
value = value.split("-").reverse.join("-")
|
51
|
+
end
|
52
|
+
cmd = super(param, value)
|
53
|
+
cmd << "-m" if @resource.managehome?
|
54
|
+
cmd
|
55
|
+
end
|
56
|
+
|
57
|
+
def create
|
58
|
+
super
|
59
|
+
|
60
|
+
# Set the password after create if given
|
61
|
+
self.password = @resource[:password] if @resource[:password]
|
62
|
+
end
|
63
|
+
|
64
|
+
# use pw to update password hash
|
65
|
+
def password=(cryptopw)
|
66
|
+
Puppet.debug "change password for user '#{@resource[:name]}' method called with hash '#{cryptopw}'"
|
67
|
+
stdin, stdout, stderr = Open3.popen3("pw user mod #{@resource[:name]} -H 0")
|
68
|
+
stdin.puts(cryptopw)
|
69
|
+
stdin.close
|
70
|
+
Puppet.debug "finished password for user '#{@resource[:name]}' method called with hash '#{cryptopw}'"
|
71
|
+
end
|
72
|
+
|
73
|
+
# get password from /etc/master.passwd
|
74
|
+
def password
|
75
|
+
Puppet.debug "checking password for user '#{@resource[:name]}' method called"
|
76
|
+
current_passline = `getent passwd #{@resource[:name]}`
|
77
|
+
current_password = current_passline.chomp.split(':')[1] if current_passline
|
78
|
+
Puppet.debug "finished password for user '#{@resource[:name]}' method called : '#{current_password}'"
|
79
|
+
current_password
|
80
|
+
end
|
81
|
+
|
82
|
+
# Get expiry from system and convert to Puppet-style date
|
83
|
+
def expiry
|
84
|
+
expiry = self.get(:expiry)
|
85
|
+
expiry = :absent if expiry == 0
|
86
|
+
|
87
|
+
if expiry != :absent
|
88
|
+
t = Time.at(expiry)
|
89
|
+
expiry = "%4d-%02d-%02d" % [t.year, t.month, t.mday]
|
90
|
+
end
|
91
|
+
|
92
|
+
expiry
|
93
|
+
end
|
40
94
|
end
|
41
95
|
|