Заметки о Windows и других программных продуктах Microsoft...

Управление ACL из PowerShell

Управление ACL из PowerShell

Как вы знаете, в файловой системе NTFS каждый объект  (файл или папка) имеет свой список контроля доступа (Access Control List, ACL). ACL определяет, кто (или что) имеет доступ к объекту, и какие операции разрешено (или запрещено) этому субъекту проводить над объектом.


В PowerShell для управления ACL есть целых два командлета:

  • GetACL — извлекает список ACL для объекта. Полученные данные можно передать для дальнейшей обработки (напр. по конвейеру) или просто сохранить в файл;
  • SetACL — устанавливает новые или изменяет существующие списки ACL для объекта.

В качестве самого простого примера скопируем разрешения одной папки на другую:

Get-Acl C:\test | Set-Acl C:\test2

Сравним ACL до и после. Как видите, изменения налицо.

копирование списка доступа в PowerShell

 

При копировании ACL нужно иметь ввиду, что пользователь, под которым выполняется эта операция  должен являться владельцем (Owner) исходного ресурса (в примере это папка Test) и обладать правом Take Ownership. Дело в том, что при переносе разрешений нельзя перенести другого владельца. Если владельцем папки Test является текущий пользователь и он обладает правом Take Ownership, то все разрешения включая владельца будут скопированы на папку Test2. Если же одно из условий не выполняется, то будет выдана ошибка.

Копирование штука полезная, но чаще приходится задавать разрешения более детально. Для установки разрешений NTFS используется .NET класс FileSystemAccessRule, а список прав перечислен в FileSystemRights Enumeration. Вывести список возможных разрешений можно командой:

[system.enum]::getnames([System.Security.AccessControl.FileSystemRights])

В списке будут показаны как основные, так и детальные разрешения (обычно они показываются на вкладке Advanced).

список прав доступа NTFS

 

Для примера попробуем дать пользователю Testuser1 полные права на папку Test2:

#считываем текущий список ACL папки Test2
$acl = Get-Acl C:\Test2
#Cоздаем переменную с указанием пользователя, прав доступа и типа разрешения
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule `
(″Testuser1″,″FullControl″,″Allow″)
#Передаем переменную в класс FileSystemAccessRule для создания объекта
$acl.SetAccessRule($AccessRule)
#Применяем разрешения к папке
$acl | Set-Acl c:\Test2

Удаление разрешений производится по такой же схеме, только вместо метода SetAccessRule будет использоваться метод RemoveAccessRule:

$acl = Get-Acl C:\Test2
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule `
(″Testuser1″,″FullControl″,″Allow″)
$acl.RemoveAccessRule($AccessRule)
$acl | Set-Acl c:\Test2

И еще один момент. Метод SetAccessRule полностью заменяет разрешения для пользователя. Поэтому, если нужно добавить новые права к уже имеющимся, то используем  AddAccessRule.

изменение разрешений доступа в PowerShell

 

Для удаления всех разрешений пользователя (полное удаление из ACL) используется метод PurgeAccessRules, для работы которого в качестве параметра нужно передать имя пользователя или группы. В работе этого метода есть одна особенность — он не умеет работать со строковыми значениями имён пользователей и групп, поэтому нужен механизм преобразования строковых значений в SID. Для примера удалим группу Users из списка доступа папки Test2:

#Считываем ACL 
$acl = Get-Acl C:\Test2
#Преобразуем строковое значение группы users в SID. Для преобразования воспользуемся 
#классом Ntaccout
$users = New-Object System.Security.Principal.Ntaccount (″users″)
#Применяем метод,передав в него в качестве аргумента переменную $users
$acl.PurgeAccessRules($users)
#Применяем ACL к папке 
$acl | Set-Acl C:\Test2

Стоит иметь в виду, что подобным образом можно удалять только явно назначенные (не наследуемые) разрешения.

удаление разрешений в PowerShell

 

Следующий этап настройки разрешений — это управление наследованием.  За управление наследованием отвечает метод SetAccessRuleProtection. Метод имеет два параметра, каждый из которых может быть $true или $false. Значение первого параметра $true блокирует наследование разрешений от родителя, $false включает наследование для объекта. Второй параметр отвечает за судьбу текущих разрешений для объекта при отключении наследования. Значение $true оставляет унаследованные разрешения в виде явно заданных разрешений, $false наоборот удалит унаследованные разрешения и оставит только те, которые были явно заданы. Например SetAccessRuleProtection ($true,$false) — убираем наследование и удаляем унаследованые разрешения.

По умолчанию вновь созданный объект наследует разрешения от родителя. Для примера создадим новый объект (папку Test3) и отключим у нее наследование:

#Создаем новую папку и выводим ее ACL
md C:\Test3 | Get-Acl | fl
#Считываем ACL папки Test3
$acl = Get-Acl C:\Test3
#Отключаем наследование и удаляем все унаследованные разрешения
$acl.SetAccessRuleProtection($true,$false)
#Применяем ACL к папке Test3
$acl | Set-Acl C:\Test3

Если теперь посмотреть на разрешения папки Test3, то в поле Access мы увидим пустоту. И не удивительно, ведь все наследуемые разрешения мы удалили, а явно заданных у нее не было. Теперь доступ к папке сможет получить только ее владелец (Owner).

настройка наследования в PowerShell

 

И раз речь зашла о владельце. Владельцем объекта автоматически становится пользователь, этот объект создавший — Creator Owner. Есть политика Take Ownership, позволяющая захватывать права владения объектом. По умолчанию это право есть только у членов группы локальных администраторов.

Для управления владельцами объектов в PowerShell  используется метод SetOwner. В качестве примера поменяем владельца папки Test2 :

#Считываем ACL
$acl = Get-Acl C:\Test2
#Преобразуем строковый параметр группы Administrators в SID
$group = New-Object System.Security.Principal.Ntaccount(″Administrators″)
#Применяем метод SetOwner
$acl.SetOwner($group)
#Применяем ACL к объекту
$acl | Set-Acl C:\Test2

Честно говоря, управление владельцами объектов в PowerShell  не очень удобно. Например,  нельзя указать в качестве владельца другого пользователя или группу. Владельцем объекта можно назначить только текущего пользователя или его группу. Кроме того, пользователь, под которым выполняется эта операция, должен иметь следующие права:

  • право Take Ownership для данного объекта;
  • права Read и  Change Permissions для данного объекта;
  • право Restore files and directories в локальной политике безопасности.

изменение владельца в PowerShell

 

И последнее. Список методов, использующихся для управления ACL, подробно описан в классе FileSystemSecurity на MSDN.

 
 
Комментарии

«Например SetAccessRuleProtection ($true,$false) — убираем наследование но оставляем все разрешения.»(c)

Второй параметр работает ровно наоборот, если $true — сохраняет все разрешения, $False — удаляет.
вот описание: http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.objectsecurity.setaccessruleprotection.aspx

Да, здесь я ошибся. SetAccessRuleProtection ($true,$false) отменяет наследование и удаляет все унаследованные разрешения.

К сожалению добавление разрешений не работает. Пользователь добавляется как надо, а вот полный доступ к указанному каталогу уже не устанавливается. То есть добавляется просто пользователь с пустыми разрешениями.

Да, тут ошибся малость. Надо вот так $acl.SetAccessRule($AccessRule)

Я честно сказать, новичок. Пожалуйста, укажите где нужно применить эту конструкции и вместо какой.
У меня есть:
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule («user»,»FullControl»,»Allow»)
$perm = Get-Acl -Path $Path\$folder
$perm.AddAccessRule($rule)
$perm | Set-Acl $path\$Folder
И вот в итоге пользователь «user» к указанной папке добавляется, а его разрешения — нет.

Все хорошо. Разрешения вставали в качестве special, потому не отражались в обычном представлении управления разрешениями. А по факту были полными.

Подскажите как сделать чтоб разрешение применялось не только к каталогу но и к дочерним объектам?

Дочерние объекты наследуют разрешения от родительских по умолчанию.

Подскажите, как проверить наличие доступа к каталогу/файлу у текущего пользователя?

Можно командлетом Test-Path. Он выдает true, если есть доступ и false, если нет.