PowerShell: Массовые изменения NTFS прав на папки и файлы

Написал скрипт для поддерживания и назначения прав на папки. Например, у нас есть такая структура папок:

D:\Клиенты\
D:\Клиенты\Ромашка
D:\Клиенты\Справка

И стоит следующая задача:

  1. «D:\Клиенты» удалить стандартные права для пользователей домена
  2. «D:\Клиенты\Ромашка» дать полные права группе flora
  3. «D:\Клиенты\Ромашка» дать права на чтение пользователю secretary
  4. «D:\Клиенты\Справка» дать полные права для пользователя secretary
  5. «D:\Клиенты\Справка» дать права на чтения для группы flora

для этого создаем файлик acl.csv в кодировке UTF-8 следующего содержания:
[text]
Folder;SecIdentity;AccessRights;AccessControlType;BlockInherit
D:\Клиенты;BUILTIN\Users;Remove;;Yes
D:\Клиенты\Ромашка;Domain Name\flora;FullControl;Allow;
D:\Клиенты\Ромашка;Domain Name\flora;ReadAndExecute;Allow;
D:\Клиенты\Справка;Domain Name\secretary;FullControl;Allow;
D:\Клиенты\Справка;Domain Name\secretary;ReadAndExecute;Allow;
[/text]

и запускаем с админским правами скрипт
[powershell]
ntl-Set-Acl.ps1 -FolderListFile .\acl.csv
[/powershell]

Сначала опишу формат файла.

  • Folder — в этом поле просто имя файла/папки
  • SecIdentity — доменный/локальный аккаунт группы или пользователя
  • AccessRights — может принимать по одному или через запятую следующие значения FullControl, Read, ReadAndExecute и т.д. Полный список по одной из ссылок в конце статьи. Кроме того в этом поле можно указать значение Remove и тогда это даст команду удалить из ACL папки или файла аккаунт, указанный в поле SecIdentity
  • AccessControlType — значения Allow или Deny. Игнорируется, если поле AccessRights имеет значение Remove.
  • BlockInherit — Если стоит значение Yes, то перед тем, как добавить/удалить права, для папки Folder отключается применение прав от родителя с сохранением текущих настроек. В основном это нужно, когда удаляешь права. Например, для того что убрать дефолтные разрешения для доменных пользователей. Для добавления прав, обычно не нужно блокировать наследование.

Правила заполнения файла:

  • Папки верхнего уровня надо указывать раньше
  • Для стандартных групп(Administrators,Users) и пользователей(Administrator) надо указывать BUILTIN\Users, а не Domain Name\Users

Как работает скрипт.

Если просто, то ACL(Access Control List) — это все права на папку, а ACE(Access Control Entry) — это одна запись, например, пользователь Вася имеет полные права на эту папку. Таким образом, в ACL входит кучка ACE. Кроме этого в ACL хранятся настройки наследования, владелец, группа и т.д.

Скрипт ntl-Set-Acl.ps1:

[ps]
param (
[string]$FolderListFile = $(throw "Укажите файл со списком папок, аккаунтов и прав с помощью ключа -FolderListFile.")
)

$FolderList=Import-Csv $FolderListFile -Delimiter ";"

$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None

$FolderList | ForEach-Object {
if (Test-Path $_.Folder)
{
if (Test-Path $_.Folder -pathtype container){
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
} else {
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::None
}
$acl = Get-Acl $_.Folder
if ($_.BlockInherit -eq "Yes"){
#Отключаем наследование прав от родителя с сохранением текущих прав.
$acl.SetAccessRuleProtection($True, $True)
Set-ACL $_.Folder $acl
$acl = Get-ACL $_.Folder
}
if ($_.AccessRights -eq "Remove"){
#Удаляем аккаунт/группу из ACL(Access Control List)
$AccessRights = [System.Security.AccessControl.FileSystemRights]"Read"
$AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow
if ($_.SecIdentity -eq $acl.Group){
$objACL.SetGroup([System.Security.Principal.NTAccount]"BUILTIN\Administrators")
}
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($_.SecIdentity, $AccessRights, $InheritanceFlag, $PropagationFlag, $AccessControlType)
$acl.RemoveAccessRuleAll($ace)
Set-ACL $_.Folder $acl
}else{
#Добавляем ACE(access control entry) в ACL(Access Control List)
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule `
($_.SecIdentity, $_.AccessRights, $InheritanceFlag, $PropagationFlag, $_.AccessControlType)
$acl.AddAccessRule($ace)
Set-ACL $_.Folder $acl
}
} else {
Write-Host "$_.Folder не существует!" -ForegroundColor Red
}
}
[/ps]

Подробнее можно почитать на Microsoft-е:

http://technet.microsoft.com/en-us/library/ff730951.aspx
http://blogs.technet.com/b/josebda/archive/2010/11/12/how-to-handle-ntfs-folder-permissions-security-descriptors-and-acls-in-powershell.aspx

Если что не понятно, спрашивайте. Постараюсь ответить.