Имя: Пароль:
1C
1С v8
Импорт пользователей из ActiveDirectory
,
0 StagerUchenik
 
26.09.18
12:52
Добрый день. Есть стандартная обработка которая выгружает из ад пользователей, но не создает группы. (Управление IT-отделом 8, редакция 3.0 (3.0.44.2)

в ад структура такова:

Корень
-Группа1
-Пользователь1
-Группа2
-Пользователь2 итд

У пользователей кроме имени никаких данных нет.

Контекст групп такого плана: OU=Группа1, OU=Корень, dc=test, dc=org

может кто подсказать каким образом выгрузить всю эту структуру ад в справочник пользователей?
1 breezee
 
26.09.18
13:10
Дописать стандартную обработку
2 StagerUchenik
 
26.09.18
13:18
капитан очевидность в очередной раз поражает гениальностью идей! =)

вопрос был в том как в данной структуре при данном количестве данных при загрузке пользователя создать группу в которой он существует в ад =)

и да, с ад не знаком ни разу
3 s03
 
26.09.18
13:23
погугли про выгрузку структуру/пользователей АД в файл, а как загрузить из файла уже будет много способов
4 StagerUchenik
 
26.09.18
13:32
(3) Это разовое решение, а требуется более-менее постоянное. Поэтому пока в приоритете допиливание обработки, а вот в какую сторону пилить и каким напильником - вопрос...
5 s03
 
26.09.18
13:35
(4) выгрузка, скорее всего будет скриптом, соответственно запустить этот скрипт можно и из 1С и если его немного подправить, то использовать и для постоянной работы
6 Asmody
 
26.09.18
13:38
1) Посмотреть как получаются пользователи из АД. Подозреваю, что через wmi.
2) Изучить запросы wmi;
3) Поправить обработку с учетом новых знаний.
7 eklmn
 
гуру
26.09.18
14:47
типа
ЗапуститьПриложение("powershell -executionpolicy unrestricted -command Get-ADUser -SearchBase ‘OU=Grop1,DC=test,DC=org’| Export-Csv -path c:\temp\usersAD.csv")
8 StagerUchenik
 
26.09.18
15:52
вот мы подключаемся к ад и в итоге видим контекст из 3х тестовых групп. (это если установлен фильтр на корень дерева) если фильтра нет - я даже по тестовым группам не прохожу в отладке - мне сразу преподносится контекст целиком.

&НаКлиенте
Процедура ЗагрузитьНаКлиенте()
        
    Контексты.ПолучитьЭлементы().Очистить();
    
    Если ПодключениеИспользоватьУчетнуюЗапись Тогда    
        Попытка            
            Порт                = ?(ЗначениеЗаполнено(ПодключениеПорт), СокрЛП(ПодключениеПорт), "389");            
            КореньДерева        = ?(ЗначениеЗаполнено(ПодключениеКореньДерева), СокрЛП(ПодключениеКореньДерева), "");                        
            СтрокаПодключения     = "Provider=ADSDSOObject;User Id=" + ПодключениеДомен + "\"
                                    + ПодключениеУчетнаяЗапись + ";Password=" + ПодключениеПароль + ";";            
            conn                = Новый COMОбъект("ADODB.Connection");            
            conn.Open(СтрокаПодключения);                        
            Если ЗначениеЗаполнено(КореньДерева) Тогда             
                LDAPText = "LDAP://" + ПодключениеКонтроллерДомена + ":" + Порт + "/" + КореньДерева;
                rs =  Новый COMОбъект("ADODB.recordset");    
                rs.Open("<" + LDAPText + ">;(objectClass=*);ADsPath, Name, distinguishedName;onelevel", conn, 0, 1);  // source,actconn,cursortyp,locktyp,opt
            Иначе
                LDAPText = "LDAP://" + ПодключениеКонтроллерДомена + ":" + Порт;
                rs =  Новый COMОбъект("ADODB.recordset");
                rs.Open("<" + LDAPText + ">;(objectClass=domain);ADsPath, Name, distinguishedName;subtree", conn, 0, 1);
            КонецЕсли;            
        Исключение            
            ОШ = ОписаниеОшибки();
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОШ);
            Возврат;            
        КонецПопытки;                
    Иначе        
        Попытка
            DSE                = ПолучитьCOMОбъект("LDAP://rootDSE");     // определяем домен, к которому принадлежит компьютер.
            LDAP_DNC        = DSE.Get("defaultNamingContext");         // имя текущего домена.
            LDAPText        = "GC://" + LDAP_DNC;                     // используем глобальный каталог для поиска.
        Исключение
            ПоказатьПредупреждение(, НСтр("ru = 'Не найдены домены для импорта данных'"));
            Возврат;
        КонецПопытки;
        
        conn            = Новый COMОбъект("ADODB.Connection");;
        conn.Provider    = "ADSDSOObject";
        conn.Open("ADs Provider");        
        rs                 =  Новый COMОбъект("ADODB.recordset");
        Попытка
            rs.Open("<" + LDAPText + ">;(objectClass=domain);ADsPath, Name, distinguishedName;subtree", conn, 0, 1);  // source,actconn,cursortyp,locktyp,opt
        Исключение        
            ЗаписатьОшибкуВЖурналРегистрации(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
            ОбщегоНазначенияКлиентСервер.СообщитьПользователю(НСтр("ru = 'Запрос к Active Directory не выполнен. Подробности в журнале регистрации...'"));
            Возврат;
        КонецПопытки;
    КонецЕсли;
    
    Если rs.RecordCount > 0 Тогда
        Пока Не rs.EOF Цикл  
            
            НоваяСтрока            = Контексты.ПолучитьЭлементы().Добавить();
            НоваяСтрока.Name    = rs.Fields("Name").Value;
            НоваяСтрока.LDAP    = rs.Fields("distinguishedName").Value;
            НоваяСтрока.Path    = rs.Fields("ADsPath").Value;  // берем путь "как есть", в т.ч. GC.
            
            
            ДобавитьВетвьВДеревоAD(conn, НоваяСтрока);
            
            Попытка
                rs.MoveNext();
            Исключение
                ЗаписатьОшибкуВЖурналРегистрации(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю(НСтр("ru = 'Превышен допустимый размер получаемых данных.'"));
                Прервать;
            КонецПопытки;            
        КонецЦикла;
    КонецЕсли;
    
    rs.Close();
    rs = Неопределено;
    conn.Close();
    
КонецПроцедуры


вот здесь я обхожу всю структуру и получаю ветки дерева.

&НаКлиенте
Процедура ДобавитьВетвьВДеревоAD(conn, СтрокаДерева)

    rs =  Новый COMОбъект("ADODB.recordset");
    rs.Open("<" + СтрокаДерева.Path + ">;(|(objectclass=organization)(objectclass=organizationalUnit)(objectclass=container));ADsPath, Name, distinguishedName;onelevel", conn, 0, 1);
    
    Если rs.RecordCount > 0 Тогда
        
        Пока Не rs.EOF Цикл
            
            НоваяСтрока         = СтрокаДерева.ПолучитьЭлементы().Добавить();             
            НоваяСтрока.Path    = rs.Fields("ADsPath").Value;
            НоваяСтрока.Name    = rs.Fields("Name").Value;
            НоваяСтрока.LDAP    = rs.Fields("distinguishedName").Value;
            
            ДобавитьВетвьВДеревоAD(conn, НоваяСтрока);
            
            Попытка
                rs.MoveNext();
            Исключение
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю(НСтр("ru = 'Превышен допустимый размер получаемых данных.'"));
                Прервать;
            КонецПопытки;
            
        КонецЦикла;
        
    КонецЕсли;
    
    rs.Close();
    rs = Неопределено;

КонецПроцедуры

вот тут я получаю всех пользователей

&НаСервере
Процедура ЗагрузитьПользователейКлиентФрагмент()  
    
    ВыбранныеСтрокиТаблицыПользователей = ТаблицаПользователей.НайтиСтроки(Новый Структура("Исправить", Истина));    
    ТаблицаПользователейАД                 = УправлениеITОтделом8УФ.СтруктураТаблицыПользователейАД();
    
    Для Каждого СтрокаМассива Из ВыбранныеСтрокиТаблицыПользователей Цикл
        НоваяСтрока = ТаблицаПользователейАД.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаМассива);
    КонецЦикла;    
    
    ТЗРезультаты = УправлениеITОтделом8УФ.ВыполнитьИмпортИзАД(ТаблицаПользователейАД, ПрофильИмпортаИзAD);
    
    Если ТЗРезультаты.Количество()>0 Тогда
        Результаты.Загрузить(ТЗРезультаты);
    КонецЕсли;    
    
    Элементы.ГруппаСтраницы.ТекущаяСтраница = Элементы.ГруппаСтраницы.ПодчиненныеЭлементы.СтраницаРезультат;
    
КонецПроцедуры

и вот их гружу в справочник

&НаКлиенте
Процедура ЗагрузитьПользователейКлиент(Команда)
        
    ТекстСообщенияОшибки = ОшибкиВПрофиле();
    
    Если ЗначениеЗаполнено(ТекстСообщенияОшибки) Тогда
        ПоказатьПредупреждение(,ТекстСообщенияОшибки);
        Возврат;
    КонецЕсли;
    
    ОчиститьСообщения();
    
    // проверка наличия выбранных строк таблицы пользователей AD
    ВыбранныеСтрокиТаблицыПользователей = ТаблицаПользователей.НайтиСтроки(Новый Структура("Исправить", Истина));
    
    Для Каждого Юзер из ТаблицаПользователей Цикл
        
        
        КонецЦикла;
    
    Если ВыбранныеСтрокиТаблицыПользователей.Количество() = 0 Тогда
        ПоказатьПредупреждение(,НСтр("ru = 'Не выбрано ни одного пользователя для загрузки.'"));
        Возврат;
    КонецЕсли;
    
    ОписаниеОповещения = Новый ОписаниеОповещения("ЗагрузитьПользователейКлиентПослеВопроса", ЭтотОбъект);
    ПоказатьВопрос(ОписаниеОповещения, НСтр("ru = 'Будет выполнен импорт данных согласно настроек профиля. Продолжить?'"), РежимДиалогаВопрос.ДаНет);
    
КонецПроцедуры

и группы я вижу только в формате "OU"=Группа,dc=test,dc=org"

а при загрузке пользователей так вообще никаких пометок - лишь в строке ADsPAth LDAP://00.0.0.00:000/CN=Второй,OU=Группа,OU=Корень,DC=test,DC=org

эту строку что ли надо разбивать, и по OU приравнивать к группе?

(варианты с выгрузкой в файл и дальнейшей загрузкой сторонними методами не подходит от слова вообще)

хочется напиться -_-
9 StagerUchenik
 
26.09.18
15:54
криво выложил(
10 eklmn
 
гуру
26.09.18
16:10
"варианты с выгрузкой в файл и дальнейшей загрузкой сторонними методами не подходит от слова вообще"
потому что все делается 1 строкой, а ты так долго писал что жалко выкидывать? ))
11 StagerUchenik
 
26.09.18
16:12
я в этой обработке еще ничего не писал и предлагал сам вариант с выгрузкой в файл - он не устраивает. мое дело маленькое в таком случае - допилить эту обработку. а вот где ее допилить - я в упор не понимаю.
12 uno-group
 
26.09.18
17:28
Пользователь в АД входит в нацать групп, а не в 1.
Иванов группы: Пользователь. пользователь домена, пользователь удаленного рабочего стола, пользователь 1с. склад и т.п. еще может быть 2 десятка групп.
13 uno-group
 
26.09.18
17:30
А если там нацать доменов и дигилирование полномочий то там 1 бутылки будет мало. Нафига тебе это все в 1с?
14 StagerUchenik
 
26.09.18
20:40
есть такое слово - надо)

по сути выходит так:

1) Есть добрые люди, которые разработали эту прекрасную платформу Управление IT отделом. И заявили что все в ней прекрасно. а по факту, прекрасно в ней все, когда в AD тоже все прекрасно (как в человеке: погоны, кокарда, исподнее)

особенно касательно подразделений) но, мы в какой стране живем? правильно... поэтому в AD у нас бардак (веду не я, пинать не меня)

И на выходе мы имеем ток ФИО пользователя и группу. Даже если бы было другое - нам оно без надобности. но даже другого нет - до смешного.

2) По сути можно ведь фильтр сделать. До +- уровня группы типо OU=1, OU=2, OU=3, OU=n в конце концов все невозможно учесть - что-то потом и ручками можно добить.

Поэтому я просто понимаю, что ничего не понимаю. код который мог - предоставил. в АД - ни жужу. езжу на пежо и ни... ну все поняли. Вот и решил испросить совета с учетом сложившихся обстоятельств.

куда копать, какой лопатой и на какую глубину. на готовые 2-3 строчки кода даже не претендую. хотя чует моя 5я точка, что именно так и будет. до смешного просто.
15 StagerUchenik
 
26.09.18
20:46
отвлекся от сути ответа: упираться настолько глубоко - нет смысла.

Группа1
Юзер1
Юзер2
Группа2
Юзер4
  Группа3
   Юзер3

максимум что хотелось бы реализовать. даже если Юзер1 и в группе 3 и 4 и 10 числится - хрен с ним. лишь бы в первой где засветился попал и все.

мб я не правильно изъясняюсь но опять же в ад не бумбум. хорошую программу АДом - не назовут. или просто я воробушек.
16 vde69
 
26.09.18
22:46
http://catalog.mista.ru/public/22314/

Функция ПолучитьСписокДоменов () Экспорт  
    Результат = Новый Массив();
    objNameSpace = "";                  
    Попытка  objNameSpace = ПолучитьCOMОбъект("WinNT:");  
        м = Новый Массив();  м.Добавить("domain"); // Computer User Group GlobalGroup domain  
        м2 = Новый COMSafeArray(м, "VT_VARIANT");  
        objNameSpace.Filter = м2;  
        Для каждого item Из objNameSpace Цикл  
            Результат.Добавить(item.Name);  
        КонецЦикла;
    Исключение  
        Результат.Очистить();
    КонецПопытки;  
    Возврат Результат;
КонецФункции


Функция ПолучитьСписокГруппВДомене (ИмяДомена, ТипГрупп = "GlobalGroup") Экспорт  
    Результат = Новый Массив();
    objNameSpace = "";  
    Попытка  objNameSpace = ПолучитьCOMОбъект("WinNT://"+СокрЛП(ИмяДомена));  
        м = Новый Массив();  
        м.Добавить(ТипГрупп); // Computer User Group GlobalGroup domain  
        м2 = Новый COMSafeArray(м, "VT_VARIANT");  
        objNameSpace.Filter = м2;  
        Для каждого item Из objNameSpace Цикл  
            Результат.Добавить(item.Name);  
        КонецЦикла;
    Исключение  
        Результат.Очистить();
    КонецПопытки;  
    
    Возврат Результат;
КонецФункции
    
Функция ПолучитьСписокПользователейВГруппеДомена (ИмяДомена, ИмяГруппы) Экспорт  
    Результат = Новый Массив();
    objNameSpace = "";  
    Попытка  
        objNameSpace = ПолучитьCOMОбъект("WinNT://" + СокрЛП(ИмяДомена) + "/" + СокрЛП(ИмяГруппы) + ", Group");  
        Для каждого item Из objNameSpace.Members() Цикл  
            Результат.Добавить(item.Name);  
        КонецЦикла;
    Исключение  
        Результат.Очистить();
    КонецПопытки;  
    
    Возврат Результат;    
КонецФункции

Функция ПользовательВГруппеДомена (ИмяДомена, ИмяГруппы, ИмяПользователя) Экспорт  
    Результат = Ложь;  
    Массив = ПолучитьСписокПользователейВГруппеДомена (СокрЛП(ИмяДомена), ИмяГруппы);
    Для каждого элМассив из Массив Цикл  
        Если ВРег(элМассив) = ВРег(СокрЛП(ИмяПользователя)) Тогда   // пользователь уже в группе  
            Результат = Истина;    
            Прервать;  
        КонецЕсли;
    КонецЦикла;  
    
    Возврат Результат;
КонецФункции

Функция ДобавитьПользователяВГруппуДомена (ИмяДомена, ИмяГруппы, ИмяПользователя) Экспорт  
    Результат = Ложь;
    element_user = "";
    element_group = "";  
    Попытка  
        element_user = ПолучитьCOMОбъект("WinNT://" + ИмяДомена + "/" + ИмяПользователя + ", user");  
        element_group = ПолучитьCOMОбъект("WinNT://" + ИмяДомена + "/" + ИмяГруппы + ", group");  
        element_group.Add(element_user.ADsPath);  element_group.SetInfo();  
        Результат = Истина;
    Исключение  
        Результат = Ложь;
    КонецПопытки;  
    
    Возврат Результат;
КонецФункции

Функция УдалитьПользователяИзГруппыДомена (ИмяДомена, ИмяГруппы, ИмяПользователя) Экспорт  
    Результат = Ложь;
    element_user = "";
    element_group = "";  
    Попытка  element_user = ПолучитьCOMОбъект("WinNT://" + ИмяДомена + "/" + ИмяПользователя + ", user");  
        element_group = ПолучитьCOMОбъект("WinNT://" + ИмяДомена + "/" + ИмяГруппы + ", group");  
        element_group.Remove(element_user.ADsPath);  
        element_group.SetInfo();  
        Результат = Истина;
    Исключение  
        Результат = Ложь;
    КонецПопытки;  
    
    Возврат Результат;    
КонецФункции

Процедура ЗаполнитьПочтовыеАдресаИзAD()
    Попытка      
        conn = ПолучитьCOMОбъект("","ADODB.Connection");  
        conn.Provider = "ADSDSOObject";  
        conn.Open("Active Directory Provider");
    Исключение  Предупреждение("Ошибка подключения к Active Directory!");  
        Возврат;
    КонецПопытки;  
    
    Для Каждого Стр из Таблица Цикл  
        Если НЕ ПустаяСтрока(Стр.Логин) Тогда  
            Попытка        
                query = "SEL ECT ADsPath FR OM 'LDAP://DC="+СокрЛП(Домен.Код)+"' WHERE SAMAccountName='"+Стр.Логин+"'";    
                rs = conn.Execute(query);    
                Пока НЕ rs.EOF() Цикл    
                    obj = ПолучитьCOMОбъект(rs.Fields(0).Value);    
                    Если obj.Class="user" Тогда      
                        Стр.НоваяПочта=СокрЛП(obj.EmailAddress);      
                        Если Стр.НоваяПочта<>Стр.СтараяПочта Тогда      
                            Стр.Установить=Истина;      
                        КонецЕсли;    
                    КонецЕсли;    
                    rs.MoveNext();    
                КонецЦикла;  
            Исключение
                Сообщить("Ошибка получения почты для логина :"+Стр.Логин);                                                                      
            КонецПопытки;
        КонецЕсли;
    КонецЦикла;
    conn.Close();    
КонецПроцедуры
17 EvgeniuXP
 
26.09.18
23:13
закладка
18 StagerUchenik
 
27.09.18
09:30
vde69 - огромное тебе спасибо!) буду пробовать!
AdBlock убивает бесплатный контент. 1Сергей