Диаграммы последовательностей работы коннектора SberLDAP#

Данный документ содержит диаграммы последовательностей (PlantUML), описывающие алгоритмы работы коннектора SberLDAP (IDMC Connector).

Тестирование подключения (test)#

@startuml
title Диаграмма последовательности: Тестирование подключения

participant "IDM Framework" as Framework
participant "SberLdapConnector" as Connector
participant "ConnectionManager" as ConnMgr
participant "ServerConnectionPool" as Pool
participant "LdapNetworkConnection" as Conn
participant "LDAP Server" as LDAP

Framework -> Connector: test()
activate Connector

Connector -> ConnMgr: test()
activate ConnMgr

ConnMgr -> ConnMgr: close("connection test")
ConnMgr -> Pool: getServers()

alt TEST_MODE_FULL
    loop для каждого сервера
        ConnMgr -> Pool: connectServer(server)
        activate Pool
        Pool -> Conn: new LdapNetworkConnection()
        Conn -> LDAP: connect/bind
        LDAP --> Conn: OK
        Conn --> Pool: connection
        Pool --> ConnMgr: connection
        deactivate Pool
    end
else TEST_MODE_PRIMARY
    ConnMgr -> Pool: getPrimaryServer()
    Pool --> ConnMgr: server
    ConnMgr -> Pool: connectServer(server)
    Pool --> ConnMgr: connection
else TEST_MODE_ANY
    ConnMgr -> Pool: getConnection(null)
    Pool --> ConnMgr: connection
end

ConnMgr -> Conn: getRootDse(attributes)
activate Conn
Conn -> LDAP: search(base="", scope=base, filter="(objectClass=*)")
LDAP --> Conn: RootDSE Entry
Conn --> ConnMgr: RootDSE
deactivate Conn

ConnMgr --> Connector: OK
deactivate ConnMgr
Connector --> Framework: OK
deactivate Connector
@enduml

Создание объекта (create)#

@startuml
title Диаграмма последовательности: Создание объекта (create)

participant "IDM Framework" as Framework
participant "SberLdapConnector" as Connector
participant "ConnectionManager" as ConnMgr
participant "LdapNetworkConnection" as Conn
participant "LDAP Server" as LDAP
participant "ResultsHandler" as Handler

Framework -> Connector: create(objectClass, attributes, options)
activate Connector

Connector -> Connector: toDn(attributes)
Connector -> ConnMgr: getConnection(dn, options)
activate ConnMgr
ConnMgr -> ConnMgr: selectPool(dn)
ConnMgr -> Pool: getConnection(options)
Pool --> ConnMgr: LdapNetworkConnection
ConnMgr --> Connector: connection
deactivate ConnMgr

Connector -> Connector: создать Entry
loop для каждого атрибута
    Connector -> Connector: entry.add(attributeName, value)
    alt пароль
        Connector -> Connector: использовать GuardedString
    end
end

Connector -> Conn: add(entry)
activate Conn
Conn -> LDAP: LDAP Add Request
LDAP --> Conn: LDAP Add Response
Conn --> Connector: результат
deactivate Conn

alt успех
    Connector -> ConnMgr: returnConnection(connection)
    Connector -> Connector: read created object
    Connector -> Handler: handle(connectorObject)
    Connector --> Framework: Uid
else ошибка
    Connector -> Connector: processLdapException()
    Connector --> Framework: ConnectorException
end

deactivate Connector
@enduml

@startuml
title Диаграмма последовательности: Поиск объектов (executeQuery)

participant "IDM Framework" as Framework
participant "SberLdapConnector" as Connector
participant "ConnectionManager" as ConnMgr
participant "SimplePagedResultsSearchStrategy" as SearchStrategy
participant "LdapNetworkConnection" as Conn
participant "LDAP Server" as LDAP
participant "ResultsHandler" as Handler

Framework -> Connector: executeQuery(objectClass, filter, handler, options)
activate Connector

Connector -> Connector: prepareConnIdSchema()
Connector -> Connector: chooseSearchStrategy()
Connector -> SearchStrategy: new SimplePagedResultsSearchStrategy(...)

Connector -> SearchStrategy: search(baseDn, filterNode, scope, attributes)
activate SearchStrategy

SearchStrategy -> SearchStrategy: connect(baseDn)
SearchStrategy -> ConnMgr: getConnection(baseDn, options)
ConnMgr --> SearchStrategy: LdapNetworkConnection

loop для каждой страницы
    SearchStrategy -> SearchStrategy: prepareSearchRequest()
    SearchStrategy -> SearchStrategy: добавить PagedResults control\n(pageSize, cookie)
    SearchStrategy -> Conn: search(request)
    activate Conn
    Conn -> LDAP: LDAP Search Request
    LDAP --> Conn: SearchCursor
    Conn --> SearchStrategy: SearchCursor
    deactivate Conn
    
    loop для каждого SearchResultEntry
        SearchStrategy -> SearchStrategy: cursor.next()
        SearchStrategy -> SearchStrategy: getEntry()
        SearchStrategy -> SearchStrategy: handleResult(entry)
        SearchStrategy -> Handler: handle(connectorObject)
    end
    
    SearchStrategy -> SearchStrategy: получить cookie из response
    alt cookie != null
        SearchStrategy -> SearchStrategy: следующая страница
    else
        SearchStrategy -> SearchStrategy: завершить поиск
    end
end

SearchStrategy -> SearchStrategy: finishSearch()
SearchStrategy -> Conn: search с pageSize=0
Conn --> SearchStrategy: OK
SearchStrategy -> ConnMgr: returnConnection(connection)

SearchStrategy --> Connector: завершено
deactivate SearchStrategy
Connector --> Framework: OK
deactivate Connector
@enduml

Чтение объекта (read)#

@startuml
title Диаграмма последовательности: Чтение объекта (read)

participant "IDM Framework" as Framework
participant "SberLdapConnector" as Connector
participant "ConnectionManager" as ConnMgr
participant "LdapNetworkConnection" as Conn
participant "LDAP Server" as LDAP

Framework -> Connector: read(objectClass, uid, options)
activate Connector

Connector -> Connector: resolveDn(objectClass, uid, options)
alt uidAttributeName == "__UID__"
    Connector -> Connector: toDn(uid)
else
    Connector -> Connector: search(baseDn, filter="(uidAttributeName=uidValue)")
    Connector --> Connector: dn
end

Connector -> ConnMgr: getConnection(dn, options)
activate ConnMgr
ConnMgr --> Connector: LdapNetworkConnection
deactivate ConnMgr

Connector -> Conn: lookup(dn)
activate Conn
Conn -> LDAP: LDAP Search Request (base, scope=object)
LDAP --> Conn: Entry
Conn --> Connector: Entry
deactivate Conn

Connector -> Connector: toConnectorObject(entry)
activate Connector
loop для каждого атрибута Entry
    Connector -> Connector: toConnIdValue(ldapValue)
    alt poly-атрибут (language tag)
        Connector -> Connector: создать Map<String, String>
    else
        Connector -> Connector: добавить значение
    end
end
Connector --> Connector: ConnectorObject
deactivate Connector

Connector -> ConnMgr: returnConnection(connection)
Connector --> Framework: ConnectorObject
deactivate Connector
@enduml

Обновление объекта (update)#

@startuml
title Диаграмма последовательности: Обновление объекта (update)

participant "IDM Framework" as Framework
participant "SberLdapConnector" as Connector
participant "ConnectionManager" as ConnMgr
participant "LdapNetworkConnection" as Conn
participant "LDAP Server" as LDAP

Framework -> Connector: update(objectClass, uid, deltas, options)
activate Connector

Connector -> Connector: resolveDn(objectClass, uid, options)
Connector -> ConnMgr: getConnection(dn, options)
activate ConnMgr
ConnMgr --> Connector: LdapNetworkConnection
deactivate ConnMgr

loop для каждого AttributeDelta
    Connector -> Connector: toLdapModification(delta)
    alt REPLACE_ATTRIBUTE
        Connector -> Connector: new DefaultModification(REPLACE, attr, values)
    else ADD_ATTRIBUTE
        Connector -> Connector: new DefaultModification(ADD, attr, values)
    else REMOVE_ATTRIBUTE
        Connector -> Connector: new DefaultModification(REMOVE, attr, values)
    end
end

Connector -> Conn: modify(modRequest)
activate Conn
Conn -> LDAP: LDAP Modify Request
LDAP --> Conn: LDAP Modify Response
Conn --> Connector: ModifyResponse
deactivate Conn

alt passwordStrategy == "ldappasswd"
    Connector -> Conn: extended(PasswordModifyRequest)
    activate Conn
    Conn -> LDAP: LDAP Password Modify Extended Operation
    LDAP --> Conn: ExtendedResponse
    Conn --> Connector: результат
    deactivate Conn
end

Connector -> ConnMgr: returnConnection(connection)
Connector --> Framework: OK
deactivate Connector
@enduml

Удаление объекта (delete)#

@startuml
title Диаграмма последовательности: Удаление объекта (delete)

participant "IDM Framework" as Framework
participant "SberLdapConnector" as Connector
participant "ConnectionManager" as ConnMgr
participant "LdapNetworkConnection" as Conn
participant "LDAP Server" as LDAP

Framework -> Connector: delete(objectClass, uid, options)
activate Connector

Connector -> Connector: resolveDn(objectClass, uid, options)
Connector -> ConnMgr: getConnection(dn, options)
activate ConnMgr
ConnMgr --> Connector: LdapNetworkConnection
deactivate ConnMgr

Connector -> Conn: delete(deleteRequest)
activate Conn
Conn -> LDAP: LDAP Delete Request
LDAP --> Conn: LDAP Delete Response
Conn --> Connector: DeleteResponse
deactivate Conn

alt TreeDelete control
    Connector -> Conn: добавить TreeDelete control
    Conn -> LDAP: рекурсивное удаление
end

Connector -> ConnMgr: returnConnection(connection)
Connector --> Framework: OK
deactivate Connector
@enduml

Управление соединениями (ConnectionManager)#

@startuml
title Диаграмма последовательности: Получение соединения

participant "AbstractLdapConnector" as Connector
participant "ConnectionManager" as ConnMgr
participant "ServerConnectionPool" as Pool
participant "ServerDefinition" as Server
participant "LdapNetworkConnection" as Conn
participant "LDAP Server" as LDAP

Connector -> ConnMgr: getConnection(baseDn, options)
activate ConnMgr

ConnMgr -> ConnMgr: selectPool(baseDn)
loop для каждого Pool
    ConnMgr -> ConnMgr: isAncestorOf(poolBaseContext, baseDn)
    alt poolBaseContext является предком baseDn
        ConnMgr -> ConnMgr: выбрать этот pool
    end
end

ConnMgr -> Pool: getConnection(options)
activate Pool

Pool -> Pool: selectServer()
Pool -> Server: connectServer()
activate Server
Server -> Conn: new LdapNetworkConnection(host, port)
Conn -> LDAP: connect()
LDAP --> Conn: OK
Conn -> LDAP: bind(bindDn, bindPassword)
LDAP --> Conn: OK
Server --> Pool: connection
deactivate Server

Pool -> Pool: добавить connection в pool
Pool --> ConnMgr: connection
deactivate Pool

alt rootDse == null
    ConnMgr -> Conn: getRootDse()
    activate Conn
    Conn -> LDAP: search(base="", filter="(objectClass=*)")
    LDAP --> Conn: RootDSE
    Conn --> ConnMgr: Entry
    deactivate Conn
    ConnMgr -> ConnMgr: сохранить rootDse
end

ConnMgr --> Connector: LdapNetworkConnection
deactivate ConnMgr
@enduml

Синхронизация (sync)#

@startuml
title Диаграмма последовательности: Синхронизация (sync)

participant "IDM Framework" as Framework
participant "SberLdapConnector" as Connector
participant "SyncStrategy" as SyncStrategy
participant "ConnectionManager" as ConnMgr
participant "LdapNetworkConnection" as Conn
participant "LDAP Server" as LDAP
participant "SyncResultsHandler" as Handler

Framework -> Connector: sync(objectClass, token, handler, options)
activate Connector

Connector -> Connector: prepareConnIdSchema()
Connector -> Connector: chooseSyncStrategy()

alt synchronizationStrategy == "sun-changelog"
    Connector -> SyncStrategy: new SunChangelogSyncStrategy()
else synchronizationStrategy == "modifyTimestamp"
    Connector -> SyncStrategy: new ModifyTimestampSyncStrategy()
else synchronizationStrategy == "openldap-accesslog"
    Connector -> SyncStrategy: new OpenLdapAccessLogSyncStrategy()
else synchronizationStrategy == "ad-dir-sync"
    Connector -> SyncStrategy: new AdDirSyncStrategy()
else auto
    Connector -> Connector: checkRootDse for changelog
    alt changelog found
        Connector -> SyncStrategy: new SunChangelogSyncStrategy()
    else
        Connector -> SyncStrategy: new ModifyTimestampSyncStrategy()
    end
end

Connector -> SyncStrategy: sync(objectClass, token, handler, options)
activate SyncStrategy

SyncStrategy -> ConnMgr: getConnection(baseDn, options)
ConnMgr --> SyncStrategy: LdapNetworkConnection

SyncStrategy -> SyncStrategy: executeSyncQuery()
loop для каждого изменённого объекта
    SyncStrategy -> Conn: search(changeLogBase, filter)
    Conn --> SyncStrategy: ChangeLogEntry
    SyncStrategy -> SyncStrategy: parseChangeLogEntry()
    SyncStrategy -> Handler: handle(connectorObject, operation)
end

SyncStrategy -> ConnMgr: returnConnection(connection)
SyncStrategy --> Connector: новый токен
deactivate SyncStrategy
Connector --> Framework: OK
deactivate Connector
@enduml

Определение DN (resolveDn)#

@startuml
title Диаграмма последовательности: Разрешение DN из UID

participant "AbstractLdapConnector" as Connector
participant "ConnectionManager" as ConnMgr
participant "LdapNetworkConnection" as Conn
participant "LDAP Server" as LDAP

Connector -> Connector: resolveDn(objectClass, uid, options)

alt uidAttributeName == "__NAME__" или "dn"
    Connector -> Connector: toDn(uid.getUidValue())
    Connector --> Connector: dn
else
    Connector -> ConnMgr: getConnection(baseDn, options)
    ConnMgr --> Connector: LdapNetworkConnection
    
    Connector -> Connector: создать filter "(uidAttributeName=uidValue)"
    Connector -> Conn: search(baseDn, filter, scope, attributes=["uidAttributeName"])
    activate Conn
    Conn -> LDAP: LDAP Search Request
    LDAP --> Conn: SearchResultEntry
    Conn --> Connector: Entry
    deactivate Conn
    
    Connector -> Connector: entry.getDn()
    Connector --> Connector: dn
    
    Connector -> ConnMgr: returnConnection(connection)
end
@enduml