Skip to content

Powershell: list Exchange 2010 personal mailbox folders permissions

Скрипт перечисляет текущие права доступа к папкам в почтовых ящиках пользователей. На выходе — .csv-файл в формате «ящик; папка; аккаунт; права доступа».

Как видно из текста, здесь обходится ограничение апплета Get-MailboxFolder, не позволяющее перечислить перечень папок в ящиках, где запускающий не является owner, причем использование этого апплета здесь было бы более чем очевидно. Вместо него используется Get-MailboxFolderStatistics. Ну а само ограничение описано здесь. Запускать нужно в Exchange Management Shell.

Import-Module ActiveDirectory -ErrorAction SilentlyContinue
Write-Host "Reading mailboxes..."
$AllMailboxes = Get-Mailbox -ResultSize Unlimited
Write-Host "Mailbox;FolderPath;User;Permissions"
$Counter1 = 0
$AllMailboxes | % {
 $Counter1++
 $PercentComplete = (($Counter1 / $AllMailboxes.Count)*100)
 Write-Progress -Activity "Working hard!" -Status "Complete: $([Math]::Round($PercentComplete,1))%" -PercentComplete $PercentComplete
 $CurrentMailbox = $_
 $CurrentFolderArray = Get-MailboxFolderStatistics $CurrentMailbox | select FolderPath
 $CurrentFolderArray | % {
 $CurrentFolderPath = $_.FolderPath
 $CurrentFolderPermissions = Get-MailboxFolderPermission "$($CurrentMailbox.Alias):$($_.FolderPath.Replace('/','\'))" -ErrorAction SilentlyContinue
 $CurrentFolderPermissions | % {
 if ($_.User) { $CurrentADUser = Get-ADUser -Filter 'name -like $_.User' -ErrorAction SilentlyContinue }
 if (($($_.User)) -AND ($CurrentADUser) -AND ($CurrentADUser -ne $null) -AND ($_.AccessRights -ne "None") -AND ($_.User.ToString() -ne "Anonymous") -AND ($_.User.ToString() -ne "Default") -AND ($_.User.DisplayName -ne $CurrentMailbox.DisplayName)) {
 $OutResult = "$($CurrentMailbox.DisplayName);$CurrentFolderPath;$($_.User);$($_.AccessRights)"
 $OutResult
 $OutResult | Out-File "c:\result.csv" -Append
 }
}
 }
 Remove-Variable CurrentADUser,CurrentFolderArray,CurrentMailbox,CurrentFolderPath,CurrentFolderPermissions
}
Реклама

Powershell: enumerate all Exchange 2010 mailbox permissions

Навыдавали пользователям прав? Все лазают друг у друга в ящиках и благодаря этому происходит полная вакханалия? Нужно понять, кто имеет доступ к какому ящику? Их есть у нас! Перечислить права доступа к почтовым ящикам в Exchange 2010 можно следующим образом:

Clear-Host
Write-Host "Setting variables..."
$Counter1 = 0
$ExcludeAccounts = @(
"NT AUTHORITY\SELF"
)
Write-Host "Importing modules..."
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue
Import-Module ActiveDirectory -ErrorAction SilentlyContinue
Write-Host "Reading mailbox list..." -NoNewline
$AllMailboxes = Get-Mailbox -ResultSize Unlimited
Write-Host "$($AllMailboxes.Count) total"
Write-Host "Mailbox;User;Permissions"
$AllMailboxes | % {
 $Counter1++
 $PercentComplete = (($Counter1 / $AllMailboxes.Count)*100)
 Write-Progress -Activity "Working hard!" -Status "Complete: $([Math]::Round($PercentComplete,1))%" -PercentComplete $PercentComplete
 Get-MailboxPermission $_ | % {
 if ($ExcludeAccounts -notcontains $_.User -and $_.IsInherited -eq $False -and $_.Deny -eq $False) {
 $CurrentMailbox = $_.Identity.ToString().Substring($_.Identity.ToString().LastIndexOf("/")+1)
 $CurrentUserDirty = $($_.User.ToString().Substring($_.User.ToString().IndexOf("\")+1)).ToString()
 if (Get-ADObject -Filter "name -eq '$CurrentUserDirty' -or samaccountname -eq '$CurrentUserDirty'") {
 $CurrentUserObjectClass = (Get-ADObject -Filter "name -eq '$CurrentUserDirty' -or samaccountname -eq '$CurrentUserDirty'" | ? { $_.ObjectClass -eq 'group' -or $_.ObjectClass -eq 'user' }).ObjectClass
 if ($CurrentUserObjectClass -eq "user") {
 $CurrentUser = (Get-ADUser $_.User.ToString().Substring($_.User.ToString().IndexOf("\")+1) -ErrorAction SilentlyContinue).Name
 }
 if ($CurrentUserObjectClass -eq "group") {
 Get-ADGroupMember $CurrentUserDirty -Recursive | % {
 $CurrentGroupMembers += "$($_.name),"
 }
 $CurrentUser=$CurrentGroupMembers.TrimEnd(',')
 }
 } else {
 $CurrentUser = $_.User.ToString()
 }
 $CurrentAccessRight = $_.AccessRights
 $CurrentSendAs = 0
 if ($CurrentMailbox -ne $CurrentUser -and $CurrentUser -ne $null) {
 $OutResult = "$CurrentMailbox;$CurrentUser;$CurrentAccessRight"
 Write-Host $OutResult
 $OutResult | Out-File "d:\result.csv" -Append
 }
 Remove-Variable CurrentMailbox,CurrentUser,CurrentAccessRight,CurrentGroupMembers,CurrentUserObjectClass,CurrentGroupMembers -ErrorAction SilentlyContinue
 }
 }
}

Скрипт перечисляет права доступа к почтовым ящикам, выданные на административном уровне. Но ведь пользователи могут выдавать доступ к своему ящику и папкам/календарям/адресным книгам в нем самостоятельно из Outlook! Как получить перечень таких прав доступа — в следующем выпуске.

Powershell: convert IPs to hostnames

Дали айпишники, а надо хосты? Преобразуем IP-адреса в имена хостов с помощью powershell.

Clear-Host
$ErrorActionPreference = «silentlycontinue»
$ips = Get-Content «d:\temp\ip.txt»
$ips | % {
Write-Host «$_;» -NoNewline
write-host $([System.Net.Dns]::GetHostbyAddress(«$_»).HostName)
}

Lync 2010: mass enable users

Что бы включить Lync у всех пользователей в AD, можно воспользоваться следующим скриптом:

Import-Module ActiveDirectory
Import-Module Lync
$LogFile = "C:\LyncEnable\log.txt"
Get-Date | Out-File $LogFile -Append
Write-Host "Reading AD Users..."
$DomainUsers = Get-ADUser -filter * -Properties msRTCSIP-UserEnabled,mail
Write-Host "Finding Users to make them Lync-enabled..."
$DomainUsersToEnableLync = @()
$DomainUsers | % {
 if ($_.$("msRTCSIP-UserEnabled") -ne $False -and -not $_.$("msRTCSIP-UserEnabled") -and $_.mail ) {
 "Lync-enabling: $($_.Name)" | Out-File $LogFile -Append
 Enable-CsUser "DOMAIN\$($_.SamAccountName)" -RegistrarPool LYNC.DOMAIN.LOCAL -SipAddressType samaccountname -SipDomain LYNC.DOMAIN.LOCAL
 }
}

 

Powershell: почтовый робот-парсер для Exchange

Возникла необходимость обрабатывать входящие письма по MAPI протоколу по какому-либо признаку? Можно использовать платные email-парсеры (бесплатного в Интернетах не нашлось). А можно установить Exchange Web Services Managed API, написать небольшой .ps-скрипт и решить поставленную задачу. Кстати, потребуется .NET >3.5, но это ведь не проблема? ;)

В скрипте в последнем «foreach» можно реализовать любые условия: обработка адреса отправителя, фильтрация темы сообщения, разбор тела письма. Затем обработанное письмо можно поместить в «Корзину». Перед запуском в 3 и 4 строчках следует указать учетные данные служебного почтового ящика.

[Reflection.Assembly]::LoadFile("C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll") > $nul
$ServiceObj = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
$ServiceObj.Credentials = New-Object Net.NetworkCredential('Username', 'Password', 'domain.local')
$ServiceObj.AutodiscoverUrl("username@autodiscovery.domain")
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($ServiceObj,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
Write-Host "Total Messages:" $inbox.TotalCount
$psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties) 
$ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView($inbox.TotalCount)
$fiItems = $ServiceObj.FindItems($Inbox.Id,$ivItemView) 
[Void]$ServiceObj.LoadPropertiesForItems($fiItems,$psPropset) 
foreach($Item in $fiItems.Items){
 # Перечисление свойств сообщения:
 $Item
 # Перемещение сообщения в "Корзину":
 $Item.Delete("movetodeleteditems")
}

Powershell: Write-Host и Out-File одновременно

Не знаю у кого как, а у меня постоянно возникают ситуации, когда необходимо получить вывод на экране с помощью Write-Host и одновременно произвести запись в log-файл. Что бы не множить количество строчек, а упростить себе работу, можно включить следующую функцию в начало своего очередного скрипта:

Function Write-HostAndLog {
 param ($FuncWHLText,$FuncWHLOutFile)
 Write-Host $FuncWHLText
 Add-Content $FuncWHLOutFile $FuncWHLText
}

Вызывается функция так:

Write-HostAndLog "$(Get-Date): Starting my script!" "c:\Scripts\log.txt"

Здесь мы лишаемся возможности указывать ключи командлета Write-Host (например, -NoNewLine), но с другой стороны это не на столько и необходимо. Если все же очень необходимо, можно добавить еще один параметр к функции ;-)

Exchange 2010 статистика по почтовым сообщениям

Продолжаю серию публикаций кружка очумелых powershell’ных ручек. Нужно оценить почтовую активность? Будет сделано! Для этого потребуется Exchange Management Shell и .ps1-скрипт.

Пара комментариев. В массиве $SendersExclude указываются отправители, которых следует исключить из отчета. Переменные $StartDate и $EndDate имеют формат «м/д/г ч:м:с». Ну и, разумеется, все @domain.ru, встречающиеся в скрипте, должны быть заменены на реальный домен.

exchstat.ps1

Clear-Host
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue
Clear-Variable MessagesAll,SendersExclude -ErrorAction SilentlyContinue
$MessagesAll = @()
$SendersExclude = @()
$SendersExclude += "PublicFolderDatabase054545@domain.com"
$SendersExclude += "PublicFolder54545454@domain.com"
$StartDate = "06/05/2012 00:00:00"
$EndDate = "06/06/2012 00:00:00"
$ServersHUB = ( Get-ExchangeServer | ? { $_.ServerRole -match "HubTransport" } )
Write-Host "Reading message tracking log on Exchange HUB servers: "
$ServersHUB | % {
 Write-Host "-" $_.Name "..."
 Get-MessageTrackingLog -Start $StartDate -End $EndDate -Server $_ -ResultSize Unlimited | % {
 $MessagesAll += $_
 } 
}
Write-Host "`nFound" ($MessagesAll | ? { $_.EventId -eq "RECEIVE" -and $_.Source -eq "STOREDRIVER" -and $SendersExclude -notcontains $_.Sender -and $_.Sender -match "@domain.com" }).Count "message(s) from" $StartDate "to" $EndDate "`n"
Write-Host "Top 20 senders:"
$MessagesAll | ? { $_.EventId -eq "RECEIVE" -and $_.Source -eq "STOREDRIVER" -and $SendersExclude -notcontains $_.Sender -and $_.Sender -match "@domain.com" } | Group-Object Sender | Sort-Object Count -Descending | Select-Object -First 20 | ft Name,Count -AutoSize
Write-Host "Top 20 senders by total messages size:"
$MessagesAll | ? { $_.EventId -eq "RECEIVE" -and $_.Source -eq "STOREDRIVER" -and $SendersExclude -notcontains $_.Sender -and $_.Sender -match "@domain.com" } | Select-Object Sender,TotalBytes | Group-Object Sender | Select-Object @( @{ Name = 'Name' ; Expression = { $_.Name } }, @{ Name = 'TotalItemSize(MB)' ; Expression = { [System.Math]::Round(($_.Group | Measure-Object -Property TotalBytes -Sum).Sum / 1MB, 2) } } ) | Sort-Object -Property 'TotalItemSize(MB)' -Descending | Select-Object -First 20

Результат выполнения скрипта на скриншоте:

Как получить список компьютеров из списка сотрудников

В организации не ведется учет рабочих станций, нет SCCM или любого подобного продукта, и при этом нужно получить перечень имен компьютеров, закрепленных за определенными сотрудниками? Нет ничего проще!

1. Хранить данные о том, на какой компьютер сотрудник вошел, я решил хранить прямо в AD в объекте User. Подходящего для этого поля в AD не нашлось, поэтому пришлось расширить схему, добавив свойство «workstationLoggedOn». Сразу же необходимо делегировать в домене полномочия для пользователя «SELF» на чтение и запись этого свойства у всех объектов типа User, что бы сами пользователи могли вносить изменения в AD.

2. Далее создал GPO, выполняющуюся в разделе «User» и выполняющую .vbs-скрипт:

On Error Resume Next
Err.Clear
Set oShell = CreateObject( «WScript.Shell» )
connection=oShell.ExpandEnvironmentStrings(«%SESSIONNAME%»)
If (connection = «Console») then
Set objSysInfo = CreateObject(«ADSystemInfo»)
strUserName = objSysInfo.UserName
Set objUser = GetObject(«LDAP://» & strUserName)
strOUName = objUser.Parent
Set wshShell = WScript.CreateObject( «WScript.Shell» )
strComputerName = wshShell.ExpandEnvironmentStrings( «%COMPUTERNAME%» )
Const ADS_PROPERTY_UPDATE = 2
Set objUser = GetObject(«LDAP://» & objSysInfo.UserName)
objUser.Put «workstationLoggedOn», strComputerName
objUser.SetInfo
End If

Что делает скрипт. Во-первых, он проверяет, что бы пользователь был подключен в активной физической сессии, а не через удаленный рабочий стол. Если подключение выполнено через RDP, выполнение скрипта останавливается. Если же подключение идет через сессию физической консоли, скрипт получает DN пользьователя и компьютера, после чего записывает в свойство «workstationLoggedOn» пользователя имя компьютера.

3. Далее остается только ждать. Информация по рабочим станциям будет заполняться при каждом входе в систему. Включив GPO в 10 утра, к 11 я имел достаточно солидный список сотрудников, которые опоздали на свои рабочие места ;-) Такой список я получил с помощью .ps-скрипта:

Import-Module ActiveDirectory
Clear-Host
$UsersArray = @()
$ServersArray = @(Get-ADComputer -SearchBase «OU=Servers,DC=domain,DC=local» -Filter *)
Get-ADUser -Filter * -Properties * | ? {
$UserCurrent = $_
If ($_.workstationLoggedOn) {
$WorkstationLoggedOn = $_.workstationLoggedOn
$ServersArray | % { if ($_.Name -eq $WorkstationLoggedOn) { $WorkstationIsServer = $True } }
if ($WorkstationIsServer -eq $False) { $UsersArray += $UserCurrent }
$WorkstationIsServer = $False
}
}
$UsersArray | % { Write-Host $_.workstationLoggedOn $_.Name }

Скрипт импортирует модуль управления AD, считывает перечень всех сотрудников из AD и список компьютеров из OU=Servers. Список серверов нужен для того, что бы исключить из результатов выборки серверы (ведь нам не нужно фиксировать вход системных администраторов на серверы). Результат помещается в массив, из которого можно забрать любые параметры объекта User, то есть выполнить выборку по любым интересующим нас параметрам (отдел, в котором работает сотрудник, адрес офиса и т.д.).

Полученный список рабочих станций, для примера, можно поместить в группу, для которой включена GPO установки клиента Lync, получив выборку сотрудников по необходимому отделу (для предыдущей статьи о развертывании клиента Lync в домене это как раз очень актуально, ведь она использует группу с компьютерами для установки).

Вот, собственно и всё ;-)

Zabbix: развертывание клиента

Для полноценного мониторинга хостов Zabbix требует наличие установленного клиента. Сам же дистрибутив клиента подразумевает ручную установку. Не тут-то было! Вооружившись командной строкой, ставим клиента одной командой.

Для этого:

1. Создаем каталоги:

— c:\ZabbixClient
— c:\ZabbixClient\32-bit
— c:\ZabbixClient\64-bit

2. В каталоги 32-bit и 64-bit сохраняем дистрибутивы. Нужны файлы zabbix_agentd.exe, zabbix_get.exe и zabbix_sender.exe.

3. В каталог c:\ZabbixClient сохраняем zabbix.conf, psexec.exe и скрипт удаленной установки zremoteinstall.cmd:

@echo off
echo Server to install: %1
echo Server CPU: %2
mkdir \\%1\c$\Zabbix
copy /y zabbix.conf \\%1\c$\Zabbix
copy /y %2\*.* \\%1\c$\Zabbix
psexec \\%1 c:\zabbix\zabbix_agentd.exe -i -c c:\Zabbix\zabbix.conf
sc \\%1 start «zabbix agent»

Теперь для удаленной установки клиента Zabbix достаточно набрать команду: zremoteinstall.cmd server.domain.local 64-bit