Contents of this directory is archived and no longer updated.

Примечание: данный пост перепечатан в связи с закрытием бложиков на spaces.live.com, как имеющий какую-то ценность для автора и/или читателей.


В первой части я рассказал про простое использование командлетов Get-Acl и Set-Acl, которые в PowerShell позволяют работать со списками ACL для объектов, как реестр, файловая система NTFS. Во этой части я расскажу про:

  • Выборочное удаление разрешений;
  • удаление участников безопаности из списка ACL и удаление всех ACE;
  • управление наследованием разрешений; 

И в конце напишу скрипт с практическим применением.

Удаление ACE из списков разрешений ACL

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

$ACL = Get-ACL C:\Test
$AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule ("TestUser","Modify","Allow")
$ACL.RemoveAccessRule($AccessRule)
$ACL | Set-Acl C:\Test

Здесь я только выделил ту часть, которая изменилась по сравнению с предыдущим скриптом. И по совету Васи Гусева  убрал временную переменную и напрямую передал в объект необходимые параметры.

Для удаления всех ACE из ACL объекта (в нашем примере из ACL папки) мы применим метод ObjectSecurity.PurgeAccessRules, для работы которого в качестве параметра нужно передать имя пользователя или группы. Если перейти по ссылке на описание, то можно будет прочитать, что в качестве параметра будет использоваться IdentityReference. Вот так примерно получится удаление всех разрешений для группы Users (равносильно нажатию кнопки Remove в GUI интерфейсе). Вот такой получится скрипт на удаление:

# первым делом как обычно получаем текущие разрешения на папку и выгружаем их в переменную.
$ACL=Get-Acl C:\Test
# Метод PurgeAccessRules не умеет работать со строковыми значениями имён пользователей и групп,
# поэтому нужен механизм преобразования строковых значений в SID, который мы уже сможем
# передать в метод PurgeAccessRules. Для преобразования строк воспользуемся классом ntaccout.
$Account = new-object system.security.principal.ntaccount("Users")
# Теперь, когда имя пользователя или группы мы преобразовали в понятное значения для метода,
# мы спокойно его применим, передав в него в качестве аргумента переменную $Account.
$ACL.PurgeAccessRules($Account)
# Ну и теперь можно применить изменённый ACL из переменной к реальному ACL объекта (папки)
$ACL | Set-Acl C:\Test

Достаточно немного переработать этот скрипт и мы сможем удалять абсолютно все ACE из ACL объекта:

# как обычно получаем текущие разрешения на папку и выгружаем их в переменную.
# Здесь нам нужно получить только списки доступа. Если посмотреть вывод команды 
# Get-Acl, то можно увидеть, что права NTFS содержатся в секции Access с которой мы и 
# будем работать. Поэтому мы выбираем из всего списка ACL только секцию Access
# и передаём через конвейер эту секцию в цикл, который будет по очереди удалять ACE каждого участника
# безопасности в списке ACL.
($ACL=Get-Acl C:\Test).access | foreach {
    # здесь для наглядности я ввёл переменную в которую будут записываться имена пользователей
    # и групп, которые имеют доступ к ресурсу. Если в предыдущем примере мы были вынуждены 
    # преобразовывать строковые значения имён, то здесь это просто не нужно. Здесь мы будем просто
    # передавать каждое значение из ACL в метод PurgeAccessRules. Сочетание $_ означает, что это будет 
    # текущий пользователь и его параметр IdentityReference, который, в свою очередь является параметром
    # метода ObjectSecurity.PurgeAccessRules и оно будет означать имя пользователя или группы.
    $Users = $_.IdentityReference
    # теперь нужно для каждого пользователя/группы удалить все ACE. Для этого вызываем метод
    # PurgeAccessRules и в качестве аргумента передаём переменную $Users, которая будет
    # содержать имена пользователей/групп
    $ACL.PurgeAccessRules($Users)
}
$ACL | Set-Acl C:\Test

Как я уже сказал - переменную $Users я ввёл только для получения наглядности работы цикла. PurgeAccessRules можно сразу передать аргумент $_.IdentityReference и тогда у нас получится всего лишь 2 строчки:

($ACL=Get-Acl C:\Test).access | foreach {$ACL.PurgeAccessRules($_.IdentityReference)}
$ACL | Set-Acl C:\Test

И в качестве заключительного комментария для данной секции добавлю, что таким образом можно удалять только явно назначенные разрешения.

 

Управление наследованием разрешений в PowerShell

Теперь можно поговорить о более глубоком управлении списками ACL, а именно - управление наследованием и установкой необходимой области действия разрешений. Если смотреть скрипт, который был опубликован в первой части, то данный скрипт устанавливает разрешения только для конкретного объекта и дочерние объекты установленных разрешений не наследуют.

Но сперва займёмся отменой наследования от родительского объекта.

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

# В этой строке я просто создаю папку с именем Folder в текущей папке сеанса PowerShell
New-Item -ItemType directory -path .\Folder
# по умолчанию папка Folder унаследует разрешения от родителя. В этом можно убедиться
# набрав после этой строки команду Get-Acl | Format-List. Теперь мы знакомым методом
# считаем текущий список ACL для папки в переменную $ACL
$ACL=Get-Acl Folder
# к примеру, мы не будем изменять текущие разрешения для папки, а только отменим
# наследование. Управление наследованием для ресурса обеспечивается за счёт метода
# ObjectSecurity.SetAccessRuleProtection и описывается он очень просто:
$ACL.SetAccessRuleProtection(
    # здесь первое значение $true блокирует наследование разрешений от родителя,
    # значение $false включает наследование для объекта. Мы отключим его.
    $true,
    # второй параметр отвечает за судьбу текущих разрешений для объекта
    # при отключении наследования. Значение $true оставляет унаследованные
    # разрешения в виде явно заданных разрешений. $false наоборот удалит
    # унаследованные разрешения и оставит только те, которые были до этого
    # явно заданы. Мы же оставим имеющийся набор разрешений
    $true)
# ну и теперь все внесённые изменения применим к ACL самой папки
$ACL | Set-Acl .\Folder

Хочется ещё добавить по SetAccessRuleProtection, что второй параметр $false кроме явно заданных разрешений ещё оставит группу в которой состоит пользователь. Поэтому, возможно, потребуется дополнительная чистка ACL для данной группы.

Управление глубиной действия разрешений

Когда мы научились добавлять и удалять различные ACE для списка ACL, можно поговорить про установку глубины действия разрешений для папок. За управление глубиной действия разрешений (раздел Apply onto в окне просмотра расширенных прав доступа отвечают классы InheritanceFlags и PropagationFlags. Их значения могут быть знакомы тем, кто работал с утилитами командной строки CACLS и ICACLS. Класс InheritanceFlags содержит 2 представителя класса:

  • ContainerInherit (CI) - наследуют контейнеры
  • ObjectInherit (OI) - наследуют объекты

Класс PropagationFlags так же содержит 3 представителя класса:

  • InheritOnly (IO) - только наследование
  • NoPropagateInherit (NP) - не распрастронять наследование
  • None - воздействует только на сам текущий объект

комбинацией этих членов можно получить различные значения наследования раздела Apply onto в окне просмотра расширенных прав. Не пускаясь в долгие рассуждения приведу таблицу сопоставления значений и требуемых для этого флагов:

This folder only - без флагов. По умолчанию при назначении права назначаются только на данный объект.
This folder, subfolders and Files - CI, OI, None
This folder and subfolders - CI, None
This folder and files - OI, None
Subfolders and Files only - CI, OI, IO
Subfolders only - CI, IO
Files only - OI, IO

Теперь, как и обещал, получив необходимые знания, можно приступать к решению практической задачи. В качестве примера задачи будет - установка разрешений для корневой папки папок перенаправления, как это требуется в рекомендации Microsoft - How to dynamically create security-enhanced redirected folders by using folder redirection in Windows 2000 and in Windows Server 2003

New-Item -ItemType directory -Path D:\Users
# после создания корневой папки перенаправления я объявил переменные с заранее установленными флагами
# InheritanceFlags и PropagationFlags, чтобы их потом передавать в класс FileSystemAccessRule
$inheritCO = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
$propagationIO = [system.security.accesscontrol.PropagationFlags]"InheritOnly"
$PropagationN = [system.security.accesscontrol.PropagationFlags]"None"
$ACL = Get-Acl D:\Users
# убираем наследование с созданной папки
$ACL.SetAccessRuleProtection($True, $false)
# удаляем все ACE, которые были оставлены после снятия наследования
($ACL).Access | foreach {$ACL.PurgeAccessRules($_.IdentityReference)}
# Согласно рекомендациям в статье комбинацией флагов InheritanceFlags и PropagationFlags
# выставляем нужную облать действия разрешений
$AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule(
    "Creator Owner", "FullControl", $inheritCO, $propagationIO,  "Allow"
)
$ACL.SetAccessRule($AccessRule)
$AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule(
    "System", "FullControl",$inheritCO, $propagationN, "Allow"
)
$ACL.SetAccessRule($AccessRule)
$AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule(
    "Domain Admins", "FullControl", $inheritCO, $propagationN, "Allow"
)
$ACL.SetAccessRule($AccessRule)
$AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule(
    "Everyone", "ExecuteFile", "Allow"
)
$ACL.SetAccessRule($AccessRule)
$AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule(
    "Everyone", "ReadData", "Allow"
)
# в этой строке я вместо SetAccessRule применил AddAccessRule. Дело в том, что команда
# SetAccessRule полностью заменяет ACE для пользователя. Если мы хотим к имеющимся уже правам
# доступа добавить другие права, то используем AddAccessRule :) 
$ACL.AddAccessRule($AccessRule)
$AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule(
    "Everyone", "ReadAttributes", "Allow"
)
$ACL.AddAccessRule($AccessRule)
$AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule(
    "Everyone", "AppendData", "Allow"
)
$ACL.AddAccessRule($AccessRule)
$ACL | Set-Acl D:\Users

Вот так используя уже полученные знания можно начинать решать даже нетривиальные задачи по управлению списками ACL из PowerShell. Уверен, что объём кода в VBS для решения этой же задачи будет далеко не таким компактным :)

В следующей и заключительной по теме управления списками ACL в PowerShell части я расскажу как управлять списками ACL реестра и смена владельца объекта.


Share this article:

Comments:

Comments are closed.