Для человека, который сталкивается с многообразием групп в Active Directory, разобраться с ними сходу весьма трудно. Local и Domain Local, Global и Universal, Security и Distribution – всё это осложняется ситуацией “кого в кого можно включать”, и в финале сопровождается выводом “нафиг столько нагородили, уму непостижимо”. Добавляет к этому бардаку сочности то, что в фирменных курсах Microsoft данная тема освещается всё обзорнее и обзорнее – и сводится буквально к паре слайдов “запомните вот эту табличку”, без объяснения причин того, почему всё работает именно так.
Такой подход понятен – задача Microsoft – максимально удешевить чтение курсов, снижая требования по знаниям у MCT, которые обычно сами не могут объяснить, почему с группами в Windows / Active Directory всё сложилось именно так. Нужен меньший уровень знаний, чтобы вслух ртом начитывать сверху вниз слайды – можно меньше платить – ниже расходы – выше прибыль у партнёров Microsoft – больше партнёров – больше прибыли Microsoft. Приводит это к предсказуемому результату – тему “проскакивают” на бегу с логикой “зазубрите табличку, потом дампы почитаете чуток и проходной балл на экзамене кое-как перевалите, да вообще всё это некритично на самом деле”, а после работают с группами наощупь, а-ля “я на форуме читал, что всё надо делать security global, а у
distribution SID’а вообще нет, ко-ко-ко”, ну и с подобными мифами. Табличка “кого в куда включать можно”, будучи не понятой, быстро забывается, а вся
тема остаётся мистическим облачком “ой там всё мутно, нереально разобраться, да и не нужно никому”.
Как обычно, у нас подход другой. Разберёмся, что и как с группами. Вам понадобится базовая подготовка на уровне материала курса Microsoft 20410D – можете скачать бесплатно его запись у нас и посмотреть, там несложно.
Группы Windows NT и Active Directory – что, зачем, как, почему
- Часть первая – изначальная ситуация – одиночная система
- Часть вторая – домен Windows NT – появление Domain Local и Securityгрупп
- Лирическое отступление про максимальное количество групп и прочие технические мелочи
- Поведение системы при переполнении маркера доступа Часть третья – лес Active Directory – появление Universal-групп и разделения на Security и Distribution
- Universal-группы и режимы работы домена
- Можно ли жить в лесу Active Directory без Universal-групп, только с Global и Domain Local
- Проблемы масштабирования при использовании только Global и Domain Local
- Domain Local-группы и объекты Active Directory
- Миф про сниженное быстродействие Universal-групп
- Миф про одинаковость всех групп, потому что их можно друг в друга переключать
Приступим.
Часть первая – изначальная ситуация – одиночная система
Группы, как объекты, являющиеся участниками системы безопасности – т.н. “security principal” – появились в Windows NT изначально. Так же как и пользователи, группы имеют свой личный и уникальный в пределах системы идентификатор – SID (про них можно поподробнее почитать в статье про FSMO-роль RID Master).
Однако, даже на единичной системе групп уже есть два вида – это встроенные, например BUILTIN\Administrators, и дополнительно созданные – в моём случае это группа TestLocalGroup и некоторые другие:
Как отличить эти два типа групп? Исключая, конечно, то, что мне было лень писать description к тестовой группе, и она выделяется по этому признаку? Всё просто – у этих двух типов групп разные форматы SID’ов:
У встроенных это будет S-1-5-32-xxx, где XXX – идентификатор от 500 до 1000 (в теории, в реальности полтыщи встроенных групп в системе нет, их меньше полусотни). У обычных это будет S-1-5-21-yyy-zzz, где YYY – это идентификатор системы (его меняет, например, утилита sysprep), а ZZZ – это RID.
Встроенные группы будут стоять особняком – они нужны для предоставления прав учётным записям, исключительно – т.е. ни включать их друг в друга (эта операция будет называться group nesting), ни включать в них обычные локальные группы будет нельзя. Вы можете убедиться в этом, запросив на локальной системе список тех, кто может быть добавлен во встроенную группу:
Если что, ATRAINING-DEMO – это имя локальной машины, это обычная Windows 8.1, разве что на ней заведена учётка пользователя с именем Ruslan.
Т.е. задача этих групп – выдавать права тем или иным локальным пользователям или обладателям каких-то специфичных SID’ов в ntмаркере доступа – например, logon type’ов типа NETWORK или INTERACTIVE.
Возможность же создавать свои собственные группы на локальной машине нужна, чтобы предоставлять доступ к ресурсам – например, общим папкам. Вы можете создавать группы, и включать в них пользователей. Ранее, замечу, можно было включать локальные группы в локальные – для этого трюка нужна утилита net.exe и её контекст LOCALGROUP, но на данный момент этот функционал заблокирован и даже если вы сделаете так на NT 4.0 и проапгрейдите систему до современной
версии, то все равно – lsass учитывает у локальных пользователей только группы, в которые они включены напрямую, т.е. в маркере доступа других групп не будет.
Зачем же в этой ситуации, когда можно было бы обойтись, по сути, простым критерием “RID меньше тысячи – значит, встроенная группа – а больше – значит, созданная пользователем”, делать разные форматы SID’ов? Нужно это было для того, чтобы обеспечить перенос ACL’ов между системами. Пример – у вас есть внешний диск, отформатированный в NTFS. Вы создаёте там структуру папок и назначаете права – в эту папку можно участникам группы Administrators, в эту – обычным Users. Если вы перенесёте этот диск на другую систему, то все ACL’ы будут читаемы – потому что SID’ы что Administrators, что Users – одинаковы у любой NTсистемы. Но если вы создадите свою собственную группу, то такого никогда не случится – её SID никогда не совпадёт с SID’ом группы на другой системе, потому что включает компонент S-1-5-21-уникальный идентификатор системы-RID. Поэтому если вы создадите у себя локальную группу Special Secret Administrators, а на соседней машине создадут Puny Faggots, то неприятной ситуации, когда добавляли права доступа для участников первой, а при переносе
оказалось, что права доступа появились у второй, т.к. SID’ы совпали – вот такой ситуации не будет в принципе.
У пользователей, замечу, такого разделения нет – они всегда привязаны к идентификатору системы:
Что ж, с локальной системой всё ясно и несложно. Теперь – следующий шаг – появляется домен Windows NT.
Часть вторая – домен Windows NT – появление
Domain Local и Security-групп
Работа с группами в одиночной системе – штука простая. Сложности
появляются, когда надо создать свой authentication domain – т.е.
подмножество систем, которые признавали бы не только свои локальные
базы security principal’ов (хранящиеся в реестровой ветке HKLM\SAM\SAM),
но и некую центральную и общую БД учётных записей.
Если вы берёте систему на базе Windows Server и делаете её контроллером
домена – т.е. говорите, что теперь её хранилище security principal’ов будет
общим, и ему будут доверять другие системы – она понимает возложенную
ответственность и решается на апгрейд своего Security Accounts Manager’а.
Ведь одно дело, когда предполагается использование базы только на
одной системе – а другое дело, когда на нескольких. Плюс, домены могут
доверять друг другу через систему domain trust’ов – а, следовательно, надо
ещё и учитывать то, что должна обеспечиваться уникальность security
principal’ов в пределах произвольного числа доменов.
Если просто взять и сделать общим SAM локальной машины – сразу
появятся конфликты тех же builtin-групп; например, как при идентичных
SID’ах группы BUILTIN\Adminstrators на всех системах сделать свой
SAM доступным для остальных? Что будет обозначать запись в маркере
доступа на произвольной, включённой в домен, машине “входит в группу с
SID = S-1-5-32-544” – это значит, что участник локальных Administrators или
общих-доменных Administrators? Как решать ситуации с “из соседнего
домена придёт группа с таким же SID’ом”? Ситуация требовала и
расширения функционала, и введения ограничений – и это произошло.
Было сделано следующее – существующая ситуация со встроенными и
обычными группами была усложнена до “Есть два сту вида групп –
локальные для этого домена (Domain Local) и глобальные с возможностью
‘выхода наружу’, за пределы домена (Global)”. У Domain Local при этом
остаётся разделение на BUILTIN, т.е. встроенных и изначально
существующих в домене, и обычных, созданных администраторами. Было
два типа групп – стало два с половиной – локальные встроенные,
локальные обычные, и глобальные.
Новый тип групп, Global, сразу же был ограничен до “в него могут входить
только учётки”. Вложения однотипных групп (т.е. Global в Global) в домене
Windows NT не было, поэтому всё, зачем нужны Global-группы – собрать в
них ресурсы по какому-либо критерию (например, подразделение
организации) и добавить эту группу в чей-нибудь ACL. Например, у папки,
или у принтера. У любого объекта NT-системы, в общем. Простой пример –
сделать группу BUH, добавить туда учётки всех сотрудников бухгалтерии и
выдать этой группе права на папку Otchet2016 на файл-сервере.
Существующий подтип Builtin Local получил ограничение – в силу того, что
SID’ы его участников не содержат доменный компонент, групп этого типа
не видно при просмотре с рабочих станций и серверов домена. То есть,
если в домене есть рабочая станция, и у неё есть своя локальная группа
Administrators, то конфликт с имеющимися на контроллере домена
BUILTIN\Administrators разрешается просто – что в локальную группу
на этой рабочей станции, что в любой ACL на любом объекте на этой
рабочей станции – добавить доменных BUILTIN\Administrators не
выйдет, их просто не будет видно. Выборка по “потенциально возможным
к добавлению” не покажет Builtin Local’ов. Они существуют только на
системах, которые разделяют между собой “выросший” локальный SAM
самого первого сервера, который стал контроллером этого домена – то
есть, на контроллерах домена.
Domain Local же, как наследники “обычных локальных групп”, данного
ограничения не имеют – их SID ведь содержит компонент с
идентификатором домена – а, следовательно, уникальность в сравнении с
локальными группами каждой входящей в домен системы
поддерживается. Поэтому вы можете добавить, например, в локальную
группу Administrators группу из домена, у которой будет тип Domain
Local – никакого потенциального конфликта тут не будет. SID’ы этих групп,
кстати, не поменялись при превращении сервера в первый контроллер
домена в новом домене – поэтому если вы, например, создали локальную
группу и выдали ей права на какой-то папке, то после DC promotion эта
группа станет Domain Local и все её права сохранятся – ведь SID тот же.
В итоге ситуация стабильна – каждый домен обладает уникальным
идентификатором, есть специальный тип групп, у которых в SID’е всегда
этот уникальный идентификатор есть (Global). Назначение групп тоже
понятно – в Global добавляем учётки с прицелом “им можно хоть где
угодно права раздавать, хоть в другом домене”, Domain Local используем
для групп-заглушек на ресурсах, вида “SRV1 Buh-Otchet2016 RO” (Read-Only
на общей папке \srv1\BUH\Otchet2016).
Но потребности растут – и ситуация изменяется ещё раз.
Лирическое отступление про максимальное
количество групп и прочие технические мелочи
Возможность создавать много групп и делать сложные схемы вложения
одних в другие, безусловно, технически ограничена. В части ограничения
количества объектов типа “группа” в домене всё упрётся в размер
хранилища NTDS в Active Directory, а также в максимально возможное
количество RID’ов в данном домене. Оба этих барьера трудно достижимы –
наштамповать миллиарды групп всё ж задачка не из бытовых. Но есть
ограничение, которое достигнуть можно – это вопрос про “во сколько
групп может входить пользователь”.
Ответ на этот вопрос, за время развития Active Directory, несколько раз
изменялся – давайте разберёмся, почему и как.
Первичное техническое ограничение на количество групп, в которых
одновременно может состоять конкретный пользователь, вызвано тем,
что при логине с использованием протокола Kerberos (его поддержка
появляется в Windows NT 5.0 и в Active Directory с момента её создания)
будет необходимо передавать по сети сведения о членстве доменного
пользователя в группах. Протокол Kerberos по умолчанию работает с
использованием транспортного протокола UDP (впрочем, переключаем на
TCP начиная с Windows 2000), и теоретически возможный размер Kerberosданных – это максимальный размер UDP-датаграммы минус заголовок
пакета Kerberos. Получается чуть меньше 64КБ (65.5 тысяч байт).
Вычитаем минимальный размер маркера доступа (это 1200 байт – это
минимум, размер может быть чуть больше, если будет, например, очень
длинный FQDN или UPN/SPN). Получаем примерно 62КБ (где-то 63 тысячи
байт). Учитываем, что при работе с веб-сервисами, тем же IIS,
использующим при работе метод Negotiate, содержимое токена надо будет
передавать по HTTP, в Base64 (т.е. упаковывать всё в 6ти битовые
символы). В результате получим уменьшение технологически возможного
размера до примерно 47КБ (около 48 тысяч байт). Это, повторюсь,
техническое ограничение при условиях:
Наш Kerberos работает по UDP;
Мы используем Negotiate в IIS как метод авторизации доменных
учётных записей;
Мы не тюнингуем Kerberos в плане доп.информации в заголовке и у
нас учётка с нормальным именем (или хост с тривиальным по
габаритам FQDN);
Поэтому операционная система, в частности встроенный в неё модуль
поддержки Kerberos, имеет настройку, ограничивающую максимальный
размер содержимого. Исторически этот размер, появившись в Windows
2000, был 8.000. В Windows 2000 Service Pack 2 он стал 12.000, а с Windows
Server 2012 – 48.000. Вы можете его поправить, если что, простой
настройкой параметра MaxTokenSize, который сейчас уже есть в
стандартных групповых политиках (я предполагаю, что вы обновляете
административные шаблоны у себя в домене):
Находится она, если что, в Computer Configuration \ Policies \
Administrative Templates \ System \ Kerberos, а называется Set
maximum Kerberos SSPI context token buffer size. Учитывайте
только, что это – именно максимальный размер самого содержимого
токена, а не токена в смысле “весь керберосовский пакет”. Кстати, на KDC
– т.е. на всех контроллерах – можно также выставить полезную настройку
“журналировать события, когда токен не влез в указанные размеры”:
Находится она рядом с предыдущей в Computer Configuration \
Policies \ Administrative Templates \ System \ KDC,
называется Warning for large Kerberos tickets.
Теперь добрались до связи всего этого с группами. Каждая запись о том,
что данный security principal состоит в группе, занимает место. Больше
всего места занимает запись о членстве в Domain Local-группе и в
Universal-группе из чужого домена (об Universal чуть далее) – 40 байт.
Запись о членстве в Global или Universal-группе своего домена занимает 8
байт. Используя эти данные, можно прикинуть, в каком количестве групп
может состоять пользователь – это будет или 1200 Domain Local-групп, или
6000 Global-групп, или хз сколько Universal (зависит от того, из того же они
домена, что и вы, или нет).
Но это будет ещё не очень точной прикидкой, потому что есть
дополнительные факторы, влияющие на содержимое маркера доступа:
SID History – если учётная запись мигрировала из другого домена, и
этот атрибут не пустой, а содержит SID’ы групп из предыдущего
домена, то они тоже занимают место в маркере;
Delegation – если учётка trusted for delegation, то теоретический
максимум можно делить пополам, т.к. в маркере будет 2 комплекта SID’ов;
Чтобы не замучаться поддерживать весь этот дремучий лес из различных
ситуаций “много групп или не очень”, Microsoft выпустила статью про
жёсткое ограничение количества групп до 1.015, и посоветовала не
превышать число в 1.010 (хотя, как видно из вычислений, количество
может быть в разы больше). Ситуация на некоторое время успокоилась –
для спокойной работы можно выставить на уровне домена MaxTokenSize
в 48.000 и не иметь никаких проблем (ещё лучше форсировать Kerberos на
TCP-вариант, чтобы не натыкаться на ограничения размера UDPдатаграммы).
Помимо этого, в случае проблем с работой веб-сервисов, возможно,
понадобится увеличить максимальный размер одиночного поля в HTTPзаголовке и одиночного запроса. По умолчанию они оба 16K, имеет смысл
увеличить их хотя бы до 64К – это решит проблемы с ситуацией “большой
маркер доступа и сбой 401.1 при авторизации на IIS” и в подобных:
Данная ситуация была стабильна до Windows Server 2012, в котором
появилось сжатие токена – механизм Resource SID Compression.
Идея данного механизма чрезвычайно проста – “давайте от Domain Localгрупп передавать только RID’ы”. Данным механизмом можно управлять,
включая-выключая его для каждого конкретного DC:
Отключать его вам понадобится разве что в случае проблем с
взаимодействием с не-Windows системами, которые не понимают схему
сжатия SID’ов.
Технически (я не буду углубляться в дебри кербероса, это чрезвычайно
интересная, но масштабная тема) всё реализуется несложно – если KDC
поддерживает сжатие, то он проверяет бит Resource-SID-compressiondisabled в поле KerbSupportedEncryptionTypes у своей учётки и у
учётной записи krbtgt; если нигде этот бит не установлен в единицу, то
KDC формирует маркер доступа, заполнив в структуре
KERB_VALIDATION_INFO поле ResourceGroupDomainSid SID’ом текущего
домена, и добавляя поле ResourceGroupIds, указывающее на массив
“укороченных” SID’ов (которые на самом деле просто RID’ы). В финале в
поле ResourceGroupCount пишется суммарное количество записей, и
всё готово.
Использование этого механизма способно очень серьёзно снизить
затраты места в токене – вместо 40 байт для Domain Local расход падает
примерно до 6 байт на группу, плюс заголовок структуры.
Так что если у вас все DC на базе Windows Server 2012, и вы не выключили
этот механизм, то токен будет компактнее.
Что же произойдёт, если всё ж SID’ов групп окажется столько, что они не
влезут в маркер доступа?
Поведение системы при переполнении маркера доступа
Начиная с Windows Server 2003, есть “аварийный сценарий работы”,
нужный для ситуации “я доблестно добавил единственного
администратора в домене в тьму групп, и теперь не могу им залогиниться”.
Чтобы спастись в этом случае, надо зайти в режиме “Safe mode with
networking” на любой DC, используя BUILTIN\Administrator –
аварийный сценарий работает только для неё, с RID’ом = 500 – в этом
случае в маркер будут добавлены только группы, в которые явно входит
эта учётная запись – без вложенных, плюс только BUILTIN и Domain Local.
И если групп много даже в этом сценарии, то lsass просто не будет
добавлять те из них, которые не влезли – при том, начнёт добавление с:
Everyone (S-1-1-0)
BUILTIN\Users (S-1-5-32-545)
BUILTIN\Administrators (S-1-5-32-544)
NT AUTHORITY\INTERACTIVE (S-1-5-4)
NT AUTHORITY\Authenticated Users (S-1-5-11)
LOCAL (S-1-2-0)
Domain\Domain Users (S-1-5-21-xxxxxxxx-yyyyyyyy-zzzzzzzz-513)
Domain\Domain Admins (S-1-5-21-xxxxxxxx-yyyyyyyy-zzzzzzzz-512)
NT AUTHORITY\This Organization (S-1-5-15)
Такой маркер сгенерить точно получится и вход администратора в
аварийной ситуации сработает.
Надеюсь, я не сильно вас запутал, но, в общем, тема “во сколько групп
может входить юзер”, как видно, весьма обширная и не ограничивается “в
этой версии винды во столько, а в этой – во столько”, как иногда бездумно
заучивают на авторизованных курсах Microsoft.
Продолжим про разновидности групп – статья вообще-то именно про это,
а не про тонкости реализации Kerberos в современных версиях Windows
Server.
Часть третья – лес Active Directory – появление
Universal-групп и разделения на Security и Distribution
Active Directory добавляет целую пачку нового – теперь вместо одиночных
доменов, связанных ниточками-трастами, есть пачки дружественных друг
к другу доменов, называемые лесами. Появляется возможность изменять
атрибуты объектов, хранимых в Active Directory, и создавать новые типы
объектов. Все эти добавления нуждаются в изменениях в работе групп.
Первым делом смотрим на новое разделение групп – на Security и
Distribution.
Чем отличаются Security и Distribution группы
Миф про “у Distribution-групп нет SID’ов” – один из самых живучих. Его
бездумно копируют преподаватели авторизованных курсов Microsoft, ни
разу не работавшие с Active Directory в production и просто ни разу не
интересовавшиеся, как оно вообще работает. Его копируют
расплодившиеся в последнее время “архитекторы”, павшие жертвой
подхода работодателей “давайте сисадмина Ваську переименуем в
должности, чтобы зарплату не поднимать”. Его озвучивают набранные по
критерию “амбициозный туповатый услужливый региональный сисадмин”
сотрудники системных интеграторов, потому что “ребята из МС, эксперты,
архитекторы, говорили”.
Технически же всё просто – Distribution-группы отличаются от Security
(или, если быть точным, Security Enabled) групп одним битом в атрибуте
groupType – у Security-группы этот атрибут будет содержать бит
SECURITY_ENABLED:
а у Distribution – нет:
Вы можете сколько угодно раз переключать группу из Security в
Distribution, от этого её SID никуда не девается. Он и не может деться –
ведь SID – это атрибут всего класса объектов group, а не какого-то их
подвида. Поэтому при создании объекта класса group SID разово
создаётся, а смене типа с Security на Distribution – не стирается. Поэтому
при переключении между Security и Distribution не запрашиваются новые
блоки у RID Master‘а – операции “генерация SID для нового security
principal” не происходит. Поэтому, если добавить группу в ACL какогонибудь объекта, а потом переключить её в Distribution, она оттуда никуда не
пропадёт – потому что в ACL записывается SID, а он у этой группы один, с
рождения, и никак не зависит от типа группы.
Зачем же нужен этот новый тип группы, Distribution?
Этот тип нужен исключительно для вопросов оптимизации
быстродействия и обеспечения безопасности. Смысл существования
варианта Distribution – это “lite-version” обычной группы. Отсутствие бита
SECURITY_ENABLED анализируется сервисом lsass в момент создания
маркера доступа для сеанса пользователя, и доменные группы без этого
бита просто не попадают в маркер.
Пример – есть большая фирма, у которой множество тематических групп
рассылок. Например, у них внедрено управление проектами, и к каждой
задаче привязан список рассылки “кого уведомлять при изменении
связанных с задачей документов, или любом другом изменении”. Таких
групп, если проектов много, у одного пользователя могут быть тысячи, а то
и десятки тысяч. Если этот пользователь, например, является аудитором,
которому надо знать про все изменения в ходе работ у N проектов.
Если это реализовывать через простое добавление пользователя во все
эти группы, то при его входе – что на локальную рабочую станцию, что по
сети – будет формироваться маркер доступа чудовищного размера,
набитый SID’ами групп, которые – это ключевое – не применяются для
назначения прав, а нужны лишь для упорядочивания списков рассылки. То
есть эти группы изначально созданы только для одной задачи – и их
никогда не добавят в ACL у общей папки или в локальную группу
Administrators.
В результате получается, что при логине пользователя, добавляя SID’ы
Distribution-групп, делается куча лишней работы, от этого замедляется вход
в систему, а также создаются потенциальные риски безопасности – вдруг
кто-то действительно возьмёт и на локальном сервере, где имеет права,
добавит в ACL ресурса группу для рассылок? Тогда входящие в неё с одной
целью (получать письма) получат совершенно не нужные права.
Добавление бита SECURITY_ENABLED решило оба этих вопроса –
составляя маркер доступа, lsass разбирает вложения групп, и, если видит
группу без этого бита – не добавляет её в маркер доступа, и идёт дальше.
То есть добавить в ACL у общей папки или куда-либо ещё Distribution-группу
можно – просто т.к. её SID не попадает в маркер доступа, то пользователь
в неё с точки зрения Active Directory входит, но получить доступ на ресурс,
где она в ACL – не может.
В официальной документации Microsoft содержится ошибка – Distribution
groups are not security-enabled, which means that they cannot be listed in
discretionary access control lists (DACLs) – вот никакого cannot be listed нет,
вы можете проверить это, явно назначив Distribution группу в любой ACL.
Вот и всё. И весь “волшебный механизм”. Поэтому увидите “икспертаархитектора” с рассказами о том, что у Distribution-групп нет SID’а –
смейтесь над ним и унижайте его, обзывайте его дампером и
характеризуйте его “знания” “бауманским качеством”. Показывайте ему
SID у Distribution-группы, открыв вкладку Attributes, и выкладывайте в
соц.сети реакцию – будет много просмотров.
Ну а мы, разобравшись с этим горе-битом, перейдём к новому типу групп
– универсальным.
Зачем нужны Universal-группы
Universal-группы и режимы работы домена
Первым делом зафиксируем тот факт, что само по себе появление типа
Universal связано с появлением лесов в Active Directory. Universal-группы –
новый тип объектов, которого не было в домене Windows NT, поэтому
чтобы этот тип групп появился, ваш домен должен быть в “native”-режиме
– то есть без включённого признака “работаем в режиме совместимости с
доменами Windows NT”. Это просто проверить – у корневого контейнера
доменного контекста есть атрибут nTMixedDomain:
Наличие значения 1 у данного атрибута показывает, что домен работает в
режиме совместимости с Windows NT – т.е. на владельце FSMO-роли PDC
Emulator запущен сервис, который имитирует для старых контроллеров
домена Windows NT (т.н. BDC) работу старого PDC. Этот сервис умеет брать
содержимое Active Directory и “пережёвывать” его в понятный для Windows
NT 4.0-контроллеров формат. Очевидно, что эти контроллеры ничего про
Universal-группы не знают, поэтому в режимах работы домена “совместим
со старыми Windows NT-системами” универсальную группу вам создать не
дадут – ведь неясно, как в этой ситуации отправить BDC-контроллеру
содержимое такой группы, или другой группы, в которую включена
Universal. Такая ситуация возникнет лишь в двух старых режимах работы
домена Active Directory – Windows 2000 Mixed и Windows 2003
Interim. Как только вы переключитесь в любой из “native” режимов
работы домена – возможность создания Universal-групп появится.
Впрочем, натолкнуться сейчас на домен, работающий в одном из этих двух
режимов, достаточно сложно. Поэтому далее предполагаем, что у вас
домен – как минимум Windows 2000 Native.
Итак, зачем же нужны Universal-группы?
Если вы домотали до этого момента, то, пожалуйста, перечитайте
верхнюю часть ещё раз – потому что чтобы разово уложить новые
сведения в голове, нужно понять всё предыдущее.
Можно ли жить в лесу Active Directory без Universal-групп, только с Global
и Domain Local
Начнём с простого – без универсальных групп вполне можно жить. Т.е.
Global и Domain Local покрывают все существующие задачи. Глобальные
группы, как и было заведено изначально, нужны для консолидации
учётных записей – разве что в домене Windows NT нельзя было делать
group nesting, т.е. вкладывать глобальную в глобальную, а в Active Directory
(речь про Native-режимы) – можно. Вложить в глобальную группу группу из
другого домена – что Global, что Domain Local – нельзя, всё, ещё раз
повторюсь, чётко – в глобальные вкладываем учётки из нашего домена и
другие глобальные группы только из нашего домена.
Domain Local же наоборот – самый “гостепреимный” вариант – в них
можно вкладывать и учётные записи, и глобальные группы из любого
доступного через trusts домена. Можно даже другие Domain Local – но, как
понятно, только из своего домена – ведь домены в силу ряда ограничений
(см.начало статьи) не позволяют друг другу добавлять Domain Local из
одного домена в члены Domain Local из другого.
Жить, таким образом, можно – собираем учётки по отделам-задачам в
Global (например, в каждом домене делаем группы BUHGALTERIA и
MARKETING). Эти группы добавляем в Domain Local’ы с названиями вида
“SRV1 BUH-Otchets RO” (которым заранее раздаём соответствующие их
названию права – этой, например, на файл-сервере SRV1 на общей папке
BUH и подпапке Otchets разрешаем Read Only), и удобно управляем
доступами для групп пользователей.
Сразу ответ на типовой вопрос “а можно ли вообще всё глобальными
делать?” – в пределах одного домена – да, а как только доменов больше
одного, то вы не сможете, “повесив” в ACL ресурса Global-группу, включить
в неё Global-группу из другого домена, и придётся использовать
“гостепреимную” Domain Local, в которую можно запихнуть кого угодно из
какого угодно домена.
Но не всё так однозначно – будут и проблемы.
Проблемы масштабирования при использовании только Global и Domain
Local
Так вот, основное веселье с ситуацией “используем только глобальные и
домен-локальные” начинается, если доменов в лесу много. Тогда штука с
“нельзя засунуть в Global из нашего домена Global из другого” сразу же
всплывает. В этом случае, если надо будет создать группу вида “Все
сотрудники фин.департаментов”, куда логично добавить группы вида
“Accountants”, “Fincontrol”, “Finauditors”, то ничего не получится – технически
это не реализуется. В результате Domain Local-группы, висящие на ACL’ах у
ресурсов, начнут ощутимо тяжелеть, потому что там надо будет в явном
виде перечислять все Global из всех доменов леса. Этот процесс вызовет и
замедление обработки, и увеличение сложности обслуживания.
Более того, начнёт появляться проблема с логином. Суть её проста – при
входе пользователя с использованием UPN-имени (по факту всегда; просто
с UPN-именем нагляднее) DC обращается к GC, чтобы выяснить, что это за
пользователь такой. Ведь UPN суффиксы уникальны в пределах леса, а не
домена – т.е. у вас может быть лес с 8 доменами, в котором 3 UPNсуффикса, и по “хвосту” имени пользователя сходу сказать “да, он из такого
домена” просто нельзя.
Обращаясь к GC, контроллер домена запрашивает вначале “кто это ко мне
такой за составлением маркера доступа обратился”, а после, узнав кто это
(т.е. получив SID по UPN’у), начинает составлять маркер доступа, вычисляя,
в каких группах состоит данная учётная запись. Тонкость в том, что состав
групп – т.е. поле member у Global и Domain Local, на GC не реплицируется,
поэтому получив ссылку вида “Данный пользователь входит в группу Х”,
контроллер домена находит у себя эту группу, и уже читая domain naming
context, а не ответ GC, вычисляет, в какие группы в свою очередь входит
она. Этот итеративный процесс “парсинга вложенных групп” вполне будет
достаточно ёмким по количеству итераций и общему объёму.
Почему ж так странно сделали, спросите вы – ну т.е. почему на GC не
реплицируется атрибут member у групп? Тонкость в том, что на момент
разработки оригинальной версии Active Directory, в NT 5.0, не было
механизма частичной репликации multivalued-атрибутов (т.н. LVR, Linked
Value Replication). В результате, если бы у GC кэшировался этот атрибут, то
для групп с большим числом участников (тысячи, а то и десятки тысяч),
любое изменение приводило бы к запуску полной репликации всех GC
леса. То есть ещё раз – есть лес с кучей доменов, в одном из них в одной
из групп добавляется один участник – вот если бы GC кэшили member, то
это заставляло бы все GC леса, во всех доменах, полностью
перекопировать этот объект. Эта ситуация уходит с появлением NT 5.2, и
уровня леса “Windows Server 2003”, но на момент выхода Active Directory это
всё – критично. Каналы слабые (я помню, как регионы реплицировались
по диалапу, поверх которого поднимался RRaS’овский VPN, и полоса
составляла единицы килобайт), GC не на каждом контроллере (опять же
из-за экономии, чтобы меньше репликаций было).
В результате имеем сложную ситуацию – логинящемуся пользователю
надо собрать маркер, для этого надо распарсить “матрёшку” из “какая
группа в какую вложена”, для этого надо бегать вначале на GC, чтобы
узнать, кто логинится, а потом, узнавая в какие группы он включен, бегать
за уточнениями “а кто в эту группу входит” уже на DC.
Всё это решается проще, если добавляется новый тип групп –
универсальные.
Состав универсальной группы кэшируется на GC – то есть, обратившись к
GC, можно получить из этого запроса список участников данной группы.
Сразу, без беготни туда-сюда. Притом на любом GC леса есть все Universalгруппы этого леса – поэтому можно, если имеет место вложенность одной
в другую, сразу же разрешить это с одним GC – вся информация на нём
есть.
Это быстрее – и именно поэтому, к примеру, когда вы читаете
документацию на Exchange Server, то можете заметить, что почтовые
группы предлагается делать Universal – тогда их быстрее можно
“раскрывать” в плане состава, за одно обращение к ближайшему GC.
Да, изменение состава Universal-групп инициирует репликацию во всём
лесу (и в том домене, в котором эта группа существует, разумеется) – но
всё ж, благодаря LVR-репликации, масштаб не настолько критичен и
огромен. Суть в том, что если вы реже меняете состав групп, чем их
читаете (так обычно и происходит), то Universal-группы выгодны – трафик
репликации растёт мало, на фоне явной экономии времени и трафика на
запросах о членстве.
Универсальные группы, подчеркну, будут запрашиваться с GC – поэтому
необходимо, чтобы в каждом сайте AD был хотя бы один GC – иначе
работать будет, но появится большая задержка от round-trip запросов
поверх WAN-каналов между сайтами – именно из-за этого на уровне сайта
есть опция “включить на всех DC этого сайта кэширование состава
универсальных групп”, понимаемая всеми Windows 2003 Server и более
новыми:
Эту настройку, как понятно, имеет смысл включать, если теоретически
возможна ситуация “в этом сайте не на всех DC есть GC, и есть шанс, что
все GC умрут, тогда долго ходить за GC, проще кэш использовать” – если
же у вас современная ситуация “каждый DC в сайте – GC”, то эта настройка
уже не имеет смысла.
Что же у универсальных групп по части членства? Всё очень хорошо – в
универсальную группу могут входить учётки, глобальные группы, и другие
универсальные – из любого домена нашего леса. Это очень удобно.
Domain Local’ы, как понятно, не могут – они, находящиеся в других
доменах, просто не видны из нашего – впрочем, мы это уже много раз
подчеркнули.
Кроме того, универсальные группы из нашего же домена занимают 8 байт
в PAC’е (т.е. в итоговом маркере доступа) – это выгодно.
Таким образом, вырисовывается следующая картинка с универсальными
группами – они действительно гораздо более просты в части “что в них
можно положить” – можно всё, кроме не видимых нами из нашего домена
Domain Local’ов других доменов ; плюс запрос у GC состава этих групп
делается в одно движение; плюс места в токене занимают мало.
Что ж, давайте теперь немного посуммируем то, что имеется на данный
момент.
В Active Directory есть три типа групп – каждый со своей спецификой;
У каждого типа есть вариант “с пометкой о не-использовании в
составе маркера доступа” – это называется Distribution-группой;
Разные типы групп занимают разное число байт – некоторые
занимают 40 байт, т.е. пишется SID целиком, с доменной частью,
некоторые 8 – когда только тип и RID;
Специфика универсальных групп будет связана в основном с фактом
появления леса Active Directory – впрочем, некоторое увеличение
скорости работы можно будет получить, заменяя Global на Universal и в
сценарии “один домен в лесу”;
Универсальные группы ускоряют работу только если нет проблем с GC
– т.е. он доступен, он в нашем сайте (требуется правильная настройка
сайтов и подсетей); при риске потенциальной недоступности можно
подстраховаться включением кэширования состава универсальных
групп на уровне сайта;
Что ещё можно добавить? По мат.части всё – теперь перейдём к
отдельным вопросам и тонкостям.
Тонкость в назначении прав с использованием Domain Local-групп на
объекты Active Directory.
Domain Local-группы и объекты Active Directory
В Active Directory, назначая права на объекты, не используйте схему “ACL
объекта -> в нём группы-заглушки Domain Local -> в них включаются
Universal или Global -> в которые включаются учётные записи”. Почему?
Дело в том, что когда пользователь из домена Х будет пытаться провести
операцию с каким-то объектом Active Directory, подключившись к DC из
домена Y (это важно – т.е. у нас лес, много доменов, и есть например
лесной раздел Configuration, который есть на всех DC в лесу) – так вот, этот
пользователь, когда будет идти проверка “а можно ли ему сделать
операцию”, может оказаться в ситуации “на объекте в ACL указана Domain
Local группа, но не из домена Y – поэтому данный DC не может её
запросить, её состава нет на GC, а контроллер домена, на котором живёт
эта группа, не показывает чужим Domain Local-группы”). В этом случае
маркер доступа будет сформирован с ошибкой, без SID’ов таких групп, и
пользователь может не получить доступ (или наоборот, ему явно
запрещено, а он получит).
Поэтому применяемый для доступа к ресурсам доменных рабочих
станций и серверов подход с Domain Local-группами – это одно, а
специфика Active Directory, как существующей на нескольких системах-DC с
общей базой безопасности – другое.
Миф про сниженное быстродействие Universal-групп
Корни данного мифа, формулируемого как “Universal-группы
универсальные, поэтому тормозят”, лежит в советах времён Windows 2000,
где вся “тормознутость” сводилась к “часто менять будете состав, и
большие группы – значит, большая репликация GC”. По факту и
добавление LVR, и рост скорости каналов связи на несколько порядков,
этот вопрос полностью убрали. Размеры объектов AD-то не выросли
вместе со скоростью каналов – сейчас вопрос “скорость репликации GC”
совершенно другую актуальность имеет. Так что используйте Universalгруппы смело, они дают явный плюс в скорости при использовании. И не
пользуйтесь кэшированием состава Universal-групп на уровне сайта AD,
пока нет ситуации “очень далёкий очень медленный филиал, где хотя бы 2
DC, и не все из них GC” – если хотя бы одно из этого не является верным,
кэширование просто не нужно.
Производительность дополнительно вырастет, если заменять по
возможности Domain Local-группы на Universal (из того же домена) – тогда
размер маркера доступа, при прочих равных, уменьшится.
Миф про одинаковость всех групп, потому что их можно друг в
друга переключать
Все три типа групп могут превращаться друг в друга – схема достаточно
проста, группы Global или Domain Local можно сделать Universal, а Universal
– превратить в Global или Domain Local. Т.е. нельзя разве что напрямую
Global в Domain Local, надо через превращение в Universal:
Из-за этого функционала, визуально “простого”, и рождается миф, что
“понаделают тут просто так от скуки типов групп, ведь это подтверждается
тем, что любую в любую, по сути, можно переделать, и ничего не
поменяется”.
Не любую в любую. Исключением будет попытка превратить Domain Local
в Universal в ситуации, когда в Domain Local есть foreign security principal.
Проверим на практике. Исходные данные – корневой домен леса
atraining.z и его дочерний домен с удручающим названием
dom2.atraining.z. В каждом из доменов создано 3 тестовых группы
разных видов и по одному пользователю:
В Domain Local-группе у нас будет одинокий местный участник Vasya:
Ищем ему компаньона-иностранца из другого домена:
И получаем сообщение The following Active Directory Domain
Services error occurred: Foreign security principals cannot
be members of universal groups., или LDAP-ошибку 50 (0x32) от
контроллера – ERROR_NOT_SUPPORTED.
Так что не всё так однозначно – и преобразование групп из одного вида в
другой, хоть и выглядит “тривиальным”, является операцией, при которой
проводятся доп.проверки, поэтому никакого “любую в любую можно
спокойно, поэтому пофигу на все эти виды групп” не нужно.
Что ж. В общем, всё.
Финал
Я надеюсь, что не очень сильно вас запутал, а даже наоборот – что-то
распутал. Впрочем, такие темы проще, конечно же, рассказывать на курсах
– так что заходите, у нас интересно. Тема Active Directory – огромна и очень
увлекательна.
До встреч!
References
atraining.ru
Ruslan V. Karmanovrk@atraining.ru
- 2 views