puppet 4.10.10 → 4.10.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/CONTRIBUTING.md +15 -15
- data/Gemfile +3 -0
- data/README.md +11 -11
- data/ext/project_data.yaml +4 -2
- data/lib/puppet/application/agent.rb +1 -3
- data/lib/puppet/application/apply.rb +1 -3
- data/lib/puppet/application/cert.rb +6 -1
- data/lib/puppet/application/lookup.rb +11 -1
- data/lib/puppet/configurer.rb +17 -4
- data/lib/puppet/environments.rb +1 -1
- data/lib/puppet/functions/map.rb +1 -1
- data/lib/puppet/indirector/indirection.rb +3 -3
- data/lib/puppet/indirector/request.rb +6 -2
- data/lib/puppet/network/http/connection.rb +8 -0
- data/lib/puppet/parser/functions/new.rb +29 -44
- data/lib/puppet/parser/functions/return.rb +22 -1
- data/lib/puppet/pops/resource/resource_type_impl.rb +1 -1
- data/lib/puppet/provider/group/windows_adsi.rb +4 -7
- data/lib/puppet/provider/package/dnf.rb +1 -1
- data/lib/puppet/provider/service/systemd.rb +1 -1
- data/lib/puppet/provider/user/aix.rb +1 -1
- data/lib/puppet/provider/user/windows_adsi.rb +1 -1
- data/lib/puppet/reference/configuration.rb +2 -0
- data/lib/puppet/type/tidy.rb +8 -1
- data/lib/puppet/type/user.rb +34 -3
- data/lib/puppet/util/reference.rb +2 -9
- data/lib/puppet/util/windows/adsi.rb +28 -31
- data/lib/puppet/util/windows/file.rb +61 -9
- data/lib/puppet/util/windows/principal.rb +9 -7
- data/lib/puppet/util/windows/sid.rb +60 -7
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +79 -11
- data/man/man5/puppet.conf.5 +6 -8
- data/man/man8/extlookup2hiera.8 +1 -1
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-ca.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-cert.8 +1 -1
- data/man/man8/puppet-certificate.8 +1 -1
- data/man/man8/puppet-certificate_request.8 +1 -1
- data/man/man8/puppet-certificate_revocation_list.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-file.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-inspect.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-master.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-resource_type.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/integration/application/lookup_spec.rb +21 -0
- data/spec/integration/parser/pcore_resource_spec.rb +1 -1
- data/spec/integration/util/windows/adsi_spec.rb +86 -1
- data/spec/integration/util/windows/principal_spec.rb +10 -1
- data/spec/unit/application/agent_spec.rb +0 -9
- data/spec/unit/application/apply_spec.rb +0 -9
- data/spec/unit/application/cert_spec.rb +40 -1
- data/spec/unit/configurer_spec.rb +14 -0
- data/spec/unit/indirector/indirection_spec.rb +24 -2
- data/spec/unit/provider/group/windows_adsi_spec.rb +79 -22
- data/spec/unit/provider/service/systemd_spec.rb +1 -1
- data/spec/unit/provider/user/windows_adsi_spec.rb +4 -4
- data/spec/unit/type/tidy_spec.rb +14 -0
- data/spec/unit/util/windows/adsi_spec.rb +31 -27
- data/spec/unit/util/windows/sid_spec.rb +86 -15
- data/tasks/manpages.rake +1 -1
- metadata +3621 -3609
- checksums.yaml +0 -7
@@ -4,7 +4,8 @@ Puppet::Parser::Functions::newfunction(
|
|
4
4
|
:doc => <<-DOC
|
5
5
|
Immediately returns the given optional value from a function, class body or user defined type body.
|
6
6
|
If a value is not given, an `undef` value is returned. This function does not return to the immediate caller.
|
7
|
-
If called from within a lambda the return
|
7
|
+
If this function is called from within a lambda, the return action is from the scope of the
|
8
|
+
function containing the lambda (top scope), not the function accepting the lambda (local scope).
|
8
9
|
|
9
10
|
The signal produced to return a value bubbles up through
|
10
11
|
the call stack until reaching a function, class definition or
|
@@ -63,6 +64,26 @@ The code would notice `'bar'` but not `'foo'`
|
|
63
64
|
|
64
65
|
Note that the returned value is ignored if used in a class or user defined type.
|
65
66
|
|
67
|
+
**Example:** Using `return` in a lambda
|
68
|
+
|
69
|
+
```puppet
|
70
|
+
# Concatenate three strings into a single string formatted as a list.
|
71
|
+
function getFruit() {
|
72
|
+
with("apples", "oranges", "bananas") |$x, $y, $z| {
|
73
|
+
return("${x}, ${y}, and ${z}")
|
74
|
+
}
|
75
|
+
notice "not reached"
|
76
|
+
}
|
77
|
+
$fruit = getFruit()
|
78
|
+
notice $fruit
|
79
|
+
|
80
|
+
# The output contains "apples, oranges, and bananas".
|
81
|
+
# "not reached" is not output because the function returns its value within the
|
82
|
+
# calling function's scope, which stops processing the calling function before
|
83
|
+
# the `notice "not reached"` statement.
|
84
|
+
# Using `return()` outside of a calling function results in an error.
|
85
|
+
```
|
86
|
+
|
66
87
|
* Also see functions `return` and `break`
|
67
88
|
* Since 4.8.0
|
68
89
|
DOC
|
@@ -149,7 +149,7 @@ class ResourceTypeImpl
|
|
149
149
|
# Here it is silently ignored.
|
150
150
|
nil
|
151
151
|
when 1
|
152
|
-
if @
|
152
|
+
if @title_patterns_hash.nil?
|
153
153
|
[ [ /(.*)/m, [ [@key_attributes.first] ] ] ]
|
154
154
|
else
|
155
155
|
# TechDebt: The case of having one namevar and an empty title patterns is unspecified behavior in puppet.
|
@@ -23,12 +23,9 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
23
23
|
# Cannot use munge of the group property to canonicalize @should
|
24
24
|
# since the default array_matching comparison is not commutative
|
25
25
|
|
26
|
+
current_sids = current.map(&:sid)
|
26
27
|
# dupes automatically weeded out when hashes built
|
27
|
-
|
28
|
-
specified_users = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should)
|
29
|
-
|
30
|
-
current_sids = current_users.keys.to_a
|
31
|
-
specified_sids = specified_users.keys.to_a
|
28
|
+
specified_sids = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should).keys.to_a
|
32
29
|
|
33
30
|
if @resource[:auth_membership]
|
34
31
|
current_sids.sort == specified_sids.sort
|
@@ -40,7 +37,7 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
40
37
|
def members_to_s(users)
|
41
38
|
return '' if users.nil? or !users.kind_of?(Array)
|
42
39
|
users = users.map do |user_name|
|
43
|
-
sid = Puppet::Util::Windows::SID.
|
40
|
+
sid = Puppet::Util::Windows::SID.name_to_principal(user_name)
|
44
41
|
if !sid
|
45
42
|
resource.debug("#{user_name} (unresolvable to SID)")
|
46
43
|
next user_name
|
@@ -58,7 +55,7 @@ Puppet::Type.type(:group).provide :windows_adsi do
|
|
58
55
|
end
|
59
56
|
|
60
57
|
def member_valid?(user_name)
|
61
|
-
! Puppet::Util::Windows::SID.
|
58
|
+
! Puppet::Util::Windows::SID.name_to_principal(user_name).nil?
|
62
59
|
end
|
63
60
|
|
64
61
|
def group
|
@@ -28,7 +28,7 @@ Puppet::Type.type(:package).provide :dnf, :parent => :yum do
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
defaultfor :operatingsystem => :fedora, :operatingsystemmajrelease =>
|
31
|
+
defaultfor :operatingsystem => :fedora, :operatingsystemmajrelease => (22..30).to_a
|
32
32
|
|
33
33
|
def self.update_command
|
34
34
|
# In DNF, update is deprecated for upgrade
|
@@ -25,7 +25,7 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
|
|
25
25
|
defaultfor :osfamily => :coreos
|
26
26
|
defaultfor :operatingsystem => :amazon, :operatingsystemmajrelease => ["2"]
|
27
27
|
defaultfor :operatingsystem => :debian, :operatingsystemmajrelease => ["8", "stretch/sid", "9", "buster/sid"]
|
28
|
-
defaultfor :operatingsystem => :ubuntu, :operatingsystemmajrelease => ["15.04","15.10","16.04","16.10"]
|
28
|
+
defaultfor :operatingsystem => :ubuntu, :operatingsystemmajrelease => ["15.04","15.10","16.04","16.10","17.04","17.10"]
|
29
29
|
defaultfor :operatingsystem => :cumuluslinux, :operatingsystemmajrelease => ["3"]
|
30
30
|
|
31
31
|
def self.instances
|
@@ -268,7 +268,7 @@ Puppet::Type.type(:user).provide :aix, :parent => Puppet::Provider::AixObject do
|
|
268
268
|
# Must receive "user:enc_password" as input
|
269
269
|
# command, arguments = {:failonfail => true, :combine => true}
|
270
270
|
# Fix for bugs #11200 and #10915
|
271
|
-
cmd = [self.class.command(:chpasswd), get_ia_module_args, '-e', '-c'
|
271
|
+
cmd = [self.class.command(:chpasswd), get_ia_module_args, '-e', '-c'].flatten
|
272
272
|
begin
|
273
273
|
output = execute(cmd, {:failonfail => false, :combine => true, :stdinfile => tmpfile.path })
|
274
274
|
# chpasswd can return 1, even on success (at least on AIX 6.1); empty output indicates success
|
@@ -52,7 +52,7 @@ Puppet::Type.type(:user).provide :windows_adsi do
|
|
52
52
|
def groups_to_s(groups)
|
53
53
|
return '' if groups.nil? || !groups.kind_of?(Array)
|
54
54
|
groups = groups.map do |group_name|
|
55
|
-
sid = Puppet::Util::Windows::SID.
|
55
|
+
sid = Puppet::Util::Windows::SID.name_to_principal(group_name)
|
56
56
|
if sid.account =~ /\\/
|
57
57
|
account, _ = Puppet::Util::Windows::ADSI::Group.parse_name(sid.account)
|
58
58
|
else
|
@@ -34,6 +34,8 @@ config = Puppet::Util::Reference.newreference(:configuration, :depth => 1, :doc
|
|
34
34
|
val = 'Unix/Linux: /var/log/puppetlabs/puppet -- Windows: C:\ProgramData\PuppetLabs\puppet\var\log -- Non-root user: ~/.puppetlabs/var/log'
|
35
35
|
elsif name.to_s == 'hiera_config'
|
36
36
|
val = '$confdir/hiera.yaml. However, if a file exists at $codedir/hiera.yaml, Puppet uses that instead.'
|
37
|
+
elsif name.to_s == 'certname'
|
38
|
+
val = "the Host's fully qualified domain name, as determined by facter"
|
37
39
|
end
|
38
40
|
|
39
41
|
# Leave out the section information; it was apparently confusing people.
|
data/lib/puppet/type/tidy.rb
CHANGED
@@ -222,7 +222,14 @@ Puppet::Type.newtype(:tidy) do
|
|
222
222
|
# Make a file resource to remove a given file.
|
223
223
|
def mkfile(path)
|
224
224
|
# Force deletion, so directories actually get deleted.
|
225
|
-
|
225
|
+
parameters = {
|
226
|
+
:path => path, :backup => self[:backup],
|
227
|
+
:ensure => :absent, :force => true
|
228
|
+
}
|
229
|
+
|
230
|
+
parameters[:noop] = self[:noop] unless self[:noop].nil?
|
231
|
+
|
232
|
+
Puppet::Type.type(:file).new(parameters)
|
226
233
|
end
|
227
234
|
|
228
235
|
def retrieve
|
data/lib/puppet/type/user.rb
CHANGED
@@ -212,13 +212,44 @@ module Puppet
|
|
212
212
|
* OS X 10.8 and higher use salted SHA512 PBKDF2 hashes. When managing passwords
|
213
213
|
on these systems, the `salt` and `iterations` attributes need to be specified as
|
214
214
|
well as the password.
|
215
|
-
* Windows passwords can
|
216
|
-
for setting the password hash.
|
215
|
+
* Windows passwords can be managed only in cleartext, because there is no Windows
|
216
|
+
API for setting the password hash.
|
217
217
|
|
218
218
|
[stdlib]: https://github.com/puppetlabs/puppetlabs-stdlib/
|
219
219
|
|
220
220
|
Enclose any value that includes a dollar sign ($) in single quotes (') to avoid
|
221
|
-
accidental variable interpolation.
|
221
|
+
accidental variable interpolation.
|
222
|
+
|
223
|
+
To redact passwords from reports to PuppetDB, use the `Sensitive` data type. For
|
224
|
+
example, this resource protects the password:
|
225
|
+
|
226
|
+
```puppet
|
227
|
+
user { 'foo':
|
228
|
+
ensure => present,
|
229
|
+
password => Sensitive("my secret password")
|
230
|
+
}
|
231
|
+
```
|
232
|
+
|
233
|
+
This results in the password being redacted from the report, as in the
|
234
|
+
`previous_value`, `desired_value`, and `message` fields below.
|
235
|
+
|
236
|
+
```yaml
|
237
|
+
events:
|
238
|
+
- !ruby/object:Puppet::Transaction::Event
|
239
|
+
audited: false
|
240
|
+
property: password
|
241
|
+
previous_value: "[redacted]"
|
242
|
+
desired_value: "[redacted]"
|
243
|
+
historical_value:
|
244
|
+
message: changed [redacted] to [redacted]
|
245
|
+
name: :password_changed
|
246
|
+
status: success
|
247
|
+
time: 2017-05-17 16:06:02.934398293 -07:00
|
248
|
+
redacted: true
|
249
|
+
corrective_change: false
|
250
|
+
corrective_change: false
|
251
|
+
```
|
252
|
+
}
|
222
253
|
|
223
254
|
validate do |value|
|
224
255
|
raise ArgumentError, "Passwords cannot include ':'" if value.is_a?(String) and value.include?(":")
|
@@ -12,11 +12,6 @@ class Puppet::Util::Reference
|
|
12
12
|
|
13
13
|
instance_load(:reference, 'puppet/reference')
|
14
14
|
|
15
|
-
def self.footer
|
16
|
-
#TRANSLATORS message accompanied by date of generation
|
17
|
-
"\n\n----------------\n\n*" + _("This page autogenerated on ") + "#{Time.now}*\n"
|
18
|
-
end
|
19
|
-
|
20
15
|
def self.modes
|
21
16
|
%w{pdf text}
|
22
17
|
end
|
@@ -112,15 +107,13 @@ class Puppet::Util::Reference
|
|
112
107
|
def to_markdown(withcontents = true)
|
113
108
|
# First the header
|
114
109
|
text = markdown_header(@title, 1)
|
115
|
-
|
116
|
-
text << _("\n\n**This page is autogenerated; any changes will get overwritten
|
110
|
+
|
111
|
+
text << _("\n\n**This page is autogenerated; any changes will get overwritten**\n\n")
|
117
112
|
|
118
113
|
text << @header
|
119
114
|
|
120
115
|
text << generate
|
121
116
|
|
122
|
-
text << self.class.footer if withcontents
|
123
|
-
|
124
117
|
text
|
125
118
|
end
|
126
119
|
end
|
@@ -16,7 +16,7 @@ module Puppet::Util::Windows::ADSI
|
|
16
16
|
begin
|
17
17
|
WIN32OLE.connect(uri)
|
18
18
|
rescue WIN32OLERuntimeError => e
|
19
|
-
raise Puppet::Error.new( "ADSI connection error:
|
19
|
+
raise Puppet::Error.new( _("ADSI connection error: %{e}") % { e: e }, e )
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -39,7 +39,7 @@ module Puppet::Util::Windows::ADSI
|
|
39
39
|
buffer_size.write_dword(max_length) # length in TCHARs
|
40
40
|
|
41
41
|
if GetComputerNameW(buffer, buffer_size) == FFI::WIN32_FALSE
|
42
|
-
raise Puppet::Util::Windows::Error.new("Failed to get computer name")
|
42
|
+
raise Puppet::Util::Windows::Error.new(_("Failed to get computer name"))
|
43
43
|
end
|
44
44
|
@computer_name = buffer.read_wide_string(buffer_size.read_dword)
|
45
45
|
end
|
@@ -66,7 +66,7 @@ module Puppet::Util::Windows::ADSI
|
|
66
66
|
return sid_uri(sid) if sid.kind_of?(Puppet::Util::Windows::SID::Principal)
|
67
67
|
|
68
68
|
begin
|
69
|
-
sid = Puppet::Util::Windows::SID.
|
69
|
+
sid = Puppet::Util::Windows::SID.name_to_principal(sid)
|
70
70
|
sid_uri(sid)
|
71
71
|
rescue Puppet::Util::Windows::Error, Puppet::Error
|
72
72
|
nil
|
@@ -77,7 +77,7 @@ module Puppet::Util::Windows::ADSI
|
|
77
77
|
# used for IAdsGroup::Add / IAdsGroup::Remove. These URIs are not useable
|
78
78
|
# to resolve an account with WIN32OLE.connect
|
79
79
|
def sid_uri(sid)
|
80
|
-
raise Puppet::Error.new( "Must use a valid SID::Principal" ) if !sid.kind_of?(Puppet::Util::Windows::SID::Principal)
|
80
|
+
raise Puppet::Error.new( _("Must use a valid SID::Principal") ) if !sid.kind_of?(Puppet::Util::Windows::SID::Principal)
|
81
81
|
|
82
82
|
"WinNT://#{sid.sid}"
|
83
83
|
end
|
@@ -114,7 +114,7 @@ module Puppet::Util::Windows::ADSI
|
|
114
114
|
Puppet::Util::Windows::SID.sid_to_name('S-1-5-32').upcase,
|
115
115
|
# localized version of NT AUTHORITY (can't use S-1-5)
|
116
116
|
# for instance AUTORITE NT on French Windows
|
117
|
-
Puppet::Util::Windows::SID.
|
117
|
+
Puppet::Util::Windows::SID.name_to_principal('SYSTEM').domain.upcase
|
118
118
|
]
|
119
119
|
end
|
120
120
|
|
@@ -129,7 +129,7 @@ module Puppet::Util::Windows::ADSI
|
|
129
129
|
|
130
130
|
def parse_name(name)
|
131
131
|
if name =~ /\//
|
132
|
-
raise Puppet::Error.new( "Value must be in DOMAIN\\user style syntax" )
|
132
|
+
raise Puppet::Error.new( _("Value must be in DOMAIN\\user style syntax") )
|
133
133
|
end
|
134
134
|
|
135
135
|
matches = name.scan(/((.*)\\)?(.*)/)
|
@@ -139,10 +139,12 @@ module Puppet::Util::Windows::ADSI
|
|
139
139
|
return account, domain
|
140
140
|
end
|
141
141
|
|
142
|
+
# returns Puppet::Util::Windows::SID::Principal[]
|
143
|
+
# may contain objects that represent unresolvable SIDs
|
142
144
|
def get_sids(adsi_child_collection)
|
143
145
|
sids = []
|
144
146
|
adsi_child_collection.each do |m|
|
145
|
-
sids << Puppet::Util::Windows::SID.
|
147
|
+
sids << Puppet::Util::Windows::SID.ads_to_principal(m)
|
146
148
|
end
|
147
149
|
|
148
150
|
sids
|
@@ -152,8 +154,8 @@ module Puppet::Util::Windows::ADSI
|
|
152
154
|
return {} if names.nil? || names.empty?
|
153
155
|
|
154
156
|
sids = names.map do |name|
|
155
|
-
sid = Puppet::Util::Windows::SID.
|
156
|
-
raise Puppet::Error.new( "Could not resolve name:
|
157
|
+
sid = Puppet::Util::Windows::SID.name_to_principal(name)
|
158
|
+
raise Puppet::Error.new( _("Could not resolve name: %{name}") % { name: name } ) if !sid
|
157
159
|
[sid.sid, sid]
|
158
160
|
end
|
159
161
|
|
@@ -183,7 +185,7 @@ module Puppet::Util::Windows::ADSI
|
|
183
185
|
end
|
184
186
|
|
185
187
|
def sid
|
186
|
-
@sid ||= Puppet::Util::Windows::SID.
|
188
|
+
@sid ||= Puppet::Util::Windows::SID.octet_string_to_principal(native_user.objectSID)
|
187
189
|
end
|
188
190
|
|
189
191
|
def uri
|
@@ -211,12 +213,12 @@ module Puppet::Util::Windows::ADSI
|
|
211
213
|
# ERROR_BAD_USERNAME 2202L from winerror.h
|
212
214
|
if e.message =~ /8007089A/m
|
213
215
|
raise Puppet::Error.new(
|
214
|
-
"Puppet is not able to create/delete domain users with the user resource.",
|
216
|
+
_("Puppet is not able to create/delete domain users with the user resource."),
|
215
217
|
e
|
216
218
|
)
|
217
219
|
end
|
218
220
|
|
219
|
-
raise Puppet::Error.new( "User update failed:
|
221
|
+
raise Puppet::Error.new( _("User update failed: %{e}") % { e: e }, e )
|
220
222
|
end
|
221
223
|
self
|
222
224
|
end
|
@@ -311,7 +313,7 @@ module Puppet::Util::Windows::ADSI
|
|
311
313
|
|
312
314
|
def self.create(name)
|
313
315
|
# Windows error 1379: The specified local group already exists.
|
314
|
-
raise Puppet::Error.new(
|
316
|
+
raise Puppet::Error.new(_("Cannot create user if group '%{name}' exists.") % { name: name }) if Puppet::Util::Windows::ADSI::Group.exists? name
|
315
317
|
new(name, Puppet::Util::Windows::ADSI.create(name, 'user'))
|
316
318
|
end
|
317
319
|
|
@@ -325,7 +327,7 @@ module Puppet::Util::Windows::ADSI
|
|
325
327
|
buffer_size.write_dword(max_length) # length in TCHARs
|
326
328
|
|
327
329
|
if GetUserNameW(buffer, buffer_size) == FFI::WIN32_FALSE
|
328
|
-
raise Puppet::Util::Windows::Error.new("Failed to get user name")
|
330
|
+
raise Puppet::Util::Windows::Error.new(_("Failed to get user name"))
|
329
331
|
end
|
330
332
|
# buffer_size includes trailing NULL
|
331
333
|
user_name = buffer.read_wide_string(buffer_size.read_dword - 1)
|
@@ -336,12 +338,12 @@ module Puppet::Util::Windows::ADSI
|
|
336
338
|
end
|
337
339
|
|
338
340
|
def self.current_user_sid
|
339
|
-
Puppet::Util::Windows::SID.
|
341
|
+
Puppet::Util::Windows::SID.name_to_principal(current_user_name)
|
340
342
|
end
|
341
343
|
|
342
344
|
def self.exists?(name_or_sid)
|
343
345
|
well_known = false
|
344
|
-
if (sid = Puppet::Util::Windows::SID.
|
346
|
+
if (sid = Puppet::Util::Windows::SID.name_to_principal(name_or_sid))
|
345
347
|
return true if sid.account_type == :SidTypeUser
|
346
348
|
|
347
349
|
# 'well known group' is special as it can be a group like Everyone OR a user like SYSTEM
|
@@ -403,7 +405,7 @@ module Puppet::Util::Windows::ADSI
|
|
403
405
|
# but warn if we fail
|
404
406
|
raise e unless e.message.include?('80041010')
|
405
407
|
|
406
|
-
Puppet.warning "Cannot delete user profile for '
|
408
|
+
Puppet.warning _("Cannot delete user profile for '%{sid}' prior to Vista SP1") % { sid: sid }
|
407
409
|
end
|
408
410
|
end
|
409
411
|
end
|
@@ -431,7 +433,7 @@ module Puppet::Util::Windows::ADSI
|
|
431
433
|
end
|
432
434
|
|
433
435
|
def sid
|
434
|
-
@sid ||= Puppet::Util::Windows::SID.
|
436
|
+
@sid ||= Puppet::Util::Windows::SID.octet_string_to_principal(native_group.objectSID)
|
435
437
|
end
|
436
438
|
|
437
439
|
def commit
|
@@ -441,12 +443,12 @@ module Puppet::Util::Windows::ADSI
|
|
441
443
|
# ERROR_BAD_USERNAME 2202L from winerror.h
|
442
444
|
if e.message =~ /8007089A/m
|
443
445
|
raise Puppet::Error.new(
|
444
|
-
"Puppet is not able to create/delete domain groups with the group resource.",
|
446
|
+
_("Puppet is not able to create/delete domain groups with the group resource."),
|
445
447
|
e
|
446
448
|
)
|
447
449
|
end
|
448
450
|
|
449
|
-
raise Puppet::Error.new( "Group update failed:
|
451
|
+
raise Puppet::Error.new( _("Group update failed: %{error}") % { error: e }, e )
|
450
452
|
end
|
451
453
|
self
|
452
454
|
end
|
@@ -463,18 +465,13 @@ module Puppet::Util::Windows::ADSI
|
|
463
465
|
end
|
464
466
|
end
|
465
467
|
|
468
|
+
# returns Puppet::Util::Windows::SID::Principal[]
|
469
|
+
# may contain objects that represent unresolvable SIDs
|
470
|
+
# qualified account names are returned by calling #domain_account
|
466
471
|
def members
|
467
|
-
# WIN32OLE objects aren't enumerable, so no map
|
468
|
-
members = []
|
469
|
-
# Setting WIN32OLE.codepage in the microsoft_windows feature ensures
|
470
|
-
# values are returned as UTF-8
|
471
|
-
native_group.Members.each {|m| members << m.Name}
|
472
|
-
members
|
473
|
-
end
|
474
|
-
|
475
|
-
def member_sids
|
476
472
|
self.class.get_sids(native_group.Members)
|
477
473
|
end
|
474
|
+
alias member_sids members
|
478
475
|
|
479
476
|
def set_members(desired_members, inclusive = true)
|
480
477
|
return if desired_members.nil?
|
@@ -502,13 +499,13 @@ module Puppet::Util::Windows::ADSI
|
|
502
499
|
|
503
500
|
def self.create(name)
|
504
501
|
# Windows error 2224: The account already exists.
|
505
|
-
raise Puppet::Error.new( "Cannot create group if user '
|
502
|
+
raise Puppet::Error.new( _("Cannot create group if user '%{name}' exists.") % { name: name } ) if Puppet::Util::Windows::ADSI::User.exists? name
|
506
503
|
new(name, Puppet::Util::Windows::ADSI.create(name, 'group'))
|
507
504
|
end
|
508
505
|
|
509
506
|
def self.exists?(name_or_sid)
|
510
507
|
well_known = false
|
511
|
-
if (sid = Puppet::Util::Windows::SID.
|
508
|
+
if (sid = Puppet::Util::Windows::SID.name_to_principal(name_or_sid))
|
512
509
|
return true if sid.account_type == :SidTypeGroup
|
513
510
|
|
514
511
|
# 'well known group' is special as it can be a group like Everyone OR a user like SYSTEM
|
@@ -111,11 +111,15 @@ module Puppet::Util::Windows::File
|
|
111
111
|
|
112
112
|
# return true if path exists and it's not a symlink
|
113
113
|
# Other file attributes are ignored. https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117(v=vs.85).aspx
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
114
|
+
reparse_point = (result & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT
|
115
|
+
if reparse_point && symlink_reparse_point?(path)
|
116
|
+
# walk the symlink and try again...
|
117
|
+
seen_paths << path.downcase
|
118
|
+
path = readlink(path)
|
119
|
+
else
|
120
|
+
# file was found and its not a symlink
|
121
|
+
return true
|
122
|
+
end
|
119
123
|
end
|
120
124
|
|
121
125
|
false
|
@@ -177,6 +181,18 @@ module Puppet::Util::Windows::File
|
|
177
181
|
"#{flags_and_attributes.to_s(8)}, #{template_file_handle})")
|
178
182
|
end
|
179
183
|
|
184
|
+
IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003
|
185
|
+
IO_REPARSE_TAG_HSM = 0xC0000004
|
186
|
+
IO_REPARSE_TAG_HSM2 = 0x80000006
|
187
|
+
IO_REPARSE_TAG_SIS = 0x80000007
|
188
|
+
IO_REPARSE_TAG_WIM = 0x80000008
|
189
|
+
IO_REPARSE_TAG_CSV = 0x80000009
|
190
|
+
IO_REPARSE_TAG_DFS = 0x8000000A
|
191
|
+
IO_REPARSE_TAG_SYMLINK = 0xA000000C
|
192
|
+
IO_REPARSE_TAG_DFSR = 0x80000012
|
193
|
+
IO_REPARSE_TAG_DEDUP = 0x80000013
|
194
|
+
IO_REPARSE_TAG_NFS = 0x80000014
|
195
|
+
|
180
196
|
def self.get_reparse_point_data(handle, &block)
|
181
197
|
# must be multiple of 1024, min 10240
|
182
198
|
FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) do |reparse_data_buffer_ptr|
|
@@ -184,11 +200,11 @@ module Puppet::Util::Windows::File
|
|
184
200
|
|
185
201
|
reparse_tag = reparse_data_buffer_ptr.read_win32_ulong
|
186
202
|
buffer_type = case reparse_tag
|
187
|
-
when
|
203
|
+
when IO_REPARSE_TAG_SYMLINK
|
188
204
|
SYMLINK_REPARSE_DATA_BUFFER
|
189
|
-
when
|
205
|
+
when IO_REPARSE_TAG_MOUNT_POINT
|
190
206
|
MOUNT_POINT_REPARSE_DATA_BUFFER
|
191
|
-
when
|
207
|
+
when IO_REPARSE_TAG_NFS
|
192
208
|
raise Puppet::Util::Windows::Error.new("Retrieving NFS reparse point data is unsupported")
|
193
209
|
else
|
194
210
|
raise Puppet::Util::Windows::Error.new("DeviceIoControl(#{handle}, " +
|
@@ -202,6 +218,20 @@ module Puppet::Util::Windows::File
|
|
202
218
|
nil
|
203
219
|
end
|
204
220
|
|
221
|
+
def self.get_reparse_point_tag(handle)
|
222
|
+
reparse_tag = nil
|
223
|
+
|
224
|
+
# must be multiple of 1024, min 10240
|
225
|
+
FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) do |reparse_data_buffer_ptr|
|
226
|
+
device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr)
|
227
|
+
|
228
|
+
# DWORD ReparseTag is the first member of the struct
|
229
|
+
reparse_tag = reparse_data_buffer_ptr.read_win32_ulong
|
230
|
+
end
|
231
|
+
|
232
|
+
reparse_tag
|
233
|
+
end
|
234
|
+
|
205
235
|
def self.device_io_control(handle, io_control_code, in_buffer = nil, out_buffer = nil)
|
206
236
|
if out_buffer.nil?
|
207
237
|
raise Puppet::Util::Windows::Error.new("out_buffer is required")
|
@@ -229,12 +259,18 @@ module Puppet::Util::Windows::File
|
|
229
259
|
end
|
230
260
|
|
231
261
|
FILE_ATTRIBUTE_REPARSE_POINT = 0x400
|
232
|
-
def
|
262
|
+
def reparse_point?(file_name)
|
233
263
|
attributes = get_attributes(file_name, false)
|
234
264
|
|
235
265
|
return false if (attributes == INVALID_FILE_ATTRIBUTES)
|
236
266
|
(attributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT
|
237
267
|
end
|
268
|
+
module_function :reparse_point?
|
269
|
+
|
270
|
+
def symlink?(file_name)
|
271
|
+
# Puppet currently only handles mount point and symlink reparse points, ignores others
|
272
|
+
reparse_point?(file_name) && symlink_reparse_point?(file_name)
|
273
|
+
end
|
238
274
|
module_function :symlink?
|
239
275
|
|
240
276
|
GENERIC_READ = 0x80000000
|
@@ -375,6 +411,22 @@ module Puppet::Util::Windows::File
|
|
375
411
|
path
|
376
412
|
end
|
377
413
|
|
414
|
+
# these reparse point types are the only ones Puppet currently understands
|
415
|
+
# so rather than raising an exception in readlink, prefer to not consider
|
416
|
+
# the path a symlink when stat'ing later
|
417
|
+
def self.symlink_reparse_point?(path)
|
418
|
+
symlink = false
|
419
|
+
|
420
|
+
open_symlink(path) do |handle|
|
421
|
+
symlink = [
|
422
|
+
IO_REPARSE_TAG_SYMLINK,
|
423
|
+
IO_REPARSE_TAG_MOUNT_POINT
|
424
|
+
].include?(get_reparse_point_tag(handle))
|
425
|
+
end
|
426
|
+
|
427
|
+
symlink
|
428
|
+
end
|
429
|
+
|
378
430
|
ffi_convention :stdcall
|
379
431
|
|
380
432
|
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa365512(v=vs.85).aspx
|