LDAPディレクトリを投入しフィルタで照会する
한국어 원문으로 표시합니다.
목표
slapd 를 직접 기동하고 조직 LDIF 를 적재한 뒤, LDAP 검색 필터를 조합해 원하는 사용자·그룹을 정확히 뽑아낼 수 있게 됩니다.
왜 중요한가
SI 프로젝트에서 "우리 시스템에 사내 계정 붙여 주세요"는 결국 LDAP 조회로 끝납니다.
그런데 필터를 대충 쓰면 비활성 계정과 서비스 계정까지 사용자 목록에 들어오고,
반환 속성을 지정하지 않으면 10만 명 디렉터리에서 전 속성을 끌어와 서버를 괴롭힙니다.
또 이 실습의 디렉터리는 그룹이 사람을 가리키는(member) 구조인데,
로그인마다 '이 사람의 그룹'을 구하려고 전체 그룹을 스캔하는 코드가
실제로 만들어집니다. 사용자 100명일 땐 모르다가 1만 명이 되면 로그인이 3초가 됩니다.
단계
- slapd 를 1389 포트로 기동합니다.
slapd -h ldap://127.0.0.1:1389 -F /opt/lab/ldap/slapd.d그리고 Root DSE 를 조회해/root/ldap/root-dse.txt에 저장합니다. 파일에dc=labhub,dc=co,dc=kr이 들어 있어야 합니다. /opt/lab/fixtures/auth/ldif/00-base.ldif를 적재합니다. Base DNdc=labhub,dc=co,dc=kr조회가 성공해야 합니다./opt/lab/fixtures/auth/ldif/10-people.ldif를 적재합니다.objectClass=inetOrgPerson엔트리가 30개 있어야 합니다./opt/lab/fixtures/auth/ldif/20-groups.ldif를 적재합니다.objectClass=groupOfNames엔트리가 6개 있어야 합니다.- 개발팀 소속이면서 직급이 과장인 사람의
uid만 골라 한 줄에 하나씩 오름차순으로/root/ldap/q1.txt에 저장합니다. (부서 속성은ou, 직급 속성은title입니다.) - 직급이 부장 또는 차장이면서 총무팀이 아닌 사람의
uid를 같은 형식으로/root/ldap/q2.txt에 저장합니다. uid=hong이 속한 그룹의 cn 을 한 줄에 하나씩 오름차순으로/root/ldap/groups-of-hong.txt에 저장합니다./root/ldap/whois.sh를 만듭니다. 인자 하나(uid)를 받아 아래 네 줄을 정확히 이 순서로 출력합니다. 없는 uid 면 0 이 아닌 종료코드로 끝냅니다.cn=<이름> ou=<부서> title=<직급> groups=<소속 그룹 수>
참고
- 기본 조회:
ldapsearch -x -H ldap://127.0.0.1:1389 -b "dc=labhub,dc=co,dc=kr" -LLL "(필터)" 속성명 - 적재:
ldapadd -x -H ldap://127.0.0.1:1389 -D "cn=admin,dc=labhub,dc=co,dc=kr" -w labhub123 -f 파일.ldif - 건수 세기: 결과에서
dn:으로 시작하는 줄을 세면 됩니다. - 흔한 실수 1: 필터 괄호 짝이 안 맞는 것.
(&(a=1)(b=2))처럼 전체를 한 번 더 감싸야 합니다. - 흔한 실수 2: 반환 속성을 지정하지 않아 전 속성이 쏟아지는 것.
- 흔한 실수 3:
-b를 빼먹는 것. Base 없이는 어디서부터 찾을지 서버가 모릅니다.
slapd 기동과 Root DSE 확인
slapd 를 1389 포트로 기동합니다.
slapd -h ldap://127.0.0.1:1389 -F /opt/lab/ldap/slapd.d
그리고 Root DSE 를 조회해 /root/ldap/root-dse.txt 에 저장합니다.
파일에 dc=labhub,dc=co,dc=kr 이 들어 있어야 합니다.
이 환경은 1024 미만 포트에 바인딩할 수 없습니다. Root DSE 는 base 를 빈 문자열로, scope 를 base 로 주면 조회됩니다. 서버가 어떤 네이밍 컨텍스트를 갖고 있는지 알려 줍니다.
베이스 엔트리 적재
/opt/lab/fixtures/auth/ldif/00-base.ldif 를 적재합니다.
Base DN dc=labhub,dc=co,dc=kr 조회가 성공해야 합니다.
LDIF 는 위에서 아래로 적용되므로 부모 엔트리가 먼저 있어야 자식을 넣을 수 있습니다. ldapadd 에 -f 로 파일을 줍니다.
사용자 엔트리 적재
/opt/lab/fixtures/auth/ldif/10-people.ldif 를 적재합니다.
objectClass=inetOrgPerson 엔트리가 30개 있어야 합니다.
적재 후 건수를 세는 습관을 들이세요. LDIF 를 넣었다고 다 들어간 것이 아닙니다. 중복 DN 이 있으면 그 항목만 실패합니다.
그룹 엔트리 적재
/opt/lab/fixtures/auth/ldif/20-groups.ldif 를 적재합니다.
objectClass=groupOfNames 엔트리가 6개 있어야 합니다.
groupOfNames 는 member 속성이 최소 하나 필요합니다. 빈 그룹을 만들려다 스키마 위반을 만나는 것이 첫 관문입니다.
복합 조건 필터
개발팀 소속이면서 직급이 과장인 사람의 uid 만 골라
한 줄에 하나씩 오름차순으로 /root/ldap/q1.txt 에 저장합니다.
(부서 속성은 ou, 직급 속성은 title 입니다.)
LDAP 필터는 연산자가 앞에 오는 전위 표기입니다. AND 는 (&(...)(...)) 형태이고 괄호 짝이 맞아야 합니다.
OR 와 NOT 조합
직급이 부장 또는 차장이면서 총무팀이 아닌 사람의 uid 를
같은 형식으로 /root/ldap/q2.txt 에 저장합니다.
OR 안에 여러 조건을 넣고, 전체를 AND 로 묶은 뒤 NOT 으로 하나를 제외합니다. 괄호를 종이에 그려 보면 실수가 줄어듭니다.
그룹 멤버십 역조회
uid=hong 이 속한 그룹의 cn 을 한 줄에 하나씩 오름차순으로
/root/ldap/groups-of-hong.txt 에 저장합니다.
이 디렉터리는 사람이 그룹을 가리키지 않고 그룹이 사람을 가리킵니다. 그래서 '이 사람이 속한 그룹'은 그룹 쪽에서 찾아야 합니다.
사용자 조회 스크립트
/root/ldap/whois.sh 를 만듭니다. 인자 하나(uid)를 받아 아래 네 줄을
정확히 이 순서로 출력합니다. 없는 uid 면 0 이 아닌 종료코드로 끝냅니다.
cn=<이름>
ou=<부서>
title=<직급>
groups=<소속 그룹 수>
인자로 받은 uid 하나에 대해 필요한 정보를 모아 출력합니다. ldapsearch 출력에서 값만 뽑을 때는 -LLL 옵션이 도움이 됩니다.