puppet 5.3.5 → 5.3.6
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/lib/puppet/application/cert.rb +3 -1
- data/lib/puppet/application/device.rb +99 -12
- data/lib/puppet/application/lookup.rb +11 -1
- data/lib/puppet/context.rb +1 -1
- data/lib/puppet/functions/map.rb +1 -1
- data/lib/puppet/indirector/request.rb +6 -10
- data/lib/puppet/indirector/rest.rb +9 -9
- data/lib/puppet/network/http/connection.rb +8 -0
- data/lib/puppet/parser/compiler.rb +7 -0
- data/lib/puppet/parser/functions/new.rb +31 -46
- data/lib/puppet/parser/functions/return.rb +22 -1
- data/lib/puppet/provider/group/windows_adsi.rb +4 -7
- 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/resource/catalog.rb +1 -1
- data/lib/puppet/type/user.rb +34 -3
- data/lib/puppet/util/plist.rb +1 -1
- data/lib/puppet/util/reference.rb +1 -8
- data/lib/puppet/util/windows/adsi.rb +15 -18
- data/lib/puppet/util/windows/principal.rb +7 -6
- data/lib/puppet/util/windows/sid.rb +60 -7
- data/lib/puppet/version.rb +1 -1
- data/locales/ja/puppet.po +163 -140
- data/locales/puppet.pot +94 -76
- data/man/man5/puppet.conf.5 +91 -16
- data/man/man8/puppet-agent.8 +6 -2
- data/man/man8/puppet-apply.8 +2 -2
- 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 +33 -11
- 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-filebucket.8 +22 -4
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.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 +11 -2
- 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-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/integration/application/lookup_spec.rb +21 -0
- data/spec/integration/util/windows/adsi_spec.rb +86 -1
- data/spec/integration/util/windows/principal_spec.rb +10 -1
- data/spec/unit/application/cert_spec.rb +17 -5
- data/spec/unit/application/device_spec.rb +96 -2
- data/spec/unit/indirector/rest_spec.rb +43 -0
- data/spec/unit/parser/compiler_spec.rb +8 -0
- 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/util/plist_spec.rb +3 -3
- 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 +3415 -3415
@@ -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
|
@@ -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
|
@@ -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","18.04"]
|
29
29
|
defaultfor :operatingsystem => :cumuluslinux, :operatingsystemmajrelease => ["3"]
|
30
30
|
|
31
31
|
def self.instances
|
@@ -275,7 +275,7 @@ Puppet::Type.type(:user).provide :aix, :parent => Puppet::Provider::AixObject do
|
|
275
275
|
# Must receive "user:enc_password" as input
|
276
276
|
# command, arguments = {:failonfail => true, :combine => true}
|
277
277
|
# Fix for bugs #11200 and #10915
|
278
|
-
cmd = [self.class.command(:chpasswd), get_ia_module_args, '-e', '-c'
|
278
|
+
cmd = [self.class.command(:chpasswd), get_ia_module_args, '-e', '-c'].flatten
|
279
279
|
begin
|
280
280
|
output = execute(cmd, {:failonfail => false, :combine => true, :stdinfile => tmpfile.path })
|
281
281
|
# 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.
|
@@ -595,7 +595,7 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
|
|
595
595
|
transaction = Puppet::Transaction.new(self, options[:report], prioritizer)
|
596
596
|
transaction.tags = options[:tags] if options[:tags]
|
597
597
|
transaction.ignoreschedules = true if options[:ignoreschedules]
|
598
|
-
transaction.for_network_device = options[:network_device]
|
598
|
+
transaction.for_network_device = Puppet.lookup(:network_device) { nil } || options[:network_device]
|
599
599
|
|
600
600
|
transaction
|
601
601
|
end
|
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?(":")
|
data/lib/puppet/util/plist.rb
CHANGED
@@ -41,7 +41,7 @@ module Puppet::Util::Plist
|
|
41
41
|
|
42
42
|
Puppet.debug "Plist #{file_path} ill-formatted, converting with plutil"
|
43
43
|
begin
|
44
|
-
plist = Puppet::Util::Execution.execute(['/usr/bin/plutil', '-convert', 'xml1', '-o', '
|
44
|
+
plist = Puppet::Util::Execution.execute(['/usr/bin/plutil', '-convert', 'xml1', '-o', '-', file_path],
|
45
45
|
{:failonfail => true, :combine => true})
|
46
46
|
return parse_plist(plist)
|
47
47
|
rescue Puppet::ExecutionFailure => detail
|
@@ -12,10 +12,6 @@ class Puppet::Util::Reference
|
|
12
12
|
|
13
13
|
instance_load(:reference, 'puppet/reference')
|
14
14
|
|
15
|
-
def self.footer
|
16
|
-
"\n\n----------------\n\n" + _("*This page autogenerated on %{current_time}*\n") % { current_time: Time.now.to_s }
|
17
|
-
end
|
18
|
-
|
19
15
|
def self.modes
|
20
16
|
%w{pdf text}
|
21
17
|
end
|
@@ -111,15 +107,12 @@ class Puppet::Util::Reference
|
|
111
107
|
def to_markdown(withcontents = true)
|
112
108
|
# First the header
|
113
109
|
text = markdown_header(@title, 1)
|
114
|
-
|
115
|
-
text << _("\n\n**This page is autogenerated; any changes will get overwritten** *(last generated on %{current_time})*\n\n") % { current_time: Time.now.to_s }
|
110
|
+
text << _("\n\n**This page is autogenerated; any changes will get overwritten**\n\n")
|
116
111
|
|
117
112
|
text << @header
|
118
113
|
|
119
114
|
text << generate
|
120
115
|
|
121
|
-
text << self.class.footer if withcontents
|
122
|
-
|
123
116
|
text
|
124
117
|
end
|
125
118
|
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
|
@@ -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
|
|
@@ -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,7 +154,7 @@ 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.
|
157
|
+
sid = Puppet::Util::Windows::SID.name_to_principal(name)
|
156
158
|
raise Puppet::Error.new( _("Could not resolve name: %{name}") % { name: name } ) if !sid
|
157
159
|
[sid.sid, sid]
|
158
160
|
end
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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?
|
@@ -508,7 +505,7 @@ module Puppet::Util::Windows::ADSI
|
|
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
|
@@ -32,9 +32,10 @@ module Puppet::Util::Windows::SID
|
|
32
32
|
@sid_bytes == compare.sid_bytes
|
33
33
|
end
|
34
34
|
|
35
|
-
#
|
35
|
+
# returns authority qualified account name
|
36
|
+
# prefer to compare Principal instances with == operator or by #sid
|
36
37
|
def to_s
|
37
|
-
@
|
38
|
+
@domain_account
|
38
39
|
end
|
39
40
|
|
40
41
|
# = 8 + max sub identifiers (15) * 4
|
@@ -64,14 +65,14 @@ module Puppet::Util::Windows::SID
|
|
64
65
|
last_error = FFI.errno
|
65
66
|
|
66
67
|
if (success == FFI::WIN32_FALSE && last_error != ERROR_INSUFFICIENT_BUFFER)
|
67
|
-
raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountNameW'), last_error)
|
68
|
+
raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountNameW with account: %{account_name}') % { account_name: account_name}, last_error)
|
68
69
|
end
|
69
70
|
|
70
71
|
FFI::MemoryPointer.new(:lpwstr, domain_length_ptr.read_dword) do |domain_ptr|
|
71
72
|
if LookupAccountNameW(system_name_ptr, account_name_ptr,
|
72
73
|
sid_ptr, sid_length_ptr,
|
73
74
|
domain_ptr, domain_length_ptr, name_use_enum_ptr) == FFI::WIN32_FALSE
|
74
|
-
|
75
|
+
raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountNameW with account: %{account_name}') % { account_name: account_name} )
|
75
76
|
end
|
76
77
|
|
77
78
|
# with a SID returned, loop back through lookup_account_sid to retrieve official name
|
@@ -116,14 +117,14 @@ module Puppet::Util::Windows::SID
|
|
116
117
|
last_error = FFI.errno
|
117
118
|
|
118
119
|
if (success == FFI::WIN32_FALSE && last_error != ERROR_INSUFFICIENT_BUFFER)
|
119
|
-
raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountSidW'), last_error)
|
120
|
+
raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountSidW with bytes: %{sid_bytes}') % { sid_bytes: sid_bytes}, last_error)
|
120
121
|
end
|
121
122
|
|
122
123
|
FFI::MemoryPointer.new(:lpwstr, name_length_ptr.read_dword) do |name_ptr|
|
123
124
|
FFI::MemoryPointer.new(:lpwstr, domain_length_ptr.read_dword) do |domain_ptr|
|
124
125
|
if LookupAccountSidW(system_name_ptr, sid_ptr, name_ptr, name_length_ptr,
|
125
126
|
domain_ptr, domain_length_ptr, name_use_enum_ptr) == FFI::WIN32_FALSE
|
126
|
-
raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountSidW'))
|
127
|
+
raise Puppet::Util::Windows::Error.new(_('Failed to call LookupAccountSidW with bytes: %{sid_bytes}') % { sid_bytes: sid_bytes} )
|
127
128
|
end
|
128
129
|
|
129
130
|
return new(
|
@@ -52,18 +52,18 @@ module Puppet::Util::Windows
|
|
52
52
|
# 'BUILTIN\Administrators', or 'S-1-5-32-544', and will return the
|
53
53
|
# SID. Returns nil if the account doesn't exist.
|
54
54
|
def name_to_sid(name)
|
55
|
-
sid =
|
55
|
+
sid = name_to_principal(name)
|
56
56
|
|
57
57
|
sid ? sid.sid : nil
|
58
58
|
end
|
59
59
|
module_function :name_to_sid
|
60
60
|
|
61
|
-
# Convert an account name, e.g. 'Administrators' into a SID object,
|
61
|
+
# Convert an account name, e.g. 'Administrators' into a Principal::SID object,
|
62
62
|
# e.g. 'S-1-5-32-544'. The name can be specified as 'Administrators',
|
63
63
|
# 'BUILTIN\Administrators', or 'S-1-5-32-544', and will return the
|
64
64
|
# SID object. Returns nil if the account doesn't exist.
|
65
65
|
# This method returns a SID::Principal with the account, domain, SID, etc
|
66
|
-
def
|
66
|
+
def name_to_principal(name)
|
67
67
|
# Apparently, we accept a symbol..
|
68
68
|
name = name.to_s.strip if name
|
69
69
|
|
@@ -81,21 +81,50 @@ module Puppet::Util::Windows
|
|
81
81
|
rescue
|
82
82
|
nil
|
83
83
|
end
|
84
|
-
module_function :
|
84
|
+
module_function :name_to_principal
|
85
|
+
class << self; alias name_to_sid_object name_to_principal; end
|
85
86
|
|
86
|
-
# Converts an octet string array of bytes to a SID object,
|
87
|
+
# Converts an octet string array of bytes to a SID::Principal object,
|
87
88
|
# e.g. [1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0] is the representation for
|
88
89
|
# S-1-5-18, the local 'SYSTEM' account.
|
89
90
|
# Raises an Error for nil or non-array input.
|
90
91
|
# This method returns a SID::Principal with the account, domain, SID, etc
|
91
|
-
def
|
92
|
+
def octet_string_to_principal(bytes)
|
92
93
|
if !bytes || !bytes.respond_to?('pack') || bytes.empty?
|
93
94
|
raise Puppet::Util::Windows::Error.new(_("Octet string must be an array of bytes"))
|
94
95
|
end
|
95
96
|
|
96
97
|
Principal.lookup_account_sid(bytes)
|
97
98
|
end
|
98
|
-
module_function :
|
99
|
+
module_function :octet_string_to_principal
|
100
|
+
class << self; alias octet_string_to_sid_object octet_string_to_principal; end
|
101
|
+
|
102
|
+
# Converts a COM instance of IAdsUser or IAdsGroup to a SID::Principal object,
|
103
|
+
# Raises an Error for nil or an object without an objectSID / Name property.
|
104
|
+
# This method returns a SID::Principal with the account, domain, SID, etc
|
105
|
+
# This method will return instances even when the SID is unresolvable, as
|
106
|
+
# may be the case when domain users have been added to local groups, but
|
107
|
+
# removed from the domain
|
108
|
+
def ads_to_principal(ads_object)
|
109
|
+
if !ads_object || !ads_object.respond_to?(:ole_respond_to?) ||
|
110
|
+
!ads_object.ole_respond_to?(:objectSID) || !ads_object.ole_respond_to?(:Name)
|
111
|
+
raise Puppet::Error.new("ads_object must be an IAdsUser or IAdsGroup instance")
|
112
|
+
end
|
113
|
+
octet_string_to_principal(ads_object.objectSID)
|
114
|
+
rescue Puppet::Util::Windows::Error => e
|
115
|
+
# if the error is not a lookup / mapping problem, immediately re-raise
|
116
|
+
raise if e.code != ERROR_NONE_MAPPED
|
117
|
+
|
118
|
+
# if the Name property isn't formatted like a SID, OR
|
119
|
+
if !valid_sid?(ads_object.Name) ||
|
120
|
+
# if the objectSID doesn't match the Name property, also raise
|
121
|
+
((converted = octet_string_to_sid_string(ads_object.objectSID)) != ads_object.Name)
|
122
|
+
raise Puppet::Error.new("ads_object Name: #{ads_object.Name} invalid or does not match objectSID: #{ads_object.objectSID} (#{converted})", e)
|
123
|
+
end
|
124
|
+
|
125
|
+
unresolved_principal(ads_object.Name, ads_object.objectSID)
|
126
|
+
end
|
127
|
+
module_function :ads_to_principal
|
99
128
|
|
100
129
|
# Convert a SID string, e.g. "S-1-5-32-544" to a name,
|
101
130
|
# e.g. 'BUILTIN\Administrators'. Returns nil if an account
|
@@ -193,6 +222,30 @@ module Puppet::Util::Windows
|
|
193
222
|
end
|
194
223
|
module_function :get_length_sid
|
195
224
|
|
225
|
+
def octet_string_to_sid_string(sid_bytes)
|
226
|
+
sid_string = nil
|
227
|
+
|
228
|
+
FFI::MemoryPointer.new(:byte, sid_bytes.length) do |sid_ptr|
|
229
|
+
sid_ptr.write_array_of_uchar(sid_bytes)
|
230
|
+
sid_string = Puppet::Util::Windows::SID.sid_ptr_to_string(sid_ptr)
|
231
|
+
end
|
232
|
+
|
233
|
+
sid_string
|
234
|
+
end
|
235
|
+
module_function :octet_string_to_sid_string
|
236
|
+
|
237
|
+
# @api private
|
238
|
+
def self.unresolved_principal(name, sid_bytes)
|
239
|
+
Principal.new(
|
240
|
+
name + " (unresolvable)", # account
|
241
|
+
sid_bytes, # sid_bytes
|
242
|
+
name, # sid string
|
243
|
+
nil, #domain
|
244
|
+
# https://msdn.microsoft.com/en-us/library/cc245534.aspx?f=255&MSPPError=-2147217396
|
245
|
+
# Indicates that the type of object could not be determined. For example, no object with that SID exists.
|
246
|
+
:SidTypeUnknown)
|
247
|
+
end
|
248
|
+
|
196
249
|
ffi_convention :stdcall
|
197
250
|
|
198
251
|
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa379151(v=vs.85).aspx
|