패키지 설치
root:# apt install slapd ldap-utils root:# vi /etc/hosts
/etc/hosts 파일을 열어서 OpenLDAP이 resolving할 호스트명을 적어준다
127.0.0.1 localhost ldap ldap.abc.com
/etc/ldap/ldap.conf 를 열고 BASE DN과 URI를 적어준다.
BASE dc=abc,dc=com URI ldap://ldap.abc.com:389/
패키지를 재설정
root:# dpkg-reconfigure slapd
선택사항
omit OpenLDAP server configuration: No DNS domain name: abc.com Organization name: dc=abc,dc=com Database backend to use: MDB Do you want the database to be removed when slapd is purged? No Move old database? Yes Allow LDAPv2 protocol? No
제대로 됐는지 확인
root# ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn
출력
dn: cn=config dn: cn=module{0},cn=config dn: cn=schema,cn=config dn: cn={0}core,cn=schema,cn=config dn: cn={1}cosine,cn=schema,cn=config dn: cn={2}nis,cn=schema,cn=config dn: cn={3}inetorgperson,cn=schema,cn=config dn: olcBackend={0}mdb,cn=config dn: olcDatabase={-1}frontend,cn=config dn: olcDatabase={0}config,cn=config dn: olcDatabase={1}mdb,cn=config
root# ldapsearch -x -LLL -H ldap:/// -b dc=abc,dc=com dn
출력
dn: dc=abc,dc=com dn: cn=admin,dc=abc,dc=com
TLS / LDAPS 설정
root:# apt install apparmor-utils sasl2-bin gnutls-bin ssl-cert root:# cd certs root:# chown root:ssl-cert * root:# cp -a abc.com_ca.pem abc.com.crt /etc/ssl/certs/ root:# cp -a abc.com.key /etc/ssl/private/ root:# adduser openldap ssl-cert root:# adduser openldap sasl root:# usermod -a -G ssl-cert openldap root:# aa-complain /usr/sbin/slapd
/etc/ldap/ldap.conf 파일을 열고 TLS 항목을 추가한다.
TLS_REQCERT demand
만약 사용자의 패스워드 인증을 상위 기관 등에서 할 경우 SASL을 설정해준다.
/etc/saslauthd.conf 파일을 생성하고 필요한 항목을 넣는다.
ldap_servers: ldaps://ldap.abc.com ldap_version: 3 ldap_start_tls: no ldap_search_base: ou=people,dc=abc,dc=com ldap_filter: (uid=%u) ldap_bind_dn: cn=cn_name,ou=your_department,dc=abc,dc=com ldap_bind_pw: PASSWORD ldap_verbose: on
/etc/ldap/sasl2/slapd.conf 파일을 열고 패스워드 인증 매커니즘을 LDAP으로 바꿔준다.
START=yes
MECHANISMS="ldap"
/etc/default/slapd 파일을 열고 slapd.conf 파일 정의 및 서비스 프로토콜을 지정한다.
SLAPD_CONF=/etc/ldap/slapd.conf SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///"
재구축인 경우 기존의 mdb 파일과 스키마를 가져온다.
root:# mkdir -p /var/lib/ldap/abc root:# cp *.mdb /var/lib/ldap/abc/ root:# chown openldap: -R /var/lib/ldap/abc root:# cp -i *.schema /etc/ldap/schema/
/etc/ldap/slapd.conf 파일을 아래와 같이 생성한다.
include "/etc/ldap/schema/core.schema" include "/etc/ldap/schema/cosine.schema" include "/etc/ldap/schema/inetorgperson.schema" include "/etc/ldap/schema/nis.schema" include "/etc/ldap/schema/pykota.schema" include "/etc/ldap/schema/autofs.schema" include "/etc/ldap/schema/ppolicy.schema" include "/etc/ldap/schema/ldapns.schema" include "/etc/ldap/schema/dyngroup.schema" include "/etc/ldap/schema/eduperson2.schema" include "/etc/ldap/schema/dhcp2.schema" include "/etc/ldap/schema/abc.schema" include "/etc/ldap/schema/publications.schema" include "/etc/ldap/schema/sudo.schema" include "/etc/ldap/schema/quota.schema" include "/etc/ldap/schema/puppet.schema" include "/etc/ldap/schema/encryptionObject.schema" include "/etc/ldap/schema/dlz.schema" TLSCACertificateFile "/etc/ssl/certs/abc.com_ca.pem" TLSCertificateFile "/etc/ssl/certs/abc.com.crt" TLSCertificateKeyFile "/etc/ssl/private/abc.com.key" pidfile "/var/run/slapd/slapd.pid" argsfile "/var/run/slapd/slapd.args" modulepath "/usr/lib/ldap" moduleload back_mdb.la moduleload memberof.la moduleload syncprov.la moduleload accesslog.la moduleload ppolicy.la moduleload refint.la moduleload dynlist.la moduleload back_monitor.la loglevel stats sync sizelimit -1 serverID 2 sortvals member pubContributor documentAuthor access to * by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage by * break access to dn.base="" by * read access to dn.base="cn=subschema" by * read database config rootdn "cn=admin,dc=abc,dc=com" database mdb suffix "dc=abc,dc=com" rootdn "cn=admin,dc=abc,dc=com" limits dn.exact=cn=syncuser,dc=abc,dc=com size=unlimited index default eq index objectClass index cn eq,pres,sub index uidNumber index gidNumber index loginShell index uid eq,pres,sub index memberUid eq,pres,sub index uniqueMember eq,pres index member eq,pres index entryCSN index entryUUID index sudoUser eq,sub index departmentNumber index abcChairDept index documentAuthor index pubOwner index memberOf index dhcpHWAddress index givenName index sn directory "/var/lib/ldap/abc" maxsize 34359738368 access to * by dn="cn=syncuser,dc=abc,dc=com" read by * break access to attrs=userPassword by anonymous auth by self none by dn="cn=manager,dc=abc,dc=com" write stop by * none access to attrs=shadowLastChange by self write by * none access to dn.one="ou=people,dc=abc,dc=com" filter=(objectClass=abcPerson) attrs=jpegPhoto,loginShell by dn="cn=web,dc=abc,dc=com" write stop by * break access to dn.one="ou=people,dc=abc,dc=com" filter=(objectClass=abcPerson) attrs=@abcPerson,roomNumber,telephoneNumber,physicalDeliveryOfficeName,facsimileTelephoneNumber,displayName by self write stop by dnattr=owner write by set="this/memberOf/owner & user" write by dn="cn=manager,dc=abc,dc=com" write by dn="cn=cloud,dc=abc,dc=com" read stop by users read access to dn.sub="ou=people,dc=abc,dc=com" by self write stop by dn="cn=manager,dc=abc,dc=com" write stop by dn="cn=cloud,dc=abc,dc=com" read stop by dn="cn=stack,dc=abc,dc=com" read stop by * read access to dn.sub="ou=named,dc=abc,dc=com" by dn="cn=manager,dc=abc,dc=com" write stop by dn="cn=bind,dc=abc,dc=com" read stop by * none access to dn.sub="ou=roles,dc=abc,dc=com" by dn="cn=manager,dc=abc,dc=com" write stop by dn="cn=cloud,dc=abc,dc=com" manage stop by dn="cn=stack,dc=abc,dc=com" break by * read access to dn.sub="ou=openstack,ou=roles,dc=abc,dc=com" by dn="cn=stack,dc=abc,dc=com" write stop by * none access to dn.sub="ou=openstack-groups,ou=accessGroups,dc=abc,dc=com" by dn="cn=stack,dc=abc,dc=com" manage stop by * none access to dn="cn=openstack,ou=accessGroups,dc=abc,dc=com" by dn="cn=stack,dc=abc,dc=com" write stop by * none access to dn="cn=enabled-projects,ou=tenants,dc=abc,dc=com" by dn="cn=stack,dc=abc,dc=com" write stop by * none access to dn.sub="ou=tenants,dc=abc,dc=com" by dn="cn=stack,dc=abc,dc=com" manage stop by * none access to dn.sub="cn=heimdall.abc.com,dc=abc,dc=com" by dn="cn=dhcp-user,dc=abc,dc=com" read by * none access to dn.sub="ou=pending,dc=abc,dc=com" by dn="cn=register,dc=abc,dc=com" write stop by dn="cn=manager,dc=abc,dc=com" write stop by * break access to dn.sub="ou=groups,dc=abc,dc=com" attrs=memberUid by dn="cn=register,dc=abc,dc=com" write stop by dn="cn=manager,dc=abc,dc=com" write stop by dn="cn=web,dc=abc,dc=com" read break by * break access to dn.regex="cn=.+-editor,ou=groups,dc=abc,dc=com" attrs=memberUid by dn="cn=web,dc=abc,dc=com" write stop by * break access to dn.sub="ou=departments,dc=abc,dc=com" by dn="cn=register,dc=abc,dc=com" read stop by dn="cn=manager,dc=abc,dc=com" write stop by * break access to dn.sub="ou=inactive,dc=abc,dc=com" by dn="cn=directory,dc=abc,dc=com" none by dn="cn=register,dc=abc,dc=com" read stop by dn="cn=manager,dc=abc,dc=com" write stop by * break access to dn.sub="ou=people,dc=abc,dc=com" attrs=userPassword,gidNumber,uidNumber,homeDirectory,employeeNumber,loginShell,objectClass by dn="cn=directory,dc=abc,dc=com" none stop by * break access to dn.sub="ou=people,dc=abc,dc=com" by dn="cn=manager,dc=abc,dc=com" write stop by dn="cn=cloud,dc=abc,dc=com" read stop by * break access to dn.sub="ou=accessGroups,dc=abc,dc=com" by dn="cn=manager,dc=abc,dc=com" write stop by * read access to dn.sub="ou=groups,dc=abc,dc=com" by dn="cn=cloud,dc=abc,dc=com" read stop by * break access to dn.sub="ou=publications,dc=abc,dc=com" by dn.sub="ou=people,dc=abc,dc=com" write stop by dn="cn=abcPubEditor,ou=roles,dc=abc,dc=com" write stop by dn="cn=manager,dc=abc,dc=com" write stop by * read break access to dn.sub="ou=groups,dc=abc,dc=com" attrs=gidNumber by dn="cn=directory,dc=abc,dc=com" none break by dn="cn=register,dc=abc,dc=com" read stop by * break access to dn.one="" filter=(objectClass=dcObject) by * read access to * by users read by * none # This server will retrieve data from these servers below. syncrepl rid=0 provider=ldap://ldap2.abc.com searchbase=dc=abc,dc=com type=refreshAndPersist retry="30 +" bindmethod=simple binddn=cn=syncuser,dc=abc,dc=com credentials=PASSWORD tls_cacert=/etc/ssl/certs/abc.com_ca.pem tls_reqcert=demand starttls=critical syncdata=default overlay ppolicy ppolicy_default "cn=default,ou=ppolicy,dc=abc,dc=com" overlay refint refint_attributes memberOf member manager owner seeAlso roleOccupant pubOwner documentAuthor overlay memberof overlay dynlist dynlist-attrset groupOfURLs memberURL overlay syncprov syncprov-checkpoint 1000 60 mirrormode on database monitor access to * by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read by dn.exact="cn=admin,dc=abc,dc=com" read by dn.exact="cn=monitoring,dc=abc,dc=com" read by * none
saslauthd와 slapd를 재시작해준다. 보통 데비안/우분투 계열에서는 systemctl restart/stop 혹은 service restart/stop 명령어로는 프로세스가 죽지않는 증상이 있으므로, 이 경우 직접 PID를 찾아서 kill을 해줘야한다.
root:# systemctl restart saslauthd root:# systemctl restart slapd
트러블 슈팅
ldapwhoami 명령어가 Can’t contact LDAP server (-1)라는 에러를 낼 경우
conn=1000 op=0 BIND dn="uid=seowon,ou=people,dc=abc,dc=com" method=128 audit: type=1400 audit(1507160608.094:34): apparmor="ALLOWED" operation="connect" profile="/usr/sbin/slapd" name="/run/saslauthd/mux" pid=10291 comm="slapd" requested_mask="wr" denied_mask="wr" fsuid=111 ouid=0 audit: type=1400 audit(1507160608.094:35): apparmor="ALLOWED" operation="file_perm" profile="/usr/sbin/slapd" name="/run/saslauthd/mux" pid=10291 comm="slapd" requested_mask="w" denied_mask="w" fsuid=111 ouid=0
aa-complain으로 slapd를 apparmor의 예외항목에 넣어서 재시작해보고, 그래도 안될 경우 MDB 파일을 삭제하고 기존의 LDIF 파일을 통째로 넣는다.
root:# systemctl stop slapd root:# aa-complain /usr/sbin/slapd root:# systemctl restart apparmor root:# systemctl start slapd
root:# systemctl stop slapd root:# slapadd -v -c -l ~/abc.com.ldif -f /etc/ldap/slapd.conf root:# systemctl start slapd
그래도 해결되지 않으면 증상을 확인하기 위해 /etc/ldap/ldap.conf 파일을 열고 TLS를 꺼본다.
TLS_REQCERT never
daemon: bind(13) failed errno=2 (No such file or directory) 라는 에러가 나올시
root:# mkdir /var/run/slapd root:# chown openldap: -R /var/run/slapd
saslauthd가 상위 LDAP 서버로 접근을 못할 경우
root:# systemctl stop saslauthd root:# systemctl stop slapd root:# systemctl stop apparmor root:# ps ax |grep slapd root:# kill -9 PID root:# /etc/apparmor.d/usr.sbin.slapd root:# Add: /{,var/}run/saslauthd/mux rw, root:# aa-complain /usr/sbin/slapd root:# systemctl start apparmor root:# systemctl start slapd root:# systemctl start saslauthd
LDAP 백업용 Perl 스크립트 패키지 설치
root:# apt install build-essential libssl-dev libcrypto++-dev zlib1g-dev root:# cpan install Net::SSLeay install IO:Socket::SSL install Net::LDAP install Net::LDAP::Entry install Net::LDAP::LDIF
LDAP 사용자 정보 수정하기
root:# cp /var/tmp/backup/abc.com.ldif.gpg /tmp/ root:# gpg --output abc.com.ldif --decrypt abc.com.ldif.gpg Password:
수정을 위한 LDIF 파일 생성
dn: cn=staff-tech,ou=groups,dc=abc,dc=com changetype: modify delete: memberUid add: memberUid memberUid: ziliox memberUid: kori memberUid: giscom memberUid: myab memberUid: alevine memberUid: tanare memberUid: anguyen memberUid: sambo
실행
root:# ldapmodify -Y EXTERNAL -H 'ldapi:///' -f mod-group.ldif -vn root:# ldapsearch -Y EXTERNAL -H ldapi:/// -b 'cn=staff-tech,ou=groups,dc=abc,dc=com' -s 'base' memberUid root:# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'cn=staff-tech,ou=groups,dc=abc,dc=com' -s 'base' memberUid root:# ldapmodify -x -D 'cn=admin,dc=abc,dc=com' -W -H 'ldap://ldap.abc.com:389' -ZZ -f mod-group.ldif -v
memberOf 생성하기
기존 서버 쪽에서 memberOf 데이터를 뽑아온다.
$ ldapsearch -x -D 'cn=register,dc=abc,dc=com' -H 'ldap://ldap.abc.com:389' -ZZ -W -b 'ou=people,dc=abc,dc=com' '(uid=*)' memberOf > memberOf.ldif
신규 서버 쪽
기존 서버에서 뽑아낸 memberOf.ldif 파일을 열고 각각의 dn마다 아래의 라인을 삽입한다.
changetype: modify add: memberOf
그리고나서 ldapmodify로 적용해준다.
$ ldapmodify -x -D "cn=admin,dc=abc,dc=com" -W -H ldap://ldap.abc.com -f memberOf.ldif
유용한 명령어
eduPerson이라는 objectClass가 없는 사용자를 검색 ldapsearch -x -D 'cn=search,dc=abc,dc=com' -H 'ldaps://ldap.abc.com:636' -W -b 'ou=people,dc=abc,dc=com' '(!(objectClass=eduPerson))' cn 사용자 확인 $ ldapwhoami -xWZ -D 'uid=seowon,ou=people,dc=abc,dc=com' -H 'ldap://ldap.abc.com:389/' 그룹멤버 목록 나열 $ ldapsearch -x -D 'cn=register,dc=abc,dc=com' -H 'ldap://ldap.abc.com:389' -ZZ -W -b 'ou=people,dc=abc,dc=com' '(uid=seowon)' | less $ ldapsearch -xZZ -D 'cn=register,dc=abc,dc=com' -W -H 'ldap://ldap.abc.com:389' -b 'ou=departments,dc=abc,dc=com' -s 'one' '(cn=facstaff-tdp)' member 기존 LDAP 서버 덤프 뜨기 $ ldapsearch -xW -D "cn=admin,dc=abc,dc=com" -b "dc=abc,dc=com" -H ldap://ldap.abc.com -LLL > ~/ldap_dump-09072020-1035pm.ldif
Leave a Reply