Аудит пользователей в AD через VBS с занесением в SharePoint при помощи PowerShell

в 6:07, , рубрики: active directory, ldap, powershell, sharepoint, vbscript, системное программирование, метки: , , , ,
Добрый день наблюдатели НЛО

Хотел описать, как собирал информацию о пользователях из AD и затем размещал информацию на SharePoint для удобочитаемости и в любой момент посмотреть о том, или ином пользователе нужную для нас информацию.
Опишу просто, так как всё оно было…

Поставлена задача собрать из AD информацию о пользователях что можно выдернуть и определенные свои цели.
Из того что имелось: был выбран VBS для сбора информации о пользователях через LDAP, собираем все в простой текстовый файл (так как сбор происходит в нескольких сегментах разделенных между собой), файлы собираются в одном месте и затем с помощью PowerShell размещаем на подготовленном сайте SharePoint.

On Error Resume Next
Dim oQuery
Dim objConnection
Dim objCommand
Dim objRecordSet
Dim strMember
Dim strAC
Dim arrMember

' сюда сохраним всю информацию о пользователях
logfile = "users-lvs.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")


oQuery = "<LDAP://dc=my,dc=site>;" & _
    "(objectCategory=user)" & _ ";distinguishedName,name,sAMAccountname,mail,memberOf,userAccountControl,description;subtree"
' выше перечислены поля из которых именно нам нужна информация о пользователе

Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Open "Provider=ADsDSOObject;"
objCommand.ActiveConnection = objConnection
objCommand.CommandText = oQuery
Set objRecordSet = objCommand.Execute


' если нет файла - создаем, если есть - перезаписываем
if objFSO.FileExists(logfile) then
	Set objFile = objFSO.OpenTextFile(logfile, 2)
	objFile.Write "" 
else
	Set objFile = objFSO.CreateTextFile(logfile) 
	objFile.Close
	Set objFile = objFSO.OpenTextFile(logfile, 2) 
	objFile.Write "" 
end if
objFile.Close


' начинаем сбор, пока не закончатся объекты
While Not objRecordSet.EOF
 
  strMember = objRecordSet.Fields("memberOf")

  strStr = ""
  
 For i = 0 To UBound(strMember)
    
    ' переменная где хранится длина символов до запятой
    liluka = InStr(2, strMember(i), ",", vbTextCompare)
    ' все группы делаем в одну строку
    strStr = strStr & Right(Left(strMember(i), liluka - 1), liluka - 4) & ", "

 Next


 arrOpis = objRecordSet.Fields("description")
 strOpis = ""
 
 For i = 0 To UBound(arrOpis)
    strOpis = strOpis & arrOpis(i) & ", "
 Next

' проверка признака отключен ли пользователь
 Select Case objRecordSet.Fields("userAccountControl")
  Case 512
    strAC = "Нет"
  Case 514
    strAC = "Да"
  Case 66048
    strAC = "Нет"
  Case 66050
    strAC = "Да"
 End Select
  
 
' запись всей информации в файл 
 Set objFile = objFSO.OpenTextFile(logfile, 8)
  objFile.WriteLine objRecordSet.Fields("sAMAccountname") & ";1" & _
    objRecordSet.Fields("name") & ";2" &  _
    objRecordSet.Fields("mail") & ";3" & _
    strStr & ";4" & strAC & ";5" & strOpis & ";6ЛВС"
 objFile.Close
   
  objRecordSet.MoveNext

Wend

objConnection.Close

Из кода видно что в конце строки дописывается ";6ЛВС", как уже говорил выше сегментов у нас несколько и это первый из них ЛВС. С признаком отключен ли пользователь не стал долго думать и взял 4 встречающихся у нас значения, если усложнить жизнь и копаться то можно по битам читать переменную…
Что бы скрипт PowerShell понимал где какая информация находится, не придумал ни чего лучше чем как через точку с запятой ставить цифру обозначающую индекс определенной информации.
Не профессионал, а всего лишь любитель кода я, как программировать, так и анализа/разбора.
Собственно сам код PowerShell:

# заполнение страницы на шарепойнт информацией о пользователях из тхт файлов, построчно
		write-host open Sharepoint from USERS
		# sharepoint
		$env:SPpath = "${env:CommonProgramFiles}Microsoft Sharedweb server extensions12"
		[System.Reflection.Assembly]::LoadFrom("$env:SPPathISAPIMicrosoft.SharePoint.dll")
        write-host open web
		# открываем web
		$nsite="http://my_site/sites/MonitorUser"
		$SpSite = New-Object -TypeName "Microsoft.SharePoint.SPSite" -ArgumentList $nsite;
		$spweb=$spsite.OpenWeb();
        write-host open Sharepoint list
		# открываем  список
		$nlist="http://my_site/sites/MonitorUser/Lists/List5/AllItems.aspx"
		$splist=$spweb.getlist($nlist);
		
		# очистим страницу
		write-host clearing list...
		$iCnt = $splist.Items.Count;
		#$icnt;
		for ($jj=1; $jj -le $iCnt; $jj++){
			$splist.Items.Delete(0);
		}
		write-host clearing list Done

# перебираем информацию во всех тхт файлах, какие подходят под маску
write-host Processing log files...
foreach ($file in $(get-childitem 'D:scriptswork' -include users*.txt -recurse))
 	{
	$hostout = $file.FullName + "..."
	Write-Host $hostout

	$fl = get-content $file.FullName;
        # $fl;

	for ($i=1; $i -lt $fl.Count; $i++)
		{
		
		$st1 =$fl[$i];
                
                
    
        # делаем переменные наших признаков определенных данных
        $ind1 = $st1.IndexOf(";1")
        $ind2 = $st1.IndexOf(";2")
        $ind3 = $st1.IndexOf(";3")
        $ind4 = $st1.IndexOf(";4")
        $ind5 = $st1.IndexOf(";5")
        $ind6 = $st1.IndexOf(";6")	
			

	$stLogin = $st1.substring(0,$ind1)
	$stUserName = $st1.substring($ind1+2,$ind2-$ind1-2)
	$stMail = $st1.substring($ind2+2,$ind3-$ind2-2)


	$ind7 = $ind4-$ind3
	if ($ind7 -eq 2)
	{
         $stGroup = "Нет групп"
	}
	else
	{
         $stGroup = $st1.substring($ind3+2,$ind4-$ind3-4)
	}

	$ind7 = $ind6-$ind5
	if ($ind7 -eq 2)
	{
         $stOpis = ""
	}
	else
	{
	 $stOpis = $st1.substring($ind5+2,$ind6-$ind5-4)
	}

	$stBlock = $st1.substring($ind4+2,$ind5-$ind4-2)
	$stSeg = $st1.substring($ind6+2,3)

       
         
         # создаем запись на странице шарепойнт с нашими данными
          $NewItem = $SpList.Items.Add();
          $NewItem["Логин"] = $stLogin;
          $NewItem["Полное имя"] = $stUserName;
          $NewItem["e-mail"] = $stMail;
          $NewItem["Группы"] = $stGroup;
          $NewItem["Отключен"] = $stBlock;
          $NewItem["Сегмент"] = $stSeg;
          $NewItem["Описание"] = $stOpis;
          
          $NewItem.Update();
		
		}
}

write-host Processing log files DONE
$spweb.Dispose();
$spsite.Dispose();
write-host Program END

Теперь после того как собрали тхт в одном месте, запускаем батник

cscript users-lvs.vbs
%SystemRoot%system32WindowsPowerShellv1.0powershell.exe "& 'D:scriptsworkusers.ps1'"
%SystemRoot%system32WindowsPowerShellv1.0powershell.exe "& 'D:scripts workpk.ps1'"

Так как наш сайт выполняется в сегменте ЛВС то заодно и обновляется у нас информация по данным пользователям. И как вы могли заметить, рабочий скрипт собирает информацию по компьютерам (ОС, версия, пак, описание, когда включался), но там все по аналогии как с пользователями.
Самое долгое, что занимает во всем, это – очищение страницы с информацией (примерно 2-3 минуты). Если страницы чисты, то сбор и обработка нескольких файлов в общей сложности занимает не более 30 секунд, 700-800 записей.
На самом деле в LDAP много лежит информации и свой рабочий скрипт дополнил тем, что он смотрит когда пользователь заходил последний раз а так же когда менял пароль крайний раз. В WMI есть «directoryLDAP» и там в принципе можно найти много интересной информации.

P.S. На быстро руку набросал, рад буду любой критике, а лучше советам как улучшить, где какие моменты не нравятся и почему, аргументировав это…

Автор: fulse

Источник

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


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js