Инвентаризация малой кровью

в 22:00, , рубрики: active directory, vbscript, windows, Песочница, метки: ,

Однажды потребовалось провести «инвентаризацию», то есть узнать за каким компьютером, какой пользователь сидит.

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

Итак, для инвентаризации Нужно:

  • Сетевое имя компьютера.(Все компьтеры под Win разных версий)
  • Мак адрес этого компьютера.(Все компьютеры находятся в одной подсети 255.255.0.0)
  • ФИО пользователя, который за этим компом закреплен.

И самое главное условие — это крайнее нежелание ставить на комп каких-либо сторонних приложений, писать приложение на «правильных» языках, тоже было лень. Поэтому для реализации был выбран VBS, так как в нем есть все, что необходимо и ничего дополнительно ставить не нужно и среда для него самая легковесная — notepad.exe.
С сетевыми именами все просто, они есть в службе каталогов. Пример работы с AD из VBS нагуглился довольно быстро. Для получения списка атрибутов объектов использовался скрипт написанный
товарищем Andrew J. Healey listAllProperties
Так что получить имена компьютеров получилось таким нехитрым скриптом.

	set cn=CreateObject("ADODB.Connection")
	set cmd=CreateObject("ADODB.Command")
	cn.Provider="ADsDSOObject"
	cn.Open "Active Directory Provider"
	set cmd.ActiveConnection=cn
используя SQL диалект запросов к Active directory выбираем все обекты класса "Computer"
	cmd.CommandText="SELECT * FROM 'LDAP://DC=***,DC=ru' WHERE objectClass='Computer'"
	set objRecordSet=cmd.Execute
	on error resume next
	do while Not objRecordSet.Eof
	set objComputer=GetObject(objRecordSet("adspath"))
	'путем бесчеловечных экспериментов было выяснено, что если путь содержит данную фразу 
	'то это демонтированное оборудование, или уволенный работник
	if(inSTR(1,objComputer.distinguishedName,"OU=Garbage",vbTextCompare) = 0)then 
		wscript.echo  objComputer.CN 'В данном поле и хранилось заветное сетевое имя
	end if
	objRecordSet.MoveNext
Loop

Далее, нужно получить мак адрес этих компов. Тут все просто, при помощи стандартной утилиты «nbtstat» с параметром "-a" можно получить искомое(есть конечно еще вариант с arp -a, но работает не всегда).

	set oShell=Wscript.CreateObject("wscript.shell")
	set re=new regexp
	'Регулярка для поиска MAC адреса
	re.Pattern = "[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2}"
	' В данном случае ComputerNetworkName имя компа которое мы взяли из AD
	set oExec=oShell.Exec("nbtstat -a" & ComputerNetworkName) 
	for each obj in re.execute(oExec.StdOut.ReadAll)
		GetData=obj.value
	next

Теперь возникает вопрос: «А где собсно взять список пользователей зарегистрированных на данном компьютере?». Путем непродолжительного гугления было найдено множество способов, которые сводились к удаленному выполнению wmi скрипта. Этот путь мне не подходил, так как в домене запрещено удаленное выполнение скриптов. И тут вспомнилось, что в Windows по умолчанию доступны для чтения по сети, 2 ветки реестра, а именно «HKEY_USERS» и «HKEY_LOCAL_MACHINE».
Значит, получить SID для зарегистрированных пользователей можно получить при помощи утилиты «reg» и в этом нам поможет код, который мы использовали для получения MAC адреса, все, что в нем нужно изменить так это шаблон для регулярки, и текст команды.

	set oShell=Wscript.CreateObject("wscript.shell")
	set re=new regexp
	'Регулярка для поиска SID в выводе команды reg query
	re.Pattern = "S-d+-d+-d+-d+-d+-d+-d+"
	' В данном случае ComputerNetworkName имя компа которое мы взяли из AD

	set oExec=oShell.Exec("reg query \" & iComputerNetworkName&"HKEY_USERS") 
	for each obj in re.execute(oExec.StdOut.ReadAll)
		GetData=obj.value
	next

Ну, хорошо сиды у нас есть, но они на ФИО не похожи, совсем. Чтобы получить ФИО опять придется обращаться к AD.
У каждого объекта в AD есть поле «objectSID», а значит выбрать инфу о пользователе можно, поэтому самому сиду. Для этого возьмем код, который мы использовали для получения списка компьютеров, и изменим в нем запрос в поле «cmd.commandtext»:

	dim cn,cmd,objRecordSet
	set cn=CreateOBject("ADODB.Connection")
	set cmd=CreateObject("ADODB.Command")
	cn.Provider="ADsDSOObject"
	cn.Open "Active Directory Provider"
	set cmd.ActiveConnection=cn
	' objSid это сиды которые мы получили из реестра.
	cmd.CommandText="SELECT * FROM 'LDAP://DC=***,DC=ru' where objectClass='User' and objectSid='"& objSid &"' " 
	set objRecordSet=cmd.Execute
	'Вдруг пользователя с таким сидом нет
	if( not objRecordSet.Eof) then
		set objUser=GetObject(objRecordSet("adspath"))
		if(inSTR(1,objUser.distinguishedName,"OU=Garbage",vbTextCompare) = 0)then
			' Если он всетаки есть, и еще и не в мусоре, выводим его данные.
			Wscript.Echo objUser.FirstName &" "& objUser.LastName &" "& objUser.Patronim
		end if
	end if

Ну, вот и все нужные данные получены, причем, даже если они изменятся в дальнейшем получить их, не будет проблемой (если конечно служба каталогов не будет реорганизована). И что самое главное не пришлось бегать, всему предприятию в поисках компов и пользователей.

Автор: 0serd0

* - обязательные к заполнению поля