We rise up for the things we believe in over and over again

Казалось бы, ситуация с принтерами уже давно отлажена. Ну иногда переезжают они, но какого-то прям ада в этом уже нет. Скрипты работают на полную мощность, снимая изрядную часть нагрузки с сотрудников по отслеживанию и актуализации данных на инфраструктурных серверах. Но идилия не вечна.
Повадились сотрудники печатать на чужих принтерах. Как именно - я не понимаю, учитывая, что сами они принтеры не подключают (я даже не в курсе, знают ли они, как это вообще делается), все выполняется автоматом через политики. И высокому начальству это стало не по нраву.
В общем, спустили задачу. Из всех принтеров в настройках безопасности нужно убрать запись Everyone - Allow Print, а вместо нее подставить группу, в которую входят сотрудники, имеющие право на этом принтере печатать. Группы эти уже давно есть, хоть что-то не придется в авральном порядке создавать.
То есть имеем ситуацию: есть принтер prn-hp1235. В недрах AD есть группа с таким же именем, в ней сидит кучка пользователей, которым этот принтер через политики и подключается. Порядок действий:
- Открыть настройки безопасности принтера,
- вынести оттуда запись с группой Everyone,
- добавить группу prn-hp1235, отметив галкой разрешение Allow Print и только его,
- закрыть настройки принтера.
И так, порядка 600 штук. Весело, правда?

В свойствах принтера есть такой параметр как PermissionSDDL. Собственно, это и есть запись того, кто и что может делать с объектом, просто записано это в формате SDDL - не самая удобная вещь для понимания. Выглядит она вот так:
Да-да, именно так. И вот эту строку (а это именно одна строка) надо как-то распарсить, изменить, измененное утрамбовать обратно в такую же строку и поменять свойства принтера.
Отправной точкой в исследованиях стала вот эта статья, за которую автору огромное спасибо. Для разбора SDDL-строки она использует объект класса Security.AccessControl.CommonSecurityDescriptor - туда заносится SDDL, там формируется нормальный список объектов и их прав, там же меняется состав этих объектов, а затем при промощи метода GetSDDLForm() формируется новая строка SDDL, которая и заносится в свойства принтера.
В теории все просто. На практике... На практике получаем, что на выходе в разрешениях принтера теряются сущности CREATOR OWNER и APPLICATION PACKAGES. И если с пакетами еще куда ни шло, то потеря CREATOR OWNER может привести к невозможности печати (в сети есть упоминания таких случаев). Что же делать? Искать, на каком этапе теряется информация об этих объектах. Выяснилось, что исчезают они как раз в момент парсинга SDDL в объект CommonSecurityDescriptor. Не умеет он, видимо, с ними работать (хотя почему?).
Пришлось искать замену. И она нашлась в лице System.Security.AccessControl.RawSecurityDescriptor. Конечно, работать с Raw немного муторнее, чем с Common (формирование записи с группой сотрудников с нуля доставило), но результат получился тот, что и заказывали.
Итак, исходная информация:
- имя принт-сервера: ps1
- маска имен принтеров: либо prn*, либо mfd* (multifunctional device)
- SID группы Everyone: S-1-1-0 (константа, не меняется нигде и никогда)
Поехали

Пожалуй, за всю мою практику еще не приходилось настолько плотно работать с DACL. Хорошо, что хотя бы SACL тут не участвовал

Шёл 2018 год… (^ ^)'
> чего-то более удобного для машин пока еще не придумали.
Управлять этой байдой всё равно человеку, даже если кодом. Чем это удобнее XML или JSON для машины (экранирование всё равно нужно, если что)? Да хоть ini-файлы. А так одно неверное движение и у тебя всё уехало к чертям. Нафиг нафиг такое удобство.
читать дальше
Ничего удивительного. SDDL - универсальная вещь, и используется для записи ACL любых объектов в виндах
/* Но так уж исторически сложилось. */