2008/6/27
Ещё несколько слов об управлении ACL в PowerShell и полезных деталях
Во второй части серии статей про управление списками ACL в PowerShell я опубликовал скрипт, который создаёт общую папку для папок перенаправления и расставляет необходимые ACE в списке ACL. Перечитывая свой пост я обнаружил, что забыл рассказать об одной вещи. А именно - установка набора разрешений для группы/пользователя.
Итак, нашем примере группе Everyone требовались следующие права:
- ExecuteFile
- ReadData
- ReadAttributes
- AppendData
В скрипте мы каждой строчкой добавляли разрешения по одиночке для пользователя и потом записывали их в ACL при помощи метода AddAccessRule. Не самое лучшее решение. А если одной строкой перечислить все права?
$AccessRule = new-object System.Security.AccessControl.FileSystemAccessRule ("Everyone", "ExecuteFile, ReadData, ReadAttributes, AppendData", "Allow")
$ACL.SetAccessRule($AccessRule)
Вот так одной строчкой мы смогли добавить набор прав для группы. Здесь хочу лишь отметить, что пользователей так перечислять нельзя. Для каждого пользователя нужно создавать отдельный ACE.
Теперь немного поговорим о практической стороне вопроса. А именно - передача параметров запуска в тело скрипта. В примере я явно указал путь и имя домашней папки. Во всяком случае я использую такой путь. Кто-то хочет другой путь, кто-то хочет других пользователей использовать и т.д. Это придётся в каждом частном случае править скрипт по новой. Например, путь к папке в скрипте используется 3 раза. А если их там будет 5, 10? Это ни разу не прибавляет гибкости скрипту. А что если мы будем использовать один скрипт и передавать праметры (например, параметр пути) из командной строки CMD? А давайте! Строка запуска очень простая:
powershell %path%\Test.ps1 [parameter1] [parameter2] [parameter3] -SwitchParameter
Разберём, что мы тут имеем:
- powershell - тут комментарии излишни, это команда, которая будет обрабатывать наш скрипт
- %path%\Test.ps1 - это полный путь к файлу скрипта. Можно не указывать путь к скрипту, а только его имя, если путь к скрипту указан в системной или пользовательской переменной %path%. Скажем, я держу скрипты в одной рабочей папке и добавил путь к ней в переменную %path%, чтобы не указывать постоянно длиннющий путь.
- [parameters] - пользовательские параметры, которые передаются в тело скрипта. Параметры просто перечисляются через пробел. Например: powershell %path%\Test.ps1 E:\Users, 'Domain Users' - передаст в тело скрипта путь к домашней папке и группу Domain Users. Если передаваемый параметр содержит пробел, то этот параметр нужно заключить в одинарные кавычки.
- -SwitchParameter - это параметр запуска самого приложения PowerShell. Доступные параметры запуска можно посмотреть, набрав в консоли CMD (или в самом PowerShell) powershell /?
В скрипте эти параметры принимаются командой Param. Синтаксис тут тоже очень простой:
Param ($parameter1, $parameter2, $parameter3)
Команда Param в последовательном порядке выбирает параметры и по очереди присваивает их переменным, которые уже будут работать в скрипте. В качестве примера я передам в скрипт путь к папке и группу Domain Users:
powershell c:\Test.ps1 d:\Users\Home 'Domain Users'
отмечу, что если скрипт запускается из консоли PowerShell то имя исполняемого файла указывать не надо, а начинать сразу с пути к скрипту.
и сам скрипт:
Param ($path, $users)
New-Item -ItemType directory -Path $path
$inheritCO = [system.security.accesscontrol.InheritanceFlags]"ContainerInherit, ObjectInherit"
$propagationIO = [system.security.accesscontrol.PropagationFlags]"InheritOnly"
$PropagationN = [system.security.accesscontrol.PropagationFlags]"None"
$ACL = Get-Acl $path
$ACL.SetAccessRuleProtection($True, $false)
($ACL).Access | foreach {$ACL.PurgeAccessRules($_.IdentityReference)}
$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 ("$users", "ExecuteFile, ReadData, ReadAttributes, AppendData", "Allow")
$ACL.SetAccessRule($AccessRule)
$ACL | Set-Acl $path
Я выделил жирным участки кода, где будут использовать переменные с переданными в них параметрами командной строки.