Class: Puppet::Util::Windows::ADSI::User

Inherits:
Object
  • Object
show all
Extended by:
Enumerable, FFI::Library
Defined in:
lib/puppet/util/windows.rb,
lib/puppet/util/windows/adsi.rb

Constant Summary collapse

MAX_USERNAME_LENGTH =

UNLEN from lmcons.h - stackoverflow.com/a/2155176

256

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from FFI::Library

attach_function_private

Constructor Details

#initialize(name, native_user = nil) ⇒ User

Returns a new instance of User.



112
113
114
115
# File 'lib/puppet/util/windows/adsi.rb', line 112

def initialize(name, native_user = nil)
  @name = name
  @native_user = native_user
end

Instance Attribute Details

#nameObject (readonly)



111
112
113
# File 'lib/puppet/util/windows/adsi.rb', line 111

def name
  @name
end

#native_userObject



110
111
112
# File 'lib/puppet/util/windows/adsi.rb', line 110

def native_user
  @native_user
end

#sidObject (readonly)



111
112
113
# File 'lib/puppet/util/windows/adsi.rb', line 111

def sid
  @sid
end

Class Method Details

.create(name) ⇒ Object

Raises:



227
228
229
230
231
# File 'lib/puppet/util/windows/adsi.rb', line 227

def self.create(name)
  # Windows error 1379: The specified local group already exists.
  raise Puppet::Error.new( "Cannot create user if group '#{name}' exists." ) if Puppet::Util::Windows::ADSI::Group.exists? name
  new(name, Puppet::Util::Windows::ADSI.create(name, 'user'))
end

.current_user_nameObject



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/puppet/util/windows/adsi.rb', line 235

def self.current_user_name
  user_name = ''
  max_length = MAX_USERNAME_LENGTH + 1 # NULL terminated
  FFI::MemoryPointer.new(max_length * 2) do |buffer| # wide string
    FFI::MemoryPointer.new(:dword, 1) do |buffer_size|
      buffer_size.write_dword(max_length) # length in TCHARs

      if GetUserNameW(buffer, buffer_size) == FFI::WIN32_FALSE
        raise Puppet::Util::Windows::Error.new("Failed to get user name")
      end
      # buffer_size includes trailing NULL
      user_name = buffer.read_wide_string(buffer_size.read_dword - 1)
    end
  end

  user_name
end

.delete(name) ⇒ Object



257
258
259
# File 'lib/puppet/util/windows/adsi.rb', line 257

def self.delete(name)
  Puppet::Util::Windows::ADSI.delete(name, 'user')
end

.each(&block) ⇒ Object



261
262
263
264
265
266
267
268
269
270
# File 'lib/puppet/util/windows/adsi.rb', line 261

def self.each(&block)
  wql = Puppet::Util::Windows::ADSI.execquery('select name from win32_useraccount where localaccount = "TRUE"')

  users = []
  wql.each do |u|
    users << new(u.name)
  end

  users.each(&block)
end

.exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


253
254
255
# File 'lib/puppet/util/windows/adsi.rb', line 253

def self.exists?(name)
  Puppet::Util::Windows::ADSI::connectable?(User.uri(*User.parse_name(name)))
end

.logon(name, password) ⇒ Object



149
150
151
# File 'lib/puppet/util/windows/adsi.rb', line 149

def self.logon(name, password)
  Puppet::Util::Windows::User.password_is?(name, password)
end

.parse_name(name) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/puppet/util/windows/adsi.rb', line 117

def self.parse_name(name)
  if name =~ /\//
    raise Puppet::Error.new( "Value must be in DOMAIN\\user style syntax" )
  end

  matches = name.scan(/((.*)\\)?(.*)/)
  domain = matches[0][1] || '.'
   = matches[0][2]

  return , domain
end

.uri(name, host = '.') ⇒ Object



137
138
139
140
141
142
143
# File 'lib/puppet/util/windows/adsi.rb', line 137

def self.uri(name, host = '.')
  if sid_uri = Puppet::Util::Windows::ADSI.sid_uri_safe(name) then return sid_uri end

  host = '.' if ['NT AUTHORITY', 'BUILTIN', Socket.gethostname].include?(host)

  Puppet::Util::Windows::ADSI.uri(name, 'user', host)
end

Instance Method Details

#[](attribute) ⇒ Object



153
154
155
# File 'lib/puppet/util/windows/adsi.rb', line 153

def [](attribute)
  native_user.Get(attribute)
end

#[]=(attribute, value) ⇒ Object



157
158
159
# File 'lib/puppet/util/windows/adsi.rb', line 157

def []=(attribute, value)
  native_user.Put(attribute, value)
end

#add_flag(flag_name, value) ⇒ Object



174
175
176
177
178
179
180
# File 'lib/puppet/util/windows/adsi.rb', line 174

def add_flag(flag_name, value)
  flag = native_user.Get(flag_name) rescue 0

  native_user.Put(flag_name, flag | value)

  commit
end

#add_to_groups(*group_names) ⇒ Object Also known as: add_to_group



196
197
198
199
200
# File 'lib/puppet/util/windows/adsi.rb', line 196

def add_to_groups(*group_names)
  group_names.each do |group_name|
    Puppet::Util::Windows::ADSI::Group.new(group_name).add_member_sids(sid)
  end
end

#commitObject



161
162
163
164
165
166
167
168
# File 'lib/puppet/util/windows/adsi.rb', line 161

def commit
  begin
    native_user.SetInfo unless native_user.nil?
  rescue Exception => e
    raise Puppet::Error.new( "User update failed: #{e}", e )
  end
  self
end

#groupsObject



189
190
191
192
193
194
# File 'lib/puppet/util/windows/adsi.rb', line 189

def groups
  # WIN32OLE objects aren't enumerable, so no map
  groups = []
  native_user.Groups.each {|g| groups << g.Name} rescue nil
  groups
end

#password=(password) ⇒ Object



182
183
184
185
186
187
# File 'lib/puppet/util/windows/adsi.rb', line 182

def password=(password)
  native_user.SetPassword(password)
  commit
  fADS_UF_DONT_EXPIRE_PASSWD = 0x10000
  add_flag("UserFlags", fADS_UF_DONT_EXPIRE_PASSWD)
end

#password_is?(password) ⇒ Boolean

Returns:

  • (Boolean)


170
171
172
# File 'lib/puppet/util/windows/adsi.rb', line 170

def password_is?(password)
  self.class.logon(name, password)
end

#remove_from_groups(*group_names) ⇒ Object Also known as: remove_from_group



203
204
205
206
207
# File 'lib/puppet/util/windows/adsi.rb', line 203

def remove_from_groups(*group_names)
  group_names.each do |group_name|
    Puppet::Util::Windows::ADSI::Group.new(group_name).remove_member_sids(sid)
  end
end

#set_groups(desired_groups, minimum = true) ⇒ Object



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/puppet/util/windows/adsi.rb', line 210

def set_groups(desired_groups, minimum = true)
  return if desired_groups.nil? or desired_groups.empty?

  desired_groups = desired_groups.split(',').map(&:strip)

  current_groups = self.groups

  # First we add the user to all the groups it should be in but isn't
  groups_to_add = desired_groups - current_groups
  add_to_groups(*groups_to_add)

  # Then we remove the user from all groups it is in but shouldn't be, if
  # that's been requested
  groups_to_remove = current_groups - desired_groups
  remove_from_groups(*groups_to_remove) unless minimum
end

#uriObject



145
146
147
# File 'lib/puppet/util/windows/adsi.rb', line 145

def uri
  self.class.uri(sid., sid.domain)
end