Contents of this directory is archived and no longer updated.

Posts on this page:

Update 28.10.2010: исправлена ошибка с назначением права ManageDocuments.


Вот и пришло время закрыть тему управления принтерами и их списками ACL в PowerShell с использованием WMI. Я в блоге уже расписывал решение частных задач по основным задачам управления принтеров и по управлению их ACL списками. В этом посте я сложу все наработки по этому вопросу в единый концептуальный скрипт, который будет называться PrinterUtils.ps1 с достаточно объёмным набором функций, которые нацелены на упрощение для администраторов автоматизации принтеров с использованием PowerShell. Если кто-то захочет разобраться в работе скрипта и понять используемые приёмы, то предлагаю ознакомиться с следующими ссылками:

В качестве основы я использовал свои предыдущие наработки с SecurityDescriptor в предыдущем блоге, когда разбирал вопрос управления SharePermissions из PowerShell:

Материала у меня на эту тему набралось достаточно много, чтобы проникнуться в идею работы классов WMI и SecurityDescriptor, который не раз пытался посадить меня в лужу :) Однако версия скрипта ShareUtils чётко говорит о том, что скрипт далеко не идеален и не оптимален, имеет свои недостатки, т.к. это был мой первый опыт работы с функциями. Сейчас я значительно переработал структуру работы скрипта (оставив только Core работы с SecurityDescriptor), добавив удалённое управление (в разумных пределах) и, главное (как мне кажется), реализовал работу функций в конвейере. Примеры использования скрипта распишу чуть ниже. Итак, представляю набор функций, которые реализованы в скрипте:

  1. Подключение (маппинг) сетевого принтера к пользователю;
  2. Отключение маппинга сетевого принтера от пользователя;
  3. Получение сведений о принтерах;
  4. Установка принтера по умолчанию;
  5. Установка принтера для общего пользования (расшаривание принтера);
  6. Отмена принтера для общего пользования;

Данная секция представляет собой базовые возможности по управлению принтерами и полностью работоспособна в среде Windows XP/Windows Server 2003. А вот секция управления ACL списками принтеров доступна только в среде Windows Vista/Windows Server 2008. Сюда входят следующие функции:

  1. Получение сведений о правах доступа на конкретный принтер, конкретный принтсервер или по списку компьютеров;
  2. Импорт сведений о правах доступа из внешнего источника. Это может быть и CSV и XML или другой формат;
  3. Добавление пользователя или группы в ACL список принтера или всех принтеров, которые подключены к принтсерверу;
  4. Удаление пользователя или группы из ACL списка принтера или всех принтеров, которые подключены к принтсерверу;
  5. Установка пользователя или группы в ACL список принтера или всех принтеров, которые подключены к принтеру. При этом все имеющиеся права доступа будут удалены и заменены только одним ACE с правом ManagePrinters.

Для этих функций полностью реализована поддержка удалённой работы и работа в конвейере. Синтаксис команд используется примерно следующий:


Read more →

Итак, как я и обещал, я вернулся к вопросу изменения ACL принтеров в PowerShell. В первой части (Странности метода SetSecurityDescriptor класса Win32_Printer) я изложил проблематику вопроса. В конечном итоге я сегодня смог найти решение, которое оказалось не совсем понятным, но относительно предсказуемым.

Вернёмся снова к документации MSDN: SetSecurityDescriptor Method of the Win32_Printer Class

Это, конечно же, было моим попустительством, что не указал флаг управления SE_DACL_PRESENT и не включил привилегии SeSecurityPrivilege ("умение читать - первое умение системного администратора" (c) Peter.G). Понимание этого факта пришло после очередного прочтения поста о смене владельца папки (Смена владельца папки или файла в PowerShell (часть 2)). Что касается флагов управления, то выложу здесь значения флагов:


Read more →

Как-то давно Александр Станкевич просил у меня вариант скрипта, который бы менял владельца файла или папки из PowerShell. В своё время я занимался этим вопросом и результат моих исследований:

Что-то меня натолкнуло снова вернуться к этому вопросу. Учитывая проблематику, изложенных в предыдущих статьях, я перестал искать нативный способ изменения владельца в PowerShell через .NET и решил поискать его в WMI (что означает очередные мучения многострадального SecurityDescriptor :( ). Итак, у WMI есть несколько классов для работы с ACL (AccessControlList) файлов и папок. Например:


Read more →

Навеяно темой на форуме: http://forum.sysfaq.ru/index.php?showtopic=13274

Итак, есть задача отслеживать события удаления объектов (файлов и/или папок) с файлового сервера. Итак, для начала необходимо настроить аудит на файловом сервере. Приведу рекомендации коллеги WindowsNT:

  1. Включить аудит успешных событий типа Object Access.
  2. Отрегулировать размер журнала и параметры перезаписи.
  3. В свойствах папки Shared Documents (и других папок общего доступа) включить Аудит на Успешные Everyone: Delete, Delete Subfolders and Files.

Учитывая сопутствующую проблематику удалений, что для части программ при работе нормально удалять файлы при сохранении было предложено фиксировать 5 событий удаления в секунду. Такая схема вполне сгодится для среднестатистического решения. В любом случае предложенный скрипт можно будет изменить под свои нужды вполне свободно. За основу будет взят пост из моего предыдущего блога (Аудит входов на сервере терминалов с использованием PowerShell), но с некоторыми доработками.

Итак, задача разбивается на 4 составные части:

  1. получение всех эвентов с кодом EventID = 560;
  2. из полученных эвентов получить массив с уникальным временем;
  3. подсчитать количество эвентов для каждого уникального времени из массива, который был получен на втором этапе;
  4. если кол-во эвентов больше или равно 5 (цифра может быть и немного другой), то записываем их в лог и отмечаем, как "возможно нелегальное".

Итак, давайте пробовать решить все этапы:

1) получение массива эвентов по коду 560:

$Events = Get-EventLog security | ?{$_.eventid -eq 560 -and
    $_.EntryType -eq "SuccessAudit" -and
    $_.message -like "*Object Name:`tD:\Shared Documents\*" -and
    $_.message -like "*Accesses:`t%delete*"
}

Итак, здесь я сделал 3 фильтра: код события - 560, Тип аудита Success Audit (т.к. под кодом 560 регистрируются и неуспешные аудиты), имя корневой папки, которая нас будет интересовать (только для случаев, если настроено несколько аудитов на различных папках) и явно будем интересоваться действием $Delete. Теперь из этого массива нужно получить массив уникального времени:

$UniqueTime = $Events | select -Unique TimeGenerated | %{($_.timegenerated).datetime}

Здесь я получил массив с набором уникального времени. Отмечу, что я взял свойство DateTime, которое даст нам точность до 1 секунды. Массив мы делаем затем, чтобы потом считать сколько событий удаления зафиксировано с этим временем (отличить легальное удаление от нелегального). Теперь при помощи полученной переменной соберём кол-во эвентов удаления на момент уникального времени. Иными словами мы берём отметку времени, когда зафиксирован лог удаления файла или папки и посмотрим, сколько ещё логов было зафиксировано за эту секунду:

[object[]]$SelectedEvents = $Events | ?{($_.timegenerated).datetime -eq UniqueTime}
$SelectedEvents.count

Переменная $SelectedEvents будет содержать все эвенты удаления в течении секунды. И их количество можно посчитать свойством Count. И дальше можно проводить сравнительный анализ по кол-ву эвентов. Если их за секунду зафиксировано больше 5 (вероятность нелегального удаления файлов), то продолжаем разбирать переменную $SelectedEvents. Разбирается скрипт по той же схеме, что и в упомянутой выше статье по аудиту доступа на терминальный сервер. В итоге мы получим такой скрипт:

########################################################
# FileServerDeleteAudit.ps1
# Version 1.0
#
# Windows Server 2003 eventlog parser
#
# Vadims Podans (c) 2008
# http://www.sysadmins.lv/
########################################################

$Data = New-Object System.Management.Automation.PSObject
$Data | Add-Member NoteProperty Time ($null)
$Data | Add-Member NoteProperty UserName ($null)
$Data | Add-Member NoteProperty FileName ($null)
$Data | Add-Member NoteProperty EventCount ($null)
$Events = Get-EventLog security | ?{$_.eventid -eq 560 -and
    $_.EntryType -eq "SuccessAudit" -and
    $_.message -like "*Object Name:`tD:\Shared Documents\*" -and
    $_.message -like "*Accesses:`t%delete*"
}
$UniqueTime = $Events | select -Unique TimeGenerated | %{($_.timegenerated).datetime}
foreach ($time in $UniqueTime) {[object[]]$SelectedEvents = $Events | ?{($_.timegenerated).datetime -eq $time}
    if ($SelectedEvents.count -ge 5) {
    $Data.EventCount = $SelectedEvents.Count
    $SelectedEvents | %{
    $message = $_.message.split("`n") |    %{$_.trim()}
    $Data.time = $_.TimeGenerated
    if ($message -like "Primary User Name:`t*$") {
        $Data.UserName = ($message | ?{$_ -like "Client User Name:*"} | %{$_ -replace "^.+`t *"})}
    else {
        $Data.UserName = ($message | ?{$_ -like "Primary User Name:*"} | %{$_ -replace "^.+`t *"})}
    $Data.FileName = ($message | ?{$_ -like "Object Name:*"} | %{$_ -replace "^.+`t *"})
    $Data
        }
    }
}

Что касается поля $Data.UserName, то здесь я сделал проверку поля Primary User Name. Если файл или папка были удалены с компьютера локально, то данное поле заполняется именем пользователя. Если же файл или папку удалили по сети, то в данном поле будет указано имя компьютера в формате ComputerName$, а имя пользователя будет отражено в поле Client User Name. Поэтому если в поле Primary User Name будет встречаться знак доллара ($), то мы в поле $Data.UserName записываем имя пользователя из поля эвентлога Client User Name. Жирным в скрипте я отметил те места, которые в зависимости от местных условий могут изменяться. В первом случае отмечена корневая папка, которая будет изучаться и кол-во инцидентов удаления в секунду описывает порог срабатывания скрипта. И результат работы скрипта:

Time                          UserName              FileName                              EventCount
----                          --------              --------                              ----------
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog                        140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin                    140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin\AR                 140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin\...                140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin\...                140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin\BG                 140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin\...                140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin\...                140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin\DA                 140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin\...                140
2008.11.15. 23:33:44          Administrator         C:\New Folder\dasblog\bin\...                140

Enjoy!

В первой и второй части я рассказал про основные моменты управления принтерами в PowerShell и теперь хочу поговорить о правах на принтеры. Т.к. принтеры управляются с помощью классов WMI, то управление правами доступа к ним будет превращаться в очередную эпохальную эпопею, которую я исследовал при изучении безопасности Share Permissions (вот ссылка на эти статьи в моём прежнем блоге: http://vpodans.spaces.live.com/lists/cns!BB1419A2CFC1E008!178). Однако, с принтерами оказалось всё печальней :( Мне так и не удалось заставить работать метод SetSecurityDescriptor. Итак, я расскажу о своих кратких исследованиях и в чём же мы имеем проблему.

Для чтения прав доступа принтера потребуется метод GetSecurityDescriptor:


Read more →