Похоже, в Редмонде набирает силу новая тенденция.

Стимулом для преобразований послужило появление технологии Windows Management Instrumentation (WMI), на основе которой создаются инструменты.

Не нужно забывать, что WMI с самого начала была разработана для удаленных сценариев администрирования. Любая задача, решаемая локально с помощью WMI-совместимого инструмента, может быть выполнена и дистанционно. В данной статье приводится несколько сценариев, которые наглядно демонстрируют возможности удаленного администрирования с WMI. Сначала речь пойдет о простом WMI-сценарии для выполнения административных задач на локальном компьютере. Затем я покажу, как можно преобразовать этот сценарий для удаленного управления. И, наконец, мы рассмотрим, как запустить сценарий на всех компьютерах удаленной IP-подсети.

Статья рассчитана на тех читателей, которые уже имеют базовые знания о WMI и WMI-сценариях. Хорошее руководство для начинающих — «WMI Scripting Primer: Part 1» (http://msdn.microsoft.com/library/en-us/dnclinic/ html/scripting06112002.asp) компании Microsoft.

Решение для любых задач

Административная задача, которую я хочу выполнить на локальном компьютере, — проверка типа запуска (Startup Type) и статуса службы Telnet. Прежде чем читатели попросят избавить их от очередного сценария, я поспешу предупредить, что тип задачи не имеет значения. Вместо этой задачи можно взять любой из сотен WMI-сценариев, опубликованных на сайте Microsoft TechNet Script Center (http://www.microsoft.com/technet/scriptcenter). Цель данной статьи — показать, как преобразовать типичный сценарий для обслуживания сотен и тысяч удаленных компьютеров.

В Листинге 1 показана локальная версия сценария Telnet Server с подходящим названием TelnetCheck.vbs. Сценарий начинается с инициализации переменной strComputer строкой, состоящей из единственной точки. В сценариях WMI точка представляет локальный компьютер. Поскольку сценарий выполняется на локальном компьютере, я мог бы пропустить переменную strComputer, но, изолировав целевой компьютер с переменной (как показано в Листинге 1), проще приспособить сценарий к работе с удаленными машинами.

Функция GetObject обеспечивает соединение с WMI-службой на целевом компьютере. Строка, передаваемая сценарием в функцию GetObject, представляет собой строку связи WMI (моникер), состоящую из трех компонентов:

  • обязательный префикс WMI, «winmgmts:";
  • параметры безопасности, которые указывают WMI на необходимость имперсонализации вызывающего пользователя или программы (т. е. использование контекста безопасности лица или процесса, запускающего сценарий для организации соединения);
  • путь к объекту WMI, с которым нужно установить связь на целевом компьютере, состоящий из имени целевого компьютера и пространства имен WMI.

Функция GetObject возвращает ссылку на объект SWbemServices из библиотеки сценариев WMI, который представляет аутентифицированное соединение с WMI на локальном или удаленном компьютере. Более подробно о строке связи WMI рассказано в статье «WMI Monikers» (опубликованной по адресу: http://www.winnetmag.ru/win2000/worknt/701.htm).

После того как соединение установлено, сценарий в Листинге 1 вызывает метод SWbemServices ExecQuery, чтобы извлечь экземпляр класса Win32_Service, который представляет службу Telnet. ExecQuery возвращает ссылку на набор SWbemObjectSet — еще один объект автоматизации в библиотеке сценариев WMI. Если служба Telnet на целевом компьютере установлена, то ExecQuery возвращает набор, содержащий только один элемент, который ставится в соответствие переменной ссылочного типа с именем colServices. Если Telnet не установлена, то ExecQuery возвращает пустой набор. Свойство SWbemObjectSet Count используется для того, чтобы определить, есть ли на целевом компьютере Telnet. Если значение свойства Count равно 0, то метод WScript Echo пересылает на консоль сообщение, указывающее, что Telnet не установлена. В противном случае метод Echo передает Startup Type (свойство Win32_Service StartMode) и Status (свойство Win32_Service State) службы Telnet.

Чтобы запустить сценарий, приведенный в Листинге 1, нужно открыть командную строку и ввести с клавиатуры (предполагается, что сценарий сохранен в каталоге с именем C:\scripts):

C:\scripts>cscript telnetcheck.vbs

Если Telnet на локальном компьютере имеется, то на экране появится сообщение, аналогичное отображаемому на консоли:

ATL-LAB-01,Disabled,Stopped

Дистанционные сценарии

Нетрудно догадаться, что для переноса сценария в Листинге 1 на удаленные компьютеры достаточно заменить значение переменной strComputer на имя любого WMI-совместимого компьютера в данном домене. Например, чтобы запустить сценарий на удаленном компьютере с именем ATL-WEB-01, достаточно заменить

strComputer = «.»

на

strComputer = «atl-web-01»

Конечно, на практике невозможно изменять сценарий каждый раз, когда требуется запустить его на новом удаленном компьютере. Более удачное решение — указать имя удаленного компьютера в командной строке в качестве аргумента, как показано в Листинге 2.

Единственное различие между Листингами 1 и 2 — замена строки инициализации strComputer в Листинге 1 подпрограммой A в Листинге 2. Оператор If...Then...Else в подпрограмме A проверяет, есть ли в командной строке аргумент. Если аргумент сценарию передан, то переменной strComputer присваивается значение аргумента. В противном случае strComputer инициализируется точкой, которая представляет локальный компьютер. В остальном Листинг 1 идентичен Листингу 2.

Следующая команда показывает, как запустить сценарий в Листинге 2 на удаленном компьютере с именем ATL-WEB-01:

C:\scripts>cscript

telnetcheck.vbs atl-web-01

Легкость удаленного доступа подчеркивает одну из важнейших особенностей WMI: любая локальная задача может быть выполнена дистанционно. WMI использует распределенную модель объектов Distributed COM (DCOM), в которой для доступа к удаленным компьютерам, в свою очередь, применяется вызов удаленных процедур (remote procedure call, RPC) через подходящий сетевой транспорт. Простота удаленного администрирования WMI может вызвать у администратора ощущение уязвимости, однако по умолчанию дистанционный доступ к удаленному компьютеру через WMI возможен только при наличии у пользователя полномочий уровня Administrator. При отсутствии таких полномочий попытка запустить сценарий из Листинга 2 на удаленном WMI-совместимом компьютере приведет к ошибке Permission denied функции GetObject.

Можно посоветовать следующее: чтобы подготовить сотни WMI-сценариев, хранящихся в Script Center, для дистанционного применения, нужно просто заменить строку

strComputer = «.»

в сценарии Microsoft подпрограмn мой A из Листинга 2. В результате мгновенно формируются сотни сценариев, пригодных для работы с удаленными компьютерами; пользователь должен лишь указать имя удаленной машины в командной строке при запуске сценария.

Дистанционное управление всей IP-подсетью

Наряду с именами NetBIOS, для идентификации удаленных компьютеров можно использовать имена DNS и IP-адреса. Предположим, что компьютеру с именем ATL-WEB-01 из домена atl.acme.com назначен IP-адрес 192.168.0.3. Для обращения к удаленному компьютеру из сценария, показанного в Листинге 2, можно применить любой из перечисленных ниже способов:

strComputer = «atl-web-01»

strComputer = «192.168.0.3»

strComputer = «atl-web-01.atl.acme.com»

Благодаря распознаванию имен DNS и IP-адресов открываются дополнительные возможности видоизменения сценариев. Например, сценарий в Листинге 3 показывает, как запустить WMI-сценарий во всей IP-подсети.

Листинг 3 начинается с инициализации переменной strIPSubnet сетевым адресом целевой подсети. В данном примере используется частная сеть 192.168.0.0/24 класса C. Затем сценарий создает объект Windows Script Host (WSH) Shell. Объект Shell, на который указывает переменная objShell, будет вызывать метод Exec объекта Shell (чуть ниже объясняется, почему). Кроме того, сценарий активизирует механизм обработки ошибок VBScript, On Error Resume Next, чтобы перехватить ошибку, которая возникает при попытке сценария установить связь с WMI-несовместимым устройством или с WMI-совместимым компьютером при отсутствии административных полномочий.

Настоящая работа начинается в цикле For. При каждом повторении цикла For увеличивается счетчик с именем strIPNode. Счетчик strIPNode представляет базовую часть целевого IP-адреса. Первое действие в теле цикла For объединяет текущее значение strIPNode с strIPSubnet и сохраняет результирующую строку в strComputer.

Затем сценарий использует метод Exec объекта WSH Shell и утилиту ping.exe операционной системы для тестирования целевого компьютера. Необходимость предварительного тестирования вызвана особенностями работы WMI-соединений. В типичных условиях тайм-аута WMI приходится ждать довольно долго — не менее 1 мин. Если большое число компьютеров в целевой подсети работает в автономном режиме и недоступно, то время выполнения сценария заметно увеличивается.

Например, предположим, что недоступна половина узлов типичной подсети класса C. Если не запустить утилиту Ping, то пройдет несколько часов, пока WMI будет пытаться установить соединение с каждым IP-адресом, и половина попыток закончится тайм-аутом. Благодаря предварительному тестированию каждого компьютера сокращается время, затрачиваемое на определение доступности каждой машины.

Для запуска Ping используется метод Exec объекта WSH Shell. Чтобы управлять работой Ping, число посылаемых запросов Ping уменьшено до 2 (-n 2), а время ожидания ответа установлено равным 1000 мс (-w 1000). В результате ожидание длительностью 60 с и более (тайм-аут WMI-соединения) сокращается до нескольких секунд.

Метод Exec возвращает ссылку на объект WshScriptExec, которую сценарий может применять для взаимодействия и управления процессом. Я использую полученную ссылку objScriptExec для перехвата выходных данных утилиты Ping, которые затем преобразуются в нижний регистр и сохраняются в переменной strPingStdOut. Далее, отыскивая с помощью функции InStr подстроку reply from (за которой следует целевой IP-адрес) в выходных данных Ping, я выясняю, успешно ли завершилась работа Ping. Если это так, то фрагмент сценария с меткой A пытается установить WMI-соединение с удаленным компьютером, IP-адрес которого сохранен в ссылках strComputer. Вызов GetObject идентичен вызову GetObject, приведенному в Листингах 1 и 2.

Хотя я тестировал узел, чтобы проверить, подключен ли он к сети, вызов GetObject может закончиться неудачей, если в strComputer указан IP-адрес WMI-несовместимого компьютера или контекст безопасности, в котором исполняется сценарий, не имеет прав административного доступа к удаленному компьютеру. Оператор On Error Resume Next (активизированный ранее) и код проверки ошибки, расположенный сразу за вызовом GetObject, перехватывают обе ошибки.

Оставшаяся часть Листинга 3 — после того как соединение WMI установлено — идентична Листингам 1 и 2. Ниже приведена часть выходных данных, генерируемых Листингом 3.

ATL-LAB-01: Disabled,Stopped

ATL-DC-01: Manual,Stopped

ATL-WEB-01: Disabled,Stopped

192.168.0.4: Permission denied

192.168.0.5: Telnet not installed.

192.168.0.6: Telnet not installed.

192.168.0.7: Host unreachable

Узел с IP-адресом 192.168.0.4 — компьютер Windows XP Home Edition, с которым нельзя установить WMI-соединение.

Чтобы запустить сценарий Листинга 3 в диапазоне IP-адресов сети, необходимо изменить значение переменной strIPSubnet и начальную и конечную величины, назначенные strIPNode в операторе For. Кроме того, следует убедиться, что используется версия WSH 5.6, в которой реализован метод Exec объекта Shell.

Практическое применение

Приспособить Листинг 3 для запуска одного из WMI-сценариев, хранящихся в Script Center, не так уж сложно.

Предположим, требуется запустить сценарий Restart a Computer (http://www.microsoft.com/technet/scriptcenter/ compmgmt/scrcm38.asp) на всех компьютерах в указанном диапазоне IP-адресов. Необходимо выполнить следующие действия.

  1. Заменить исходный текст с меткой A Листинга 3 вызовом GetObject в сценарии Microsoft:
    objWMIService =

    GetObject("winmgmts:" & _

    "{impersonationLevel=impersonate," & _

    "(Shutdown)}!\\» & strComputer & _

    "\root\cimv2")

  2. Заменить исходный текст с меткой B Листинга 3 вызовом ExecQuery в сценарии Microsoft:
    colOperatingSystems = _

    objWMIService.ExecQuery _

    ("Select * from _

    Win32_OperatingSystem")

  3. Заменить исходный текст с меткой C Листинга 3 циклом For Each в сценарии Microsoft:
    Each objOperatingSystem in _

    colOperatingSystems _

    ObjOperatingSystem.Reboot()

    Next

В Листинге 4 показан окончательный сценарий. При запуске сценария в сети необходимо соблюдать осторожность: если компьютер, уже выполняющий данный сценарий, находится в диапазоне IP-адресов целевой подсети, то он также будет перезапущен. В этом случае можно дополнить тело основного цикла For условным оператором (If...Then...Else), чтобы сценарий пропустил локальный компьютер. Применив описанные выше действия к большинству WMI-сценариев Script Center, можно превратить локальный сценарий в мощный корпоративный инструмент.

Проблема безопасности

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

В WMI используется несколько контрольных уровней безопасности. Первый из них уже упоминался: контроль полномочий WMI. Полномочия WMI реализованы на уровне пространства имен (\root\cimv2) и проверяются при организации соединения WMI с локальным или удаленным компьютером. Для управления полномочиями WMI используется оснастка WMI Control консоли Microsoft Management Console (MMC). По умолчанию администраторы — единственные доверенные лица, которым предоставляется право Remote Enable.

Второй уровень контроля — безопасность DCOM. Стандартный режим DCOM для WMI — имперсонализация вызывающего сценарий пользователя или процесса. Третий и последний уровень контроля — подсистема безопасности операционной системы. Базовое правило подразумевает, что WMI не предоставляет доступ ни к одному объекту, к которому пользователь или процесс еще не обращались.

И, наконец, о роли браузера. Все объекты в библиотеке сценариев WMI (например, SWbemServices, SWbemObject) отмечены как небезопасные. Поэтому, если пользователи не ослабили режим безопасности браузера, он защищен надежно. Но если пользователи изменили параметры защиты браузера, сделав его более уязвимым, следует применить системную политику для управления режимом безопасности организации.

Боб Уэллс — консультант по программному обеспечению; специализируется на вопросах проектирования и реализации инфраструктуры информационных систем на базе NT. Имеет сертификаты MCSE и MCT. С ним можно связаться по адресу: bobwells@winnetmag.com.