Let's look what we have now:
AD user have fields 'telephoneNumber' - for internal extension number, 'fax' - for direct inward dialing number (DID) like this:
From the asterisk side:
users.conf
[lan](!) type=peer host=dynamic ... ;And all users as child from this template [502](lan) fullname = Ryabov; Needed for username display on snom phones secret = *** ;Your super secret password email = [email protected]; I use for fax to email callgroup = 1; Number of room for call pickup pickupgroup = 1 context = 1234567; DID for external callssip.conf
All my DIDs with same context name
[1234567] type=friend host=8.8.8.8 fromuser = 1234567 secret = *** context=from-sats ...extensions.conf
Outgoing extensions, same as DIDs
[1234567] include => dial_internal exten => _XXX.,1,Dial(SIP/1234567/${EXTEN},60); same => n,Hangup; ;Incoming calls [from-sats] exten => 1234567,1,SIPAddHeader("Alert-Info:<http://nohost>\;info=alert-external\;x-line-id=0"); Different ring melody for external calls same => n,Dial(SIP/502&SIP/503,60,r); Internal number to dial same => n,Hangup;
So what is possible to automate here? In my case we have different correspondence between DID and internal number for incoming calls. But always have one DID for external calls, which is stored in AD in user info. My idea in brief - dynamically generate users.conf by information provided in AD. No need any changes to sip.conf and extensions.conf outgoing calls section. For incoming calls section - it's impossible to automate, cuz all departments wants custom incoming dialplan for their's DID.
Ok, let's do it!) All we need is PHP installed with
extension=php_ldap.soin php.ini enabled.
Save this script as /etc/asterisk/ldap.php and cmod +x it
#!/usr/bin/php <? //by sepa.spb.ru v23.09.2011 //config------------------------------------------------------------------------ $cache='/etc/asterisk/users.cache'; //cache used when no connection to DC $ldap['srv']='dc.crpp.ru'; //LDAP server $ldap['user']='[email protected]'; //user to bind with $ldap['pass']='***'; //user password $ldap['dn']='DC=crpp,DC=ru'; //DN path to filter users $conf['tpl']='lan'; //template name in users.conf $conf['mail']='[email protected]'; //error notify //------------------------------------------------------------------------------ $error=''; $out=''; $ldap['dc'] = ldap_connect($ldap['srv']) or die("Could not connect to LDAP!</br>"); ldap_set_option($ldap['dc'],LDAP_OPT_PROTOCOL_VERSION, 3); ldap_set_option($ldap['dc'],LDAP_OPT_REFERRALS, 0); if(ldap_bind($ldap['dc'], $ldap['user'], $ldap['pass'])) { $filter = "(&(telephoneNumber=*)(objectCategory=user)(objectClass=user)(samAccountName=*))"; $attr=array('samaccountname','telephoneNumber','facsimileTelephoneNumber', 'userPrincipalName'); if($result=ldap_search($ldap['dc'], $ldap['dn'], $filter, $attr)){ $info = ldap_get_entries($ldap['dc'], $result); for($i=0; $i<$info['count']; $i++){ $num=$info[$i]['telephonenumber'][0]; $login=$info[$i]['samaccountname'][0]; $login=strtoupper( substr($login,0,1) ).substr($login,1); $context=(array_key_exists('facsimiletelephonenumber', $info[$i]))?$info[$i]['facsimiletelephonenumber'][0]:'users'; $grp=$num[0]; $mail=$info[$i]['userprincipalname'][0]; $out.=" [$num]({$conf['tpl']}) fullname = $login secret = *** ; generate your super password here email = $mail callgroup = $grp pickupgroup = $grp context = $context "; } } else $error="Unable to search ldap server<br>msg:'".ldap_error($ldap['dc'])."'</br>"; } else $error="LDAP bind failed!"; if($error || !$out) { mail($conf['mail'], 'LDAP sync error!', $error); $out=file_get_contents($cache); } else file_put_contents($cache,$out); echo $out; ?>As you see, we use AD field 'facsimileTelephoneNumber' for our DID numbers. Test this script - it must generate needed part of users.conf without template. It must work even without connection to LDAP server, read data from it's cache and send you error report by mail. (You need to make mail configured for this to work)
If script works as you need - include it to users.conf after SIP user template, like this
[lan](!) type=peer host=dynamic ... #exec /etc/asterisk/ldap.phpAnd clear all your old extensions lines for SIP users, cuz this script wil generate them for you.
To make exec-includes work in asterisk you need to edit asterisk.conf too.
[options] execincludes = yes; Support #exec in config files.
Test this by 'sip reload' and check by 'sip show peers' - you must get all your SIP users right from AD every time you make 'sip reload'.
And last step - add user sync run by schedule:
#crontab -e */10 8-20 * * * /usr/sbin/asterisk -rx "sip reload"Upper line means run every 10 minutes from 8am till 8pm every day.
Now your junior admins can manage users right from AD and not disturb you.
А как сделать скрипт который просто будет получать имя звонящего на телефон с лдап. Просматривая внутренний номер ну и мобильный
ReplyDeleteЕсть 2 решения:
Delete1. Написать AGI скрипт, который будет перехватывать событие звонка и подставлять нужный clid
2. Тут вопрос уже к телефонному аппарату, который этот номер собирается получить. Вроде у linksys есть возможность переходить по ссылке при звонке для получения номера, или загрузке адресной книги. Тут уже зависит от формата, который у каждого производителя свой. Т.е. нужно переделать, например, PHP-скрипт выше так, чтобы он отдавал адреску в нужном формате и вывесить его через апач, а на телефоне настроить путь к скрипту.
Ну собственно телефон Grandstream gxp 1405 пока станция не вылетела и не потерялся весь функционал. То в настройка конфиг файла для телефона была сылка на тел книгу вида, http://ххх.хх.ххх.х/gs_phonebook.php
ReplyDeleteНу сам скрипт утерян , вот и думаю как лучше восстановить функционал. Находил вариант через ldapsearch shell ( perl скрипт ) но что-то не пашет , да и в контролере информацию надо конвертить в UTF
Спасибо за скрипт, но у меня появился один вопрос. У меня возникла проблема фильтром по нестандартных полям LDAP (нужно экспортировать аккаунты из Zimbra). К примеру мы хотим хранить пароли пользователей в поле zimbraNotes, но скрипт напрочь отказывается видеть это поле. filter и attr правил соответствующим образом:
ReplyDelete$filter = "(&(telephoneNumber=*)(objectClass=zimbraAccount)(uid=*))";
$attr=array('cn','telephoneNumber','facsimileTelephoneNumber','mail','zimbraNotes');
Через ldapsearch фильтр работает правильно.
Возможно php5-ldap не умеет вычитывать нестандартные поля?
Ситуацию негде сэмулировать, но я бы проверял так:
Delete1. удалил из $filter часть с zimbraAccount и посмотрел будет ли вывод от ldap_search
2. удалить zimbraNotes из $attr и посмотреть есть ли вывод у ldap_search. Если есть - то возможно атрибут надо писать регистрозависимо
3. В зависимости от результата 1 и 2 копать решение дальше :)
собственно есть оставить только в $filter - вывод пустой (вроде как нет записей, попадающих под фильтр)
Deleteесли оставляю только в $attr - дальше получаю ошибку мол Undefined index: zimbranotes (при любом регистре)
такое такое впечатление, что php5-ldap просто игнорирует поля, которых нет в стандартных схемах.
DeleteДа вроде должно работать
Deletehttp://php.net/manual/en/function.ldap-search.php
ничего не сказано про extended atributes
При этом по (google "ldap_search" zimbranotes)
первая ссылка
http://www.zimbra.com/forums/developers/10287-ldap-attributes-different-output-perl-php.html
см. последнюю цитату топикстартера
Спасибо за наводку.
DeleteОказалось все довольно банально, дополнительные поля, которые находятся в LDAP зимбры может читать только специальный пользователь, а я хотел их вычитать через обыкновенного юзверя.
Is it possible to use also Active Directory password in Asterisk SIP authentication?
ReplyDelete