Аудит учетных записей AD – MDaemon

Написал небольшой скрипт для аудита учетных записей MDaemon и учетных записей пользователей AD.

Задача была такова:
Имеется AD
Имеется сервер (член домена), на котором установлен почтовый сервер MDaemon (хранящий информацию о своих учетных записях в файле UserList.dat)
Необходимо найти учетные записи MDaemon, которые не принадлежат ни одному из «живых» (незаблокированных) пользователей AD.

«Погуглив», нашел на оф. сайте описание структуры файла UserList.dat. Каждая строка этого файла состоит из подстрок, хранящих значение того или иного поля для данной учетной записи. Так как известны порядковый номер и длинна любого из полей, то легко можно вырезать нужную подстрок, содержащую значение искомого поля. Для извлечения значений полей из строки файла UserList.dat я написал функцию Get-UserFields, которая производит разбор строки и возвращает, как результат своей работы, хэш-таблицу ($User=Get-UserFields [<params>]). В результате мы можем легко обращаться к содержимому любого из полей, например, так: $User.Mailbox, $User.Domain и т.п.

Кроме того, я решил выделить разными цветами в отчете, формируемым моим скриптом, почтовые ящики, к которым открыт или частично открыт доступ (пример работы скрипта см. ниже). Цветовое деление таково:

Красным помечены учетные записи MDaemon, к которым разрешен полный доступ (доступ по протоколам SMTP, IMAP, POP3), но которые не приписаны ни к одной «живой» учетной записи в AD. Это ситуация подозрительная. Возможно, что таковой почтовый ящик забыли удалить с MDaemon после удаления/блокировки учетной записи пользователя в AD.

Голубым цветом помечены учетные записи, к которым разрешен доступ по протоколу IMAP, но которые не приписаны ни к одной «живой» учетной записи в AD. Возможно, что таковой почтовый ящик забыли удалить с MDaemon после удаления/блокировки учетной записи пользователя в AD.

Не помечены никаким цветом учетные записи MDaemon, к которым заблокирован любой доступ. Адреса этих учетных записей, так же не приписаны ни к одной учетной записи в AD.

А, вот, собственно, и сам скрипт:

<#
	CheckUserList.ps1	PowerShell 20100623 shs

.Synopsis
	CheckUserList.ps1 [Userlist] <Domain2Check>

	Аудит учетных записей MDaemon и Active directory

.Параметр Userlist
	Полное имя файла UserList.dat, содержащего учетные записи почтового сервера Mdaemon
	Обычно,  <имя_диска>:\Mdaemon\App\Userlist.dat

.Параметр Domain2Check
	Доменное имя, для которого будет производится поиск учетных записей в файле UserList.dat
	(MDaemon может обслуживать несколько почтовых доменов)

.Примеры
	.\CheckUserList.ps1 -Domain2Check mydomain.ru
	.\CheckUserList.ps1 -UserList D:\Mdaemon\App\Userlist.dat -Domain2Check mydomain.ru

#>
param ($UserList="C:\Mdaemon\App\USERLIST.DAT", $Domain2Check)
###############################################################################
#
# Function Show-Help. Выыодит на экран первый блочный коментарий скрипта,
#						заданного в качестве параметра вызова.
#
#.Parameter <ScriptFullName>
#    Полное имя скрипта, чей коментарий будет выведен на экран.
#
#
Function Show-Help ($ScriptFullName){
   if ($ScriptFullName) {
       $IsHelpLine=$false
       switch -file $ScriptFullName {
           {$_ -match "<#"}     {Write-Host $_;$IsHelpLine=$true;continue}
           {$_ -match "#>"}     {Write-Host $_;$IsHelpLine=$false;break}
           {$IsHelpLine}        {Write-Host $_;}
       }
   }
}
###############################################################################
#
#	Function Get-UserFields
#.Synopsis
#	Функция производит разбор строки (переданной ей на обработку)
#	и возвращает (в качестве результата работы) хэш-таблицу,
#	содержащую имена и значения полей (извлеченных из переданной строки)
#.Описание
#	Функция производит разбор строки и возвращает (в качестве результата) хэш-таблицу,
#	содержащую имена и значения полей.
#	Имена полей берутся из шаблона  строки ($Template)
#	Значения полей вырезаются из строки в соответствии с шаблоном строки,
#	Для вырезания подстроки, содержащей значение поля, 	используется информация из шаблона
#	строки: порядковые номера полей и их длинна
#.Параметр Template
#	Содержит шаблон строки (описание полей строки).
#	Представляет из себя массив хэш-таблиц. Индеск массива - прядковый номер поля в строке.
#	Элемент массива - хеш таблица, с двумя элементами:
#	Name - имя поля в строке, Length - длина поля (подстроки)
#
function Get-UserFields ($Template, $UsrStr) {
	process {
		if (($_ -ne $null) -and ($UsrStr -eq $null)) {
			$UserString=$_
		}
		#Стартовая позиция поля в строке
		$Start=0
		#Инициируем переменную, через которую будем возвращать результат
		$Fields=@{}
		#Перебираем элементы в шаблоне строки, содержащем описание полей в строке (имя и длинну),
		#вырезаем из строки подстроку, содержащую значение найденного поля, и помещаем ее в
		#в результирующую хэш-таблицу
		for($FldNdx=0; ($FldNdx -lt $Template.Count); $FldNdx++) {
			Write-Verbose "FldNdx=$FldNdx # Template[FldNdx]=$($Template[$FldNdx].Name)"
			#Вырезаем нужную часть строки и помещаем ее в хэш-таблицу
			#ключем хэш-таблицы является название поля, взятое из шалона
			#значением - содержимое поля, вырезанное из строки
			$Fields["$($Template[$FldNdx].Name)"]=[string]::Join("",$UserString[$Start..($Start+$Template[$FldNdx].Length-1)])
			$Start+=$Template[$FldNdx].Length
		}
		$Fields
	}
}
#===============================================================================================
cls
if ($Domain2Check) {
	#
	#Получаем часть e-mail адреса, стоящую до "собаки", для всех неотключенных (enabled) пользователей домена
	$ADMails=Get-QADUser -Enabled -Email * -SizeLimit 0|%{$_.mail -replace "@.+"}
	#
	#Структура файла UserList.dat
	#http://www.altn.com/Support/KnowledgeBase/KnowledgeBaseResults/?Number=KBA-01451
	$UserStrTemplate= @(@{Name="Domain"; 			Length = 45})	#This is the domain the account is part of
	$UserStrTemplate+= @{Name="Mailbox"; 			Length = 30}	#This is the part left of the ‘@’ sign
	$UserStrTemplate+= @{Name="FullName"; 			Length = 30}	#This is the account’s first and last name
	$UserStrTemplate+= @{Name="MailDir"; 			Length = 90}	#This is the path to the directory where the account’s mail is stored
	$UserStrTemplate+= @{Name="Password"; 			Length = 20}	#This is the account’s password
	$UserStrTemplate+= @{Name="AutoDecode"; 		Length = 1}		#Set to ‘Y’ if the account is auto extracting attachments
	$UserStrTemplate+= @{Name="IsForwarding"; 		Length = 1}		#Set to ‘Y’ if the account is forwarding mail
	$UserStrTemplate+= @{Name="AllowAccess"; 		Length = 1}		#Set to ‘Y’ if the account is active, 'I' for IMAP access only, 'P' for POP access only
	$UserStrTemplate+= @{Name="AllowChangeViaEmail";Length = 1}		#Set to ‘Y’ if the account can change options via email
	$UserStrTemplate+= @{Name="KeepForwardedMail"; 	Length = 1}		#Set to ‘Y’ if the account is retaining a copy of forwarded mail
	$UserStrTemplate+= @{Name="HideFromEveryone"; 	Length = 1}		#Set to ‘Y’ if the account is to remain hidden from EVERYONE list
	$UserStrTemplate+= @{Name="EncryptMail"; 		Length = 1}		#Set to ‘Y’ if the account is storing mail in an encrypted state
	$UserStrTemplate+= @{Name="ApplyQuotas"; 		Length = 1}		#Set to ‘Y’ if the account is subject to quota restrictions
	$UserStrTemplate+= @{Name="EnableMultiPOP"; 	Length = 1}		#Set to ‘Y’ if the account is actively using MultiPOP
	$UserStrTemplate+= @{Name="LocalOnly"; 			Length = 1}		#Set to ‘Y’ if account is restricted to sending local  messages only
	$UserStrTemplate+= @{Name="MaxMessageCount"; 	Length = 4}		#Max number of messages the account can have in the mailbox at once
	$UserStrTemplate+= @{Name="MaxDiskSpace"; 		Length = 6}		#Max disk space the account is allowed to consume
	#CRLength					= 1	#Carriage return character
	#LFLength					= 1	#Linefeed character
	#
	Write-Host  "Почтовые ящики, не принадлежащие 'живым'(not disabled) пользователям AD:`n"`
				("{0,-15}     {1,-15}     {2,10}" -f "User", "Domain", "AllowAccess")
	#Считываем файл и преобразуем каждую строку в объект, содержащий значения всех полей этой строки
	gc $UserList| Get-UserFields -Template $UserStrTemplate  |%{
		#Избавляемся от пробелов, использованных в строке для выравнивания на границу поля
		$Domain=$_.Domain -replace "\s"
		#
		if ($Domain -eq $Domain2Check) {
			#Избавляемся от пробелов, использованных в строке для выравнивания на границу поля
			$User=$_.Mailbox -replace "\s"
			#Если в AD не найден пользователь, чей e-mail до собаки равен полю User...
			if ($ADMails -notcontains $User){
				#...сформируем строку отчета
				$OutputString = "{0,-15} <=> {1,15} <=> {2,10}" -f $User, $Domain, $_.AllowAccess
				#Считывем и сохраняем текущее значение BackgroundColor для host'а,
				#в котором выполняется скрипт
				$BackGndClr=$Host.UI.RawUI.BackgroundColor
				#Разукрасим BackGround строки отчета
				switch ($_.AllowAccess) {
					#Если почтовый ящик доступен по всем протоколам, то фон - красный
					"Y"	{$BackGndClr="Red";break}
					#Если почтовый ящик доступен по IMAP протоколам, то фон - голубой
					"I"	{$BackGndClr="Cyan";break}
					#если почтовый ящик доступен по IMAP протоколам, то фон - фиолетовый
					"P"	{$BackGndClr="Magenta";break}
				}
				Write-Host $OutputString -BackgroundColor $BackGndClr
			}
		}
	}
}
else {
	#Выводим справку на экран
	Show-Help $MyInvocation.MyCommand.Path
}
<#

Описание структуры файла UserList.dat
http://www.altn.com/Support/KnowledgeBase/KnowledgeBaseResults/?Number=KBA-01451

Domain				45	This is the domain the account is part of
Mailbox				30	This is the part left of the ‘@’ sign
FullName			30	This is the account’s first and last name
MailDir				90	This is the path to the directory where the account’s mail is stored
Password			20	This is the account’s password
AutoDecode			1	Set to ‘Y’ if the account is auto extracting attachments
IsForwarding		1	Set to ‘Y’ if the account is forwarding mail
AllowAccess			1	Set to ‘Y’ if the account is active, 'I' for IMAP access only, 'P' for POP access only
AllowChangeViaEmail	1	Set to ‘Y’ if the account can change options via email
KeepForwardedMail	1	Set to ‘Y’ if the account is retaining a copy of forwarded mail
HideFromEveryone	1	Set to ‘Y’ if the account is to remain hidden from EVERYONE list
EncryptMail			1	Set to ‘Y’ if the account is storing mail in an encrypted state
ApplyQuotas			1	Set to ‘Y’ if the account is subject to quota restrictions
EnableMultiPOP		1	Set to ‘Y’ if the account is actively using MultiPOP
LocalOnly			1	Set to ‘Y’ if account is restricted to sending local  messages only
MaxMessageCount		4	Max number of messages the account can have in the mailbox at once
MaxDiskSpace		6	Max disk space the account is allowed to consume
CR					1	Carriage return character
LF					1	Linefeed character

#>

Результат работы скрипта:

 Почтовые ящики, не принадлежащие 'живым'(not disabled) пользователям AD:
User                Domain              AllowAccess

MDaemon         <=> mydomain.ru <=>          N
Alerts          <=> mydomain.ru <=>          Y
Kastinin        <=> mydomain.ru <=>          Y
MurzilkinaN     <=> mydomain.ru <=>          Y
M.Vorontsova    <=> mydomain.ru <=>          C
info            <=> mydomain.ru <=>          Y
cl              <=> mydomain.ru <=>          Y
I.Trofimova     <=> mydomain.ru <=>          C
V.Borzov        <=> mydomain.ru <=>          C
Adm_ttk         <=> mydomain.ru <=>          Y
auditors        <=> mydomain.ru <=>          I

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.