Основной способ ограничения доступа к файлам и папкам дает файловая система NTFS с ее таблицами ACL. Это может быть право только на чтение файла (открытие и просмотр), на чтение и запись (открытие, просмотр, изменение и сохранение) и многие другие. Такие права мы чаще устанавливаем через GUI назначая права не конечному пользователю, а группе в которой он состоит. Все действия по созданию и изменению мы так же можем сделать через Powershell.
На мой взгляд использование консоли Powershell лишнее при выдаче таких прав. Риск совершить ошибку в консоли намного выше, чем при работе в GUI, да и время для написания команды уйдет больше. Есть специфичные задачи, например в виде аудита или перенос прав где Powershell очень поможет.
Содержание[Скрыть]
Основы разрешений
ACL (access controll list) — делится на два вида:
- SACL (System Access Control List) — используется для аудита;
- DACL (Discretionary Access Control List) — используется для выдачи и проверки разрешений пользователям и группам.
Оба этих типа разрешений хранятся в специальной таблице MFT (Master File Table).
Основное средство для редактирования этих разрешений в GUI можно увидеть зайдя в свойства файла или папки:
В области 4 выделены следующие разрешения:
- Read — открытие файла и папки;
- List folder contents — открытие папки;
- Write — создание файлов и папок и их изменение;
- Read & Execute — открытие и запуск исполняемых файлов;
- Modify — открытие, создание, изменение и удаление файлов и папок;
- Full Control — включает разрешения modify, а так же управление разрешениями файла или папки.
Чаще всего мы работаем с разрешениями выше, но есть еще один список с возможностью настройки прав более тонко:
Как можно догадаться — разрешения указанные в области 1 это просто набор нескольких правил из области 3. Их так же еще называют «Premission Sets» и «Special Premissions».
Групповые разрешения могут принимать флаги Allow и Deny, которые разрешат или запретят указанные действия. Указывать разрешения для пользователей через Deny считается плохой практикой и практически не используется.
Кроме этого существует наследование:
Наследование помогает установить разрешения для одной папки так, что оно будет применяться ко вложенным файлам и папкам. Если наследование отключить (2), то у нас будет возможность убрать все наследуемые разрешения или оставить их.
Получение текущих разрешений в Powershell
На примере ниже я верну разрешения для папки «C:TestFolder»
Get-ACL -Path "C:TestFolder" | fl
В области 1 выделен владелец папки, а под областью 2 отображаются все группы и пользователи с правами.
Мы можем проверять права не только локальной, но и сетевой папки. На примере ниже возвращена та же папка:
Get-ACL -Path "\localhostC$TestFolder" | fl
Поиск всех папок с правами у определенной группы
Представим, что мы хотим проверить права данные определенной группе. Мы можем заходить в свойства каждой папки и смотреть вкладку «Безопасности», а можем сделать это через Powershell.
Обычно у нас есть какой-то каталог с общим доступом с папками внутри, на которые мы выдаем разрешения. В моем случае такой каталог «Moscow», а на папки внутри я уже даю права:
В следующем примере я узнаю на какие папки установлены разрешения для TestGroup:
# Получаем все директории внутри это папки $path = Get-ChildItem -Path 'C:Moscow' # Получаем все выданные разрешения $acl = $path | Get-ACL # Группа, которую мы ищем $group = 'DomainTestGroup' # Ищем группу в ACL foreach ($folder in $acl){ if ($folder.Access.IdentityReference -eq $group){ Write-Output "Путь папки: " $folder.Path # Получаем только разрешения $access = ($folder.Access | where IdentityReference -eq $group).FileSystemRights Write-Output "Разрешения выданные группе: " $access } }
Изменение, копирование и добавление разрешений
Еще одна причина использовать Powershell — это возможность копирования разрешений. Например так я поставлю разрешения для папки Folder2 такие же, как и Folder2:
# Получаем действующие разрешения у папки Folder1 $acl = Get-ACL -Path "C:Folder1" # Устанавливаем эти же разрешения для папки Folder2 $acl | Set-Acl -Path "C:Folder2"
Возможности добавить нового пользователя в список ACL или изменить его права одним командлетом у нас нет. В обоих случаях мы должны будет создавать копию объекта ACL, изменять ее отдельным классом, а затем применять используя метод. Сам объект, который мы получаем через Get-ACL, имеет множество методов:
Get-ACL -Path "C:Folder1" | Get-Member -MemberType Method
Для создания нового объекта с правами используется класс «FileSystemAccessRule», который в команде будет выглядеть так:
New-Object Security.AccessControl.FileSystemAccessRule('IdentityReferenceString', 'FileSystemRights', 'InheritanceFlags, PropagationFlags', 'AccessControlType')
Расшифровать значения можно следующим образом:
- IdentityReferenceString — пользователь или группа формата «DOMAINAdministrator»;
- FileSystemRights — сами разрешения, например «Read»;
- InheritanceFlags и PropagationFlags — определяют наследование. Например вы можете сделать так, что папки внутри указанной будут наследовать разрешения, а файлы нет. Ниже будут приведены несколько примеров. Более подробно об этом можно почитать на сайте Microsoft;
- AccessCpmtrolType — разрешить или запретить (Allow/Deny).
Изменение и добавление прав у пользователя и групп
Допустим у нас есть пользователь «Test User (001)» с возможностью чтения папки «Folder1» и мы хотим добавить еще права на запись. Это будет выглядеть так:
# Делаем копию существующих прав на папку $old_acl = Get-ACL -Path "C:Folder1" # Создаем права, которые хотим добавить к папке $new_acl = New-Object System.Security.AccessControl.FileSystemAccessRule('DOMAINTest User (1)', 'Write', 'ContainerInherit, ObjectInherit', 'None', 'Allow') # Изменяем скопированные разрешения $old_acl.AddAccessRule($new_acl) # Устанавливаем все разрешения к папке Set-ACL -Path "C:Folder1" -ACLObject $old_acl
Наследование типа ‘ContainerInherit, ObjectInherit’ говорит о том, что оно касается этой папки и всех вложенных папок и файлов.
Таким же образом работает добавление новой группы или пользователя в список ACL:
# Делаем копию существующих прав на папку $old_acl = Get-ACL -Path "C:Folder1" # Права и новый пользователь $new_acl = New-Object System.Security.AccessControl.FileSystemAccessRule('DOMAINTest 2', 'Write,Read', 'ContainerInherit, ObjectInherit', 'None', 'Allow') # Изменяем скопированные разрешения $old_acl.AddAccessRule($new_acl) # Устанавливаем все разрешения к папке Set-ACL -Path "C:Folder1" -ACLObject $old_acl
Права, которые мы можем дать имеют сокращенное название и они отображены далее:
У вас может быть много ошибок связанных с созданием класса с новыми разрешениями. Я бы советовал выводить существующие права и сравнивал бы их с новыми — это позволит снизить вероятность ошибок.
При этом вы можете применить набор разрешений, например в виде Write, но результат будет отображаться в виде «Special Premission»:
Если бы я указал наследование в виде ‘ContainerInherit, ObjectInherit’, то права бы применились как нужно:
Поэтому я рекомендую смотреть существующие разрешения на примере того, как я сделал это выше.
Удаление прав у пользователя или группы
Для удаления всех разрешений есть метод «RemoveAccessRuleAll». Работает он так же:
# Делаем копию существующих прав на папку $old_acl = Get-ACL -Path "C:Folder1" # Права и новый пользователь $new_acl = New-Object System.Security.AccessControl.FileSystemAccessRule('DOMAINTest User (1)', 'Write,Read', 'ContainerInherit, ObjectInherit', 'None', 'Allow') # Удаляем все разрешения $old_acl.RemoveAccessRuleAll($new_acl) # Устанавливаем все разрешения к папке Set-ACL -Path "C:Folder1" -ACLObject $old_acl
Для удаления конкретного права, например только возможность чтения, есть метод «RemoveAccessRule». С этим методом у меня были проблемы после которых действующие разрешения менялись на Special и изменить эту ситуацию у меня не получилось. Если вам нужно все же убрать одно разрешение — я бы советовал удалять все разрешения у пользователя, а затем добавлять их заново. У пользователя было право на Чтение и Запись, но мне нужно было оставить только чтение:
# Делаем копию существующих прав на папку $old_acl = Get-ACL -Path "C:Folder1" # Указываем пользователя для удаления $new_acl = New-Object System.Security.AccessControl.FileSystemAccessRule('DOMAINTest User (1)', 'Read', 'ContainerInherit, ObjectInherit', 'None', 'Allow') # Удаляем все разрешения данного пользователя $old_acl.RemoveAccessRuleAll($new_acl) # Применяем правильные разрешения $old_acl.AddAccessRule($new_acl) # Записываем все разрешения Set-ACL -Path "C:Folder1" -ACLObject $old_acl
Смена владельца
Смена владельца файла или папки делается через метод SetOwner. Этот метод, в качестве идентификатора, принимает SID пользователя и что бы его узнать нужно использовать класс «System.Security.Principal.Ntaccount». На практике это выглядит так:
# Получаем старый список ACL $old_acl = Get-ACL -Path "C:Folder2" # Получаем SID пользователя $user_sid = New-Object System.Security.Principal.Ntaccount("DOMAINTest 3") # Устанавливаем нового владельца $old_acl.SetOwner($user_sid) # Записываем Set-Acl -Path "C:Folder2" -ACLObject $old_acl
Включение или отключение наследования папок и файлов
Для управления наследованием используется метод «SetAccessRuleProtection», который устанавливает следующее:
- Нужно ли блокирование от родительской папки.
- Нужна ли перезапись прав.
Значения указываются в $True или $False. Например так я включу наследование и заменю существующие разрешения родительскими:
# Получаем старый список ACL $acl = Get-Acl -Path "C:Folder1OneMoreFolder" # Устанавливаю наследование и перезапись прав $acl.SetAccessRuleProtection($false,$true) # Записываю Set-Acl -Path "C:Folder1OneMoreFolder" -ACLObject $acl
Сбор всех прав и их экспорт в CSV
Учитывая примеры выше мы можем временно собирать отчеты по выданным правам. Пример того, как может выглядеть отчет:
Такой отчет сформирует следующий скрипт:
# Указываем путь к директории, где нужно собрать все права $folder_path = dir -Directory -Path "C:WorkFolder" -Recurse -Force # Переменная, которая будет хранить данные из цикла $Report = @() Foreach ($folder in $folder_path) { # Получаем права на текущий каталог $Acl = Get-Acl -Path $Folder.FullName foreach ($Access in $acl.Access) { # Формируем массив PSCustomObject из каждого права $Properties = [ordered]@{ 'Папка'=$Folder.FullName;` 'Пользователь или группа'=$Access.IdentityReference;` 'Права'=$Access.FileSystemRights;` 'Наследование'=$Access.IsInherited} # Записываем в переменную $Report += New-Object -TypeName PSObject -Property $Properties } } # Экспортируем в CSV $Report | Export-Csv -path "C:Permissions.csv" -NoTypeInformation -Encoding Unicode
Ваш комментарий будет первым