Ondrej Žilinec mě upozornil na jednu novinku ve Windows 2012 a protože je to zajímavé, upřesníme tu trošku různá omezení, která se týkají "počtů skupin".
"Počet skupin" není jen jedna věc
Existuje několik limitů na počet členství ve skupinách ve Windows a Active Directory doméně. Jsou to tato:
- pokud máte Windows 2000 forest functional level (FFL), tak do jedné skupiny v Active Directory můžete vložit maximálně 5000 přímých členů. Tzn. skupina může obsahovat maximálně dohromady 5000 uživatelů a/nebo jiných skupin. Je to ale limit jen na přímé členství. Tzn. není omezena hloubka vnořování skupin. Potažmo může mít jedna skupina tedy i více jak 5000 členů, pokud do ní vložíte jiné skupiny a ty uživatele dáte až do těch druhoúrovňových skupin. S vyšším FFL omezení na přímé členství zmizelo (linked multi-value).
- lokální access token má limit na 1025 SIDů. Vysvětlení v podrobnostech později. Znamená to, že uživatel nemůže za žádných okolností být členem více skupin, jak 1024. Jinak se nepřihlásí na stanici, ani nikam ze sítě. Tohle nelze změnit ani v registrech, ani se to nemění mezi verzemi ani nijak jinak.
- Kerberos má omezení na velikost síťového packetu, ve kterém se přenáší ticket. Už zde si všiměte rozdílu slov Kerberos ticket a Access token. Tedy přesněji řečeno, má limit na velikost samotného tiketu. Jde o limit přenosový, který se týká pouze Kerberos tiketů. Detaily zase v dalším.
- Další aplikační protokoly mohou mít svá vlastní omezení. Příkladem je například HTTP.SYS, jak se o tom zmíníme opět později.
Access token
Po ověření uživatele na počítači se vytváří jeho session a pro ni se musí vytvořit v paměti datová struktura zvaná access token. V této struktuře je zapsán login uživatele, jeho SID (security ID), jeho práva (user rights/privileges) a seznam SIDů všech jeho skupin.
Vznik této struktury je lokální (na stanici, nebo na serveru, na který zrovna přistupujete ze sítě) a můžete to sledovat pomocí auditování Logon Events. V Security logu budete vidět události Logon, když tahle struktura vzniká a Logoff když ta struktura z paměti mizí.
Tento access token se potom používá k ověřování přístupu k prostředkům, jako jsou soubory, registry, tiskárny, plocha, okna, WMI, DCOM i všechno ostatní. Access token vzniká vždy. Jak při ověření lokálním (interactive logon, remote interactive logon), tak síťovém (network logon) a podobně. Jeho obsah se nemění, pokud chcete obnovit seznam skupin, u kterého došlo k nějakým změnám v Active Directory, musíte se odhlásit, nebo odpojit (sdílené soubory SMB, LDAP, HTTP apod.).
Access token vzniká na základě ověření uživatele, bez ohledu na protokol. Tzn. je jedno, jestli se uživatel ověří pomocí NTLM, Kerberos, nebo SSL client authentication (SCHANNEL SSP) cetifikátem. Takže tohle vůbec nesouvisí přímo s Kerberosem.
Access token obsahuje SID uživatele a SIDy všech jeho skupin, včetně BUILTIN a NT AUTHORITY skupin. Limit počtu SIDů je 1025, to znamená, že na skupiny zbývá 1024. Limit je natvrdo zkompilován do kódu Windows, takže nelze měnit. Je ve všech Windows od Windows 2000 až po Windows 2012 i Windows 8 pořád stejný.
Svůj access token si můžete vypsat buď z příkazové řádky pomocí WHOAMI /all,- to vidíte access token té konkrétní příkazové řádky. Nebo se na něho můžete podívat, pro každý proces, pomocí programu Process Explorer, na záložce Security. Ano, každý proces má svoji vlastní kopii access token struktury, což má jistý vliv v případě User Account Control (UAC) - ale to je už jiná pohádka.
Všiměte si, že access token obsahuje skupiny jako je Users, INTRACTIVE, local, Everyone, Authenticated Users apod. Tyhle SIDy v něm užírají políčka. Takže pro doménové skupiny tam zůstane jen něco málo více než 1000 políček. Vzhledem k tomu, že jsou v něm i lokální skupiny, tak se tento počet také může lišit na různých stanicích i serverech při přístupu ze sítě.
Pokud se někde ověříte a systém nemůže nacpat všechny vaše SIDy do access tokenu, odmítne vás přihlásit s hláškou:
During a logon attempt, the user’s security context accumulated too many security IDs
Tomuhle nemůžete zabránit vůbec jinak, než že uživateli odeberete nějaké skupiny. Buď lokální, nebo doménové, podle toho, co tam žere to místo.
Upozorňují znovu, že limit na počet SID v access token nelze změnit a že to vůbec nesouvisí s Kerberosem.
Omezení na Kerberos ticket
Pokud se k ověření používá Kerberos, narážíte možná na další limit. Kerberos vydává uživatelům tzv. tikety (Kerberos ticket). Název je ticket, nikoliv token. K jeho přenosu po síti i uložení v paměti DC i stanic a serverů se samozřejmě používá nějaký buffer, který má také svůj limit na velikost.
Například ověřování NTLM, nebo SSL/TLS client certificate authentication (SCHANNEL) takový limit nemá. Takže s Kerberosem máte dva limity. Prvním je limit na Kerberos ticket a teprve druhým je počet SIDů v access token. Zatímco NTLM a SCHANNEL naráží jen na access token.
Kerberos ticket má výchozí limity podle verze operačního systému, ale lze to změnit v registrech. Výchozí limity jsou:
Windows 2000 |
8 kB |
Windows XP |
12 kB |
Windows 2003 |
12 kB |
Windows Vista |
12 kB |
Windows 2008/R2 |
12 kB |
Windows 7 |
12 kB |
Windows 8 |
48 kB |
Windows 2012 |
48 kB |
Výchozí limit tam je, protože tikety mohou být poměrně veliké, podle počtu a typu skupin, ve který jste. Je to přenosový limit, takže je tam nastaven proto, abyste si pokud možno všimli, že vcelku hodně zatěžujete komunikace. Pokud bude tiket o limitu 12 kB, už to je vélmi hodně v porovnání s tím, jaký objem dat přenášíte při připojení na služby jako je SMB, nebo HTTP. Kdybyste nepřenášeli Kerberos tiket, komunikace SMB, nebo HTTP by vzala něco v řádu 1 kB.
Pokud vás to skutečně omezuje, a není možné prostě jen ubrat lidem skupiny, můžete tento Kerberosový přenosový limit zvýšit v registrech:
HKLM\System\CurrentControlSet\Control\Lsa\Kerberos\Parameters
MaxTokenSize = DWORD
Ano, hodnota v registrech je opravedu maxTOKENsize. To je matoucí, správně by se to mělo jmenovat MaxTicketSize, ale opravdu se to jmenuje MaxTokenSize. Ale opravdu se to vztahuje jen na velikost ticketů, které generuje Kerberos.
Jak si můžete všimnout, pro Windows 2012 a Windows 8 byl limit zvýšen na 48 kB. Zřejmě si Microsoft myslí, že linky jsou už dnes tak silné, že to utáhne. Cílem je odstrani nepříjemné komplikace pro větší prostředí. Ale je paráda, že pro jistotu přidali varování. Prostě si můžete nastavit úroveň varování na něco nižšího a dozvíte se, že už to přesahuje hranice slušného provozu. Všechno najdete ve výše zmíněném článku.
Upozorňuji, že limit platí pro všechny účastníky ověřovacích transakcí - tzn. pro DCčka, stanice i servery, na které přistupujete. Takže pokud máte v síti ještě Windows 2008, Windows 7, nebo Windows XP, nebo cokoliv, stejně máte pořád výchozí celkový limit na úrovni 12 kB.
Co způsobuje velikost Kerberos tiketů?
Ta velikost může být opravdu strašlivá. Ale není to přímo závislé na počtu skupin, ve kterých jste. Je to mnohem více závislé na typu (tedy přesněji řečeno scope skupin).
Skupiny v Active Directory mohou být tři scope (naštěstí ani nevím, jak se to řekne česky, to bude nějaký strašidelný překlad :-)):
- global group - uživatel může být členem pouze skupin ze své vlastní domény. Tyto skupiny jsou použitelné pro zabezpečení ve všech doménách
- universal group - uživatel může být členem jak skupiny ze své domény, tak i skupiny z jiné domény. Tyto skupiny jsou použitelné ve všech doménách
- domain local group - uživatel může být členem jak skupiny ze své domény, tak i skupiny z jiné domény. Tyto skupiny jsou použitelné k zabezpečení, jen ve své doméně. Tedy v resource doméně.
Až do Windows 2008 R2 a Windows 7 platí, že skupin global group a universal group z vaší vlastní domény žerou v Kerberos ticketech 8 Byte. Skupiny domain local group a universal group z cizích domén žerou 40 Byte.
Od Windows 2012 a Windows 8 existuje nová resource SID compression. Pokud vám vydá ticket DC verze Windows Server 2012, tak libovolná skupina bude žrát jen 8 Byte.
Proč jsou to různé velikosti? Protože v tiketu máte svůj vlastní SID v celé formě - to je 40 Byte. Skupiny z vaší vlastní domény tam už mohou být potom uvedeny jen pomocí svého RID (relative ID). To je jen 8 Byte. Nemusí tam být celý SID. Zatímco cizí skupiny universal group a všechny domain local group tam jsou zapsány v plné formě a žere to 40 Byte.
A od Windows Server 2012 to provádí to, že tam ty doménové SIDy dává prostě jen jednou a opět používá pouze RID, tentokrát už pro všechny skupiny.
Takže velikost Kerberos tiketu je závislá na typu skupin a jejich počtu, plus na tom, jestli ten tiket vydalo DC verze Windows 2012, nebo nějaké starší.
Pokud budete například pouze v domain local group skupinách, tak se vám jich do výchozího 12 kB limitu vejde jen přibližně 260. On totiž i "prázdný tiket" má velikost cca 1,5 kB, takže zbývá jen cca 10,5 kB na ty skupiny. Zatímco pro global group a vaše vlastní universal group je limit 12 kB úplně dostatečný. Více jak cca 100x jich stejně mít nemůžete kvůli access tokenu.
Velikost Kerberos ticketů podle typu tiketu
Ještě bych pro zajímavost měl dodat, že Kerberos tikety jsou dvou typů:
- TGT - ticket granting ticket, tedy tiket, který garantuje další tikety. Tzv. uživatelský, neboli přihlašovací tiket. Tenhle dostanete na základě (před)ověření (pre-authentication) heslem - vélmi zjednodušeně řečeno. Tento tiket potřebujete jako první a každý ho musí mít, aby vůbec mohl dál fungovat a chodit na nějaké služby.
- TGS - ticket granting service, tedy tike, který garantuje přístup k nějaké službě. Toto je tzv. servisní tiket. Když máte už uživatelský TGT a chcete jít na nějakou službu (sdílené soubory, lokální přihlášení, HTTP apod.), tak potřebujete TGS. Pro každou instanci služby je jiné TGS. Například pokud na jednom serveru poběží dvě instance SQL serveru a připojujete se tam i na sdílené soubory, budete potřebovat alespoň 3 TGS.
Do TGT se umísťují pouze SIDy global group a všech universal group (tedy všech, z vaší domény i ze všech ostatních - tohle se zjistí z GC). Za použití global catalog (GC) to vygeneruje vaše přihlašovací DCčko. Takže v něm nejsou žádné domain local group skupiny. Je to zbytečné.
Domain local group skupiny se umísťují - přidávají - až do TGS tiketů. TGS vydává DC z příslušné resource domain, takže jen ono ví přesně, co se má do TGS vložit.
Z toho plyne, že TGT bude vždy menší, než TGS. Pokud máte více domén, tak také budete mít pravděpodobně různá TGS
Výšezmíněný limit na velikost Kerberos tiketů se vztahuje na všechny typy tiketů. Tzn. je samozřejmě možné, že některé přístupy fungovat budou, zatímco některé jiné nikoliv - čistě podle toho, jestli váš TGT přelezl hranici, nebo se tak stalo například až při přístupu na službu z jiné domény.
Jak se tedy chovat k limitům
Nemůžete být ve více jak 1025 skupinách. S tím nic neuděláte (access token). Pokud přelízáte hranici pro Kerberos tikety (dnes zřejmě 12 kB), můžete zvážit dvě věci. Ideálně snížit počet skupin. Nebo jen přepnout skupiny z domain local na global. Nebo prozkoumat, jak to vlastně máte universal skupinami.
Samozřejmě můžete také zvýšit velikost Kerberos tiketu, ale nevím, jestli není lepší to pořešit raději tím snížením.
Problémy s velikostí vám také nemusí nastávat ve všech případech. Pokud se například ně najaký web server hlásíte pomocí SSL/TLS client certificate authentication (SCHANNEL), vůbec vás nějaký Kerberos limit nezajímá. Pokud se používá NTLM, stejně tak vám to může být úplně jedno.
Ale to ještě nejsou všechny problémy
Dobře, řekněme, že jsem vyřešili problém s velkým množstvím skupin tím, že jsme zvýšili jeho velikost pomocí hodnosty MaxTokenSize. Možná to ale pořád pro některé aplikace a služby nepomůže. Proč?
Protože i jiné protokoly mají svá omezení. Krásným příkladem je HTTP a Windows integrovaný webový server HTTP.SYS a IIS. Web server Internet Information Services (IIS), i jiné HTTP služby - jako jsou SQL Reporting Services, nebo WinRM - používají ovladač HTTP.SYS.
Tento ovladač má v registrech nastavení na maximální velikost HTTP požadavku i jednotlivých hlaviček. Limit je 16 kB. Pokud se do HTTP paketu vkládá binární Kerberos tiket, musí se zakódovat do Base-64, aby byl přenos jen 7bitový. Takže výchozí Kerberos limit 12 kB sežere právě těch 16 kB v HTTP paketu.
Pokud zvýšíte MaxTokenSize pro Kerberos, musíte také zvýšit parametry HTTP.SYS:
HKLM\System\CurrentControlSet\Services\HTTP\Parameters
MaxRequestBytes = DWORD
MaxFieldLength = DWORD
A kdoví, jaké další aplikace budou mít problémy :-) Tak pěkný den a zábavný boj se skupinami!