Auto provisioning или механизм автоматического распространения конфигурации используется в большинстве аппаратных телефонов. В MicroSIP нет такого механизма, но есть простой конфигурационный файл с которым мы собственно и будем работать. А наличие portable версии программы сыграет нам на руку при решении вопроса распространения дистрибутива и обновлений.
Для разработки скрипта распространения конфигурации и обновлений использовался JScript. Суть процесса сводится к следующему: при входе пользователя в систему запускается скрипт, который вытягивает актуальную версию дистрибутива и настройки и применяет их на локальной машине для вошедшего пользователя. При применении настроек изменяются только настройки, указанные в конфигурационном файле на сервере, остальные настройки пользователя остаются без изменений.
Создаем на Windows сервере общую папку с правами доступа на чтение для всех пользователей домена и размещаем в ней 2 файла: microsip_autoconf.js и MicroSIP.ini. В js файле находится сам скрипт, в котором (при сохранении структуры, описанной в этой статье) необходимо изменить значение переменной srvConfPath на путь к папке хранения конфигурации и дистрибутива. Далее через групповые политики создаем задание на выполнение этого скрипта при входе пользователя в систему. В ini файле размещаем общую для всех конфигурацию.
// ============================================================================
// Скрипт автонастройки программы-софтфона MicroSIP
// ============================================================================
var WSN = WScript.CreateObject("WScript.Network");
var FSO = WScript.CreateObject("Scripting.FileSystemObject");
var WSS = WScript.CreateObject('WScript.Shell');
var confFileName = 'MicroSIP.ini';
var confFolderName = 'MicroSIP';
var distFolderName = 'Dist';
var usersFolderName = 'Users';
var srvConfPath = '\\\\<server_name>\\microsip$';
var userName = WSN.UserName;
var srvDistPath = srvConfPath + '\\' + distFolderName;
var usrConfPath = WSS.ExpandEnvironmentStrings('%APPDATA%') + '\\' + confFolderName;
var genConfFileOnSrv = srvConfPath + '\\' + confFileName;
var usrConfFileOnSrv = srvConfPath + '\\' + usersFolderName + '\\' + userName + '.ini';
var usrConfFileOnLoc = usrConfPath + '\\' + confFileName;
var genSrvINI = {};
var usrSrvINI = {};
var usrLocINI = {};
// Проверяем наличие конфигурации на сервере для текущего пользователя
if ( !(FSO.FileExists(usrConfFileOnSrv) && FSO.GetFile(usrConfFileOnSrv).Size > 0) ) {
// Нет конфигурации для текущего пользователя, выходим
WScript.Quit();
}
// Проверяем наличие дистрибутива программы и обновляем его
if (FSO.FolderExists(srvDistPath)) {
// Запоминаем состояние процесса MicroSIP (запущен/не запущен)
var cmdLine = 'tasklist /fi "IMAGENAME eq microsip.exe" /fi "USERNAME eq ' + userName + '" /FO CSV /NH';
var wasRunning = /microsip.exe/.test(WSS.Exec(cmdLine).StdOut.ReadAll());
// Закрываем процесс MicroSIP (если запущен) и обновляем дистрибутив
WSS.run("taskkill.exe /T /F /IM MicroSIP.exe", 0, true);
FSO.CopyFolder(srvDistPath, usrConfPath);
// Создаем ярлык на рабочем столе
strDesktop = WSS.SpecialFolders("Desktop");
oMyShortcut = WSS.CreateShortcut(strDesktop + "\\MicroSIP.lnk");
oMyShortcut.WindowStyle = 4;
oMyShortcut.IconLocation = usrConfPath + '\\microsip.exe, 0';
oMyShortcut.TargetPath = usrConfPath + '\\microsip.exe';
oMyShortcut.WorkingDirectory = usrConfPath;
oMyShortcut.Save();
}
// Читаем основной конфиг файл на сервере
ReadINIFile(genSrvINI, genConfFileOnSrv);
// Читаем пользовательский конфиг файл на сервере
ReadINIFile(usrSrvINI, usrConfFileOnSrv);
// Читаем пользовательский конфиг файл на текущем компьютере
ReadINIFile(usrLocINI, usrConfFileOnLoc);
// Мерджим данные в текущий локальный конфиг пользователя
// Сначала добавляем данные из глобального конфига на сервере
// Затем добавляем данные из пользовательского конфига на сервере
MergeINIObj(usrLocINI,genSrvINI);
MergeINIObj(usrLocINI,usrSrvINI);
// Сохраняем полученный конфиг
SaveINIFile(usrLocINI,usrConfPath,usrConfFileOnLoc);
// Восстанавливаем работу MicroSIP
if (wasRunning) {
WSS.run(usrConfPath + "\\microsip.exe", 1, false);
}
// Функция для чтения всех параметров ini файла в объект
function ReadINIFile(INIObj, filename) {
if ((FSO.FileExists(filename)) && (FSO.GetFile(filename).Size > 0)) {
var fileh = FSO.OpenTextFile(filename, 1);
while (!fileh.AtEndOfStream) {
var line = fileh.ReadLine();
if (/^\[(\w+)\]/.test(line)){
var section = RegExp.$1.toLowerCase();
INIObj[section] = {};
}
if (/^([^;#][^=]*?)\s*=\s*([^\r\n]*?)\s*$/.test(line)){
var param = RegExp.$1.toLowerCase();
var value = RegExp.$2;
INIObj[section][param] = value;
}
}
fileh.Close();
}
}
// Функция сохранения объекта INI в ini-файл
function SaveINIFile(INIObj, confPath, filename){
function WriteArray(arr){
for (var i in arr){
var value = arr[i];
if (typeof(value)=='object') {
if (value) {
file.Write('[' + i + ']\r\n');
WriteArray(value);
}
}else{
if (value) {
file.Write(i + '=' + value + '\r\n');
}
}
}
}
if (!FSO.FolderExists(confPath)){
FSO.CreateFolder(confPath);
}
var file = FSO.OpenTextFile(filename, 2, true);
WriteArray(INIObj);
file.Close();
}
// Функция объединения INI объектов в один (первый) INI объект
function MergeINIObj(firstINIObj, secondINIObj){
for (var section in secondINIObj){
if (!firstINIObj[section]) {
firstINIObj[section] = {};
}
for (var param in secondINIObj[section]){
if (!firstINIObj[section][param] || firstINIObj[section][param] != secondINIObj[section][param]){
firstINIObj[section][param] = secondINIObj[section][param];
}
}
}
}
[Settings]
disableLocalAccount=1
EnableLog=0
updatesInterval=never
CheckUpdatesTime=1466489328
denyIncoming=
usersDirectory=http://phonebook.local
SingleMode=1
LocalDTMF=1
autoanswer=button
denyIncoming=button
micAmplification=1
swLevelAdjustment=1
audioCodecs=PCMA/8000/1 PCMU/8000/1
accountId=1
[Account1]
Server=voip.local
Domain=voip.local
Proxy=
PublicAddr=
ListenPort=
SRTP=
Transport=udp
Publish=0
STUN=
ICE=0
allowRewrite=1
voicemailNumber=
disableSessionTimer=0
Далее нам потребуется создать еще 2 директории: Dist — для хранения актуального дистрибутива программы и Users — для персональных конфигурационных файлов пользователей. В Dist распаковываем portable версию MicroSIP и добавляем языковой файл (при необходимости). Для Users настраиваем разрешение на чтение всем пользователям домена и отключаем наследование разрешений. Разрешение будем выдавать отдельно для каждого конфигурационного файла в этом каталоге только тому пользователю, настройки которого содержатся в этом файле.
Теперь мы можем создать конфигурационные файлы для пользователей в директории Users формата sAMAccountName.ini Приоритет этого файла выше, что позволяет переопределять глобальные настройки заданные в MicroSIP.ini и при необходимости делать настройки персонализировано для каждого пользователя.
[Account1]
label=number
AuthID=number
Username=number
DisplayName=sAMAccountName
Password=password
Собственно, вот и все. Теперь при входе в систему у сотрудников, конфигурационные файлы которых имеются в директории Users, в папку профиля будет скопирован дистрибутив из Dist, сформирован файл конфигурации и создан ярлык для запуска MicroSIP.lnk на рабочем столе. Таким нехитрым способом нам удалось решить поставленные задачи по распространению и управлению программными телефонами на рабочих станциях.
Комментарии (11)
BigElectricCat
28.05.2018 11:31в папку профиля будет скопирован дистрибутив из Dist
Это самая порочная практика, которую почему-то некоторые админы продвигают. Профиль пользователя не должен содержать исполняемые файлы и даже возможность исполнения файлов из мест, куда пользователь может что-то записать должна быть исключена…StuxForce Автор
28.05.2018 11:38Если не ошибаюсь, тот же Chrome или Dropbox при отсутствии у пользователей прав на установку программ (а права на рабочих станциях у пользователей минимальны) устанавливаются в пользовательский каталог. В чем собственно заключается порочность? Ткните, пожалуйста.
BigElectricCat
29.05.2018 14:27Видимо вы никогда не сталкивались и не лечили последствия различных Петь/Ваннакраев и т.п.
Если у пользователя нет прав запускать программы (любые, в том числе и js/vb/cmd/bat) из тех мест, куда он может писать — то и нет проблем с возможными заражениями рансомварами/троянами, исключая различные вариации нулевого дня с повышением привилегий и запуском из оперативной памяти браузера, что при надлежащем обслуживании/обновлениях довольно быстро пресекается… да и браузерные песочницы тоже стоит использовать.) Естественно такие запреты раскатывается групповыми политиками на все машинки в домене.
rionnagel
29.05.2018 08:50Извините, но как-то вилами по воде. puppet, темплейты, пару строчек кода… например. Да дюжина способов. А тут непонятно куда что ложить и какие условия должны быть соблюдены. Комп в ad например какие службы должны работать, какие порты открыты, какие системы должны строять и т.д. и т.п.
StuxForce Автор
29.05.2018 08:58Развертывать целую систему управления конфигурациями для одной небольшой задачи, которая решается парой строчек кода на WSH, мне показалось нецелесообразным. Стандартное Windows окружение, все работает через SMB.
rionnagel
29.05.2018 10:48Не, не. Это то понятно). Но хотелось бы видеть всё совсем чуть более детально. Как для детей. А то выглядит как «во вам код — растваряйтесь как хатите!».
зы. Вот как-раз таки когда одна такая задача появляется — появятся и остальные аналогичные) из серии «Ну вот один разик выкати аплейтик везде»… и потом в неделю по пару раз надо до конца смерти!
jamakasi666
Не рассматривали варианта симлинками все сделать? Окна начиная с висты давно умеют в т.ч. по unc их делать.
StuxForce Автор
Если я верно понял ваш вопрос, то пользователи иногда покидают корпоративную сеть, поэтому с симлинками будут проблемы с запуском при отсутствии сервера.
jamakasi666
Групповой политикой сделать logoff скрипт в котором проверяется существование файлы\директории и если она есть то удалить ссылку. С помощью штатного kixtart скрипта создавать ссылки.
Пользователь включил ноут не в корп сети то ничего и не будет, в корп сети все будет. Тут конечно дело вкуса и все фломастеры разные но я бы лично пошел по пути симлинков и kixtart скриптов.
jamakasi666
Подумал, можно все еще проще и удобнее сделать. в AD прописать нужные параметры. В kix скрипте дернуть их и сгенерировать MicroSIP.ini записав в нужное место. Тогда управлять учетками можно будет прямо в AD со всеми вытекающими.
StuxForce Автор
Интересные мысли, надо будет изучить такую возможность. Спасибо!