Использую на прокси-сервере squid анализатор логов LightSquid, и вот, однажды захотелось чтобы статистика была в виде компьютер – реальное имя, а так как править конфигурационный файл для 100+ юзеров показалось делом рутинным, ну и при изменении имени или добавлении новых пользователей лазить опять в конфиг не хотелось, решил брать автоматом имена из Active Directory. За деталями прошу под кат.
У меня используется Active Directory, но с минимальными изменениями скрипт должен работать и с обычной LDAP.
Описывать установку LightSquid не буду, она довольно проста, гугл вам в помощь. Для преобразования IP в hostname будем использовать DNS, описывается ето в конфигурационном файле lightsquid.cfg строчкой:
$ip2name=«dns»;
Парсер перечитывает файлы realname.cfg и group.cfg и берет оттуда реальные имена юзеров, привязаных к хостам. Формат файлов такой:
realname.cfg:
«hostname» «real name»
group.cfg:
«hostname» «group number» «group name»
Что нам надо?
Надо взять с АД хосты, имена юзеров привязаных к хостам, группы в каких содержатся юзеры; потом пишем всё ето в конфигурационные файлы в соответственном формате.
Вот собственно скрипт, который ето делает:
#!/usr/local/bin/perl # # ldap2lightsquid (c) Roman Melko <romanmelko@gmail.com> # Description: Synchronize users and computers of LightSquid with LDAP server # Requirements: Should run periodically # Version: 2012030601 # License: BSD # use strict; use Net::LDAP; my $domain = "example.ua"; # Domain is supposed to have 2 levels my @parts = split(/./,$domain); my $domain0 = $parts[1]; my $domain1 = $parts[0]; my $user = "<username>"; # LDAP user my $password = "<password>"; # LDAP password my $cfgpath = "/usr/local/etc/lightsquid/"; # depends on OS my $realname = "$cfgpath/realname.cfg"; my $group = "$cfgpath/group.cfg"; # departments OU my @units = ( "MGT", "OPR", "PRO", "Sales "); # computers OU my @pcunits = ( "Developer servers", "Servers", "Workstation OPR", "Workstations PRO", "Workstations Sales", "Workstations Telemarketing" ); my @dep = ("no in group"); my $ldap = Net::LDAP->new("$domain") or die "$0"; $ldap->bind("CN=$user,DC=$domain1,DC=$domain0", password=>$password); my $base_path = "OU=<some path>,OU=<some path>,DC=$domain1,DC=$domain0"; # base LDAP path, change to yours my $num = @units; my $pcnum = @pcunits; my $attrs = "sn, givenname, department, samaccountname"; my $filter = "(objectcategory=CN=Person,CN=Schema,CN=Configuration,DC=$domain1,DC=$domain0)"; my $pcattrs = "cn, managedBy"; my $pcfilter = "(objectcategory=CN=Computer,CN=Schema,CN=Configuration,DC=$domain1,DC=$domain0)"; my $count; my $results; my %department_id = (); my %department_name = (); sub get_host_info { for (my $i=0; $i<$count; $i++) { my $entry = $results->entry($i); my $hostname = join(".",lc($entry->get_value('cn')),$domain); my @tmp_array = split(/,/,$entry->get_value('managedBy')); @tmp_array = split(/=/,$tmp_array[0]); my $fullname = $tmp_array[1]; if(!$fullname) { next; } print(REALNAME "$hostnamet$fullnamen"); print(GROUP "$hostnamet$department_id{$fullname}t$department_name{$fullname}n"); } } sub get_user_info { for (my $i=0; $i<$count; $i++) { my $entry = $results->entry($i); my $depnum = @dep; my $depid = $depnum; $depid++; foreach $depnum (0 .. @dep) { if ($entry->get_value('department') eq $dep[$depnum]) { $depid = $depnum; } } if ($depid > $depnum) { $dep[$depid] = $entry->get_value('department'); } if (length $depid < 2) { $depid = "0".$depid; } my $name = $entry->get_value('givenname'); my $surname = $entry->get_value('sn'); $name =~ s/^s+//; $name =~ s/s+$//; $surname =~ s/^s+//; $surname =~ s/s+$//; my $fullname = join(" ",$name,$surname); $department_id{$fullname} = $depid; $department_name{$fullname} = $entry->get_value('department'); } } open (REALNAME, ">", $realname) or die $!; open (GROUP, ">", $group) or die $!; # Getting real names and departments foreach $num (0 .. @units) { my $base = 'OU='.$units[$num].','.$base_path; $results = $ldap->search(base=>$base,filter=>$filter,attrs=>$attrs); $count = $results->count; if ($count > 0) { get_user_info(); } } # Getting pc names and owners, writing results to conf files foreach $pcnum (0 .. @pcunits) { my $base = 'OU='.$pcunits[$pcnum].',OU=Resources,'.$base_path; $results = $ldap->search(base=>$base,filter=>$pcfilter,attrs=>$pcattrs); $count = $results->count; if ($count > 0) { get_host_info(); } } # Closing connection to LDAP and files $ldap->unbind; close (REALNAME); close (GROUP); exit 0
Важные моменты:
— в каждом хосте в АД должно быть заполнено поле managedby, так привязывается хост к юзеру;
— в каждого юзера в АД должно быть заполнено поле department, так привязывается юзер к группе (у меня пока что так, до реальных групп руки не дошли, так как у меня один юзер может принадлежать к многим группам с похожыми именами);
— units и pcunits вы должны заполнить сами своими данными;
— для того чтобы заставить работать скрипт с стандартной базой LDAP курите маны, там есть различия с АД.
Автор: romanmelko