Od niedawna mam okazję pracować, przy pomocy API .NET'owego, z usługami katalogowymi w wydaniu Microsoft'u, czyli z Active Directory. Dla mnie nowa rzecz, więc z zapałem dziecka, które dostało nową zabawkę, zabrałem się do pracy i, jak to często bywa w takich sytuacjach, od razu napotkałem problemy właściwe dla początkujących. W ten sposób dowiedziałem się wielu rzeczy, które dla wyjadaczy mogą być oczywiste, ale dla mnie były nowością. Zebrałem więc je do kupy i tak powstała poniższa lista ku pamięci.
Niektóre z tych rzeczy to drobnostki i jeśli o nich zapomnimy nic wielkiego się nie stanie. Niektóre są jednak bardzo ważne i ich pominięcie może sprowadzić na nas większe kłopoty. Tego rodzaju rzeczy oznaczyłem jako [Ważne]
Projektowanie schematu
Stronicowanie
Niektóre z tych rzeczy to drobnostki i jeśli o nich zapomnimy nic wielkiego się nie stanie. Niektóre są jednak bardzo ważne i ich pominięcie może sprowadzić na nas większe kłopoty. Tego rodzaju rzeczy oznaczyłem jako [Ważne]
Projektowanie schematu
- [Ważne] Przy projektowaniu schematu AD (definicja klas, atrybutów) trzeba być bardzo ostrożnym. AD nie wspiera usuwania klas lub atrybutów, a wiele rzeczy można zdefiniować tylko przy ich tworzeniu, na przykład atrybuty obowiązkowe dla danej klasy. AD wspiera natomiast tzw. dezaktywację. Ma to podobne skutki jak usunięcie, ale i tak wprowadzanie zmian do już używanego schematu AD może być bardzo kłopotliwe.
- [Ważne] AD to nie C# i nie możesz sobie tak po prostu dodać nowego atrybutu do klasy i oczekiwać, że wszystkie jej instancje zostaną z automatu uaktualnione. Mam tutaj na myśli atrybut mustContain, który określa atrybuty obowiązkowe. Niestety, ale można go podać tylko przy tworzeniu danej klasy. Więcej ograniczeń znajdziecie tutaj.
- Zamiast atrybutu mustContain można jednak użyć atrybutu mayContain, który określa atrybuty potencjalne.
- Pisząc skrypt ldif definiujący nowy atrybut nie wystarczy użyć atrybutu attributeSyntax. Potrzebny jest jeszcze atrybut oMSyntax.
- [Ważne] Ponownie AD to nie C#. Obiekty w AD nie mogą mieć więcej niż 8KB, a co za tym idzie, nie mogą zawierać dowolnej liczby atrybutów i wartości. Należy o tym pamiętać szczególnie, jeśli używamy atrybutów wielowartościowych. Ja analizowałem błąd, w którym nie można było dodać nowych wartości do atrybutu właśnie z tego powodu. Przekroczenie limitu 8KB dla danego obiektu skutkuje błędem Administrative limit for this request was exceeded
- Aby było śmieszniej, nie można łatwo wyznaczyć maksymalnej dopuszczalnej liczby wartości, jakie zmieszczą się w danym atrybucie. Zależy to na przykład od tego, ile atrybutów ma dany obiekt. Ten artykuł zawiera fajną dyskusję praktycznych limitów na liczbę wartości w obiekcie. Sekcja Maximum Database Record Size
- Pewnym rozwiązaniem problemu ograniczonej wielkości obiektów są tzw. atrybuty powiązane (ang. linked attributes), w których zawartość jednego atrybutu zależy od zawartości innych obiektów. Problemem jest natomiast to, że taki wyliczany atrybut musi być typu distinquished name, a więc nie obsłużymy w ten sposób np.: listy liczb całkowitych.
- [Ważne] Jeśli atrybuty mają być powiązane to muszą być takie od początku.
- Działanie atrybutów powiązanych może nie być intuicyjne, a więc załączam poglądowy schemat. Jak widać atrybuty połączone to para atrybutów tzw. forward link oraz backward link. Backward link przechowuje wskazania na obiekty, które wskazują go w atrybucie forward link.
Stronicowanie
- AD ma ograniczenie na liczbę obiektów, jakie można pobrać z bazy w jednym zapytaniu. .NET pozwala to jednak bardzo łatwo obejść dzięki stronicowaniu. Należy ustawić właściwość DirectorySearcher.SizeLimit na 0, a właściwość DirectorySearcher.PageSize na wartość inną niż 0. Nic więcej nie trzeba robić. Więcej szczegółów tutaj.
- [Ważne] Domyślnie .NET nie używa stronicowania. Jeśli o ty zapomnimy, może dojść do sytuacji, kiedy nasz program nagle przestanie działać, bo nie będzie pobierał wszystkich oczekiwanych obiektów z AD.
- [Ważne] Klasy z przestrzeni nazw System.DirectoryServices, takie jak DirectorySearcher, DirectoryEntry, SearchResultCollection implementują interfejs IDisposable. Piszę o tym ponieważ nawet przykłady na MSDN nie biorą tego pod uwagę!
- Skrypt ldif, służy do wprowadzania zmian do AD i składa się z sekwencji operacji dodania, usunięcia lub zmodyfikowania czegoś. W przypadku operacji modyfikacji (changetype: add) na końcu powinien znaleźć się znak „-“.
- Uwaga na spacje w atrybucie cn. Mój skrypt ldif dodający do schematu nowy atrybut wywalił się, bo wartość dla atrybutu cn zawierała na końcu spacje.
- AD ma różne limity ograniczające, na przykład maksymalna liczbę wartości, jakie można pobrać, maksymalną wielkość strony itp. Pełną listę można znaleźć tutaj.