puppet 2.7.6 → 2.7.8
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 +168 -0
- data/conf/auth.conf +5 -4
- data/conf/redhat/puppet.spec +16 -1
- data/conf/solaris/pkginfo +2 -2
- data/conf/suse/puppet.spec +9 -3
- data/ext/upload_facts.rb +120 -0
- data/install.rb +11 -16
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application/agent.rb +0 -3
- data/lib/puppet/application/apply.rb +0 -3
- data/lib/puppet/application/queue.rb +21 -1
- data/lib/puppet/defaults.rb +6 -4
- data/lib/puppet/face/file/store.rb +1 -1
- data/lib/puppet/feature/base.rb +2 -1
- data/lib/puppet/file_bucket/dipper.rb +3 -2
- data/lib/puppet/file_serving/content.rb +1 -1
- data/lib/puppet/file_serving/metadata.rb +5 -2
- data/lib/puppet/indirector/facts/inventory_service.rb +20 -0
- data/lib/puppet/indirector/file_bucket_file/file.rb +3 -2
- data/lib/puppet/indirector/report/processor.rb +1 -1
- data/lib/puppet/network/handler/filebucket.rb +2 -0
- data/lib/puppet/network/handler/fileserver.rb +1 -1
- data/lib/puppet/network/handler/master.rb +1 -0
- data/lib/puppet/network/handler/report.rb +2 -0
- data/lib/puppet/network/handler/runner.rb +1 -0
- data/lib/puppet/network/handler/status.rb +2 -0
- data/lib/puppet/network/http/mongrel/rest.rb +8 -1
- data/lib/puppet/network/http_server.rb +3 -0
- data/lib/puppet/network/http_server/mongrel.rb +129 -0
- data/lib/puppet/network/rest_authconfig.rb +12 -4
- data/lib/puppet/parameter.rb +18 -0
- data/lib/puppet/parser/compiler.rb +1 -1
- data/lib/puppet/parser/grammar.ra +1 -1
- data/lib/puppet/parser/parser.rb +360 -350
- data/lib/puppet/property.rb +3 -3
- data/lib/puppet/provider/augeas/augeas.rb +1 -1
- data/lib/puppet/provider/exec/windows.rb +6 -7
- data/lib/puppet/provider/file/windows.rb +9 -2
- data/lib/puppet/provider/group/aix.rb +8 -8
- data/lib/puppet/provider/group/groupadd.rb +1 -3
- data/lib/puppet/provider/group/ldap.rb +8 -10
- data/lib/puppet/provider/group/windows_adsi.rb +8 -2
- data/lib/puppet/provider/package/aix.rb +1 -1
- data/lib/puppet/provider/package/macports.rb +3 -3
- data/lib/puppet/provider/package/msi.rb +12 -5
- data/lib/puppet/provider/package/nim.rb +1 -1
- data/lib/puppet/provider/package/pkgdmg.rb +3 -3
- data/lib/puppet/provider/package/ports.rb +1 -1
- data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +560 -0
- data/lib/puppet/provider/service/base.rb +2 -2
- data/lib/puppet/provider/service/bsd.rb +4 -3
- data/lib/puppet/provider/service/daemontools.rb +25 -25
- data/lib/puppet/provider/service/debian.rb +6 -4
- data/lib/puppet/provider/service/freebsd.rb +1 -1
- data/lib/puppet/provider/service/gentoo.rb +4 -3
- data/lib/puppet/provider/service/init.rb +3 -8
- data/lib/puppet/provider/service/launchd.rb +129 -96
- data/lib/puppet/provider/service/redhat.rb +2 -3
- data/lib/puppet/provider/service/runit.rb +20 -20
- data/lib/puppet/provider/service/smf.rb +8 -7
- data/lib/puppet/provider/service/src.rb +5 -6
- data/lib/puppet/provider/service/systemd.rb +1 -1
- data/lib/puppet/provider/service/upstart.rb +3 -5
- data/lib/puppet/provider/service/windows.rb +7 -7
- data/lib/puppet/provider/sshkey/parsed.rb +2 -3
- data/lib/puppet/provider/user/aix.rb +21 -21
- data/lib/puppet/provider/user/hpux.rb +3 -1
- data/lib/puppet/provider/user/ldap.rb +7 -7
- data/lib/puppet/provider/user/user_role_add.rb +10 -6
- data/lib/puppet/provider/user/useradd.rb +3 -1
- data/lib/puppet/provider/user/windows_adsi.rb +4 -3
- data/lib/puppet/rb_tree_map.rb +388 -0
- data/lib/puppet/reference/configuration.rb +7 -7
- data/lib/puppet/reference/indirection.rb +5 -6
- data/lib/puppet/reference/metaparameter.rb +3 -1
- data/lib/puppet/reference/network.rb +8 -8
- data/lib/puppet/reference/providers.rb +17 -21
- data/lib/puppet/reference/type.rb +12 -9
- data/lib/puppet/resource.rb +2 -5
- data/lib/puppet/resource/catalog.rb +1 -1
- data/lib/puppet/ssl/certificate_request.rb +70 -0
- data/lib/puppet/ssl/host.rb +6 -0
- data/lib/puppet/transaction.rb +158 -55
- data/lib/puppet/transaction/event_manager.rb +1 -1
- data/lib/puppet/type.rb +60 -30
- data/lib/puppet/type/augeas.rb +83 -49
- data/lib/puppet/type/computer.rb +1 -1
- data/lib/puppet/type/cron.rb +11 -11
- data/lib/puppet/type/exec.rb +28 -21
- data/lib/puppet/type/file.rb +17 -7
- data/lib/puppet/type/file/content.rb +2 -2
- data/lib/puppet/type/file/ensure.rb +15 -12
- data/lib/puppet/type/file/mode.rb +30 -5
- data/lib/puppet/type/file/source.rb +11 -10
- data/lib/puppet/type/file/target.rb +2 -2
- data/lib/puppet/type/filebucket.rb +1 -1
- data/lib/puppet/type/group.rb +4 -5
- data/lib/puppet/type/host.rb +1 -1
- data/lib/puppet/type/interface.rb +13 -10
- data/lib/puppet/type/k5login.rb +6 -6
- data/lib/puppet/type/macauthorization.rb +37 -36
- data/lib/puppet/type/maillist.rb +2 -2
- data/lib/puppet/type/mcx.rb +6 -6
- data/lib/puppet/type/mount.rb +3 -2
- data/lib/puppet/type/notify.rb +1 -1
- data/lib/puppet/type/package.rb +24 -23
- data/lib/puppet/type/router.rb +4 -1
- data/lib/puppet/type/schedule.rb +52 -44
- data/lib/puppet/type/scheduled_task.rb +222 -0
- data/lib/puppet/type/selmodule.rb +10 -6
- data/lib/puppet/type/service.rb +11 -11
- data/lib/puppet/type/ssh_authorized_key.rb +2 -5
- data/lib/puppet/type/sshkey.rb +1 -1
- data/lib/puppet/type/stage.rb +1 -1
- data/lib/puppet/type/tidy.rb +10 -8
- data/lib/puppet/type/user.rb +61 -53
- data/lib/puppet/type/vlan.rb +4 -4
- data/lib/puppet/type/whit.rb +6 -2
- data/lib/puppet/type/yumrepo.rb +33 -31
- data/lib/puppet/type/zfs.rb +34 -32
- data/lib/puppet/type/zone.rb +21 -19
- data/lib/puppet/type/zpool.rb +3 -3
- data/lib/puppet/util.rb +24 -6
- data/lib/puppet/util/adsi.rb +12 -7
- data/lib/puppet/util/checksums.rb +1 -1
- data/lib/puppet/util/diff.rb +1 -1
- data/lib/puppet/util/nagios_maker.rb +2 -2
- data/lib/puppet/util/reference.rb +16 -17
- data/lib/puppet/util/settings/file_setting.rb +14 -2
- data/lib/puppet/util/windows/security.rb +96 -32
- data/spec/integration/file_serving/terminus_helper_spec.rb +1 -1
- data/spec/integration/indirector/direct_file_server_spec.rb +9 -15
- data/spec/integration/indirector/file_content/file_server_spec.rb +1 -1
- data/spec/integration/indirector/file_metadata/file_server_spec.rb +1 -1
- data/spec/integration/provider/package_spec.rb +4 -0
- data/spec/integration/provider/service/init_spec.rb +8 -2
- data/spec/integration/reference/providers_spec.rb +1 -1
- data/spec/integration/ssl/certificate_request_spec.rb +1 -2
- data/spec/integration/ssl/certificate_revocation_list_spec.rb +1 -2
- data/spec/integration/ssl/host_spec.rb +1 -2
- data/spec/integration/transaction_spec.rb +25 -17
- data/spec/integration/type/exec_spec.rb +77 -0
- data/spec/integration/type/file_spec.rb +322 -2
- data/spec/integration/util/windows/security_spec.rb +393 -230
- data/spec/integration/util_spec.rb +16 -0
- data/spec/lib/puppet_spec/files.rb +3 -7
- data/spec/unit/application/apply_spec.rb +0 -9
- data/spec/unit/application/inspect_spec.rb +1 -0
- data/spec/unit/configurer/downloader_spec.rb +3 -3
- data/spec/unit/face/certificate_spec.rb +6 -2
- data/spec/unit/file_bucket/dipper_spec.rb +67 -10
- data/spec/unit/file_bucket/file_spec.rb +22 -28
- data/spec/unit/file_serving/content_spec.rb +1 -1
- data/spec/unit/file_serving/metadata_spec.rb +30 -3
- data/spec/unit/indirector/facts/inventory_service_spec.rb +22 -0
- data/spec/unit/indirector/file_bucket_file/file_spec.rb +21 -24
- data/spec/unit/indirector/node/store_configs_spec.rb +1 -0
- data/spec/unit/indirector/resource/ral_spec.rb +1 -1
- data/spec/unit/indirector/resource_type/parser_spec.rb +2 -2
- data/spec/unit/indirector/rest_spec.rb +1 -1
- data/spec/unit/network/handler/ca_spec.rb +1 -1
- data/spec/unit/network/http/mongrel/rest_spec.rb +54 -25
- data/spec/unit/parameter_spec.rb +36 -0
- data/spec/unit/parser/parser_spec.rb +4 -0
- data/spec/unit/property_spec.rb +2 -2
- data/spec/unit/provider/exec/windows_spec.rb +2 -8
- data/spec/unit/provider/file/posix_spec.rb +6 -0
- data/spec/unit/provider/file/windows_spec.rb +18 -0
- data/spec/unit/provider/group/windows_adsi_spec.rb +22 -6
- data/spec/unit/provider/mount/parsed_spec.rb +1 -1
- data/spec/unit/provider/package/msi_spec.rb +2 -2
- data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +1571 -0
- data/spec/unit/provider/service/launchd_spec.rb +143 -130
- data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +5 -0
- data/spec/unit/provider/user/user_role_add_spec.rb +39 -9
- data/spec/unit/provider/user/useradd_spec.rb +1 -1
- data/spec/unit/provider/user/windows_adsi_spec.rb +8 -1
- data/spec/unit/rb_tree_map_spec.rb +572 -0
- data/spec/unit/resource/catalog_spec.rb +1 -1
- data/spec/unit/simple_graph_spec.rb +9 -9
- data/spec/unit/ssl/host_spec.rb +60 -12
- data/spec/unit/transaction/report_spec.rb +3 -3
- data/spec/unit/transaction_spec.rb +394 -11
- data/spec/unit/type/exec_spec.rb +35 -15
- data/spec/unit/type/file/content_spec.rb +11 -10
- data/spec/unit/type/file/mode_spec.rb +73 -19
- data/spec/unit/type/file/source_spec.rb +1 -1
- data/spec/unit/type/file_spec.rb +15 -0
- data/spec/unit/type/group_spec.rb +1 -1
- data/spec/unit/type/mount_spec.rb +5 -5
- data/spec/unit/type/resources_spec.rb +3 -3
- data/spec/unit/type/scheduled_task_spec.rb +102 -0
- data/spec/unit/type/ssh_authorized_key_spec.rb +2 -3
- data/spec/unit/type/user_spec.rb +2 -1
- data/spec/unit/type_spec.rb +48 -4
- data/spec/unit/util/adsi_spec.rb +18 -7
- data/spec/unit/util/checksums_spec.rb +20 -2
- data/spec/unit/util/execution_stub_spec.rb +10 -5
- data/spec/unit/util/logging_spec.rb +6 -6
- data/spec/unit/util/rdoc/parser_spec.rb +1 -1
- data/spec/unit/util/reference_spec.rb +29 -0
- data/spec/unit/util/settings/file_setting_spec.rb +8 -2
- data/spec/unit/util_spec.rb +115 -0
- data/test/other/transactions.rb +5 -11
- data/test/ral/type/exec.rb +1 -1
- metadata +24 -11
data/lib/puppet/type/zpool.rb
CHANGED
@@ -37,7 +37,7 @@ module Puppet
|
|
37
37
|
ensurable
|
38
38
|
|
39
39
|
newproperty(:disk, :array_matching => :all, :parent => Puppet::Property::VDev) do
|
40
|
-
desc "The disk(s) for this pool. Can be an array or space separated string"
|
40
|
+
desc "The disk(s) for this pool. Can be an array or a space separated string."
|
41
41
|
end
|
42
42
|
|
43
43
|
newproperty(:mirror, :array_matching => :all, :parent => Puppet::Property::MultiVDev) do
|
@@ -71,7 +71,7 @@ module Puppet
|
|
71
71
|
end
|
72
72
|
|
73
73
|
newproperty(:log, :array_matching => :all, :parent => Puppet::Property::VDev) do
|
74
|
-
desc "Log disks for this pool.
|
74
|
+
desc "Log disks for this pool. This type does not currently support mirroring of log disks."
|
75
75
|
end
|
76
76
|
|
77
77
|
newparam(:pool) do
|
@@ -80,7 +80,7 @@ module Puppet
|
|
80
80
|
end
|
81
81
|
|
82
82
|
newparam(:raid_parity) do
|
83
|
-
desc "Determines parity when using raidz
|
83
|
+
desc "Determines parity when using the `raidz` parameter."
|
84
84
|
end
|
85
85
|
|
86
86
|
validate do
|
data/lib/puppet/util.rb
CHANGED
@@ -191,7 +191,15 @@ module Util
|
|
191
191
|
return bin if FileTest.file? bin and FileTest.executable? bin
|
192
192
|
else
|
193
193
|
ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
|
194
|
-
dest=File.join(dir, bin)
|
194
|
+
dest = File.expand_path(File.join(dir, bin))
|
195
|
+
if Puppet.features.microsoft_windows? && File.extname(dest).empty?
|
196
|
+
exts = ENV['PATHEXT']
|
197
|
+
exts = exts ? exts.split(File::PATH_SEPARATOR) : %w[.COM .EXE .BAT .CMD]
|
198
|
+
exts.each do |ext|
|
199
|
+
destext = File.expand_path(dest + ext)
|
200
|
+
return destext if FileTest.file? destext and FileTest.executable? destext
|
201
|
+
end
|
202
|
+
end
|
195
203
|
return dest if FileTest.file? dest and FileTest.executable? dest
|
196
204
|
end
|
197
205
|
end
|
@@ -355,17 +363,21 @@ module Util
|
|
355
363
|
stdout = arguments[:squelch] ? File.open(null_file, 'w') : Tempfile.new('puppet')
|
356
364
|
stderr = arguments[:combine] ? stdout : File.open(null_file, 'w')
|
357
365
|
|
358
|
-
|
359
366
|
exec_args = [command, arguments, stdin, stdout, stderr]
|
360
367
|
|
361
368
|
if execution_stub = Puppet::Util::ExecutionStub.current_value
|
362
369
|
return execution_stub.call(*exec_args)
|
363
370
|
elsif Puppet.features.posix?
|
364
371
|
child_pid = execute_posix(*exec_args)
|
365
|
-
|
372
|
+
exit_status = Process.waitpid2(child_pid).last.exitstatus
|
366
373
|
elsif Puppet.features.microsoft_windows?
|
367
374
|
child_pid = execute_windows(*exec_args)
|
368
|
-
|
375
|
+
exit_status = Process.waitpid2(child_pid).last
|
376
|
+
# $CHILD_STATUS is not set when calling win32/process Process.create
|
377
|
+
# and since it's read-only, we can't set it. But we can execute a
|
378
|
+
# a shell that simply returns the desired exit status, which has the
|
379
|
+
# desired effect.
|
380
|
+
%x{#{ENV['COMSPEC']} /c exit #{exit_status}}
|
369
381
|
end
|
370
382
|
|
371
383
|
[stdin, stdout, stderr].each {|io| io.close rescue nil}
|
@@ -376,8 +388,8 @@ module Util
|
|
376
388
|
Puppet.warning "Could not get output" unless output
|
377
389
|
end
|
378
390
|
|
379
|
-
if arguments[:failonfail] and
|
380
|
-
raise ExecutionFailure, "Execution of '#{str}' returned #{
|
391
|
+
if arguments[:failonfail] and exit_status != 0
|
392
|
+
raise ExecutionFailure, "Execution of '#{str}' returned #{exit_status}: #{output}"
|
381
393
|
end
|
382
394
|
|
383
395
|
output
|
@@ -490,6 +502,12 @@ module Util
|
|
490
502
|
end
|
491
503
|
end
|
492
504
|
module_function :secure_open
|
505
|
+
|
506
|
+
# Because IO#binread is only available in 1.9
|
507
|
+
def binread(file)
|
508
|
+
File.open(file, 'rb') { |f| f.read }
|
509
|
+
end
|
510
|
+
module_function :binread
|
493
511
|
end
|
494
512
|
end
|
495
513
|
|
data/lib/puppet/util/adsi.rb
CHANGED
@@ -51,12 +51,13 @@ module Puppet::Util::ADSI
|
|
51
51
|
|
52
52
|
def sid_for_account(name)
|
53
53
|
sid = nil
|
54
|
-
|
55
|
-
|
56
|
-
"SELECT Sid from Win32_Account
|
57
|
-
|
58
|
-
|
59
|
-
|
54
|
+
if name =~ /\\/
|
55
|
+
domain, name = name.split('\\', 2)
|
56
|
+
query = "SELECT Sid from Win32_Account WHERE Name = '#{name}' AND Domain = '#{domain}' AND LocalAccount = true"
|
57
|
+
else
|
58
|
+
query = "SELECT Sid from Win32_Account WHERE Name = '#{name}' AND LocalAccount = true"
|
59
|
+
end
|
60
|
+
execquery(query).each { |u| sid ||= u.Sid }
|
60
61
|
sid
|
61
62
|
end
|
62
63
|
end
|
@@ -138,7 +139,7 @@ module Puppet::Util::ADSI
|
|
138
139
|
def groups
|
139
140
|
# WIN32OLE objects aren't enumerable, so no map
|
140
141
|
groups = []
|
141
|
-
native_user.Groups.each {|g| groups << g.Name}
|
142
|
+
native_user.Groups.each {|g| groups << g.Name} rescue nil
|
142
143
|
groups
|
143
144
|
end
|
144
145
|
|
@@ -174,6 +175,8 @@ module Puppet::Util::ADSI
|
|
174
175
|
end
|
175
176
|
|
176
177
|
def self.create(name)
|
178
|
+
# Windows error 1379: The specified local group already exists.
|
179
|
+
raise Puppet::Error.new( "Cannot create user if group '#{name}' exists." ) if Puppet::Util::ADSI::Group.exists? name
|
177
180
|
new(name, Puppet::Util::ADSI.create(name, 'user'))
|
178
181
|
end
|
179
182
|
|
@@ -264,6 +267,8 @@ module Puppet::Util::ADSI
|
|
264
267
|
end
|
265
268
|
|
266
269
|
def self.create(name)
|
270
|
+
# Windows error 2224: The account already exists.
|
271
|
+
raise Puppet::Error.new( "Cannot create group if user '#{name}' exists." ) if Puppet::Util::ADSI::User.exists? name
|
267
272
|
new(name, Puppet::Util::ADSI.create(name, 'group'))
|
268
273
|
end
|
269
274
|
|
@@ -136,7 +136,7 @@ module Puppet::Util::Checksums
|
|
136
136
|
# Perform an incremental checksum on a file.
|
137
137
|
def checksum_file(digest, filename, lite = false)
|
138
138
|
buffer = lite ? 512 : 4096
|
139
|
-
File.open(filename, '
|
139
|
+
File.open(filename, 'rb') do |file|
|
140
140
|
while content = file.read(buffer)
|
141
141
|
digest << content
|
142
142
|
break if lite
|
data/lib/puppet/util/diff.rb
CHANGED
@@ -16,7 +16,7 @@ module Puppet::Util::NagiosMaker
|
|
16
16
|
type.ensurable
|
17
17
|
|
18
18
|
type.newparam(nagtype.namevar, :namevar => true) do
|
19
|
-
desc "The name
|
19
|
+
desc "The name of this nagios_#{nagtype.name} resource."
|
20
20
|
end
|
21
21
|
|
22
22
|
# We deduplicate the parameters because it makes sense to allow Naginator to have dupes.
|
@@ -33,7 +33,7 @@ module Puppet::Util::NagiosMaker
|
|
33
33
|
end
|
34
34
|
|
35
35
|
type.newproperty(:target) do
|
36
|
-
desc 'target'
|
36
|
+
desc 'The target.'
|
37
37
|
|
38
38
|
defaultto do
|
39
39
|
resource.class.defaultprovider.default_target
|
@@ -81,10 +81,20 @@ class Puppet::Util::Reference
|
|
81
81
|
self.dynamic
|
82
82
|
end
|
83
83
|
|
84
|
-
def
|
84
|
+
def markdown_header(name, level)
|
85
85
|
"#{HEADER_LEVELS[level]} #{name}\n\n"
|
86
86
|
end
|
87
87
|
|
88
|
+
def markdown_definitionlist(term, definition)
|
89
|
+
lines = definition.split("\n")
|
90
|
+
str = "#{term}\n: #{lines.shift}\n"
|
91
|
+
lines.each do |line|
|
92
|
+
str << " " if line =~ /\S/
|
93
|
+
str << "#{line}\n"
|
94
|
+
end
|
95
|
+
str << "\n"
|
96
|
+
end
|
97
|
+
|
88
98
|
def initialize(name, options = {}, &block)
|
89
99
|
@name = name
|
90
100
|
options.each do |option, value|
|
@@ -109,31 +119,20 @@ class Puppet::Util::Reference
|
|
109
119
|
":#{name.to_s.capitalize}: #{value}\n"
|
110
120
|
end
|
111
121
|
|
112
|
-
def paramwrap(name, text, options = {})
|
113
|
-
options[:level] ||= 5
|
114
|
-
#str = "#{name} : "
|
115
|
-
str = h(name, options[:level])
|
116
|
-
str += "- **namevar**\n\n" if options[:namevar]
|
117
|
-
str += text
|
118
|
-
#str += text.gsub(/\n/, "\n ")
|
119
|
-
|
120
|
-
str += "\n\n"
|
121
|
-
end
|
122
|
-
|
123
122
|
def text
|
124
123
|
puts output
|
125
124
|
end
|
126
125
|
|
127
126
|
def to_markdown(withcontents = true)
|
128
127
|
# First the header
|
129
|
-
text =
|
130
|
-
text
|
128
|
+
text = markdown_header(@title, 1)
|
129
|
+
text << "\n\n**This page is autogenerated; any changes will get overwritten** *(last generated on #{Time.now.to_s})*\n\n"
|
131
130
|
|
132
|
-
text
|
131
|
+
text << @header
|
133
132
|
|
134
|
-
text
|
133
|
+
text << generate
|
135
134
|
|
136
|
-
text
|
135
|
+
text << self.class.footer if withcontents
|
137
136
|
|
138
137
|
text
|
139
138
|
end
|
@@ -91,7 +91,20 @@ class Puppet::Util::Settings::FileSetting < Puppet::Util::Settings::Setting
|
|
91
91
|
resource = Puppet::Resource.new(:file, path)
|
92
92
|
|
93
93
|
if Puppet[:manage_internal_file_permissions]
|
94
|
-
|
94
|
+
if self.mode
|
95
|
+
# This ends up mimicking the munge method of the mode
|
96
|
+
# parameter to make sure that we're always passing the string
|
97
|
+
# version of the octal number. If we were setting the
|
98
|
+
# 'should' value for mode rather than the 'is', then the munge
|
99
|
+
# method would be called for us automatically. Normally, one
|
100
|
+
# wouldn't need to call the munge method manually, since
|
101
|
+
# 'should' gets set by the provider and it should be able to
|
102
|
+
# provide the data in the appropriate format.
|
103
|
+
mode = self.mode
|
104
|
+
mode = mode.to_i(8) if mode.is_a?(String)
|
105
|
+
mode = mode.to_s(8)
|
106
|
+
resource[:mode] = mode
|
107
|
+
end
|
95
108
|
|
96
109
|
# REMIND fails on Windows because chown/chgrp functionality not supported yet
|
97
110
|
if Puppet.features.root? and !Puppet.features.microsoft_windows?
|
@@ -122,4 +135,3 @@ class Puppet::Util::Settings::FileSetting < Puppet::Util::Settings::Setting
|
|
122
135
|
}
|
123
136
|
end
|
124
137
|
end
|
125
|
-
|
@@ -60,6 +60,7 @@
|
|
60
60
|
# (and different) owner or group.
|
61
61
|
|
62
62
|
require 'puppet/util/windows'
|
63
|
+
require 'pathname'
|
63
64
|
|
64
65
|
require 'win32/security'
|
65
66
|
|
@@ -68,6 +69,7 @@ require 'windows/handle'
|
|
68
69
|
require 'windows/security'
|
69
70
|
require 'windows/process'
|
70
71
|
require 'windows/memory'
|
72
|
+
require 'windows/volume'
|
71
73
|
|
72
74
|
module Puppet::Util::Windows::Security
|
73
75
|
include Windows::File
|
@@ -76,6 +78,7 @@ module Puppet::Util::Windows::Security
|
|
76
78
|
include Windows::Process
|
77
79
|
include Windows::Memory
|
78
80
|
include Windows::MSVCRT::Buffer
|
81
|
+
include Windows::Volume
|
79
82
|
|
80
83
|
extend Puppet::Util::Windows::Security
|
81
84
|
|
@@ -92,6 +95,7 @@ module Puppet::Util::Windows::Security
|
|
92
95
|
S_IRWXU = 0000700
|
93
96
|
S_IRWXG = 0000070
|
94
97
|
S_IRWXO = 0000007
|
98
|
+
S_ISVTX = 0001000
|
95
99
|
S_IEXTRA = 02000000 # represents an extra ace
|
96
100
|
|
97
101
|
# constants that are missing from Windows::Security
|
@@ -116,6 +120,8 @@ module Puppet::Util::Windows::Security
|
|
116
120
|
# SE_BACKUP_NAME privilege in their process token can get the owner
|
117
121
|
# for objects they do not have read access to.
|
118
122
|
def get_owner(path)
|
123
|
+
return unless supports_acl?(path)
|
124
|
+
|
119
125
|
get_sid(OWNER_SECURITY_INFORMATION, path)
|
120
126
|
end
|
121
127
|
|
@@ -136,9 +142,24 @@ module Puppet::Util::Windows::Security
|
|
136
142
|
# SE_BACKUP_NAME privilege in their process token can get the group
|
137
143
|
# for objects they do not have read access to.
|
138
144
|
def get_group(path)
|
145
|
+
return unless supports_acl?(path)
|
146
|
+
|
139
147
|
get_sid(GROUP_SECURITY_INFORMATION, path)
|
140
148
|
end
|
141
149
|
|
150
|
+
def supports_acl?(path)
|
151
|
+
flags = 0.chr * 4
|
152
|
+
|
153
|
+
root = Pathname.new(path).enum_for(:ascend).to_a.last.to_s
|
154
|
+
# 'A trailing backslash is required'
|
155
|
+
root = "#{root}\\" unless root =~ /[\/\\]$/
|
156
|
+
unless GetVolumeInformation(root, nil, 0, nil, nil, flags, nil, 0)
|
157
|
+
raise Puppet::Util::Windows::Error.new("Failed to get volume information")
|
158
|
+
end
|
159
|
+
|
160
|
+
(flags.unpack('L')[0] & Windows::File::FILE_PERSISTENT_ACLS) != 0
|
161
|
+
end
|
162
|
+
|
142
163
|
def change_sid(old_sid, new_sid, info, path)
|
143
164
|
if old_sid != new_sid
|
144
165
|
mode = get_mode(path)
|
@@ -173,15 +194,23 @@ module Puppet::Util::Windows::Security
|
|
173
194
|
end
|
174
195
|
|
175
196
|
def add_attributes(path, flags)
|
176
|
-
|
197
|
+
oldattrs = get_attributes(path)
|
198
|
+
|
199
|
+
if (oldattrs | flags) != oldattrs
|
200
|
+
set_attributes(path, oldattrs | flags)
|
201
|
+
end
|
177
202
|
end
|
178
203
|
|
179
204
|
def remove_attributes(path, flags)
|
180
|
-
|
205
|
+
oldattrs = get_attributes(path)
|
206
|
+
|
207
|
+
if (oldattrs & ~flags) != oldattrs
|
208
|
+
set_attributes(path, oldattrs & ~flags)
|
209
|
+
end
|
181
210
|
end
|
182
211
|
|
183
212
|
def set_attributes(path, flags)
|
184
|
-
raise Puppet::Util::Windows::Error.new("Failed to set file attributes")
|
213
|
+
raise Puppet::Util::Windows::Error.new("Failed to set file attributes") unless SetFileAttributes(path, flags)
|
185
214
|
end
|
186
215
|
|
187
216
|
MASK_TO_MODE = {
|
@@ -192,15 +221,17 @@ module Puppet::Util::Windows::Security
|
|
192
221
|
|
193
222
|
# Get the mode of the object referenced by +path+. The returned
|
194
223
|
# integer value represents the POSIX-style read, write, and execute
|
195
|
-
# modes for the user, group, and other classes, e.g. 0640.
|
196
|
-
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
# do not have read access to.
|
224
|
+
# modes for the user, group, and other classes, e.g. 0640. Any user
|
225
|
+
# with read access to an object can get the mode. Only a user with
|
226
|
+
# the SE_BACKUP_NAME privilege in their process token can get the
|
227
|
+
# mode for objects they do not have read access to.
|
200
228
|
def get_mode(path)
|
229
|
+
return unless supports_acl?(path)
|
230
|
+
|
201
231
|
owner_sid = get_owner(path)
|
202
232
|
group_sid = get_group(path)
|
203
233
|
well_known_world_sid = Win32::Security::SID::Everyone
|
234
|
+
well_known_nobody_sid = Win32::Security::SID::Nobody
|
204
235
|
|
205
236
|
with_privilege(SE_BACKUP_NAME) do
|
206
237
|
open_file(path, READ_CONTROL) do |handle|
|
@@ -226,6 +257,13 @@ module Puppet::Util::Windows::Security
|
|
226
257
|
mode |= (v << 6) | (v << 3) | v
|
227
258
|
end
|
228
259
|
end
|
260
|
+
if File.directory?(path) and (ace[:mask] & (FILE_WRITE_DATA | FILE_EXECUTE | FILE_DELETE_CHILD)) == (FILE_WRITE_DATA | FILE_EXECUTE)
|
261
|
+
mode |= S_ISVTX;
|
262
|
+
end
|
263
|
+
when well_known_nobody_sid
|
264
|
+
if (ace[:mask] & FILE_APPEND_DATA).nonzero?
|
265
|
+
mode |= S_ISVTX
|
266
|
+
end
|
229
267
|
else
|
230
268
|
#puts "Warning, unable to map SID into POSIX mode: #{ace[:sid]}"
|
231
269
|
mode |= S_IEXTRA
|
@@ -248,17 +286,18 @@ module Puppet::Util::Windows::Security
|
|
248
286
|
S_IROTH => FILE_GENERIC_READ,
|
249
287
|
S_IWOTH => FILE_GENERIC_WRITE,
|
250
288
|
S_IXOTH => (FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES),
|
251
|
-
(S_IWOTH | S_IXOTH) => FILE_DELETE_CHILD,
|
252
289
|
}
|
253
290
|
|
254
291
|
# Set the mode of the object referenced by +path+ to the specified
|
255
292
|
# +mode+. The mode should be specified as POSIX-stye read, write,
|
256
293
|
# and execute modes for the user, group, and other classes,
|
257
|
-
# e.g. 0640.
|
258
|
-
#
|
259
|
-
#
|
260
|
-
#
|
261
|
-
#
|
294
|
+
# e.g. 0640. The sticky bit, S_ISVTX, is supported, but is only
|
295
|
+
# meaningful for directories. If set, group and others are not
|
296
|
+
# allowed to delete child objects for which they are not the owner.
|
297
|
+
# By default, the DACL is set to protected, meaning it does not
|
298
|
+
# inherit access control entries from parent objects. This can be
|
299
|
+
# changed by setting +protected+ to false. The owner of the object
|
300
|
+
# (with READ_CONTROL and WRITE_DACL access) can always change the
|
262
301
|
# mode. Only a user with the SE_BACKUP_NAME and SE_RESTORE_NAME
|
263
302
|
# privileges in their process token can change the mode for objects
|
264
303
|
# that they do not have read and write access to.
|
@@ -266,10 +305,12 @@ module Puppet::Util::Windows::Security
|
|
266
305
|
owner_sid = get_owner(path)
|
267
306
|
group_sid = get_group(path)
|
268
307
|
well_known_world_sid = Win32::Security::SID::Everyone
|
308
|
+
well_known_nobody_sid = Win32::Security::SID::Nobody
|
269
309
|
|
270
310
|
owner_allow = STANDARD_RIGHTS_ALL | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES
|
271
311
|
group_allow = STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | SYNCHRONIZE
|
272
312
|
other_allow = STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | SYNCHRONIZE
|
313
|
+
nobody_allow = 0
|
273
314
|
|
274
315
|
MODE_TO_MASK.each do |k,v|
|
275
316
|
if ((mode >> 6) & k) == k
|
@@ -283,12 +324,36 @@ module Puppet::Util::Windows::Security
|
|
283
324
|
end
|
284
325
|
end
|
285
326
|
|
327
|
+
if (mode & S_ISVTX).nonzero?
|
328
|
+
nobody_allow |= FILE_APPEND_DATA;
|
329
|
+
end
|
330
|
+
|
331
|
+
isdir = File.directory?(path)
|
332
|
+
|
333
|
+
if isdir
|
334
|
+
if (mode & (S_IWUSR | S_IXUSR)) == (S_IWUSR | S_IXUSR)
|
335
|
+
owner_allow |= FILE_DELETE_CHILD
|
336
|
+
end
|
337
|
+
if (mode & (S_IWGRP | S_IXGRP)) == (S_IWGRP | S_IXGRP) and (mode & S_ISVTX) == 0
|
338
|
+
group_allow |= FILE_DELETE_CHILD
|
339
|
+
end
|
340
|
+
if (mode & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH) and (mode & S_ISVTX) == 0
|
341
|
+
other_allow |= FILE_DELETE_CHILD
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
286
345
|
# if owner and group the same, then map group permissions to the one owner ACE
|
287
346
|
isownergroup = owner_sid == group_sid
|
288
347
|
if isownergroup
|
289
348
|
owner_allow |= group_allow
|
290
349
|
end
|
291
350
|
|
351
|
+
# if any ACE allows write, then clear readonly bit, but do this before we overwrite
|
352
|
+
# the DACl and lose our ability to set the attribute
|
353
|
+
if ((owner_allow | group_allow | other_allow ) & FILE_WRITE_DATA) == FILE_WRITE_DATA
|
354
|
+
remove_attributes(path, FILE_ATTRIBUTE_READONLY)
|
355
|
+
end
|
356
|
+
|
292
357
|
set_acl(path, protected) do |acl|
|
293
358
|
#puts "ace: owner #{owner_sid}, mask 0x#{owner_allow.to_s(16)}"
|
294
359
|
add_access_allowed_ace(acl, owner_allow, owner_sid)
|
@@ -301,8 +366,11 @@ module Puppet::Util::Windows::Security
|
|
301
366
|
#puts "ace: other #{well_known_world_sid}, mask 0x#{other_allow.to_s(16)}"
|
302
367
|
add_access_allowed_ace(acl, other_allow, well_known_world_sid)
|
303
368
|
|
369
|
+
#puts "ace: nobody #{well_known_nobody_sid}, mask 0x#{nobody_allow.to_s(16)}"
|
370
|
+
add_access_allowed_ace(acl, nobody_allow, well_known_nobody_sid)
|
371
|
+
|
304
372
|
# add inheritable aces for child dirs and files that are created within the dir
|
305
|
-
if
|
373
|
+
if isdir
|
306
374
|
inherit = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
|
307
375
|
|
308
376
|
add_access_allowed_ace(acl, owner_allow, Win32::Security::SID::CreatorOwner, inherit)
|
@@ -311,11 +379,6 @@ module Puppet::Util::Windows::Security
|
|
311
379
|
end
|
312
380
|
end
|
313
381
|
|
314
|
-
# if any ACE allows write, then clear readonly bit
|
315
|
-
if ((owner_allow | group_allow | other_allow ) & FILE_WRITE_DATA) == FILE_WRITE_DATA
|
316
|
-
remove_attributes(path, FILE_ATTRIBUTE_READONLY)
|
317
|
-
end
|
318
|
-
|
319
382
|
nil
|
320
383
|
end
|
321
384
|
|
@@ -331,7 +394,7 @@ module Puppet::Util::Windows::Security
|
|
331
394
|
raise Puppet::Util::Windows::Error.new("Failed to initialize ACL")
|
332
395
|
end
|
333
396
|
|
334
|
-
raise Puppet::Util::Windows::Error.new("Invalid DACL")
|
397
|
+
raise Puppet::Util::Windows::Error.new("Invalid DACL") unless IsValidAcl(acl)
|
335
398
|
|
336
399
|
yield acl
|
337
400
|
|
@@ -348,9 +411,9 @@ module Puppet::Util::Windows::Security
|
|
348
411
|
|
349
412
|
def add_access_allowed_ace(acl, mask, sid, inherit = NO_INHERITANCE)
|
350
413
|
string_to_sid_ptr(sid) do |sid_ptr|
|
351
|
-
raise Puppet::Util::Windows::Error.new("Invalid SID")
|
414
|
+
raise Puppet::Util::Windows::Error.new("Invalid SID") unless IsValidSid(sid_ptr)
|
352
415
|
|
353
|
-
|
416
|
+
unless AddAccessAllowedAceEx(acl, ACL_REVISION, inherit, mask, sid_ptr)
|
354
417
|
raise Puppet::Util::Windows::Error.new("Failed to add access control entry")
|
355
418
|
end
|
356
419
|
end
|
@@ -358,9 +421,9 @@ module Puppet::Util::Windows::Security
|
|
358
421
|
|
359
422
|
def add_access_denied_ace(acl, mask, sid)
|
360
423
|
string_to_sid_ptr(sid) do |sid_ptr|
|
361
|
-
raise Puppet::Util::Windows::Error.new("Invalid SID")
|
424
|
+
raise Puppet::Util::Windows::Error.new("Invalid SID") unless IsValidSid(sid_ptr)
|
362
425
|
|
363
|
-
|
426
|
+
unless AddAccessDeniedAce(acl, ACL_REVISION, mask, sid_ptr)
|
364
427
|
raise Puppet::Util::Windows::Error.new("Failed to add access control entry")
|
365
428
|
end
|
366
429
|
end
|
@@ -369,7 +432,7 @@ module Puppet::Util::Windows::Security
|
|
369
432
|
def get_dacl(handle)
|
370
433
|
get_dacl_ptr(handle) do |dacl_ptr|
|
371
434
|
# REMIND: need to handle NULL DACL
|
372
|
-
raise Puppet::Util::Windows::Error.new("Invalid DACL")
|
435
|
+
raise Puppet::Util::Windows::Error.new("Invalid DACL") unless IsValidAcl(dacl_ptr)
|
373
436
|
|
374
437
|
# ACL structure, size and count are the important parts. The
|
375
438
|
# size includes both the ACL structure and all the ACEs.
|
@@ -390,7 +453,8 @@ module Puppet::Util::Windows::Security
|
|
390
453
|
|
391
454
|
0.upto(ace_count - 1) do |i|
|
392
455
|
ace_ptr = [0].pack('L')
|
393
|
-
|
456
|
+
|
457
|
+
next unless GetAce(dacl_ptr, i, ace_ptr)
|
394
458
|
|
395
459
|
# ACE structures vary depending on the type. All structures
|
396
460
|
# begin with an ACE header, which specifies the type, flags
|
@@ -492,9 +556,9 @@ module Puppet::Util::Windows::Security
|
|
492
556
|
sid_buf = 0.chr * 256
|
493
557
|
str_ptr = 0.chr * 4
|
494
558
|
|
495
|
-
raise Puppet::Util::Windows::Error.new("Invalid SID")
|
559
|
+
raise Puppet::Util::Windows::Error.new("Invalid SID") unless IsValidSid(psid)
|
496
560
|
|
497
|
-
raise Puppet::Util::Windows::Error.new("Failed to convert binary SID")
|
561
|
+
raise Puppet::Util::Windows::Error.new("Failed to convert binary SID") unless ConvertSidToStringSid(psid, str_ptr)
|
498
562
|
|
499
563
|
begin
|
500
564
|
strncpy(sid_buf, str_ptr.unpack('L')[0], sid_buf.size - 1)
|
@@ -562,14 +626,14 @@ module Puppet::Util::Windows::Security
|
|
562
626
|
tmpLuid = 0.chr * 8
|
563
627
|
|
564
628
|
# Get the LUID for specified privilege.
|
565
|
-
|
629
|
+
unless LookupPrivilegeValue("", privilege, tmpLuid)
|
566
630
|
raise Puppet::Util::Windows::Error.new("Failed to lookup privilege")
|
567
631
|
end
|
568
632
|
|
569
633
|
# DWORD + [LUID + DWORD]
|
570
634
|
tkp = [1].pack('L') + tmpLuid + [enable ? SE_PRIVILEGE_ENABLED : 0].pack('L')
|
571
635
|
|
572
|
-
|
636
|
+
unless AdjustTokenPrivileges(token, 0, tkp, tkp.length , nil, nil)
|
573
637
|
raise Puppet::Util::Windows::Error.new("Failed to adjust process privileges")
|
574
638
|
end
|
575
639
|
end
|
@@ -579,7 +643,7 @@ module Puppet::Util::Windows::Security
|
|
579
643
|
def with_process_token(access)
|
580
644
|
token = 0.chr * 4
|
581
645
|
|
582
|
-
|
646
|
+
unless OpenProcessToken(GetCurrentProcess(), access, token)
|
583
647
|
raise Puppet::Util::Windows::Error.new("Failed to open process token")
|
584
648
|
end
|
585
649
|
begin
|