python ldap распространение схемы samba на пользователя

340 просмотра
0
0 Комментариев

Описание : есть сервер Centos 7.4 на нем установлен openldap 2.4.44, создан домен «test.rdi» администратор домена «manager», в ldap добавлена схема samba, в которой в свою очередь убрана привязка к sambasid. В домене заведен пользователь testuser. Я начал писать скрипт который делал бы поиск определенных пользователей по логину и в случае нахождения его в базе добавлял бы ему новый objectclass sambaSamaccount и два атрибута sambaLMPassword и sambaNTPassword , а также заменял поле пароль. По причине плохого знания ldap я смог только подключиться к серверу и сделать поиск.

#!/usr/bin/python
import ldap
ip_ldap ='ldap://192.168.59.239'
nt='8846f7eaee8fb117ad06bdd830b7586c'
lm='e52cac67419a9a224a3b108f3fa6cb6d'
ssha='{SSHA}dxedyX796NFkdcJ81iVOGycB1pc4J2TM'
manager_passwd = raw_input('enter ldap admin pass \n')
uid_manager ="cn=Manager,dc=test,dc=rdi"
dn = "dc=test,dc=rdi"
login = "testuser"
uid='(uid={0})'.format(login)
uid_user_people = 'uid=testuser,ou=People,dc=test,dc=rdi'
def ldap_search (ip_ldap,manager_passwd,uid_manager,dn):
    con = ldap.initialize(ip_ldap)
    con.simple_bind_s(uid_manager, manager_passwd)
    result = con.search_s(uid_user_people, ldap.SCOPE_SUBTREE, )
    return result
a = ldap_search (ip_ldap, manager_passwd, uid_manager, dn)
print a

Вопрос : Как с помощью питона добавлять objectclass и атрибуты на пользователя, а также как их менять?


Добавить комментарий

1 Ответы

Python Опубликовано 10.12.2018
0

Коротко о том, что такое LDAP

Во-первых, это стандартизированный протокол. Да, он так и называется Легковесный Протокол Доступа к Каталогам (Lightweight Directory Access Protocol). На практике это может означать следующее, что не возникнет проблем (или почти не возникнет), когда вы задумаете поменять реализацию LDAP-а (сервер бэкенда). Ваши интерфейсы работы с LDAP-сервером останутся неизменными.

Во-вторых, это способ хранения данных. В этом месте многие пытаются сравнивать LDAP с классическими sql-ными СУБД, но мы это делать не будем, т.к. это приведёт к дилемме — «забить мне гвоздь микроскопом или молотком».

В-третьих, это способ получения данных. Основной ориентацией LDAP-а является принцип: «один раз записал – много раз прочитал». Не нужно пытаться делать из LDAP-а «базу данных для биллинга» с тысячами «инсертов/апдейтов/делитов» — это не его задача.

Коротко о структуре

Каталог LDAP состоит из записей (records). Каждая запись имеет уникальное (отличительное) имя DN (Distinguished Name). Это имя может выглядеть, например, так: cn=Василий Пушкин,ou=Personal,o=Рога и копыта,dc=example,dc=com. В каталоге не может быть двух записей с одинаковыми DN. Части DN, разделенные запятой, называются RDN (Relative Distinguished Name). RDN тоже должен быть уникален, но только в рамках своего «уровня» («пути»).
Как это понимать?

Из примера выше: RDN = cn=Василий Пушкин, следовательно не может быть еще одной записи с таким же RDN на «уровне» ou=Personal,o=Рога и копыта,dc=example,dc=com. Но никто не запрещает иметь запись с этим RDN на «уровне» ou=Personal,o=Харчевня у Василия,dc=example,dc=com. Также никто не запрещает иметь запись с этим RDN в таком виде: cn=Василий Пушкин,o=Рога и копыта,dc=example,dc=com. Тут мы просто поместили Василия в «корень» o=Рога и копыта. При этом Василий, «принадлежащий» ou=Personal, o=Рога и копыта,dc=example,dc=com и другой Василий (работающий в корпорации o=Харчевня у Василия) никак не мешают друг другу.

Такая организация данных позволяет представить все записи в виде дерева, как это обычно и принято делать на практике.

Все DN-ы, перечисленные выше, можно изобразить в виде такого дерева:

dc=example,dc=com
    |_ o=Рога и копыта
    |   |_ ou=Personal
    |   |   |_ cn=Василий Пушкин
    |   |_ cn=Василий Пушкин
    |_ o=Харчевня у Василия
        |_ ou=Personal
            |_ cn=Василий Пушкин

Что это за непонятные аббревиатуры dc, ou, o и т.д. из которых состоят записи LDAP-а?

Чтобы не усложнять данный текст, представим, что это «объекты» структуры, которые являются хранилищами информации (данных). Эти «объекты» наследуются от специальных классов (objectClasses) и содержат наборы атрибутов (attributes). В атрибутах записывается необходимая для хранения информация. Атрибуты могут содержать много значений (например, такой как, memberUid), а также есть такие, которые обязаны определяться только один раз (например, gidNumber).

Теперь к практической части

Дабы не усложнять текст, предположим, что у нас настроен и запущен LDAP сервер и с ним можно работать. Но сам каталог пустой, т.е. нет никаких записей.

Добавление записи

Мы хотим добавить запись (из примера выше): cn=Василий Пушкин,ou=Personal,o=Рога и копыта,dc=example,dc=com.

Добавляем новую запись:

add_record = [('objectClass', ['person']), ('sn', ['Пушкин'])]
l.add_s('cn=Василий Пушкин,ou=Personal,o=Рога и копыта,dc=example,dc=com', add_record)

… и обламываемся с ошибкой: ldap.NO_SUCH_OBJECT: {'matched': 'dc=example,dc=com', 'desc': 'No such object'}

Почему это произошло?

Как мы помним, каталог у нас совершенно пустой. Фактически в нем, кроме «корня», ничего нет. Поэтому добавляя в каталог запись (DN) из пяти RDN-ов, ошибка возникает на моменте определения первого от корня RDN — o=Рога и копыта.

Дело в том, что LDAP сам не занимается созданием несуществующих «объектов» в каталоге, пытаясь догадаться, что же это за тип записи подразумевал пользователь. Это ключевой момент (и как показывает практика – для многих самый непонятный) при добавлении новой записи в каталог.

В связи с этим вся ответственность за создание полного «пути» лежит на пользователе, который сам должен явно описать все необходимые данные (objectClass, attributes) для создаваемого объекта.

Поэтому правильной будет такая последовательность:

add_record = [('objectClass', ['organization'])]
l.add_s('o=Рога и копыта,dc=example,dc=com', add_record)
 
add_record = [('objectClass', ['organizationalUnit'])]
l.add_s('ou=Personal,o=Рога и копыта,dc=example,dc=com', add_record)
 
add_record = [('objectClass', ['person']), ('sn', ['Пушкин'])]
l.add_s('cn=Василий Пушкин,ou=Personal,o=Рога и копыта,dc=example,dc=com', add_record)

Удаление

Это самое простое действие.

l.delete_s('cn=Василий Пушкин,ou=Personal,o=Рога и копыта,dc=example,dc=com')

Будет удален cn=Василий Пушкин, расположенный тут ou=Personal,o=Рога и копыта,dc=example,dc=com.

Модификация

Расширим запись Василия objectClass-ом posixAccount:

mod_attrs = [( ldap.MOD_ADD, 'objectClass', 'posixAccount' ), (ldap.MOD_ADD, 'uid', 'vasya' ), (ldap.MOD_ADD, 'uidNumber', '123'), (ldap.MOD_ADD, 'gidNumber', '321'), (ldap.MOD_ADD, 'hom
eDirectory', '/home/vasya')]
l.modify_s('cn=Василий Пушкин,ou=Personal,o=Рога и копыта,dc=example,dc=com', mod_attrs)

Класс posixAccount содержит 4 обязательных атрибута, поэтому их необходимо определить при модификации объекта.

Поиск

Найдем в компании «Рога и копыта» сотрудника с uid равным vasya и отобразим его домашний каталог.

basedn = "o=Рога и копыта,dc=example,dc=com"
searchFilter = "(uid=vasya)"
searchAttribute = ["homeDirectory"]
searchScope = ldap.SCOPE_SUBTREE
ldap_result_id = l.search(basedn, searchScope, searchFilter, searchAttribute)
result_set = []
while 1:
    result_type, result_data = l.result(ldap_result_id, 0)
    if (result_data == []):
        break
    else:
        if result_type == ldap.RES_SEARCH_ENTRY:
            print result_data    # вывод результата полностью
            print result_data[0][1]['homeDirectory'][0]  # вывод homeDirectory

Теперь для наглядности можно собрать все описанные действия в один алгоритм:

создадим новую запись, модифицируем ее, найдем и удалим

import ldap
 
l = ldap.initialize('ldap://ldap-server')
 
binddn = "cn=admin,dc=example,dc=com"  # учетка администратора (пример)
password = "AdMinPassvv0rd"
l.protocol_version = ldap.VERSION3
l.simple_bind_s(binddn, password)
 
# добавление
add_record = [('objectClass', ['organization'])]
l.add_s('o=Рога и копыта,dc=example,dc=com', add_record)
 
add_record = [('objectClass', ['organizationalUnit'])]
l.add_s('ou=Personal,o=Рога и копыта,dc=example,dc=com', add_record)
 
add_record = [('objectClass', ['person']), ('sn', ['Пушкин'])]
l.add_s('cn=Василий Пушкин,ou=Personal,o=Рога и копыта,dc=example,dc=com', add_record)
 
# модификация
mod_attrs = [( ldap.MOD_ADD, 'objectClass', 'posixAccount' ), (ldap.MOD_ADD, 'uid', 'vasya' ), (ldap.MOD_ADD, 'uidNumber', '123'), (ldap.MOD_ADD, 'gidNumber', '321'), (ldap.MOD_ADD, 'hom
eDirectory', '/home/vasya')]
l.modify_s('cn=Василий Пушкин,ou=Personal,o=Рога и копыта,dc=example,dc=com', mod_attrs)
 
# поиск
basedn = "dc=example,dc=com"
searchFilter = "(uid=vasya)"
searchAttribute = ["homeDirectory"]
searchScope = ldap.SCOPE_SUBTREE
ldap_result_id = l.search(basedn, searchScope, searchFilter, searchAttribute)
result_set = []
while 1:
    result_type, result_data = l.result(ldap_result_id, 0)
    if (result_data == []):
        break
    else:
        if result_type == ldap.RES_SEARCH_ENTRY:
            print result_data    # вывод результата полностью
            print result_data[0][1]['homeDirectory'][0]  # вывод homeDirectory
 
# удаление
l.delete_s('cn=Василий Пушкин,ou=Personal,o=Рога и копыта,dc=example,dc=com')
 
l.unbind_s()

Надеюсь, что это поможет.

Добавить комментарий
Напишите свой ответ на данный вопрос.
Scroll Up