Как стать автором
Обновить

Комментарии 36

Очень Классно!
И интересно!
завтра будет день для фантазий и воплощения!
Я хотел бы посоветовать использовать строки с одинарными кавычками ('string') вместо двойных, особенно для таких строк как пароли. Причина — строки в двойных кавычках («string») «расширяются» Powershell: если в строке есть символ $ (а в пароле этот символ — обычное явление), то powershell будет интерпретировать дальнейшие цифро-буквенные символы как название переменной, и подставит ее значение (а если такой переменной нет, то подставит пустую строку).

Вообще, в Powershell всегда используйте одинарные кавычки, кроме случаев когда вы действительно хотите «расширить» строку. Это сэкономит время на чтении вашего скрипта: нет необходимости внимательно вчитываться в каждую констнантную строку чтобы понять возможно ли там расширение.

Пример:
$a= 5
$ab= 10

Write-Host '$a$ab'
Write-Host "$a$ab"
Write-Host "$a$abc"

Вывод на консоль:
$a$ab // no string expansion, taken literally
510 // both expressions expanded to existing variables
5    // second one expanded to $null 

Ой, только что заметил, что случайно комментировал по-английски. Привычка, однако. Вот перевод:
$a$ab // строка не «расширяется», используется буквально
510 // оба выражения ($a и $ab) «расширяются» переменными, определенными раннее
5 // второе выражение ($abc) «расширяется»/заменяется на $null (так как переменная $abc) не определена
Я не совсем понял, зачем держать пароль в открытом виде, если вы его все равно потом конвертируете в защищенную строку? Я в таких случаях заранее сохраняю защищенный пароль в текстовый файл (который потом еще и шифрую, что бы не утащили) и использую его когда надо. Вот здесь описано как это сделать.
Кстати, относительно недавно я писал статейку практически с таким же методом отслеживания создания новых учеток пользователей (вместе Get-WinEvent я юзал Get-EventLog). У меня вся информация уходила в текстовый файл, который я периодически просматривал. С почтой, конечно, по красивее.
Да, Вашу статью читал давненько, собственно это и сподвигло меня на, так сказать, продолжение…
В Get-EventLog на сколько я помню нет возможности доставать определенную информацию из поля Message:(
$Message = (get-eventlog -Logname Security -Newest 1).Message
Все вытаскивается, это же PowerShell :)
хм… поле Message содержит много служебной информации же:
Message : Создана учетная запись компьютера. Субъект: Идентификатор безопасности: S-1-5-21-451469775-2953165952-2320738315-500 Имя учетной записи: administrator Домен учетной записи: DOMAIN Идентификатор входа: 0xb3acf Новая учетная запись компьютера: Идентификатор безопасности: S-1-5-21-451469775-2953165952-2320738315-2979 Имя учетной записи: TEST$ Домен учетной записи: DOMAIN Атрибуты: Имя учетной записи SAM: TEST$ Отображаемое имя: - Основное имя пользователя: - Домашний каталог: - Домашний диск: - Путь к сценарию: - Путь к профилю: - Рабочие станции пользователя: - Последний пароль задан: <никогда> Срок действия учетной записи истекает: <никогда> Идентификатор основной группы: 515 Разрешено делегировать: - Старое значение UAC: 0x0 Новое значение UAC: 0x85 Управление учетной записью пользователя: Учетная запись отключена "Пароль не требуется" - включено "Учетная запись доверия рабочей станции" - включено Параметры пользователя: - Журнал SID: - Часы входа: <значение не задано> DNS-имя узла: - Основные имена служб: - Дополнительные сведения: Privileges -

А хочется чтоб красиво и удобочитаемо:)
Ну Вы свой вывод получаете тоже не сразу в красивом виде :)
Так что парсить все равно придется :)
Между прочим, скопировал весь ваш Message в переменную $b

PS [69] > $b -match "(Субъект: .* (?<Name>(Имя учетной записи: (\w+))) .* Новая учетная)"
True
PS [70] > $Matches.Name
Имя учетной записи: administrator
PS [71] > $b -match "(Новая учетная запись .* (?<Comp>(Имя учетной записи: (\S+))))"
True
PS [72] > $Matches.Comp
Имя учетной записи: TEST$
Сам себя исправлю:
Ну Вы свой вывод получаете тоже не сразу в красивом виде :)
Так что парсить все равно придется :)
Между прочим, скопировал весь ваш Message в переменную $b

PS [69] > $b -match "(Субъект: .* Имя учетной записи: (?<Name>(\w+)) .* Новая учетная)"
True
PS [70] > $Matches.Name
administrator
PS [71] > $b -match "(Новая учетная запись .* Имя учетной записи: (?<Comp>(\S+))"
True
PS [72] > $Matches.Comp
TEST$
PS [73] > "Оператор: {0}" -f $Matches.Name
Оператор: administrator
PS [74] > "Имя компьютера: {0}" -f $Matches.Comp
Имя компьютера: TEST$

Так красивее :)
Ну вобщем то говорим об одном и том же) Разными путями приходим)
Set-ExecutionPolicy Unrestricted

Nooooo! Whyyyyyy? (падая на колени и потрясая кулаками в сторону небес)
Использование политики Unrestricted есть бутылочное горлышко в безопасности, я запрещаю это всем и вся. Куда лучше на корпоративном УЦ выдать ключ и сертификат для подписи скриптов, и свои скрипты этим хозяйством подписывать.
А по теме — можно гонять подписки в eventvwr.msc на своей машине: это кошерно, православно и можно пользоваться в Рамадан:
Или хотя бы RemoteSigned. И да, тут в статье я бы еще добавил о необходимости для начала собирать всё в кучу со всех контроллеров, если их несколько.
в общем у меня только приходит письмо

«Добавлен новый компьютер в домен „

и дальше пусто =(
что Я делаю не так =(
p.s пока я в PS чайник =)
Проверьте, у вас точно событие есть с кодом 4741? Возможно компьютер в домен добавлялся давно и логи уже успели затереться…
Вполните команду в PS:
Get-WinEvent -FilterHashtable @{LogName=”Security”;ID=4741}
Каков будет результат?
Данные по эвенту отображаются

Проверил уже весь код (сразу)

все отрабатывает ровно как в статье

но на почту приходит только о добавлении без самого важного =(
в последней строке Send-MailMessage

-Body “$Theme `n$BodyM”
поменял на
-Body $Body

в итоге содержание письма стало таким

@{TimeCreated=08/23/2012 11:29:17; Оператор=Admin; Имя компьютера=89$}

так и должно быть (по правильному ?!)
или как все таки ?!
Прошу прощения за мою невнимательность…
Добавьте этот код перед сегмнетом по отправке письма.
И оставьте как есть в письме переменную $BodyM
$body = $body -replace "@{" -replace "}" -replace "=", ": " -replace ";","`n" -replace "TimeCreated","Время" -replace "^","`n" $body = $body -replace "Италмас.+$" -replace "CN:" -replace "OU:" $BodyM = $Body
<code>$body = $body -replace "@{" -replace "}" -replace "=", ": " -replace ";","`n" -replace "TimeCreated","Время" -replace "^","`n"
$BodyM = $Body
</code>
$body = $body -replace "@{" -replace "}" -replace "=", ": " -replace ";","`n" -replace «TimeCreated»,«Время» -replace "^","`n"
$BodyM = $Body

Извиняюсь за флуд( Вот правильный код, который нужно добавить…
Исправил код скрипта в теле поста.
ой =) опоздал с комментом
Так и не получается =( скопировал все из поста
изменений нет =(
Кароч PShell'ник из меня… даже с копированием никакой =)
вот только если вот так
#Отправка письма.
Send-MailMessage -From $From -To $To -SmtpServer $server -Body “$Theme $Body” -Subject $Subject -Credential $cred -Encoding $encoding

то на почте получаю
Добавлен новый компьютер в домен @{TimeCreated=08/23/2012 14:19:00; Оператор=Admin; Имя компьютера=333222111$}

по другому никак
Что то ничего не получилось (ну точнее не понял куда-чего)
мне как школьнику в этом деле
тяжело =)

p.s а в самой статье изменения будут ?! Я бы из статьи и скопирастил бы ;-)
Да, я в статью внес изменения… в тело скрипта… Скопипистите оттуда полностью
Отлично!!! Теперь все супер!

Добавлен новый компьютер в домен

Время: 23.08.2012 17:58:41
Оператор: Admin
Имя компьютера: PROVERO4KA$

Спасибо БОЛЬШОЕ!!!
Спасибо за критику. Принял к сведению.
Вообще статью написал давно, не прошла модерацию, вчера вспомнил, перепостил.
Честно говоря поленился дописывать…
По факту сейчас у мменя отрабатывает следующим образом скрипт (немного добавлен функционал):
1. Отправка инфорацмии на почту
2. Отправка информации о критчных событиях в Jabber-сервис (для тех у кого в сети поднят XMPP-сервис) — дает оперативность получения информации.
3. Пишет в текстовый файл инормацию. В частности сделан скрипт который отслеживает критически важные папки общего пользования, и пишет логи о доступе пользователей к файлам, а так же об удалении файлов.

Если интересно могу выложить код…
Вообще в павершеле я новичек… поэтому на многие камни придется понаступать не раз:) Интересно было замечание по поводу ковычек и про скрытие пароля.
Вообще скрипт позиционирует себя как «скопировал-вставил и все работает» :)

По поводу сборки логов со всех контроллеров… возможно, но кидать целый лог со всех контроллеров на один сервер затратнее, чем кидать с каждого контроллера уже отформатированные данные.
А для сбора логов существуют другие продукты, о них раскажу позже… как раз недавно развернул…
Ну не обязательно целыми логами разбрасываться. Можно просто добавить список КД и последовательно просматривать их логи с одного сервера. Собирать информацию со всех КД нужно обязательно (я думаю все понимают, зачем).
Все равно считаю, что лучше когда каждый такой скрипт будет работать на каждом КД. На случай если связь к КД пропадет, скрипт будет работать и писать в удаленной сети лог в отдельный файл, потом его можно просмотреть,…
Спасибо, интересная идея — запишу себе в фичи мониторинга, который хочу на шарпе написать :)
а в оффлайн режиме покопаться в событиях можно с помощью LogParser, у него есть соответсвующий тип источника
PS D:\PowerShell> D:\PowerShell\ADD_pc_to_AD-2.ps1
Get-WinEvent: Could not retrieve information about the Security log. Error: Attempted to perform an unauthorized operation…
At D:\PowerShell\ADD_pc_to_AD-2.ps1:13 char:19
+ $Body=Get-WinEvent <<<< -FilterHashtable @{LogName=”Security”;ID=4743} | Select TimeCreated,@{n=”Оператор”;e={([xml]$_.ToXml()).Event.EventData.Data |? {$_.Name -eq “Subject
UserName”} |%{$_.’#text’}}},@{n=”Имя компьютера”;e={([xml]$_.ToXml()).Event.EventData.Data |? {$_.Name -eq “SamAccountName”}| %{$_.’#text’}}} | select-object -first 1
+ CategoryInfo: NotSpecified: (:) [Get-WinEvent], Exception
+ FullyQualifiedErrorId: LogInfoUnavailable,Microsoft.PowerShell.Commands.GetWinEventCommand

Get-WinEvent: There is not an event log on the localhost computer that matches «Security».
At D:\PowerShell\ADD_pc_to_AD-2.ps1:13 char:19
+ $Body=Get-WinEvent <<<< -FilterHashtable @{LogName=”Security”;ID=4743} | Select TimeCreated,@{n=”Оператор”;e={([xml]$_.ToXml()).Event.EventData.Data |? {$_.Name -eq “Subject
UserName”} |%{$_.’#text’}}},@{n=”Имя компьютера”;e={([xml]$_.ToXml()).Event.EventData.Data |? {$_.Name -eq “SamAccountName”}| %{$_.’#text’}}} | select-object -first 1
+ CategoryInfo: ObjectNotFound: (Security:String) [Get-WinEvent], Exception
+ FullyQualifiedErrorId: NoMatchingLogsFound,Microsoft.PowerShell.Commands.GetWinEventCommand

Get-WinEvent: The parameter is incorrect
At D:\PowerShell\ADD_pc_to_AD-2.ps1:13 char:19
+ $Body=Get-WinEvent <<<< -FilterHashtable @{LogName=”Security”;ID=4743} | Select TimeCreated,@{n=”Оператор”;e={([xml]$_.ToXml()).Event.EventData.Data |? {$_.Name -eq “Subject
UserName”} |%{$_.’#text’}}},@{n=”Имя компьютера”;e={([xml]$_.ToXml()).Event.EventData.Data |? {$_.Name -eq “SamAccountName”}| %{$_.’#text’}}} | select-object -first 1
+ CategoryInfo: NotSpecified: (:) [Get-WinEvent], EventLogException
+ FullyQualifiedErrorId: System.Diagnostics.Eventing.Reader.EventLogException,Microsoft.PowerShell.Commands.GetWinEventCommand

ЧЯДНТ?
Смотрите комментарий ниже) Не туда нажал :)
Attempted to perform an unauthorized operation на мой взгляд намекает на проблему с правами.
There is not an event log on the localhost computer that matches «Security» намекает, что лога Security нет на машине
Как-то очень мудрено Вы вытаскиваете информацию из события. В объекте события есть свойство Properties которое является массивом, содержащим все ключевые сведения события.
Чтобы не было в e-mail сообщении строк вида @{TimeCreated=08/23/2012 14:19:00; Оператор=Admin; Имя компьютера=333222111$} необходимо в тексте сообщения указывать не объект, а перечислять отдельно его свойства, либо попробовать использовать ft или fl через конвеер.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации