Журнал Системный Администратор, Февраль 2004

Журнал Системный Администратор

Февраль 2004

Цена: $4.5 US

  Подписаться

Зарегистриванные пользователи, пожалуйста следуйте этой ссылке

Версия для печати Вернуться к оглавлению

Программное управление ADSI: WinNT

Иван Коробко

В предыдущей статье были рассмотрены теоретические аспекты построения Active Directory и проведен обзор доступных провайдеров, с помощью которых можно программно управлять Active Directory. Одним из таких провайдеров является WinNT, основы программирования которого будут рассмотрены в данной статье.

Объектная модель провайдера WinNT

Рассмотрим программное управление ADSI с помощью провайдера WinNT, с помощью которого осуществляется доступ к классам. Каждый класс содержит один или несколько подклассов. Объектная модель протокола WinNT, в которой перечислены только классы, приведена на рисунке 1.

Рисунок 1

Доступ к объектам по протоколу WinNT описывается запросом, имеющим вид:

WinNT:[//DomainName[/ComputerName[/ObjectName[,ClassName]]]]

 

Доступ к провайдеру WinNT осуществляется по одному из шаблонов:

1) Название класса содержится в запросе. С помощью функции GetObject формируется запрос, который включает в себя четыре параметра: название протокола – WinNT, имя домена – DomainName, рабочей станции – ComputerName, название объекта – ObjectName, название класса – ClassName. В этом случае доступ к подклассам осуществляется с помощью цикла For. На VBScript в общем виде запрос выглядит следующим образом:

 

Пример 1а)

 

Set obj=GetObject("WinNT://" & DomainName & "/" & ComputerName & "/" & ObjectName & "," &  ClassName).

For Each element In obj

element.value

Next

 

    Параметры ComputerName и ObjectName могут отсутствовать в том случае, если осуществляется поиск объектов.

2) Подключение к классу с помощью фильтра. Метод по своей сути аналогичен предыдущему. Такой способ доступа к данным позволяет значительно увеличить скорость исполнения скрипта.

 

Пример 1б)

 

Set obj = GetObject("WinNT://" & DomainName)

obj.Filter = Array("user")

For Each element In obj

element.value

Next

Приведем два примера: в первом примере будет осуществляться поиск объектов класса и вывод свойств этих объектов, во втором – чтение и вывод свойств заданного объекта. В первом примере с помощью скрипта на VBScript будут определены учетные записи пользователей домена и прочитаны их имена:

Пример 2а). Первый способ доступа к объектной модели

 

strDomain="MyDomain"

    Set Computer =GetObject("WinNT://" & strDomain & ",user")

           For Each User in Computer

           users_d=users_d & "  "& User.Name  & chr(13)

           Next

Wsh.Echo users_d

 

Пример 2б) Второй способ  доступа к объектной модели

 

strDomain="MyDomain"

    Set Computer =GetObject("WinNT://" & strDomain)

    Computer.Filter = Array("user")

           For Each User in Computer

           users_d=users_d & "  "& User.Name  & chr(13)

           Next

Wsh.Echo users_d

Во втором примере явным образом задается имя пользователя и осуществляется чтение его свойств:

Пример 3a). Первый способ  доступа к объектной модели

 

strDomain="MyDomain"

strUser="MyUserName"

    Set Computer =GetObject("WinNT://" & strDomain & "/" & strUser & ",user")

           users_d= User.Name & chr(13)

Wsh.Echo users_d

 

Пример 3б). Второй способ доступа к объектной модели

 

strDomain="MyDomain"

    Set Computer =GetObject("WinNT://" & strDomain)

    Computer.Filter = Array("user")

           For Each User in Computer

           users_d= User.Name  & chr(13)

           Next

Wsh.Echo users_d

Чтобы эффективно пользоваться объектной моделью, необходимо знать назначение классов, какие они включают в себя подклассы и какие параметры имеют подклассы. Назначение и название каждого класса приведено в таблице 1:

Таблица 1

 

objectClass

Описание класса

Domain

Класс предназначен для подключения к домену.

Явное использование домена экономит сетевой трафик.

Computer

Класс предназначен для определения роли компбютера в домену,

управления компьютера.

User

Осуществляется управление пользователями: создание, удаление.

Управление свойствами пользователя: активизация пользователя, подключение домашнего каталога или сценария загрузки; управление параметрами, касающихся пароля; Чтение характеристик пользователя: описание, расположение, телефон и др. параметры.

Group

Управление группами: создание локальных/глобальных групп,

преобразование типов групп, определение членства в группах и т.д.

FileShare

Управление файловыми ресурсами: предоставление ресурсов пользователям.

PrintQueue

Управление локальным принтером: перезагрузка принтера,

его приостановка, возобновление работы; чтение полей принтер.

PrintJobs

Подкласс класса PrintQueue, с помощью которого осуществляется управление очередью печати: установка приоритетов заданий, управление заданиями.

Соответствия классов и подклассов приведено в таблице 2:

Таблица 2

 

Название класса

Описание класса

Namespace

Контейнер верхнего уровня

Domain

Доступные домены Windows

User

Управление пользователем

Group

 

UserGroupCollection

Управление группами пользователей

GroupCollection

Управление другими группами

Computer

Определение параметров компьютера

PrintJob

 

PrintJobsCollection

Управление заданием

PrintQueue

Управление принтером

Service

 

FileService

 

FileShare

Управление предоставлением объектов в общее пользование

Resource

Управление сервисами

Session

Управление сессиями

User

Управление локальными учетными записями пользователей

Group

 

UserCollection

Свойства локальных пользователей

GroupCollection

Свойства локальных групп

Из объектной модели протокола WinNT видно, что в пространстве имен NameSpace существует всего два класса: Domain и Computer. Рассмотрим каждый из этих классов в отдельности.

Класс Domain

Определение доступных доменов

Класс Domain является верхним уровнем пространства имен, поэтому для определения доступных доменов в функции GetObject() ограничиваются название протокола. Необходимо помнить, что название протокола должно быть написано именно WinNT – в противном случае сценарий выдаст ошибку:

Пример 4

 

Set obj=GetObject("WinNT:")

    For Each element In obj

    temp=element.Name

    Next

MsgBox temp

Чтение параметров класса Domain

Класс Domain включает в себя восемь параметров. Все эти параметры задаются в групповых политиках, за исключением параметра Name. Описание параметров см. в Приложении.

При создании скрипта на VBScript необходимо помнить, что VBScript не преобразует типы данных автоматически, поэтому числовые данные необходимо преобразовывать в строковые с помощью функции cstr().

Пример 5. Чтение всех полей класса Computer

 

Set obj=GetObject("WinNT:")

    For Each element In obj

t1="Name: " + cstr(element.Name)+chr(13)

t2="MinPasswordLength: "+ cstr(element.MinPasswordLength)+chr(13)

t3="MinPasswordAge: " + cstr(element.MinPasswordAge)+chr(13)

t4="MaxBadPasswordsAllowed: "+ cstr(element.MaxBadPasswordsAllowed)+chr(13)

t5="AutoUnlockInterval: " + cstr(element.AutoUnlockInterval)+chr(13)

t6="LockoutObservationInterval: " + cstr(element.LockoutObservationInterval)

temp=temp+t1+t2+t3+t4+t5+t6+chr(13)+chr(13)

    Next

MsgBox temp

Значения MinPasswordAge и MaxPasswordAge указываются в групповых политиках в днях, поэтому необходим перевод в дни, для чего полученное число необходимо разделить на 86400; значения MinPasswordAge и LockoutObservationInterval указываются в групповых политиках в минутах, поэтому полученные значения необходимо разделить на 60.

Обновление параметров класса Domain

Установка новых параметров перечисленных значений осуществляется с помощью метода SetInfo.

Пример 6. Изменение значения минимальной длины пароля в домене (NewLenght=10)

 

    NewLenght=10

Set obj=GetObject("WinNT:")

    For Each element In obj

           element.MinPasswordLength= NewLenght

           obj.SetInfo

    temp ="NEW: MinPasswordLength: "+ cstr(element.MinPasswordLength)+chr(13)

    Next

      MsgBox temp

Перечисление объектов класса Domain

Просмотр содержимого контейнера осуществляется с помощью конструкции For в соответствии с приведенным ниже шаблоном. В качестве значения переменной Container может быть имя домена или компьютера:

Пример 7

 

Container="Value"

Set obj=GetObject("WinNT://"& Container)

    For Each element In obj

    temp = temp + element.name + ";    "

    Next

MsgBox temp

Такой метод перечисления объектов будет возвращать все содержимое любой базы SAM – контроллера домена, сервера или рабочей станции.

В приведенном примере возвращались объекты всех классов, содержащиеся в домене (или в локальной базе SAM), поскольку тип объектов не определялся. Поскольку в домене огромное количество объектов, для увеличения скорости работы скрипта целесообразно использовать фильтр. Фильтр может в себя включать следующие объекты:

Таблица 3

 

Объект

Описание

Объект

Описание

User

Учетная запись пользователя

Group

Все группы

Computer

Учетная запись компьютера

LocalGroup

Локальная группа

Service

Сервис

GlobalGroup

Глобальная группа

 

Пример 8:  Определение всех учетных записей пользователей, входящих в домен

 

Set objDomain=GetObject("WinNT:")

    For Each domain_element In objDomain

    Domain_Name= domain_element.Name

    Next

Set obj=GetObject("WinNT://" & Domain_Name)

    obj.filter=array("user")

           For Each element In obj

 temp =temp+element.name+";    "

           Next

Создание, переименование и удаление объектов в домене

В Active Directory существует три типа встроенных объектов: учетная запись пользователя; группа, которая может быть локальной или глобальной; учетная запись компьютера. С учетной записью пользователя можно проделывать следующие операции: создавать, удалять, переименовывать; группу можно создавать и удалять; учетную запись компьютера можно создавать и удалять.

Создание объектов

Создание учетной записи пользователя осуществляется с помощью функции Create(). Приведем пример, в котором создается учетная запись пользователя с именем UserName. При создании скрипта манипуляции с паролем и другими параметрами учетной записи должны производиться, когда учетная запись существует, т.е. после применения метода: SetInfo.

Пример 9

 

Set objDomain=GetObject("WinNT:")

    For Each domain_element In objDomain

    Domain_Name= domain_element.Name

    Next

           Set obj=GetObject("WinNT://" & Domain_Name)

                 NewUser="UserName"

                 Set CU=obj.Create("User",NewUser)

                 CU.SetInfo

Создание учетной записи группы отличается тем, что необходимо указать тип группы с помощью функции Put(). Локальной группе соответствует значение «4», глобальной – «2».

Пример 10. Создания локальной группы с именем GroupName

 

Set objDomain=GetObject("WinNT:")

    For Each domain_element In objDomain

    Domain_Name= domain_element.Name

    Next

           Set obj=GetObject("WinNT://" & Domain_Name)

                 NewGroup="GroupName"

                 Set CG=obj.Create("Group",NewGroup)

                 CG.Put "groupType", 4

                 CG.SetInfo

 

Создание учетной записи компьютера аналогично созданию учетной записи пользователя, за исключением следующего:

n  объект должен быть создан с использованием класса computer;

n  у объекта должен быть установлен пользовательский флаг Ошибка! Недопустимый объект гиперссылки. (см. раздел «Манипулирование пользовательскими флагами функцией UserFlags»);

n  начальный пароль учетной записи должен соответствовать имени компьютера, введенного строчными буквами. Результата добиваются с помощью функции LCase().

 

Пример 11. Создания учетной записи компьютера с именем ComputerName

 

Set objDomain=GetObject("WinNT: ")

    For Each domain_element In objDomain

    Domain_Name= domain_element.Name

    Next

           Set obj=GetObject("WinNT://" & Domain_Name)

                 NewComputer="ComputerName"

                 Set CC=obj.Create("Computer", UCase(NewComputer))

           CC.SetInfo

Set CAccount= GetObject("WinNT://" & ї

    Domain_Name&"/"& NewComputer&"$,user")

CAccount.Put "UserFlags", (CAccount.Get("UserFlags") Or &H1000)

           CAccount.SetPassword(LCase(NewComputer))

           CAccount.SetInfo

Удаление объектов

Все три типа объектов удаляются, используя метод Delete. Приведем шаблон, в котором переменная ClassName может принимать значение computer, user, group; NameOfObject – имя удаляемого объекта:

Пример 12

 

Set objDomain=GetObject("WinNT: ")

    For Each domain_element In objDomain

    Domain_Name= domain_element.Name

    Next

           Set obj=GetObject("WinNT://" & Domain_Name)

                 ClassName="____"

                 NameOfObject="____"

                 Set CC=obj.Delete (ClassName, NameOfObject)

Обратите внимание, что объект удаляется немедленно и использовать метод SetInfo не нужно.

Переименование объектов

Среди трех ранее перечисленных объектов переименованию поддается только учетная запись пользователя. Переименование учетной записи осуществляется с помощью функции MoveHere():

Пример 13

 

Set objDomain=GetObject("WinNT: ")

    For Each domain_element In objDomain

    Domain_Name= domain_element.Name

    Next

           OldUserName="____"

           NewUserName="____"

           Set obj=GetObject("WinNT://" ї

                 & Domain_Name&"/"& OldUserName&",user")

      obj.MoveHere(User.AdsPath, NewUserName)

      obj.Nothing

Подкласс User

Учетные записи пользователей домена содержатся в подклассе User. Подкласс включает в себя более 20 параметров, некоторые из которых не поддерживаются Windows 2k. Описание параметров см. в Приложении. Параметры подкласса изначально задаются в групповых политиках.

Пример 14. Чтения параметров подкласса User

 

Set obj=GetObject("WinNT:")

    For Each str In obj

    DomainName=str.Name

    Next

Set UserName="Value"

Set element=GetObject("WinNT://" & DomainName & "/"& UserName)

u1="FullName: "+ cstr(element.FullName)+chr(13)

u2="UserFlags: "+ cstr(element.UserFlags)+chr(13)

u3="LoginScript: "+ cstr(element.LoginScript)+chr(13)

u4="MaxBadPasswordsAllowed: "+ cstr(element.MaxBadPasswordsAllowed)+chr(13)

u5="PasswordHistoryLength: "+ cstr(element.PasswordHistoryLength)+chr(13)

u6="AutoUnlockInterval: "+ cstr(element.AutoUnlockInterval)+chr(13)

u7="PasswordAge: "+ cstr(element.PasswordAge)+chr(13)

u8="PasswordExpired: "+ cstr(element.PasswordExpired)+chr(13)

temp=""

temp=u1+u2+u3

Манипулирование пользовательскими флагами функцией UserFlags

Для просмотра и изменения состояния пользовательских флагов в базе SAM применяются методы Get() и Put(), соответственно. Ниже приведены константы и их описание. Константы представляют собой шестнадцатеричные значения флагов:

Таблица 4

 

Название

Значение

Описание

Ошибка! Недопустимый объект гиперссылки.

0X0001

Управление исполнения сценария загрузки

Ошибка! Недопустимый объект гиперссылки.

0X0002

Управление флагом «Account is Disable»

Ошибка! Недопустимый объект гиперссылки.

0X0003

Требуется домашний каталог

Ошибка! Недопустимый объект гиперссылки.

0X0010

Управление блокировкой учетной записи

Ошибка! Недопустимый объект гиперссылки.

0X0020

Не требуется пароль для регистрации в сети

и на локальном компьютере

Ошибка! Недопустимый объект гиперссылки.

0X0040

Управление флагом «User Cannot Change Password»

Ошибка! Недопустимый объект гиперссылки.

0X0080

Разрешить пользователя отправлять зашифрованный пароль

Ошибка! Недопустимый объект гиперссылки.

0X0100

Этот флаг обеспечивает пользователям доступ пользователя в текущем домене, но не дают

им права доступа в домены, которые имеют доверительные отношения с текущим доменом. Для данного домена учетная запись становится локальной.

Ошибка! Недопустимый объект гиперссылки.

0X0200

Типичная учетная запись пользователя

Ошибка! Недопустимый объект гиперссылки.

0X0800

Флаг, противоположный флагу Ошибка! Недопустимый объект гиперссылки. Делает учетную запись глобальной

Ошибка! Недопустимый объект гиперссылки.

0X1000

Управление членством в домене рабочей станции

Ошибка! Недопустимый объект гиперссылки.

0X2000

Учетная запись компьютера BDC

Ошибка! Недопустимый объект гиперссылки.

0X10000

Управление флагом «Password Never Expires»

Ошибка! Недопустимый объект гиперссылки.

0X20000

Учетная запись MNS Logon

Ошибка! Недопустимый объект гиперссылки.

0X40000

Необходимо использовать Smart-карту для регистрации пользователя в сети

Ошибка! Недопустимый объект гиперссылки.

0X80000

Установка делигирования

Ошибка! Недопустимый объект гиперссылки.

0X100000

Флаг, противоположный Ошибка! Недопустимый объект гиперссылки.

 

Обратите внимание, что в таблице нет флага для параметра «User Must Change Password at Next Logon». Для установки флага следует менять значение свойства PasswordExpired. О том, как это сделать, речь пойдет позже. Для просмотра и изменения шестнадцатеричных флагов используют операторы Or, Xor и And следующим образом:

n  оператор Or – для начальной установки бита. На практике используется в случае создания новой учетной записи пользователя;

n  оператор Xor – для переключения статуса флага. Флаг может быть активизирован и дезактивирован;

n  оператор And – для просмотра значения, хранящегося в базе SAM.

Для просмотра значения флага используется функция Get(). Рассмотрим пример, в котором прочитаем значение параметра ADS_UF_DONTEXPIREPASSWD – управление флагом «Password Never Expires»:

Пример 15

 

Set obj=GetObject("WinNT:")

           For Each str In obj

           DomainName=str.Name

           Next

Set UserName="Value"

temp=""

    Set element=GetObject("WinNT://" & DomainName & "/"& UserName)

           flag=element.Get("UserFlags")

           if (flag AnD &H10000)<>0 then

                 temp="Флаг установлен"

           else

                 temp="Флаг не установлен"

           end if

MsgBox temp

Для изменения значения флага используется функция Put(), которая имеет следующий формат: value.Put «UserFlags» String. Рассмотрим использование данной функции на примере, в котором изменим значение параметра на противоположное ADS_UF_DONTEXPIREPASSWD. Для того чтобы изменения вступили в силу, необходимо использовать метод value.SetInfo.

Пример 16

 

Set obj=GetObject("WinNT:")

           For Each str In obj

           DomainName=str.Name

           Next

ADS_UF_DONTEXPIREPASSWD=&H0040

Set UserName="Value"

    Set element=GetObject("WinNT://" & DomainName & "/"& UserName)

element.put "userFlags", element.Get("UserFlags") Xor ADS_UF_DONTEXPIREPASSWD

element.setinfo

 

    MsgBox element.get("UserFlags")

Подкласс Group

Подкласс Group включает в себя 2 параметра: описание и SID группы. Чтение этих параметров происходит аналогичным способом, описанным в предыдущем разделе. Изменение описание группы осуществляется использованием метода SetInfo.

Взаимосвязь учетных записей пользователей и групп

В этом параграфе будут рассмотрены вопросы добавления и исключения учетной записи пользователя из группы членства пользователей в группе, принадлежность пользователя к группам.

1) Добавление пользователя в группу осуществляется с помощью функции Add(), для удаления пользователя – функция Remove(). При использовнии метода Add() чтобы изменения вступили в силу, необходимо использовать метод SetInfo. Удаление учетной записи пользователя из группы происходит сразу после вызова метода Remove.

Пример 17. Добавление учетной записи Value_Name в группу Value_Group

 

    Set obj=GetObject("WinNT:")

                 For Each str In obj

                 DomainName=str.Name

                 Next

    Set UserName="Value_Name"

    Set GroupName="Value_Group"

 

Set element_user=GetObject("WinNT://" & DomainName & "/"& UserName & ", user")

Set element_group=GetObject("WinNT://" & DomainName & "/"& GroupName & ", group")

    element_group.Add(element_user.ADsPath)

    element_group.SetInfo

Для удаления учетной записи из группы в приведенном примере последние две строки необходимо заменить на строку element_group.Remove(element_user.ADsPath).

2) Для перечисления всех пользователей группы, например, группы GroupName, используют свойство Members:

Пример 18

 

    Set obj=GetObject("WinNT:")

                 For Each str In obj

                 DomainName=str.Name

                 Next

Set GroupName="Value_Group"

Set element_group=GetObject("WinNT://" & DomainName & "/"& GroupName & ", group")

    For each obj inGroup.Members

    temp=temp+Member.Name

    Next

MsgBox temp

3) Просмотр списка групп, к которой принадлежит пользователь. Использующийся в данном примере метод ISMember возвращает значение типа Boolean, т.е. True/False. Сценарий условно можно разделить на три части – определение текущего домена, определение списка групп в домене и проверка членства в группе.

Пример 19

 

Set objDomain=GetObject("WinNT: ")

    For Each domain_element In objDomain

    Domain_Name= domain_element.Name

    Next

UserName="Administrator"

Set element_user=GetObject("WinNT://" & DomainName & "/"& UserName)

    Set obj=GetObject("WinNT://" & DomainName)

    obj.filter=array("group")

           For Each element In obj

           Set element_group=GetObject("WinNT://" & DomainName& "/"& element.name )

                        if element_group.IsMember (element_user.ADsPath)="True" then

                               temp