본문 바로가기

반응형
Notice
Recent Posts
Link
Calendar
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Total
Today
관리 메뉴

AD와 OPENLDAP 동기화 하기 by lsc 본문

Linux Server

AD와 OPENLDAP 동기화 하기 by lsc

BinaryNumber 2022. 11. 7. 18:46
반응형

아래와 같이 구성하면 Active Directory 서버를 보호하면서 OpenLDAP을 이용하요 인증을 수행할 수 있다.

위 그림을 구성하기 위해 사용되는 솔류션이 LSC(LDAP Synchronization Connector)와 saslauthd 서비스이다.

※ saslauthd  서비스 자세히 보기) OpenLDAP Pass-through 구성 (tistory.com)

 

OpenLDAP Pass-through 구성

Pass-through OpenLDAP Authentication (Using SASL) to Active Directory on Centos 통과 인증은 다른 백엔드에 인증 작업(BIND)을 위임하기 위해 일부 LDAP 디렉토리에서 사용하는 메커니즘 ※ SASL(Simple Authentication and Secu

binarynum.tistory.com

LSC란?

LSC는 다른 LDAP 서버, DB, 파일 등 데이터의 ID를 동기화하는 오픈 소스 커텍터이다.

 

설치

다운로드

cd ~
#https://ltb-project.org/wiki/lib/RPM-GPG-KEY-LTB-project
vim RPM-GPG-KEY-LTB-project
sudo rpm --import /home/ec2-user/RPM-GPG-KEY-LTB-project 
wget https://lsc-project.org/archives/lsc-2.1.6-1.el7.noarch.rpm
sudo yum localinstall lsc*

구성 

mkdir /etc/lsc/ad2openldap
vim /etc/lsc/ad2openldap/lsc.xml

lsc.xml (연동 소스 예시)

<?xml version="1.0" ?>
<lsc xmlns="http://lsc-project.org/XSD/lsc-core-2.1.xsd" revision="0">
    <connections>
        <ldapConnection>
            <name>ldap-src-conn</name>
            <url>ldap://ad-server.publicdomain.xyz:389/DC=your_ad_domain,DC=local</url>
            <username>user_to_login@your_ad_domain.local</username>
            <password>password_to_login_ad</password>
            <authentication>SIMPLE</authentication>
            <referral>IGNORE</referral>
            <derefAliases>NEVER</derefAliases>
            <version>VERSION_3</version>
            <pageSize>-1</pageSize>
            <factory>com.sun.jndi.ldap.LdapCtxFactory</factory>
            <tlsActivated>false</tlsActivated>
        </ldapConnection>
        <ldapConnection>
            <name>ldap-dst-conn</name>
            <url>ldap://localhost:389/dc=your_ad_domain,dc=local</url>
            <username>cn=admin,dc=your_ad_domain,dc=local</username>
            <password>demopassword</password>
            <authentication>SIMPLE</authentication>
            <referral>IGNORE</referral>
            <derefAliases>NEVER</derefAliases>
            <version>VERSION_3</version>
            <pageSize>-1</pageSize>
            <factory>com.sun.jndi.ldap.LdapCtxFactory</factory>
            <tlsActivated>false</tlsActivated>
        </ldapConnection>
    </connections>
    <tasks>
        <task>
            <name>Sync_1_Users</name>
            <bean>org.lsc.beans.SimpleBean</bean>
            <ldapSourceService>
                <name>ad-source-service</name>
                <connection reference="ldap-src-conn" />
                <baseDn>DC=your_ad_domain,DC=local</baseDn>
                <pivotAttributes>
                    <string>samAccountName</string>
                </pivotAttributes>
                <fetchedAttributes>
                    <string>description</string>
                    <string>cn</string>
                    <string>sn</string>
                    <string>givenName</string>
                    <string>samAccountName</string>
                    <string>userPrincipalName</string>
                    <string>title</string>
                    <string>physicalDeliveryOfficeName</string>
                    <string>telephoneNumber</string>
                    <string>facsimileTelephoneNumber</string>
                    <string>department</string>
                    <string>company</string>
                    <string>mail</string>
                    <string>mobile</string>
                    <string>jpegPhoto</string>
                </fetchedAttributes>
                <!-- <getAllFilter>(objectClass=user)</getAllFilter> -->
                <getAllFilter>(&amp;(objectCategory=person)(objectClass=user)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))</getAllFilter>
                <!-- <getOneFilter>(&amp;(objectClass=user)(samAccountName={samAccountName})(mail=*))</getOneFilter> -->
                <getOneFilter>(&amp;(objectCategory=person)(objectClass=user)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(samAccountName={samAccountName}))</getOneFilter>
                <!-- <cleanFilter>(&amp;(objectClass=user)(samAccountName={uid})(mail=*))</cleanFilter> -->
                <cleanFilter>(&amp;(objectCategory=person)(objectClass=user)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(samAccountName={uid}))</cleanFilter>
            </ldapSourceService>
            <ldapDestinationService>
                <name>opends-dst-service</name>
                <connection reference="ldap-dst-conn" />
                <baseDn>ou=Users,dc=your_ad_domain,dc=local</baseDn>
                <pivotAttributes>
                    <string>uid</string>
                </pivotAttributes>
                <fetchedAttributes>
                    <string>description</string>
                    <string>cn</string>
                    <string>sn</string>
                    <string>userPassword</string>
                    <string>objectClass</string>
                    <string>uid</string>
                    <string>title</string>
                    <string>physicalDeliveryOfficeName</string>
                    <string>telephoneNumber</string>
                    <string>telexNumber</string>
                    <string>ou</string>
                    <string>o</string>
                    <string>mail</string>
                    <string>mobile</string>
                    <string>jpegPhoto</string>
                </fetchedAttributes>
                <getAllFilter>(objectClass=inetorgperson)</getAllFilter>
                <getOneFilter>(&amp;(objectClass=inetorgperson)(uid={samAccountName}))</getOneFilter>
            </ldapDestinationService>
            <propertiesBasedSyncOptions>
                <mainIdentifier>"uid=" +
                    srcBean.getDatasetFirstValueById("samAccountName") +
                    ",ou=Users,dc=your_ad_domain,dc=local"</mainIdentifier>
                <defaultDelimiter>;</defaultDelimiter>
                <defaultPolicy>FORCE</defaultPolicy>
                <dataset>
                    <name>description</name>
                    <policy>FORCE</policy>
                    <forceValues>
                        <string>js:(srcBean.getDatasetFirstValueById("sn") != null  ? srcBean.getDatasetFirstValueById("sn").toUpperCase() : null )</string>
                    </forceValues>
                </dataset>
                <dataset>
                    <name>userPassword</name>
                    <policy>KEEP</policy>
                    <createValues>
                        <string>js:"{SASL}" +
                            srcBean.getDatasetFirstValueById("samAccountName") + "@your_ad_domain.local"</string>
                    </createValues>
                </dataset>
                <dataset>
                    <name>sn</name>
                    <!-- <policy>FORCE</policy> -->
                    <policy>KEEP</policy>
                    <createValues>
                        <string>js:srcBean.getDatasetFirstValueById("samAccountName")</string>
                    </createValues>
                </dataset>
                <dataset>
                    <name>description</name>
                    <policy>FORCE</policy>
                    <forceValues>
                        <string>js:(srcBean.getDatasetFirstValueById("sn") != null  ? srcBean.getDatasetFirstValueById("sn").toUpperCase() : null )</string>
                    </forceValues>
                </dataset>
                <dataset>
                    <name>uid</name>
                    <policy>KEEP</policy>
                    <createValues>
                        <string>js:srcBean.getDatasetFirstValueById("samAcccountName")</string>
                    </createValues>
                </dataset>
                <dataset>
                    <name>objectClass</name>
                    <policy>KEEP</policy>
                    <createValues>
                        <string>"inetOrgPerson"</string>
                    </createValues>
                </dataset>
                <dataset>
                    <name>telexNumber</name>
                    <policy>FORCE</policy>
                    <forceValues>
                        <string>js:srcBean.getDatasetFirstValueById("facsimileTelephoneNumber")</string>
                    </forceValues>
                </dataset>
                <dataset>
                    <name>o</name>
                    <policy>FORCE</policy>
                    <forceValues>
                        <string>js:srcBean.getDatasetFirstValueById("company")</string>
                    </forceValues>
                </dataset>
                <dataset>
                    <name>ou</name>
                    <policy>FORCE</policy>
                    <forceValues>
                        <string>js:srcBean.getDatasetFirstValueById("department")</string>
                    </forceValues>
                </dataset>
            </propertiesBasedSyncOptions>
        </task>
        <task>
            <name>Sync_2_Groups</name>
            <bean>org.lsc.beans.SimpleBean</bean>
            <ldapSourceService>
                <name>group-source-service</name>
                <connection reference="ldap-src-conn" />
                <baseDn>DC=your_ad_domain,DC=local</baseDn>
                <pivotAttributes>
                    <string>cn</string>
                </pivotAttributes>
                <fetchedAttributes>
                    <string>cn</string>
                    <string>description</string>
                    <string>member</string>
                    <!-- <string>objectClass</string> -->
                </fetchedAttributes>
                <getAllFilter><![CDATA[(objectClass=group)]]></getAllFilter>
                <getOneFilter><![CDATA[(&(objectClass=group)(cn={cn}))]]></getOneFilter>
                <cleanFilter><![CDATA[(&(objectClass=group)(cn={cn}))]]></cleanFilter>
                <!-- <serverType>ActiveDirectory</serverType> -->
            </ldapSourceService>
            <ldapDestinationService>
                <name>group-dst-service</name>
                <connection reference="ldap-dst-conn" />
                <baseDn>ou=Groups,dc=your_ad_domain,dc=local</baseDn>
                <pivotAttributes>
                    <string>cn</string>
                </pivotAttributes>
                <fetchedAttributes>
                    <string>cn</string>
                    <string>description</string>
                    <string>uniqueMember</string>
                    <string>objectClass</string>
                    <!-- <string>gidNumber</string> -->
                </fetchedAttributes>
                <getAllFilter><![CDATA[(objectClass=groupOfUniqueNames)]]></getAllFilter>
                <getOneFilter><![CDATA[(&(objectClass=groupOfUniqueNames)(cn={cn}))]]></getOneFilter>
            </ldapDestinationService>
            <propertiesBasedSyncOptions>
                <mainIdentifier>js:"cn=" + srcBean.getDatasetFirstValueById("cn") + ",OU=Groups,dc=your_ad_domain,dc=local"</mainIdentifier>
                <defaultDelimiter>;</defaultDelimiter>
                <defaultPolicy>FORCE</defaultPolicy>
                <conditions>
                    <create>true</create>
                    <update>true</update>
                    <delete>true</delete>
                    <changeId>true</changeId>
                </conditions>
                <dataset>
                    <name>uniqueMember</name>
                    <policy>FORCE</policy>
                    <forceValues>
                        <string>
                            <![CDATA[rjs:
                                    var membersSrcDn = srcBean.getDatasetValuesById("member");
                                    var membersDstDn = new java.util.ArrayList();;
                                    for  (var i=0; i < membersSrcDn.size(); i++) {
                                            var memberSrcDn = membersSrcDn.get(i);
                                            var sAMAccountName = "";
                                            try {
                                                    sAMAccountName = srcLdap.attribute(memberSrcDn, "samAccountName").get(0);
                                            } catch(e) {
                                                    continue;
                                            }
                                            var destDn = ldap.search("ou=Users", "(uid=" + sAMAccountName + ")");
                                            if (destDn.size() == 0 || destDn.size() > 1) {
                                                    continue;
                                            }
                                            var destMemberDn = destDn.get(0) + "," +  ldap.getContextDn();
                                            membersDstDn.add(destMemberDn);
                                    }
                                    if (membersDstDn.size() == 0) {
                                        membersDstDn.add("uid=empty_member,dc=your_ad_domain,dc=local");
                                    }
                                    membersDstDn
                            ]]>
                        </string>
                    </forceValues>
                </dataset>
                <dataset>
                    <name>objectClass</name>
                    <policy>FORCE</policy>
                    <forceValues>
                        <string>"groupOfUniqueNames"</string>
                        <string>"top"</string>
                    </forceValues>
                    <delimiter>$</delimiter>
                </dataset>
            </propertiesBasedSyncOptions>
        </task>
    </tasks>
</lsc>

로그백 설정:

cp /etc/lsc/logback.xml /etc/lsc/ad2openldap/

 

테스트:

/usr/bin/lsc -f /etc/lsc/ad2openldap -s all -c all -n

(실제 실행은 -n 옵션 제거)

 

크론탭 설정 (매 6시간마다)

crontab -e

0 */6 * * * /usr/bin/lsc -f /etc/lsc/ad2openldap -s all 

 

전체 Flow

 

참고)

https://lsc-project.org/doku.php

https://camratus.com/blog/OpenLdap_%E2%80%93_LSC_%E2%80%93_Active_Directory_sync_and_login_pass-through-12

반응형
Comments