Использую на прокси-сервере 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»
Надо взять с АД хосты, имена юзеров привязаных к хостам, группы в каких содержатся юзеры; потом пишем всё ето в конфигурационные файлы в соответственном формате.
Вот собственно скрипт, который ето делает:
Важные моменты:
— в каждом хосте в АД должно быть заполнено поле managedby, так привязывается хост к юзеру;
— в каждого юзера в АД должно быть заполнено поле department, так привязывается юзер к группе (у меня пока что так, до реальных групп руки не дошли, так как у меня один юзер может принадлежать к многим группам с похожыми именами);
— units и pcunits вы должны заполнить сами своими данными;
— скрипт должен выполняться периодически, например в cron;
— юзер, под каким осуществляется доступ скрипта в AD, должен быть в корне AD, по другому меня не пускало;
— для того чтобы заставить работать скрипт с стандартной базой LDAP курите маны, там есть различия с АД.
У меня используется 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 "$hostname\t$fullname\n");
print(GROUP "$hostname\t$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 вы должны заполнить сами своими данными;
— скрипт должен выполняться периодически, например в cron;
— юзер, под каким осуществляется доступ скрипта в AD, должен быть в корне AD, по другому меня не пускало;
— для того чтобы заставить работать скрипт с стандартной базой LDAP курите маны, там есть различия с АД.