패키지 설치
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