PowerShell. Создание списка пользователей с указанием прав доступа к папке.
Задача выяснить кто из пользователей домена имеет доступ к сетевой папке и какими правами обладает.Если доступ имеют всего несколько пользователей, то это не сложно сделать руками. Но если пользователей много, да еще и с группами, то приходится задумываться об автоматизации процесса.
Нам нужно получить списки доступа к папке, отделить пользователей от групп, получить пользователей которые входят в группы и выгрузить все это в удобочитаемой форме.
Нюансы:
Меня интересовали только доменные учетки, по этому в итоговые данные не попадают локальные пользователи сервера.
Отличать группы от пользователей будем при помощи командлета Get-ADObject который возвращает ObjectClass «User» или «Group» для пользователя или группы соответственно.
#
#Скрипт для получения списка доменных учетных записей которые имеют права на папку. Список выгружается в CSV файл.
#
#Указываем папку по которой нужен отчет
$path = “путь до целевой папки. Допускается указать сетевую папку”
#путь куда клать CSV
$datafile = "c:\AccessRights.csv"
#Создаем файл по пути $datafile
Set-Content -Value 'Имя пользователя;Права доступа;' -Path $datafile -Encoding UTF8
#Получаем имя домена
$domain = (Get-ADDomain).name.ToUpper()
#Получаем списки безопасности целевой папки
$Acl = Get-Acl $path
$acl = $acl.Access
#Перебираем список доступа
foreach ($a in $acl)
{
#Берем только доменные учетки
if ($a.IdentityReference -match $domain)
{
#Переводим уровень доступа на человеческий)
if ($a.FileSystemRights.ToString() -eq "ReadAndExecute, Synchronize") {$AccessType = "Только Чтение"}
elseif ($a.FileSystemRights.ToString() -eq "Modify, Synchronize") {$AccessType = "Чтение и Запись"}
elseif ($a.FileSystemRights.ToString() -eq "FullControl") {$AccessType = "Полный доступ"}
else {$AccessType = "Custom"}
$name = $a.IdentityReference.Value.ToString().Replace($domain+"\",'')
#Выясняем группа или пользователь
$ADObject = Get-ADObject -filter{SamAccountName -eq $name}
if ($ADObject.ObjectClass.ToString() -eq "user") {$data = $name+";"+$AccessType}
#Если группа - получаем список пользователей в группе
if ($ADObject.ObjectClass.ToString() -eq "group")
{
$users = Get-ADGroupMember $name
foreach ($u in $users)
{
$name = $u.SamAccountName
$data = $name+";"+$AccessType
#Запись в файл
Add-Content -Value $data -Path $DataFile -Encoding UTF8
}
}
#Запись в файл
Add-Content -Value $data -Path $DataFile -Encoding UTF8
}
}
Добрый день!
Подскажите, как выудить список папок в сетевой шаре, к которым имеет доступ (с указанием типа доступа) определённая группа домена?
Необходимо получить ACL интересующих папок из шары и скриптом проверить на вхождение группы в ACL.
Получаете ACL как в скрипте выше и в foreach делаете условие(if) имя группы. Если условие выполнено — выгружаете в файл или выводите на экран.
Блин, всё это классно, но пока это выше моих возможностей 🙁
Не могли бы Вы выложить тут готовый скрипт? Буду весьма благодарен! И в дальнейшем буду его разбирать и сравнивать с первоначальным скриптом что бы научится и понять логику PS.
Опять же, в выводе скрипта не указана, какая папка проверялась, что не очень удобно. А если папок будет много, то тут вообще невозможно будет разобраться.
Что было не так в исходнике (коротко)
“ ” кавычки типографские — PowerShell их часто не понимает (нужны обычные » «).
Get-ADObject -filter{SamAccountName -eq $name} — так filter не подхватит переменную как вы ожидаете; лучше -LDAPFilter или Get-ADUser/Get-ADGroup.
Для групп вы берёте Get-ADGroupMember без -Recursive, поэтому вложенные группы теряются.
Дублирование строк: вы пишете $data внутри группы по каждому пользователю и потом ещё раз пишете $data после блока группы (и для пользователя тоже).
Add-Content в циклах медленный; лучше собрать массив и один раз Export-Csv.
Сопоставление прав “строкой” часто ломается (порядок/комбинации прав могут отличаться).
# Скрипт: выгрузка доменных пользователей, имеющих доступ к папке (через ACL и AD-группы)
# Вывод: CSV (разделитель 😉
Import-Module ActiveDirectory
# Папка для отчёта (локальная или UNC)
$path = «\\server\share\folder» # <— поменяйте
# Куда сохранить CSV
$datafile = "C:\AccessRights.csv"
# Домен (NetBIOS), чтобы отфильтровать DOMAIN\*
$domainNetbios = (Get-ADDomain).NetBIOSName
# Получаем ACL
$acl = (Get-Acl -LiteralPath $path).Access
# Функция "человеческих" прав (упрощённая)
function Convert-Rights([string]$rights) {
if ($rights -match "FullControl") { return "Полный доступ" }
if ($rights -match "Modify") { return "Чтение и Запись" }
if ($rights -match "ReadAndExecute|Read") { return "Только чтение" }
return "Custom"
}
# Кэш AD-объектов (ускорение)
$adCache = @{}
function Get-AdClassBySam([string]$sam) {
if ($adCache.ContainsKey($sam)) { return $adCache[$sam] }
# Пробуем как user
$u = Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue
if ($u) { $adCache[$sam] = "user"; return "user" }
# Пробуем как group
$g = Get-ADGroup -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue
if ($g) { $adCache[$sam] = "group"; return "group" }
$adCache[$sam] = "unknown"
return "unknown"
}
# Сбор строк результата
$result = New-Object System.Collections.Generic.List[object]
foreach ($ace in $acl) {
# Берём только DOMAIN\Name
$id = $ace.IdentityReference.Value
if ($id -notmatch "^\Q$domainNetbios\E\\") { continue }
$sam = $id -replace "^\Q$domainNetbios\E\\",""
$accessType = Convert-Rights ($ace.FileSystemRights.ToString())
$cls = Get-AdClassBySam $sam
if ($cls -eq "user") {
$result.Add([pscustomobject]@{
User = $sam
Rights = $accessType
Source = "Direct ACE"
AceIdentity = $id
}) | Out-Null
continue
}
if ($cls -eq "group") {
# Рекурсивно раскрываем членов групп
$members = Get-ADGroupMember -Identity $sam -Recursive -ErrorAction SilentlyContinue |
Where-Object { $_.objectClass -eq "user" }
foreach ($m in $members) {
$result.Add([pscustomobject]@{
User = $m.SamAccountName
Rights = $accessType
Source = "Via group"
AceIdentity = $id # группа из ACL
}) | Out-Null
}
continue
}
# неизвестный объект
$result.Add([pscustomobject]@{
User = $sam
Rights = $accessType
Source = "Unknown (not user/group?)"
AceIdentity = $id
}) | Out-Null
}
# Убираем дубли (например, пользователь в двух группах с одинаковыми правами)
$result |
Sort-Object User, Rights, AceIdentity -Unique |
Export-Csv -Path $datafile -NoTypeInformation -Delimiter ';' -Encoding UTF8
Write-Host "Готово: $datafile"