LDAP을 이용한 계정통합, 각종 애플리케이션 연동 (2007)

LDAP 개략

  • LDAP 용도는 무엇인가 : 읽기에 최적화되어있습니다. 디렉토리구조에 유용합니다. (인터넷회사에서 DHCP 로 ip할당하는 정보저장, 인증서 정보저장 등에 사용되고 있습니다)
  • LDAP을 가지고 활용할 수 있는 것은?
  • 사용자정보통합 : os계정, 이메일계정, ftp, http, outlook의 주소록등 통합가능. OS계정의 경우 호스트와 사용자 조합으로 접속제한을 할 수 있음.
  • 참고로 윈도우즈의 Active Directory는 LDAP과 커버러스를 이용함. LDAP은 계정통합, 각종 정보통합에 사용을 하고 커버러스는 싱글사인온(SSO)에 사용을 함. 커버러스를 이용하여 네트워크를 통해 패스워스를 보내지 않고 키서버를 통하여 통신을 하고 티켓을 발급한 일정한 시간동안은 필요한 자원에 대한 별도 로그인이 필요없음.

문서소개

  • 본 내용은 Redhat Enterprise Linux 3, CentOS4.4 에서 테스팅을 한 내용이며 다른 리눅스 배포판에서도 비슷하게 적용이 가능합니다. PAM 설정등은 시스템에 따라 다를 수 있습니다.
  • LDAP 에 대한 소개가 아니므로 이에 대한 설명은 다른 문서를 참고하시기 바랍니다.
  • openldap을 이용하여 계정통합을 하는 부분에 대한 자료는 여러가지가 있는데 이 문서는 거기에 추가로 필요한 상세한 내용을 담았습니다.
  • LDAP을 이용한 사용자 인증 통합 (id, group, hosts)
  • 사용자별, 호스트별 사용자 접속 제한
  • 아이디, 그룹관리 프로그램(cpu)
  • ldap replication (1 master, 1 slave)
  • TLS 사용한 암호화통신
  • nfs, autofs 이용한 사용자 홈디렉토리 공유
  • outlook 등 주소록 활용
  • 아파치 인증 활용
  • 로그확인(syslog)
  • gui 관리 프로그램
  • NIS 기능으로 호스트 접근제한 추가

문서변경사항

  • 2006.4.13 autofs 부분 스키마 추가부분
  • 2006.4.12 autofs 부분 오타 수정. ACL 주의사항 추가
  • 2006.3.30 SSL 관련부분 전체 정리 추가
  • 2006.3.27 authconfig 프로그램 내용 보강
  • 2007.3.26 아파치 웹인증부분 자료추가
  • 2007.3.22 ssl/tls 연동시 클라이언트 설정 주의사항 추가 (CA인증서 복사)
  • 2007.5.25 ldapseach 예제 추가

관련자료

LDAP 초보자를 위한 기초자료

  • LDAP에 대한 한글자료는 DSN의 자료 1개와 KLDP의 LDAP 하우투 및 기타 몇개의 문서가 있습니다. 상세한 내용은 영문자료를 보아야 합니다.
  • http://database.sarang.net/?inc=read&aid=1243&criteria=ldap&subcrit=tutorials&id=&limit=20&keyword=&page=1 : LDAP의 모든것 ver 20011126. DSN에 2001년 올라왔던 ldap 전반적인 자료. 국내에 ldap 에 대한 한글자료가 별로 없는데 그나마 상세하게 ldap 에 대한 설명이 들은 한글문서입니다. 전체적으로는 LDAP기초부터 기본적인 사용법을 담고 있어 처음에 참고를 할 만 합니다.
  • 위의 한글자료를 기초로 하여 약간 개정한 문서를 만들었습니다. 같은 URL을 참고하시면 됩니다. LDAP의 모든것2
  • http://wiki.kldp.org/wiki.php/LinuxdocSgml/LDAP-HOWTO : KLDP LDAP 하우투자료
  • O'REILLY 의 LDAP System Administration 서적 : LDAP 전반적인 설명을 담고 있으며 각종 애플리케이션을 ldap으로 통합하는 경우에 대한 상세한 자료를 제공하고 있음
  • http://www.openldap.org/doc/admin23/ openldap 문서 : openldap에 대한 기본 사용법은 openldap 에서 제공하는 문서를 참고

LDAP을 이용한 계정통합

기타 참고자료

  • http://www.redhat.com/docs/manuals/dir-server/ 레드햇의 LDAP 문서. Administrator's Guide 등은 참고로 보면 좋을듯하며 Deployment Guide 는 ldap 설계에 대한 상세한 내용을 담고 있습니다.
  • http://www.redhat.com/docs/manuals/dir-server/deploy/7.1/deployTOC.html Deployment Guide Red Hat Directory Server . 데이타 디자인, 스키마 디자인, 디렉토리 트리 디자인, 토폴리지 디자인, 리플리케이션 디자인, 보안 디자인, 튜닝 및 최적화, 운영관련 결정사항
  • http://directory.fedora.redhat.com/ 페도리 디렉토리 서버. 레드햇에서 넷스케이프 디렉토리를 인수하여 제품화한 것이 레드햇 디렉토리 서버이며 이에 대한 공개버전이 페도리 디렉토리 서버입니다.

사전 확인사항

정책결정

LDAP 설계하기 : 데이타 디자인, 스키마 디자인, 디렉토리 트리 디자인, 토폴리지 디자인, 리플리케이션 디자인, 보안 디자인, 튜닝 및 최적화, 운영관련 결정사항
dc(suffix) 정하기 : 사용할 도메인
rootdn 의 패스워드 결정
계정정책 : UID, GID 범위

설치프로그램

RPM을 이용하여 설치
openldap-devel : openldap 과 연관된 프로그램을 개발할때 필요함. cpu 프로그램을 사용해야 할 경우 필요함
openldap : OpenLDAP 서버와 클라이언트 프로그램을 실행하기 위한 라이브러리
openldap-clients : client 프로그램
openldap-servers : server 프로그램
nss_ldap : NSS library and PAM module for LDAP

ldap 서버설정

/etc/openldap/slapd.conf 에서 rootpw 를 추가함. 이를 통하여 root 권한 인증 사용함
아래 패스워드는 slappasswd 를 이용하여 생성함

[migration:root@localhost openldap]# grep -v "^#" slapd.conf
include         /etc/openldap/schema/core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/nis.schema
allow bind_v2

pidfile         /var/run/slapd.pid
argsfile        /var/run/slapd.args
loglevel        256

TLSCipherSuite HIGH:MEDIUM:+SSLv2
TLSCACertificateFile /etc/openldap/cacerts/cacert.pem
TLSCertificateFile /etc/openldap/slapdcert.pem
TLSCertificateKeyFile /etc/openldap/slapdkey.pem

database        bdb
suffix          "dc=example,dc=com"
rootdn          "cn=manager,dc=example,dc=com"
rootpw                {SSHA}aaaaaamoxk2Sswm8NbHZbCx9LxextJ

directory       /var/lib/ldap

index objectClass                       eq,pres
index ou,cn,mail,surname,givenname      eq,pres,sub
index uidNumber,gidNumber,loginShell    eq,pres
index uid,memberUid                     eq,pres,sub
index nisMapName,nisMapEntry            eq,pres,sub

cachesize       2000

access to dn.subtree="dc=example,dc=com" attr=userPassword
        by self write
        by* auth
access to dn.subtree="ou=people,dc=example,dc=com"
        by* read
access to dn.subtree="ou=group,dc=example,dc=com"
        by* read
access to dn.subtree="ou=hosts,dc=example,dc=com"
        by* read
access to*
        by* auth

replogfile /var/lib/ldap/openldap-master-replog
replica uri=ldap://cent.tunelinux.pe.kr:389
        suffix="dc=example,dc=com"
        binddn="cn=replica,dc=example,dc=com"
        credentials=xxxxxx
        bindmethod=simple
        tls=yes

위에서 suffix 를 조정하고 rootdn도 이와 맞추며 rootpw 를 설정하면 됨

# /etc/init.d/ldap start
Starting slapd:                                            [migration:  OK  ]

위에서 초기 세팅시 TLS 부분은 빼도 된다. ACI 는 사용자비밀번호는 자신만 바꿀수 있도록 하였고 people, group, hosts 정보는 누구나 읽을 수 있도록 하였다.
replication 부분도 초기 세팅시 빼도 된다.

(green star) database backend 모듈은 ldbm, bdb 등이 있다. bdb는 openldap 2.1부터 도입이 되었으며 Berkeley DB4 라이브러리만 사용하도록 맞추어져있다. bdb 가 ldbm에 비해 낫고 하는데 어떤 점이 나은지까지는 확인하지 않았다.

기본 정보 입력

directory structure 생성

아래 내용을 top.ldif 로 저장

dn: dc=example,dc=com
objectclass: dcObject
objectclass: organization
o: example Company
dc:example

dn: cn=manager, dc=example, dc=com
objectclass: organizationalRole
cn: manager

dn: ou=people,  dc=example, dc=com
ou: people
objectclass: organizationalUnit
objectclass: domainRelatedObject
associatedDomain: example.com

dn: ou=contacts,ou=people,  dc=example, dc=com
ou: contacts
ou: people
objectclass: organizationalUnit
objectclass: domainRelatedObject
associatedDomain: example.com

dn: ou=group,  dc=example, dc=com
ou: group
objectclass: organizationalUnit
objectclass: domainRelatedObject
associatedDomain: example.com

위에서 ou=contacts 는 아래에서 실제 사용하지는 않으며 이메일주소록을 ldap을 이용할 경우에 사용하면 된다.

# ldapadd -x -D 'cn=manager,dc=example,dc=com' -W -f top.ldif 
Enter LDAP Password: 
adding new entry "dc=example,dc=com"

adding new entry "cn=manager, dc=example, dc=com"

adding new entry "ou=people,  dc=example, dc=com"

adding new entry "ou=contacts,ou=people,  dc=example, dc=com"

adding new entry "ou=group,  dc=example, dc=com"

ldap 프로그램에서의 옵션참고

    • -w password 로 해도 됨. -W 는 명령행에서 입력
      -x : simple authentication. 기본인증방식임
      -D : binddn 지정
      -f file : 파일에서 입력을 받을 경우 사용
      -W : prompt for simple authentication . 기본인증에서 비밀번호를 별도 입력으로 받을 경우 사용
      -w : 비밀번호를 명령행에서 바로 옵션으로 줌
      -b : searchbase 검색범위 지정

위에서 입력한 내용을 검색하기

# ldapsearch -x -b 'dc=example,dc=com'
version: 2

#
# filter: (objectclass=*)
# requesting: ALL
#

# example, com
dn: dc=example,dc=com
objectClass: dcObject
objectClass: organization
o: example Company
dc: example

중략...

# search result
search: 2
result: 0 Success

# numResponses: 6
# numEntries: 5

참고로 -D 옵션을 이용 binddn을 지정하여 인증을 받고 검색할 수도 있고 -h 옵션을 이용하여 다른 서버에서 검색할 수 있다.

ldapsearch -x -b 'dc=example,dc=com' -D cn=readonly,ou=admingroup,dc=example,dc=com -w xxxxxxxxxxxx  -h wiki.tunelinux.pe.kr

계정추가하기

ldap 으로 단일한 리눅스 로그인 만들기

먼저 계정정책을 결정한다. 아래에서는 다음과 같이 하였다고 가정한다.

System accounts : UID < 500
Real people in LDAP : 499 < UID < 10,000
Local users, groups (not in LDAP ) > 10,000

로컬 컴퓨터 사용자 엔트리 만들기

ldaptest 라는 계정을 만들며 uid 1000 gid 1000으로 하고 홈디렉토리는 /home/ldaptest 로 함

# cat people.ldif 
# ldaptest, people, example.com
dn: uid=ldaptest,ou=people,dc=example,dc=com
cn: ldaptest
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
objectClass: top
uidNumber: 1000
gidNumber: 1000
homeDirectory: /home/ldaptest
loginShell: /bin/bash
shadowLastChange: 11192
shadowMin: -1
shadowMax: 99999
shadowWarning: 7
shadowInactive: -1
shadowExpire: -1
shadowFlag: 134538308
uid: ldaptest
userPassword: {crypt}$1$OQAQLKrD$ktucNP.aAo/w5gbuAIV6H1

아래와 같이 추가하여줌

# ldapadd -x -D 'cn=manager,dc=example,dc=com' -W -f people.ldif 
Enter LDAP Password: 
adding new entry "uid=ldaptest,ou=people,dc=example,dc=com"

아래와 같이 검색함

# ldapsearch -x -b "dc=example,dc=com" "(objectclass=*)"

사용자 지우기

ldapdelete -x  -D 'cn=manager,dc=example,dc=com'  'uid=ldaptest,ou=people,dc=example,dc=com' -W

기존계정정보 이용하여 마이그레이션하기

/usr/share/openldap/migration/ 디렉토리에 기존의 정보를 마이그레이션하기 위한 프로그램이 있다.
사전에 migrate_common.ph 에서 몇가지 옵션을 수정함. migrate_common.ph 가 변경한 프로그램이고 migrate_common.ph.orig 가 원래의 설정이다.

# diff migrate_common.ph migrate_common.ph.orig
71c71
< $DEFAULT_MAIL_DOMAIN = "tunelinux.pe.kr";
---
> $DEFAULT_MAIL_DOMAIN = "padl.com";
74c74
< $DEFAULT_BASE = "dc=example,dc=com";
---
> $DEFAULT_BASE = "dc=padl,dc=com";
90c90
< $EXTENDED_SCHEMA = 1;
---
> $EXTENDED_SCHEMA = 0;

/usr/share/openldap/migration/migrate_passwd.pl /etc/passwd
/usr/share/openldap/migration/migrate_group.pl /etc/group

이 프로그램으로 passwd, gorup 뿐만 아니라 /etc/networks, /etc/protocols, /etc/services, /etc/netgroup 등도 가능하다. 나중에 /etc/hosts 를 LDAP으로 이전하는 곳에서 다시 설명을 한다.

그룹 엔트리 만들기

# cat group.ldif 
dn: cn=webdev,ou=group,dc=example,dc=com
objectClass: posixGroup
objectClass: top
cn: webdev
gidNumber: 2000
memberUid: ldaptest

# ldapadd  -x -D 'cn=manager,dc=example,dc=com' -W -f group.ldif 
Enter LDAP Password: 
adding new entry "cn=webdev,ou=group,dc=example,dc=com"

2000 gid 에 해당하는 webdev 그룹을 만들기 ldaptest 를 이 그룹에 넣어줌

아래와 같이 검색함

  1. ldapsearch -x -b 'dc=example,dc=com'

ldap client 설정

ldap client 설정하기

authconfig 이용하여 설정한다. 이 프로그램을 이용하면 /etc/ldap.conf , /etc/nsswitch.conf, /etc/sysconfig/authconfig, /etc/pam.d/system-auth 파일을 자동으로 바꾸어준다.

User Information Configuration 에서 Use LDAP 선택 -> Next -> Authentication Configuration 에서 Use LDAP Authentication 사용함. Server 및 Base DN에 적당하게 값을 넣음. 여기서는 dc=example,dc=com
start_tls 는 나중에 다시 설명한다.

# diff /etc/ldap.conf.orig /etc/ldap.conf
18c18
< base dc=example,dc=com
---
> base dc=example,dc=com


# diff /etc/openldap/ldap.conf.orig /etc/openldap/ldap.conf
16c16
< BASE dc=example,dc=com
---
> BASE dc=example,dc=com

# diff /etc/nsswitch.conf.orig /etc/nsswitch.conf
33,35c33,35
< passwd:     files
< shadow:     files
< group:      files
---
> passwd:     files ldap
> shadow:     files ldap
> group:      files ldap
53c53
< protocols:  files
---
> protocols:  files ldap
55c55
< services:   files
---
> services:   files ldap
57c57
< netgroup:   files
---
> netgroup:   files ldap
61c61
< automount:  files
---
> automount:  files ldap

/etc/ldap.conf는 ldap 클라이언트 설정에서 필요한데 몇가지 추가옵션이 있다. 기본설정은 base, hosts 만 바꾸면 작동하는데 아래는 몇가지를 추가하였다. start_tls 를 이용하여 tls 설정, pam_check_host_attr 를 이용하여 사용자별 서버접속제한, pam_filter , pam_login_attribute 를 이용하여 사용자검색시 사용할 objectclass와 login 애트리뷰트를 설정하였다. 또한 nss_base 를 이용하여 해당 정보에 대하여 빠르게 검색할 수 있도록 기본 필터를 설정하였다. 초기 테스팅을 할 경우에는 아래와 같이 옵션을 할 필요는 없다.

# grep -v "^#" /etc/ldap.conf
host cent3.tunelinux.pe.kr
base dc=example,dc=com
timelimit 120
bind_timelimit 120
idle_timelimit 3600

ssl start_tls
tls_checkpeer yes
tls_cacertfile /etc/openldap/cacerts/cacert.pem

pam_password md5

pam_check_host_attr yes

pam_filter objectclass=posixAccount
pam_login_attribute uid

nss_base_passwd         ou=people,dc=example,dc=com?one
nss_base_shadow         ou=people,dc=example,dc=com?one
nss_base_group          ou=group,dc=example,dc=com?one
nss_base_hosts          ou=hosts,dc=example,dc=com?one
nss_base_netgroup       ou=netgroup,dc=example,dc=com?one

authconfig 프로그램을 이용해 ldap과 연동을 하면 /etc/sysconfig/authconfig 에서 ldap 부분이 yes로 설정이 바뀐다. (USELDAP, USELDAPAUTH)

# grep yes /etc/sysconfig/authconfig
USECRACKLIB=yes
USELDAP=yes
USELDAPAUTH=yes
USEMD5=yes
USESHADOW=yes

참고로 ldap 서버를 replication 등을 이용하여 여러대를 사용하는 경우 host 에서 스페이스를 이용해 여러 서버를 지정하면 된다. authconfig에서는 중간에 , 를 이용하여 여러 서버를 지정한다.

# grep ^host /etc/ldap.conf
host cent3.tunelinux.pe.kr cent.tunelinux.pe.kr

위에서는 anonymous 로 ldap에 접속을 하는데 binddn 과 bindpw 을 이용하여 접근을 제한할 수 있다. 계정정보, 그룹정보를 익명사용자에게 허용할 필요가 없다면 binddn을 이용하여 접근할 사용자를 지정하는 것이 좋을 듯 하다. 이경우 여기서 지정한 binddn이 people 등 필요한 정보에 접근할 수 있도록 접근권한을 설정하고 anonymous 사용자 접속은 막아야 한다.

group 정보표시

/etc/ldap.conf에 host, base 정보만 넣은 경우 id 등에서 그룹정보가 보이지 않고 숫자로만 나온 경우가 있었다. 이경우 /etc/ldap.conf 에서 바로 위에서 보듯이 nss_base_group 을 설정해주면 되었다.

nss_base_group          ou=group,dc=example,dc=com?one

이러한 정보들은 getent 로 확인해보면 된다. getent passwd, getent group 등으로 확인해보면 된다.

# getent passwd
# getent group

사용자 홈디렉토리 처리

LDAP을 이용하여 사용자 인증을 하는 경우 사용자 LDIF 파일에서 홈디렉토리를 지정한다고 하더라도 실제 디렉토리가 생기지는 않는다. 이에 대한 처리방법은 두가지가 있다.

  • autofs 와 nfs를 이용하여 사용자가 로그인할때 nfs에서 자동으로 홈디렉토리 마운트하기 : 사용자 데이터도 동일하게 설정할 경우 편리함.
  • pam 의 기능을 이용하여 사용자 홈디렉토리가 없을 경우 자동으로 생성하기 : /etc/pam.d/system-auth 에 다음 모듈을 추가해주면 됨. umask 는 아래에서는 기본 700으로 생성하도록 설정했고 필요에 따라 변경하면 됨

     session     optional      /lib/security/$ISA/pam_mkhomedir.so skel=/etc/skel umask=0077
    

/etc/hosts 정보 LDAP에 넣기

/usr/share/openldap/migration/ 에 각종 마이그레이션 도구들이 있다.
migrate_base.pl 는 마이그레이션 가능한 각종 기본정보에 대해서 보여준다.
migrate_base.pl 를 이용하여 hosts 에 대한 기본정보를 뽑고 /etc/hosts 정보를 변환하여 ldap에 넣어준다. 세부설명은 생략하겠다.

# ./migrate_base.pl

dn: ou=Hosts,dc=example,dc=com
ou: Hosts
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: tunelinux.pe.kr

위에서 hosts에 해당하는 내용을 ldif 파일로 해서 입력해준다.

migrate_hosts.pl 는 /etc/hosts 정보를 ldif 파일로 바꾸어준다.

[migration:root@cent3 migration]# ./migrate_hosts.pl /etc/hosts > hosts.ldif
dn: cn=localhost.localdomain,ou=Hosts,dc=example,dc=com
objectClass: top
objectClass: ipHost
objectClass: device
ipHostNumber: 127.0.0.1
cn: localhost.localdomain
cn: localhost

dn: cn=cent3.tunelinux.pe.kr,ou=Hosts,dc=example,dc=com
objectClass: top
objectClass: ipHost
objectClass: device
ipHostNumber: 222.112.137.138
cn: cent3.tunelinux.pe.kr


# ldapadd -x -D 'cn=manager,dc=example,dc=com' -W -f hosts.ldif

그런후 /etc/nsswitch.conf 를 변경한다.

[migration:root@cent3 migration]# grep hosts /etc/nsswitch.conf
#hosts:     db files ldap nis dns
#hosts:      files dns
hosts:      files dns ldap

이제 /etc/ldap.conf 에서 hosts 정보를 찾을 수 있도록 정보를 변경한다.

[migration:root@cent3 migration]# grep hosts /etc/ldap.conf
# Multiple hosts may be specified, each separated by a
#nss_base_hosts         ou=Hosts,dc=example,dc=com?one
nss_base_hosts          ou=hosts,dc=example,dc=com?one
[migration:root@cent3 migration]# getent hosts 

(green star) 테스팅과정중에 발견한 중요한 내용이 있다. /etc/nsswitch.conf 에서 hosts 설정순서가 중요하다. ldap 클라이언트에서 자신의 호스트네임을 풀어야한다. 이때문에 dns 항목이 ldap 보다 앞에 오거나 호스트명을 /etc/hosts 파일에 적어주어야 한다. 이렇게 하지 않으면 segmentation fault 에러가 나고 이후부터는 id 등 각종 프로그램에서 계속 세그멘테이션 폴트가 나면서 시스템 작동이 이상해진다.

# getent hosts
127.0.0.1       localhost.localdomain localhost
Segmentation fault

http://www.mathematik.uni-marburg.de/~gasi/Doc/install/tasks.html#ldap_client_host 참고자료

4.7.5.1 Host Resolving
(2) looping resolver - segmentation fault
The order within /etc/nsswitch.conf is important, and the ldap client code needs to resolve its own hostname! Therefor dns must be before ldap or the hostname must be in /etc/hosts!

서버, 클라이언트 몇가지 옵션

서버에서 검색제한하기

slapd.conf 에서 sizelimit , timelimit를 이용하여 검색에 대한 제한을 걸 수 있다.

  • sizelimit : 검색요청을 할 경우 클라이언트의 요청에 답하는 최대 엔트리 숫자. 기본값은 500
  • timelimit : 검색요청에 응답을 할때 걸리는 최대 시간. 기본값은 3600초(1시간)

/etc/ldap.conf 주요 옵션에 대하여

/etc/ldap.conf 주요 옵션은 다음과 같다.

  • host는 ldap 서버, base 는 base dn이다.

  • ssl start_tls

    는 TLS를 사용하는 경우 체크하는 옵션이다. 암호화되어 통신하는 것이다.

  • pam_check_host_attr 는 hosts를 이용하여 사용자별로 접속할 호스트를 제한하는데 사용한다.
  • pam_filter 는 사용자 인증시 사용할 필터이다. pam_login_attribute 는 사용자의 로그인 명과 일치하는 attribute를 지정한다.
  • nss_base_xxx 는 nss_ldap 에서 검색하는 부분을 지정하여 LDAP 서버의 부하를 줄일 수 있다. passwd, shadow는 상관없지만 group, hosts는 등록을 해주어야했다.

    ssl start_tls
    tls_cacertdir /etc/openldap/cacerts
    pam_password md5
    pam_check_host_attr yes
    
    pam_filter objectclass=posixAccount
    pam_login_attribute uid
    
    nss_base_passwd         ou=people,dc=example,dc=com?one
    nss_base_shadow         ou=people,dc=example,dc=com?one
    nss_base_group          ou=group,dc=example,dc=com?one
    nss_base_hosts          ou=hosts,dc=example,dc=com?one
    

호스트, 사용자별 접근제한

특정 호스트, 사용자를 지정하여 접근을 제한할 수 있는데 두가지 방법이 있다.
첫번째는 특정한 호스트에 접속가능한 사용자들을 지정하는 방식(a.server 에 a,b,c 사용자 접속가능)이 있고 두번째는 특정한 사용자가 접속가능한 호스트들을 지정하는 방식(a 사용자는 가,나,다 서버에 접속가능)이 있다.
실제 사용하는 경우 뒤의 방식이 더 편리하다. 앞의 방식은 클라이언트에서 설정을 일일이 세팅해야하지만 뒤의 방식은 클라이언트에서 동일한 설정을 유지하되 ldap서버에서 변경을 할 수가 있다.

특정 사용자가 접속하능한 호스트 설정하기

/etc/ldap.conf 에서 pam_check_host_attr yes로 해줌. /etc/openldap/ldap.conf가 아니다.
사용자를 추가할때 host 에 접속가능한 호스트 지정. 여기서 IP로 지정하면 접속이 되지 않았고 정확한 도메인명을 지정해야한다.

# test, people, example.com
dn: uid=test,ou=people,dc=example,dc=com
중간내용 생략
host: kldp.org
host: cent3.tunelinux.pe.kr

pam 설정은 변경할 필요가 없다.

특정 호스트에 접속가능한 사용자 제한하기

ou=hosts 가 먼저 있어야 한다.

# cat host.ldif 
dn: ou=hosts,  dc=example, dc=com
ou: hosts
objectclass: organizationalUnit
objectclass: domainRelatedObject
associatedDomain: example.com

# ldapadd -x -D 'cn=manager,dc=example,dc=com' -W -f host.ldif 

이제 특정 호스트와 사용자에 대한 정보를 입력한다. 아래에서는 cn을 linux 를 하였다.

# cat iphost.ldif 
dn: cn=linux,ou=hosts,dc=example,dc=com
objectClass: ipHost
objectClass: device
objectClass: extensibleObject
ipHostNumber: 192.168.0.23
cn: linux.example.com
cn: linux
member: uid=test,ou=people,dc=example,dc=com
member: uid=test2,ou=people,dc=example,dc=com

# ldapadd -x -D 'cn=manager,dc=example,dc=com' -W -f iphost.ldif 

위에서는 192.168.0.23 에 test, test2 계정만 접속가능하도록 설정하였다.

ldap에 위의 정보를 입력한 후 각 ldap client 에 위 기능을 사용할 수 있도록 설정해야 한다.

이는 /etc/ldap.conf 에 다음 항목을 추가한다. 위에서 사용한 dn을 넣어주어야 한다.

pam_groupdn cn=linux,ou=hostss,dc=example,dc=com
pam_member_attribute member

테스팅을 한 결과 /etc/ldap.conf 에 pam_groupdn 설정을 두개 넣으면 작동을 하지 않았다.
그렇지만 각 ldap client 쪽에 이 설정이 두가지 들어갈 일이 없으므로 문제가 되지는 않는다.

iphost.ldif 에 설정한 내용을 각 ldap client 별로 ldap에 넣어주고 이후에는 그 설정내용만 계속 수정하면 된다.

NIS netgroup 사용하여 사용자, 호스트별 접근제한하기

관련자료

오렐리 LDAP admin 117쪽
페도라 디렉토리 서버 위키의 문서중 "System Access Control using LDAP backed NIS netgroup" http://directory.fedora.redhat.com/wiki/Howto:netgroup

NIS netgroup 기능

NIS는 Sun에서 나온 기술로 여러대의 시스템을 통합적으로 관리하기 위해 나왔다. 사용자계정, 그룹, /etc/hosts 등을 통합해서 관리할 수 있다.
NIS netgroup은 다음과 같은 기능을 제공한다.

  • 개별 시스템 또는 시스템그룹에 사용자와 그룹 로그인 접근 제어
  • NFS 접근 제어 목록 관리
  • 사용자,그룹에 대한 sudo 명령어 접근제어
  • dsh(distributed shell)을 이용하여 원격 명령 실행 또는 시스템그룹에 작업
  • cfengine을 이용하여 정책 기반의 시스템 설정관리

tcp 래퍼를 통하여 간단한 예를 살펴보자.

# /etc/hosts.deny
sshd: ALL
# /etc/hosts.allow
sshd: @sysadmin

위에서 sysadmin netgroup는 다음과 같이 개별 호스트로 구성할 수 있다.

sysadmin (a.com,-,-)(b.com,-,-)

또는 다른 netgroup을 포함할 수 있다.

all_sysadmin sysadmin secure_clients

(a.com,,) 구성은 host, user, NIS-domain 으로 구성이 되며 -는 생략을 해도 된다. 마지막 NIS-domain은 생략을 해도 LDAP과 cfengine 에서 사용이 가능하였다.

이를 이용하면 시스템그룹별, 사용자그룹별로 여러가지 작업을 제어할 수 있고 시스템그룹과 사용자그룹의 조합도 가능하다.

LDAP 에서 netgroup 구현

LDAP에서는 structural nisNetgroup 오브젝트 클래스를 이용하여 netgroup 기능을 구현할 수 있다.

nisNetgroup 오브젝트 클래스에서 rdn은 cn을 쓰며두가지 중요한 attributes 가 있다.

nisNetgroupTriple : 사용자(,love,example.com), 시스템 (cent.tunelinux.pe.kr,,example.com) 을 지정할 수 있으며 여러개의 값이 들어갈 수 있다.
memberNisNetgroup : 다른 netgroup 를 포함할 수 있다. 대그룹, 소그룹 등으로 분류하여 편리하게 사용할 수 있는 기능이다. 이또한 여러개의 값을 가질 수 있다.

먼저 ou를 생성한다. LDIF 파일로 저장하여 ldapadd로 넣으면 된다.

dn: ou=netgroup,dc=example,dc=com
objectClass: organizationalUnit
ou: netgroup

dn: cn=sysadmin,ou=netgroup,dc=example,dc=com
objectClass: nisNetgroup
objectClass: top
cn: sysadmin
description: netgroup test group
nisNetgroupTriple: (cent1.tunelinux.pe.kr,-,-)
nisNetgroupTriple: (cent2.tunelinux.pe.kr,-,-)

dn: cn=sysadmin2,ou=netgroup,dc=example,dc=com
objectClass: nisNetgroup
objectClass: top
cn: sysadmin2
description: netgroup test group2
memberNisNetgroup: sysadmin
memberNisNetgroup: sysadmin2

dn: cn=allusers,ou=Netgroup,dc=example,dc=com
objectClass: nisNetgroup
objectClass: top
cn: users0
nisNetgroupTriple: (,a,)
nisNetgroupTriple: (,b,)
description: All QA users in my organization

sysadmin은 host가 cent1.tunelinux.pe.kr, cent2.tunelinux.pe.kr 를 넷그룹으로 묶으며 sysadmin2는 memberNisNetgroup을 이용하여 sysadmin, sysadmin2 넷그룹을 묶는 것이다.
nisNetgroupTriple 과 memberNisNetgroup은 같이 들어갈 수도 있다.
alluser는 a,b 사용자를 묶었다. 위에서 설명한바와 같이 NIS 도메인 명은 입력을 하지 않아도 작동하는데는 문제가 없었다.
페도라 디렉토리 서버 위키의 문서중 "System Access Control using LDAP backed NIS netgroup"에는 다음과 같이 나와있다. http://directory.fedora.redhat.com/wiki/Howto:netgroup

Finally to enable the netgroup query, NISDOMAIN must be defined (in /etc/sysconfig/network) even though it is not used. This is required because the innetgr() call is used and it requires a nisdomainname as a paramter. Once the functions resolves to LDAP via nsswitch.conf, the nisdomainname in no longer required.

필요한 엔트리를 추가한 후 /etc/ldap.conf 에서 netgroup 검색을 위하여 nss_base_netgroup 을 추가한다.

nss_base_netgroup       ou=netgroup,dc=example,dc=com?one

OS에서 netgroup을 찾을 수 있도록 /etc/nsswitch.conf 에서 netgroup 에 대한 설정을 한다.

netgroup:   ldap

getent 프로그램을 이용하여 위에서 입력한 netgroup을 검색해본다.

# getent netgroup sysadmin
sysadmin               (cent1.tunelinux.pe.kr, , ) (cent2.tunelinux.pe.kr, , )

이러한 설정을 이용하여 위에서 sshd는 sysadmin 에 속한 호스트에서만 접속을 하도록 설정을 할 수 있는 것이다.

PAM 접근제어 연동

tcp 래퍼만이 아니라 넷그룹을 이용하여 PAM 의 접근권한 제어와 연관을 시킬 수가 있다.
이에 대한 내용은 페도라 디렉토리 서버의 위키에 자세히 나와있다.

위와 같은 작업을 하여 특정 호스트와 특정 사용자별로 그룹을 묶는다.
bobby, joey 사용자를 QAUsers 그룹으로 만든다.

dn: cn=QAUsers,ou=Netgroup,dc=example,dc=com
objectClass: nisNetgroup
objectClass: top
cn: QAUsers
nisNetgroupTriple: (,bobby,example.com)
nisNetgroupTriple: (,joey,example.com)
description: All QA users in my organization

qa01, qa02 호스트를 QASystems 그룹으로 만든다.

dn: cn=QASystems,ou=Netgroup,dc=example,dc=com
objectClass: nisNetgroup
objectClass: top
cn: QASystems
nisNetgroupTriple: (qa01,,example.com)
nisNetgroupTriple: (qa02,,example.com)
description: All QA systems on our network

PAM 에서 /etc/security/access.conf 파일을 이용하여 ip 에 따라 접속가능한 호스트와 사용자를 지정할 수 있다.
이에 대해서는 별도로 PAM 정보를 참고한다.
access.conf 파일에서 nis의 넷그룹은 @netgroupname 형태로 이용하면 된다. 여기서 호스트명이나 사용자명 한가지만 이용하는 것이 아니라 두가지를 결합하면 여러가지 편리한 점이 있다.
아래의 내용은 10.x.x.x 네트워크에서 QASystems에 QAUsers 가 접속할 수 있도록 하는 것이다.

+ : <at:var at:name="QAUsers" />@QASystems : 10.

아래의 경우는 root 사용자는 로컬에서만 접속하고 Admins 넷그룹은 10.x 네트워크에서 접속할 수 있도록 하며 나머지는 모두 막는 설정이다.

+ : root : LOCAL
+ : @Admins : 10.
- : ALL : ALL

cfengine 에서의 사용

cfengine은 각종 시스템작업을 자동화할 수 있는 프로그램이며 별도 자료를 참고하기 바란다. http://www.cfengine.org/docs/cfengine-Reference.html#groups
NIS netgroup을 이용하는 경우에는 +나 +@ 기호를 이용한다. 여기서 유용한 것이 netgroup except 이다. 아래에서 testgroup은 mynetgoup을 포함하고 있는데 mynetgoup 에서 특정 호스트만 빼려고 할 경우에는 - 기호를 이용하여 지정하면 된다.

     groups:
        science = ( +science-allhosts )
        physics = ( +physics-allhosts )
        physics_theory = ( +@physics-theory-sun4 dirac feynman schwinger )
        testgroup = ( +mynetgroup -specialhost -otherhost )

참고사항

host 이름에 대하여

dns에 등록되어있지 않아도 ldap의 hosts 에 들어가있으면 동일하게 동작한다.

nisNetgroupTriple 추가, 변경시

실제 사용하면서 문제가 부딪힌 것이 있다. nisNetgroupTriple 을 추가하려고 하는 경우에는 additional info: modify/add: nisNetgroupTriple: no equality matching rule 라는 에러가 난다.
attribute 정의에서 nisNetgroupTriple 은 매칭 룰이 없다. 이 부분이 영향을 미치는 것 같다.
좋은 방법은 아닌듯하지만 스키마에서 EQUALITY 와 SYNTAX를 수정해주었지만 제대로 작동하지는 않았다.

# cat mod.txt
dn: cn=sysadmin2,ou=netgroup,dc=example,dc=com
changetype: modify
add: nisNetgroupTriple
nisNetgroupTriple: (cent2.tunelinux.pe.kr,,)

#  ldapmodify -D "cn=manager,dc=example,dc=com" -W -x -v -f mod.txt
ldap_initialize( <DEFAULT> )
add nisNetgroupTriple:
        (cent2.tunelinux.pe.kr,,)
modifying entry "cn=sysadmin2,ou=netgroup,dc=example,dc=com"
modify complete
ldap_modify: Inappropriate matching (18)
        additional info: modify/add: nisNetgroupTriple: no equality matching rule

nisNetgroupTripple attibutetype

attributetype ( 1.3.6.1.1.1.1.13 NAME 'memberNisNetgroup'
        EQUALITY caseExactIA5Match
        SUBSTR caseExactIA5SubstringsMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple'
        DESC 'Netgroup triple'
        SYNTAX 1.3.6.1.1.1.0.0 )

nisNetgroupTriple은 초기 한개 입력가능하며 한개만 있을 경우 수정, 삭제가 가능한데 두개이상 추가가 되지 않는다.
매칭룰때문에 생기는 문제라고 판단이 되며 이럴 경우 해당 dn을 삭제하고 신규로 dn를 넣어주어야 한다.

사용자 접근제한 어떤 방법이 좋을까?

호스트별로 접속가능한 사용자를 지정하는 방식은 접속하려는 클라이언트 설정이 모두 달라지므로 불편하다. (pam_groupdn, pam_member_attribute 설정)
pam_check_host_attr 또는 LDAP에 NIS를 연동하는 방식이 관리상 편리할 것이다.

각자의 장단점을 생각해보자.
pam_check_host_attr 을 이용하면 각 사용자별로 접속할 수 있는 호스트를 지정한다.
모든 것을 LDAP에서 관리하고 /etc/ldap.conf 에서 pam_check_host_attr 지정하는 것 외에 별도의 설정이 필요없으므로 구성이 간단하다.
하지만 시스템과 사용자규모가 커지면 별도의 관리툴을 만들지 않으면 불편하다.

NIS를 이용하는 경우에는 설정은 좀더 복잡해지지만 사용자, 시스템별로 그룹을 만들고 이 그룹을 필요에 따라 조정할 수 있다.
/etc/security/access.conf는 시스템에 달라지는것이 아니라 모든 시스템에서 동일한 내용을 공유할 수 있다.
기본설정은 동일하되 특정 그룹에 대한 조정은 ldap을 통하여 하면 된다.
한가지 단점이라면 nisNetgroupTriple은 한개만 입력가능, 한개만 있을 경우 수정, 삭제가 가능한데 두개이상 추가는 되지가 않는다.
매칭룰때문에 생기는 문제라고 판단이 되며 이럴 경우 해당 dn을 삭제하고 신규로 dn를 넣어주어야 한다.
이러한 불편함은 있지만 기본 제공되는 기능만으로 가장 강력하게 접근제어를 할 수가 있다.
또한 NIS기능을 cfengine 등 다른 프로그램에서도 활용이 가능하다.

user 변경 프로그램 - cpu

passwd 프로그램을 이용해서 사용자를 변경하여도 된다. 그렇지만 사용자 생성은 ldif 파일로 직접 넣거나 cpu 프로그램 이용 또는 ldap 관리자툴을 이용해야 한다. cpu가 사용자 계정 및 그룹관리에 편리하다.

http://cpu.sourceforge.net/ 최신버전 다운로드

  • rpmfind 에서 cpu rpm을 다운로드 받아도 됨. rhel4 버전에 맞춘 rpm이 있음.
    여기서 설치한 rpm의 cpu 프로그램은 다른 사용자도 사용할 수 있으므로 root만 사용하도록 조정한다.

    [migration:root@cent3 migration]# ll /usr/sbin/cpu
    -rwxr-xr-x  1 root root 12127 Feb 17  2005 /usr/sbin/cpu
    [migration:root@cent3 migration]# chmod 700 /usr/sbin/cpu
    

openldap-devel 필요함

./configure --prefix=/usr/local/cpu
make
make install

이제 /usr/local/cpu 에 프로그램이 설치가 된다.

# grep example /usr/local/cpu/etc/cpu.conf 
BIND_DN         = cn=Manager,dc=example,dc=com
USER_BASE       = ou=People,dc=example,dc=com
GROUP_BASE      = ou=Group,dc=example,dc=com

위와 같이 dn을 바꾸어준다.

#HASH = "md5"
HASH = "crypt"

HASH 를 md5 에서 crypt 로 바꾸어준다.

여기서 sldapd.conf 의 root 비밀번호를 넣어주어야 한다.

BIND_PASS       = xxxx 


MAX_UIDNUMBER = 10000
MIN_UIDNUMBER = 1000
MAX_GIDNUMBER = 10000
MIN_GIDNUMBER = 1000

MIN_UIDNUMBER, MIN_GIDNUMBER 를 100에서 적절한 값으로 바꾼다.

# /usr/local/cpu/sbin/cpu useradd test 
# /usr/local/cpu/sbin/cpu userdel test 
$ /usr/local/cpu/sbin/cpu usermod -p  test2

[migration:root@localhost openldap]# id test
uid=1001(test) gid=1001(test) groups=1001(test)
[migration:root@localhost openldap]# /usr/local/cpu/sbin/cpu groupmod -g 1005 test
Group test successfully modified!
[migration:root@localhost openldap]# id test
uid=1001(test) gid=1001 groups=1001,1005(test)
[migration:root@localhost openldap]# /usr/local/cpu/sbin/cpu groupmod -n test222 test
Group test222 successfully modified!
[migration:root@localhost openldap]# id test
uid=1001(test) gid=1001 groups=1001,1005(test222)

편하게 사용을 하려면 path에 추가해주면 좋다.

export PATH=$PATH:/usr/local/cpu/sbin
export MANPATH=$MANPATH:/usr/local/cpu/man
man cpu-ldap

cpu cat 은 전체 사용자, 그룹을 본다.

[migration:root@cent ~]# cpu cat
User Accounts
ldaptest:x:1001:1001::/home/ldaptest:/bin/bash
ldap2:x:1000:1002::/home/ldap2:/bin/bash

Group Entries
webdev:x:2000:
test:x:1000:
ldaptest:x:1001:
ldap2:x:1002:

사용자 패스워드 변경한다.

[migration:root@cent ~]# cpu usermod -p ldaptest

관리를 위해서는 먼저 필요한 그룹을 생성하고 그 사용자를 추가해주는 것이 좋을 것이다. 기본값은 사용자를 생성시 동일한 이름의 그룹을 생성한다. 그러므로 처음 생성시 -g 옵션을 이용하여 그룹을 지정하는것이 좋다. 아니면 사용자 생성후 그룹을 바꾸어주어도 된다.

[migration:root@cent3 openldap]# cpu useradd -g test5 ilove
[migration:root@cent3 openldap]# cpu usermod -g test ilove

사용자를 추가할때 -p옵션뒤에 패스워드를 넣어줄 수 있다.

USERGROUPS = no
USERS_GID = 10000

cpu.conf 에서 USERGROUPS 은 기본 yes로 되어있다. 사용자 생성시 같은 이름의 gid로 그룹을 생성한다. 이를 no로 바꾸어주고 USERS_GID 에 특정 gid를 넣어주면 자동으로 해당 gid로 그룹을 생성한다. 일관된 관리를 할때 편리할 것이다.

nfs, autofs 세팅

nfs, autofs는 홈디렉토리를 사용자가 로그인시 자동으로 파일서버에서 마운트하는 경우에만 사용하면 됩니다.
장점은 홈디렉토리를 각 서버마다 만들지 않고 일괄적으로 관리할 수 있다는 것이다.
여기에 쿼터설정하여 홈디렉토리가 계속 커지는 것을 막도록 하는 것이 좋을 것이다.

nfs 서버 세팅

nfs의 경우 방화벽 설정을 하는 경우에 해당 port만 여는 것이 아니라 작업이 필요하다.
이에 대해서는 nfs 방화벽설정에 대한 내용을 참고한다.
그리고 portmap, nfs 서버대몬을 시작시 작동하도록 해야 할 것이다.

# cat /etc/exports
/tmp   192.168.0.0/255.255.255.0(rw,sync)

# /etc/init.d/nfs start

autofs 세팅

autofs 세팅은 접속할 대상 서버에서 모두 작업을 해야 한다.
ldap을 이용하기전에 먼저 autofs를 먼저 테스팅을 해보기 바란다.
시작시 autofs를 자동으로 시작하도록 설정한다.

auto.master 파일이 메인파일이며 여기에서 마운트 포인트와 세부 설정파일을 지정함.
아래에서는 /home 디렉토리에 접근하는 경우 /etc/auto.home 파일을 참고하며 auto.home 은 /home 의 모든 하위 디렉토리(*)에 접근하는 경우 nfs 192.168.0.24:/tmp 의 해당 디렉토리에 마운트함

# cat /etc/auto.master 
/home   /etc/auto.home --timeout=5

# cat /etc/auto.home 
*               -rw,soft,intr           192.168.0.24:/tmp/&

home 디렉토리 공유하기 위해 automount 세팅하기 (사전에 autofs 는 세팅을 해야함)

autofs 스키마 설정

autofs를 이용할 경우 autofs.schema 을 sldapd.conf에 추가해주어야 한다.
그리고 autofs 설정에 대한 acl도 설정을 해야한다.
include /etc/openldap/schema/redhat/autofs.schema


# cat auto.master.ldif 
dn: ou=auto.master,dc=example,dc=com
objectClass: top
objectClass: automountMap
ou: auto.master

dn: cn=/home,ou=auto.master,dc=example,dc=com
objectClass: automount
cn: /home
automountInformation: ldap:ou=auto.home,dc=example,dc=com

# ldapadd -x -D 'cn=manager,dc=example,dc=com' -W -f auto.master.ldif 
Enter LDAP Password: 
adding new entry "ou=auto.master,dc=example,dc=com"

adding new entry "cn=/home,ou=auto.master,dc=example,dc=com"
 
# cat auto.home.ldifc 
dn: ou=auto.home,dc=example,dc=com
objectClass: top
objectClass: automountMap
ou: auto.home

dn: cn=*,ou=auto.home,dc=example,dc=com
objectClass: automount
cn:*
automountInformation:   192.168.0.24:/tmp/&

# ldapadd -x -D 'cn=manager,dc=example,dc=com' -W -f auto.home.ldifc 
Enter LDAP Password: 
adding new entry "ou=auto.home,dc=example,dc=com"

adding new entry "cn=test,ou=auto.home,dc=example,dc=com"

이렇게 하는 경우 /etc/auto.master 를 ldap 에서 사용할 수 있도록 바꾸어 줄수 있다.
ldap기반에 autofs 이용시 /etc/auto.master 파일만 설정하면 되고 시작시 autofs만 시작하도록 하면 된다.
참고로 timeout은 해당 디렉토리를 자동으로 마운트하고 사용하지 않을 경우 어느정도의 시간을 대기하다록 할 것인지를 지정한다.
해당디렉토리에 자주 접속하는 것이 아니라면 시간은 더 짧게 해놓아도 될 것이다.

# cat /etc/auto.master 
#/home  /etc/auto.home --timeout=5
/home   ldap:192.168.0.23:ou=auto.home,dc=example,dc=com --timeout=5

각종 애플리케이션 LDAP 연동

참고사항

  • outlook express에서는 고급검색에서 메일이름을 가지고 검색할 수 있어서 특정 도메인에 대한 메일을 볼 수 있어 편리하다. 그러나 Microsoft Outlook 는 사용자이름이나 id만 가지고 검색할 수 있다. 이는 검색필터가 다르기 때문이다. outlook은 회사명으로 검색을 할 경우 company 라는 attr을 찾는다. 그래서 company attr을 사용자 정의해주고 이를 이용하여 검색할 수 있다. 이에 대한 자료는 http://database.sarang.net/index.php?inc=read&aid=2318&criteria=ldap&subcrit=tutorials DSN의 자료를 참고한다.
  • text plain이 아니라 암호화하여 주소록 검색을 하려면 보안인증(ssl)을 사용하면 된다. LDAP서버에서 만든 CA인증서를 .cer 등으로 복사하여 윈도우에서 인증서을 가져오면 사용할 수 있다.

outlook 등 이메일클라이언트 세팅하기

위에서 ou=people,dc=example,dc=com 에 입력한 사용자정보는 아웃룩, 선더버드 등의 주소록에서 활용을 할 수 있다.

아웃룩

outlook express 에서는 도구->계정 으로 가서 디렉토리 서비스를 선택한다.
디렉토리 서비스 계정에 적절한 이름을 택하여 찾기 쉽도록 넣는다.
서버 이름에 ldap 서버 정보를 입력한다.
로그인 필요에서는 위에서 만든 ldaptest 등을 이용하면 된다. uid=ldaptest,ou=people,dc=example,dc=com 를 넣어주면 될 것이다.
암호는 위 id에 해당하는 비밀번호를 넣으면 된다.
보안 암호 인증을 사용하여 로그인은 잘 모르겠다.
고급에서 검색기준을 입력한다. ou=people,dc=example,dc=com

이제 outlook express 에서 주소 -> 사람찾기를 선택하여 ldap 디렉토리를 지정하고 검색조건을 입력하면 된다. 그런데 여기서 이름이나 메일을 입력하면 mail, cn, sn, givenname 에서 입력한 단어로 시작한 것을 찾는다. 그런데 고급조건을 고르면 여러가지 조건을 선택할 수 있고 전자메일에 특정 도메인을 포함하여 검색하면 한 회사의 메일을 빠르게 검색할 수 있다.

Microsoft Outlook 에서는 다음과 같다.
도구->전자메일계정-> 디렉토리 : 새 디렉토리 또는 주소록 추가

서버이름 : intranet.tunelinux.pe.kr
로그온정보 : 로그온 필요에 표시함. 사용자이름에 uid=joon,ou=people,dc=example,dc=co,dc=kr 형태로 입력하며 uid에는 자신의 id를 입력함.
기타설정->검색에서 검색기준을 지정하는데 ou=people,dc=example,dc=co,dc=kr 하면 된다.
도구메뉴의 찾기에서 검색을 하여 사용하면 된다.

선더버드

선더버드에서는 계정설정->주소->디렉토리 편집에서 디렉토리 서비스를 추가한다.
이름은 적절한 이름을 택하여 찾기 쉽도록 넣는다.
호스트 이름에 ldap 서버 정보를 입력한다.
기본 dn에 ou=people,dc=example,dc=com 를 입력한다. 기준이 되는 dn을 입력하는 것이다.
포트번호는 ldap 포트번호를 적는다.
DN 바인드는 인증을 사용할 경우에 해당한다.
uid=ldaptest,ou=people,dc=example,dc=com
암호는 접속시 입력을 하면 된다.

참고사항

현재 기본설정은 다른 사용자도 read 권한을 주기때문에 아웃룩에서 로그인필요, 선더버드에서 DN 바인드를 선택하지 않는다고 하더라도 주소록 검색이 가능하다.
이 부분은 ldap 서버 설정에서 acl을 주어야 할 것이다.

참고로 이메일클라이언트는 읽기 전용이다. 또 검색을 해서 이용해야하는 불편이 있다.

웹주소록 프로그램

  • /usr/share/doc/labe-3.3/REAME 파일을 참고.
    여기서 먼저 suffix, rootdn를 만들어주고 ldap 대몬을 다시 띄움. 아래 스키마 추가도 여기에서 언급하고 있음.
  • http://sourceforge.net/projects/labe/ 여기에서 다운로드 받아 설치하면 된다.
    설정은 ldap을 이해하고 있으면 간단하다. rpm으로 설치하면 /var/www/html/labe/ 디렉토리에 웹프로그램설치가 되고 setup.sh 에서 적절한 답변을 해주면 된다.
    참고로 이유는 모르겠는데 /etc/openldap/slapd.conf 에서 labe 프로그램이 사용하는 스키마를 수동으로 추가해준다. 이는 자동으로 되지 않는 듯하다.

    include /etc/openldap/schema/extension.schema
    

    /etc/labe/connect.conf 파일이 ldap 접속에 대한 설정파일이며 여기에 서버주소, port, bind, rootdn 정보가 들어간다. 이는 위의 스크립트를 실행하면 생성이 되는 것이다.

웹주소록 ACL 설정으로 인증된 사용자만 읽도록 하기

아래와 같이 기본 권한을 none으로 주고 users (dn이 존재하고 패스워드를 제시한 사용자)에게만 read 권한을 주는 것으로 바꾸니 인증을 해야 접속이 된다. ACL 설정부분은 추후에 좀더 살펴봐야함

access to attr=userPassword
        by self write
        by anonymous auth
        by dn="cn=manager,dc=example,dc=com"        write
        by* compare
access to*
        by self write
        by dn="cn=manager,dc=example,dc=com"        write
        by users read

위에서 users 에 read 권한을 주지 않으면 다른 정보도 볼수가 없다.

defaultaccess none 가 오렐리 책등에서는 나오는데 openldap 버전이 올라가면서 기본적으로 aci가 설정되지 않으면 거부로 동작이 바뀐듯하다.

아파치 인증에 LDAP 사용하기

  • 연동방법만 간략히 설명
  • http://httpd.apache.org/docs/2.0/ko/mod/mod_auth_ldap.html apache 에서 ldap 인증 아파치 공식한글문서중 관련내용
  • htaccess 에서 아래와 같이 사용하면 됨. dc=example,dc=co 이 부분을 적절히 바꾸면 될것임. user, group, dn, ldap attribute 등을 이용하여 접속을 제한할 수 있다.
  • mod_auth_ldap 에서는 두가지 과정을 거친다. 먼저 사용자를 인증한다. (search/bind) 그러고나서 인증받은 사용자가 요청한 정보에 접근을 허용받았는지를 확인한다 (compare)

    [migration:joon@localhost moniwiki]$ cat .htaccess
    AuthType Basic
    AuthName "joon wiki system"
    AuthLDAPURL ldap://localhost:389/ou=people,dc=example,dc=com?uid?sub?(objectClass=*)
    require valid-user
    
  • 만약 ACL에 익명사용자가 사용자정보에 접근을 하지 못하도록 해놓았다면 정보를 검색할 수 있는 binddn을 지정해주어야 한다. 아래와 같은 형태로 위에 추가를 해주어야 한다.

    AuthLDAPBindDN cn=readonly,dc=example,dc=com
    AuthLDAPBindPassword readpassword
    

samba, ldap 연동

구글검색해서 http://aput.net/~jheiss/samba/ldap.shtml 사이트를 보고했지만 잘 되지 않았음. 시간걸릴듯하여 그냥 넘어갔음

ldap 에서 TLS 사용한 암호화 통신

참고자료 http://www.openldap.org/doc/admin23/tls.html
Centralize user accounts with OpenLDAP http://www-128.ibm.com/developerworks/library/l-openldap/index.html
SSL 참고자료 http://wiki.kldp.org/wiki.php/DocbookSgml/SSL-Certificates-HOWTO

아래 내용은 자체적으로 ldap만 신경쓸 경우 사용하면 되지만 인증서를 한군데에서만 사용하는것이 아니기때문에 "SSL 인증서 만들어서 여러 서비스에 활용하기"의 내용을 참고해서 사용하는 것이 좋다.

인증 메커니즘

LDAPv3 에서는 클라이언트 인증에 여러가지 메카니즘을 사용한다.

  • anonymous authentication
  • simple authentication
  • simple authentication over SSL/TLS
  • simple authentication and Security Layer (SASL)

SSL/TLS는 두가지 방법이 있다. ssl을 통해 ldap을 사용하는 방법(ldaps, tcp port 636)보다는 StartTLS LDAP 확장기능으로 사용하는 것이 좋다. StartTLS 는 tcp 389 port(ldap포트)를 통해서 TLS 통신을 할 수 있는 기능이다. 서버의 같은 포트에서 클라이언트의 요청에 따라 암호화된 세션과 암호화되지 않은 세션을 모두 처리할 수 있다.

인증서 생성

root CA 가 없을 경우 먼저 생성을 해준다. 해당 정보는 시스템에 맞게 적절하게 수정을 한다. Common Name은 해당 서버의 호스트명을 지정한다.
참고로 openssl 기본설정(/usr/share/ssl/openssl.cnf )은 인증서의 유효기간이 default_days 옵션으로 365일이다. 아래 CA 스크립트에서도 DAYS 옵션을 이용하여 365일로 지정하고 있다.
openssl에 대해서는 별도의 자료를 참고하기 바란다.

# cd /usr/share/ssl/misc
# ./CA -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 1024 bit RSA private key
............................................................++++++
.++++++
writing new private key to './demoCA/private/./cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [migration:KO]:
State or Province Name (full name) [migration:gurogu]:
Locality Name (eg, city) [migration:seoul]:
Organization Name (eg, company) [migration:example dataservice]:
Organizational Unit Name (eg, section) [migration:ITservice]:
Common Name (eg, your name or your server's hostname) [migration:cent3.tunelinux.pe.kr]:
Email Address [migration:joon@tunelinux.pe.kr]:

이제 LDAP서버에서 사용할 서버 인증요청서(CSR)을 생성한다.
개인키는 slapd-key.pem 으로 지정하고 slapd-req.pem 이 CSR이다. 여기서 nodes 옵션을 쓴것은 ldap서버를 내리고 올려줄때 비밀번호를 넣어주지 않도록 하기 위해서이다.

openssl req -new -nodes  -keyout slapd-key.pem -out slapd-req.pem -days 1825

이제 앞에서 생성한 root CA로 인증서 사인을 한다.

openssl ca -out slapd-cert.pem -infiles slapd-req.pem

위에서 생성한 인증서를 적절한 디렉토리로 옮긴다. 참고로 CA키는 /etc/openldap/cacerts 에 두는데 CA 키 말고 아래에서 slapdcert.pem 도 이 디렉토리에 두면 TLS 기능이 제대로 작동하지 않는다. 이 디렉토리에서 ca 키를 찾도록 해 놓아서 에러가 나는 듯하다. 자세한 이유까지는 모르지만 다른 디렉토리에 두면 되므로 주의만 하면 될 것이다.

# cp -p slapd-key.pem /etc/openldap/slapdkey.pem -> private key
# cp -p slapd-cert.pem /etc/openldap/slapdcert.pem -> certificate
# chown ldap:ldap /etc/openldap/slapdcert.pem
# chmod 644 /etc/openldap/slapdcert.pem
# chown ldap:ldap /etc/openldap/slapdkey.pem
# chmod 400 /etc/openldap/slapdkey.pem

# cp /usr/share/ssl/misc/demoCA/cacert.pem /etc/openldap/cacerts/cacert.pem -> CA certificate
# chown ldap:ldap /etc/openldap/cacerts/cacert.pem
# chmod 644 /etc/openldap/cacerts/cacert.pem

귀찮은 작업이라서 복사해서 쓰게 아래에 적어놓는다.
cp -f slapd-key.pem /etc/openldap/slapdkey.pem 
cp -f slapd-cert.pem /etc/openldap/slapdcert.pem
chown ldap:ldap /etc/openldap/slapdcert.pem
chmod 644 /etc/openldap/slapdcert.pem
chown ldap:ldap /etc/openldap/slapdkey.pem
chmod 400 /etc/openldap/slapdkey.pem

cp -f /usr/share/ssl/misc/demoCA/cacert.pem /etc/openldap/cacerts/cacert.pem
chown ldap:ldap /etc/openldap/cacerts/cacert.pem
chmod 644 /etc/openldap/cacerts/cacert.pem

ldap 서버설정(slapd.conf)에 다음 내용을 추가한다. global 섹션에 추가하면 된다.

TLSCipherSuite HIGH:MEDIUM:+SSLv2  -> openssl ciphers
TLSCACertificateFile /etc/openldap/cacerts/cacert.pem -> CA private key
TLSCertificateFile /etc/openldap/slapdcert.pem -> certificate
TLSCertificateKeyFile /etc/openldap/slapdkey.pem -> private key

LDAP 서버에서 /etc/openldap/ldap.conf 에 아래 내용을 추가한다.

TLS_CACERTDIR /etc/openldap/cacerts
#TLS_REQCERT allow

TLS_REQCERT 는 TLS 세션에서 서버 인증서 체크와 연관된 부분이다. allow는 서버인증서가 없거나 잘못되어도 세션이 진행된다. TLS_REQCERT 에서 demand로 하면 서버인증서를 요청하되 서버인증서가 없거나 인증서가 잘못되었으면 세션을 바로 끊는다. (man ldap.conf)
ldap 서버를 내렸다가 다시 올려준다.

이제 ldap 클라이언트에서 다음의 설정을 /etc/ldap.conf에 한다. 여기서 cacert.pem은 ldap 클라이언트 시스템에 복사를 해두어야 한다.

ssl start_tls
tls_checkpeer yes
tls_cacertfile /etc/openldap/cacerts/cacert.pem

tls_checkpeer 서버 certificate 를 필요로 하고 검증을 하도록 한다. (설정파일의 주석내용 참고)

참고로 클라이언트 설정에서 authconfig를 이용하면

tls_cacertdir /etc/openldap/cacerts

로 설정이 된다. 위와 같이 tls_cacertfile 옵션을 이용하여 직접 파일을 지정할 수도 있고 아니면 /etc/opeanldap/cacerts 파일에 해당 인증서를 넣어두면 authconfig 에서 자동으로 c_rehah 유틸리티를 이용하여 해당 디렉토리에서 인증서파일을 가리키는 심볼릭 링크를 만든다.

# ls -alF /etc/openldap/cacerts
total 16
drwxr-xr-x  2 root root 4096 Jan  4 13:15 ./
drwxr-xr-x  4 root root 4096 Jan  4 13:18 ../
-rw-r--r--  1 root root 1346 Jan  4 13:15 cacert.pem
lrwxrwxrwx  1 root root   10 Jan  4 13:14 cc9fe289.0 -> cacert.pem

여기서 인증서파일을 가리키는 심볼릭 링크는 명령어를 이용할 수도 있다. 스크립트로 설정을 할 경우 필요하다.

/usr/sbin/cacertdir_rehash /etc/openldap/cacerts/

자신이 편한대로 쓰면 되겠지만 authconfig 를 이용한다면 자동으로 생성되는 tls_cacertdir 옵션을 써도 될 것이다.

클라이언트 설정시 주의점

클라이언트 설정은 앞에서 설명한 것과 동일하지만 ldap서버를 이용하여 접속할 각 클라이언트에서는 ldap 서버의 ca 인증서를 /etc/openldap/cacerts/ 디렉토리에 넣어두어야 한다.
그리고 바로 위에서 설명한대로 authconfig를 이용하여 설정하면 해당 인증서에 대한 심볼릭 링크를 자동으로 생성하지만 수동으로 할 경우에는 위의 cacertdir_rehash 스크립트를 이용한다.

replication 구현

주의사항

openldap은 원래 single master replication system이다. 업데이트는 마스터에서만 되고 나머지는 읽기전용이라는 것이다.현재 openldap에서는 multimaster 를 지원하는 않는다.
replication에도 두가지 방식이 있으며 기존에 사용하던 slurpd와 최근부터 지원한 LDAP Sync Replication 이 있다. 현재는 slurpd만 테스팅을 하였다.
슬레이브에서 LDAP서버를 내리는 테스팅결과 잠시동안 네트워크등의 문제가 있다고 하더라도 슬레이브가 정상으로 돌아오면 리플리케이션이 정상적으로 동작되었다. 그렇지만 몇분이내의 간단한 테스팅만 한 것이므로 이것만을 가지고 신뢰성을 확인하기는 힘들 것이다. 그런데 네트워크의 이상등으로 연결이 되어있지 못할때 마스터에서 새로운 값을 입력하면 이는 나중에 연결이 복구되더라도 자동으로 슬레이브에 들어가지는 않는다.

LDAP Sync Replication

LDAP Sync Replication 은 consumer-side replication으로 마스터서버(provider 서버)의 설정을 변경하거나 재시작하지 않고도 replicat를 생성할 수 있어 편리하다.
slurpd 방식에 비해 여러가지 장점이 있는 듯 하지만 RHEL이나 CentOS 4.4 에 기본 설치되어 있는 openldap 2.2 대에서는 몇가지 제약이 있어 실제로 쓰기는 불편한 듯 하다. 이 기능이 필요하다면 소스로 설치하여 해결할 수 있을 듯 한데 개인적으로는 이 기능이 당장 절실히 필요한 것은 아니라서 추가 테스팅은 하지 않았다. 2.2대와 2.3대에서 구현할때 약간의 차이점, 제약이 있다.

http://www.openldap.org/doc/admin22/syncrepl.html (openldap 2.2 매뉴얼)
While slapd (8) can function as the LDAP Sync provider only when it is configured with either back-bdb or back-hdb backend, the syncrepl engine, which is a consumer-side replication engine, can work with any backends.

http://www.openldap.org/doc/admin23/syncrepl.html (openldap 2.3매뉴얼)
The syncrepl engine, which is a consumer-side replication engine, can work with any backends. The LDAP Sync provider can be configured as an overlay on any backend, but works best with the back-bdb or back-hdb backend. The provider can not support refreshAndPersist mode on back-ldbm due to limits in that backend's locking architecture.

2.2 에서 마스터서버는 백엔드로 back-bdb, back-hdb 가 필요하고 슬레이브에서는 백엔드 제한이 없다. rpm 패키지에는 back-bdb 가 동작하지 않았으며 이에 대한 지원은 빠져있는 듯하다. 2.3 에서는 이러한 제한이 없다. 그렇지만 2.3에서도 백엔드로 back-bdb 나 back-hdb를 추천하고 있다.

설정하는 방법도 약간의 차이가 있으며 이는 매뉴얼을 참고한다.

구현순서

  • 마스터서버의 slapd 대몬 내림
  • 마스터서버의 slapd.conf 설정
  • 마스터서버의 데이타를 슬레이브에 복사하고 슬레이브 서버에 넣어줌 (이경우 슬레이브 서버는 내려가 있다고 가정하고 이후에 세부 설정함)
  • 슬레이브서버의 slpad.conf를 설정
  • 슬레이브서버의 slapd 시작
  • 마스터서버의 slapd 시작
  • 마스터서버의 slurpd 시작 (centOS 에서는 replica 설정이 있는 경우 시작스크립트에서 자동으로 slapd, slurpd 함께 시작함)

마스터서버 설정

마스터서버에서는 아래의 내용을 /etc/openldap/sldapd.conf 에 추가한다.

replogfile /var/lib/ldap/openldap-master-replog
replica uri=ldap://cent.tunelinux.pe.kr:389
        suffix="dc=example,dc=com"
        binddn="cn=replica,dc=example,dc=com"
        credentials=xxxx
        bindmethod=simple
        tls=yes

replogfile 은 마스터서버에서 slapd가 로그 변화를 기록하는 파일이다. 이 파일을 slurpd가 읽어서 슬레이브 서버로 보낸다.
replica 를 이용하여 각 슬레이브 서버를 지정한다.

  • uri : 슬레이브 서버 및 포트
  • suffix : suffix
  • binddn : 슬레이브 서버의 sldapd.conf 에서 updatedn 과 일치해야한다. 슬레이브 서버에서 이 권한을 가지고 마스터서버에서 오는 로그를 기록한다. 마스터서버의 rootdn과는 당연히 다르게 하는것이 좋을 것이다.
  • bindmethod는 슬레이브와 통신을 하는데 사용하며 simple, sasl 을 선택할 수 있다. 여기서는 simple을 선택하였으며 credentials 는 슬레이브 서버에 바인드하기 위한 패스워드이다. 이는 슬레이브서버에서 지정한 것을 넣으면 된다.
  • tls 는 마스터서버와 슬레이브서버간의 통신을 암호화한다.
  • 마스터서버에서 데이타를 슬레이브서버로 옮기는 경우에 ldap서버를 내리고 slapcat 을 이용하여 LDIF 파일형태로 옮길 수 있다. 리플리카(슬레이브)에서는 slapadd 를 이용하여 데이타를 복원하면 된다. 그전에 slapd.conf 설정은 되어있어야 할 것이다.

    root@master# slapcat -b "dc=example,dc=com" -l contents.ldif
    ... contents.ldif를 슬레이브로 복사한다.
    root@replica# slapadd -l contents.ldif 
    

슬레이브서버 설정

> rootdn                "cn=replica,dc=example,dc=com"
> rootpw                {SSHA}IgT24XXXXEGN9aaLhBduKPJCp
> updatedn      "cn=replica,dc=example,dc=com"
> updateref     ldap://cent3.tunelinux.pe.kr
  • updatedn : 마스터서버의 설정과 일치해야한다. updatedn은 해당 데이타에 쓰기 권한이 있어야 한다.
  • updateref : 클라이언트에게 마스터 디렉토리 서버를 알려주는 URL. 클라이언트가 업데이트 요청을 하는 경우 마스터서버를 알려준다.

리플리케이션시 작동방식

클라이언트에서는 /etc/ldap.conf 의 host 에 master, slave 서버를 모두 지정해준다. 슬레이브에서는 updateref를 이용하여 슬레이브에 업데이트요청시 마스터서버로 업데이트 요청을 보낸다. 예를 들어 위에서 people에 속한 사용자의 경우 자신의 패스워드를 변경할 수가 있다. 이경우 slave 서버에서 자신의 패스워드를 변경할 경우 이에 대한 요청은 마스터로 가고 마스터에서 업데이트한후 다시 슬레이브서버로 동기화가 된다. 단, rootdn은 직접 작동하였다.

추가정보

GUI tool

  • http://ldapadmin.sourceforge.net/ ldap 검색, 수정 등 할 수 있는 윈도우 공개프로그램(GPL) 이 실제 사용해보니 편리함. GUI에서 사용자 이동, 복사, 그룹에 여러 사용자 추가등 가능함

아래 화면과 같이 설정을 한다.
Host : ldap 서버 주소
Port : 기본 389 (ssl 체크할 경우 자동 변경됨)
Base : Base dn . 여기 예제에서는 dc=example,dc=com

Username : 접속할 dn
Password : 비밀번호

로그확인

sldapd.conf 에서 loglevel 을 설정한다.
296 = 256 log connections/operations/results + 32 search filter processing + 8 connection management

loglevel        256

LDAP은 LOG_LOCAL4 facility를 사용하므로 /etc/syslog.conf 에 아래의 설정을 한다. ldap만 별도 파일로 저장할 수도 있다. 이 경우에는 로그로테이션을 주기적으로 해주어야 한다.

# grep local4 /etc/syslog.conf
local4.*                                                /var/log/messages

이경우 syslogd 를 다시 재시작해주어야 한다.

참고로 openldap 문서에도 로그레벨에 대한 내용은 있지만 남겨진 로그를 어떻게 분석하면 되는지에 대해서는 상세한 설명은 없었다. 이에 대해서는 작동방식은 비슷할 것이라 여겨지므로 레드햇 디렉토리 서버의 매뉴얼을 참고하면 될 듯 하다. 이에 대한 내용은 http://www.redhat.com/docs/manuals/dir-server/ 레드햇 디렉토리 서버 매뉴얼 중에서 Configuration, Command, and File Reference 의 Chapter 5 Access Log and Connection Code Reference 를 참고한다. 여기서 로그에 남는 기록이 어떤 에러코드인지 설명을 참고하자.

동적인 서버설정 지원

openldap 2.3에서는 slapd.conf 설정도 LDIF 형태를 지원한다. 그래서 운영중인 상태에서도 ldap 서버의 설정값을 변경할 수 있다. 현재 CentOS 4.4 에 있는 rpm은 2.2 버전이다.

Object Class Types

Object Class Types 은 Structural , Auxiliary, Abstract 세가지가 있다.
주의사항으로는 LDAP 디렉토리의 각 엔트에는 하나의 Structural object class만 있어야 한다. (오렐리 LDAP admin 20페이지)

접근제어

http://www.openldap.org/doc/admin23/slapdconfig.html#Access%20Control 참고
아래의 경우는 userPassword는 사용자만 변경하도록 하고 다른 사람은 볼 수 없도록 하며 mobile 등의 속성은 사용자가 변경가능하되 특정 dn에 속하는 사용자가 읽을 수 있도록 하였다.
특정 서브트리마다 접근권한을 제한하였고 group을 이용하여 linuxadmin 그룹에 속한 사용자만이 ou가 group, hosts, netgroup 등에 쓰기를 할 수 있도록 하였다.

주의사항

접근제어에서 중요한 것은 특정 조건에 대한 것을 앞으로 해두어야 한다는 것이다.
포괄적인 것을 앞에 두면 뒤에 세부적인 접근제어가 있어도 앞의 내용이 적용이 되어 실제 세부적인 접근제어를 하지 못하게 된다.


access to dn.subtree="dc=example,dc=com" attr=userPassword
        by self write
        by * auth

access to dn.subtree="dc=example,dc=com" attrs=mobile,homePhone,examplehomePostalCode,homePostalAddress
        by self write
        by dn.subtree="dc=example,dc=com" read

access to dn.subtree="ou=people,dc=example,dc=com"
        by dn.subtree="dc=example,dc=com" read
        by dn="cn=intranetadmin,ou=admingroup,dc=example,dc=com" write

access to dn.subtree="ou=role,dc=example,dc=com"
        by dn.subtree="dc=example,dc=com" read
        by dn="cn=intranetadmin,ou=admingroup,dc=example,dc=com" write

access to dn.subtree="ou=group,dc=example,dc=com"
        by group/groupOfUniqueNames/uniqueMember="cn=linuxadmin,ou=admingroup,dc=example,dc=com" write
        by dn.subtree="dc=example,dc=com" read

access to dn.subtree="ou=hosts,dc=example,dc=com"
        by group/groupOfUniqueNames/uniqueMember="cn=linuxadmin,ou=admingroup,dc=example,dc=com" write
        by dn.subtree="dc=example,dc=com" read

access to dn.subtree="ou=netgroup,dc=example,dc=com"
        by group/groupOfUniqueNames/uniqueMember="cn=linuxadmin,ou=admingroup,dc=example,dc=com" write
        by dn.subtree="dc=example,dc=com" read

access to dn.subtree="ou=admingroup,dc=example,dc=com"
        by dn.subtree="dc=example,dc=com" read

access to *
        by * auth

db 생성, 관리프로그램

slapadd : 오프라인에서 데이타 추가
slapindex : 오프라인에서 인덱스 재생성. slapd.conf 에서 설정이 바뀐 경우 기존 인덱스가 자동으로 변경되지 않는다. 이러한 경우 필요하다.
slapcat : 오프파인에서 데이타를 LDIF 형태로 덤프뜰때 사용. 백업시 편리함.

nscd 네임서비스 캐슁 대몬 사용하기

nscd는 NIS, DNS 등의 네임서비스를 캐슁할 수 있는데 /etc/nscd.conf 에서 기본설정은 passwd, group, hosts 가 지정되어 있다. LDAP과 연동을 하는 경우 nscd를 사용하여 좀더 빠른 결과를 얻을 수 있을 것이다.

inetOrgPersion 이용하여 개인정보 이용하기

Object Class에서 위는 account를 이용하였다. 그런데 accout는 다양한 개인정보를 담기에 는 불편하다. 예를 들어 email 등. 이럴 경우 account 대신 inetOrgPersion Object class를 이용할 수 있다. 여기서는 cn, sn이 필수요소이다. cpu 프로그램에서는 사용자의 오브젝트 클래스 지정하는 부분에서 account를 아래와 같이 inetOrgPerson 으로 바꾸어주고 사용자를 추가하거나 변경할 때 몇가지 옵션을 더 이용해야 한다. 위에서 말을 한대로 Structural Object는 한가지만 사용할 수 있는데 accout, inetOrgPerson은 Structural 오브젝트 클래스이고 posixAccount,shadowAccount,top 는 AUXILIARY 오브젝트 클래스이다.

#USER_OBJECT_CLASS      = account,posixAccount,shadowAccount,top
USER_OBJECT_CLASS       = inetOrgPerson,posixAccount,shadowAccount,top

-f (firstname,cn), -e (lastname, sn) -e (email) 옵션을 이용하면 된다.

# cpu useradd joo --firstname=문 --lastname=태준 -e joon@tunelinux.pe.kr
User joo successfully added!

스키마 확장

스키마를 확장할 경우 attribute type 과 object classes 에 대한 유일한 OID를 할당하고 스키마 파일을 생성하여 slapd.conf에 포함시켜주면 된다. 내부적으로만 쓴다면 OID를 등록하지 않아도 되지만 외부와 함께 쓸 경우에는 충달할 수가 있다.

OID는 1.3.6.1.4.1. 이후가 private/enterprise 영역에 속한다. 아래와 같이 추가하고 이 파일을 slapd.conf에 추가해주면 여기서 만든 스키마를 사용할 수 있다. 아래는 참고예제로만 사용하길 바란다. plainjoePerson object class는 person을 상속받되 userPassword 와 mail은 필수로 있어야 하지만 새로 정의한 plainjoePath 는 없어도 괜찮다. 1.3.6.1.4.1.7777.1.1.2.1 은 OID, EQULITY 와 SUBSTR은 검색(matching rule)과 관련되어있으며 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 는 dbms에서 데이타타입과 비슷하게 생각하면 된다.

attributetype ( 1.3.6.1.4.1.7777.1.1.2.1  NAME 'plainjoePath'
        DESC 'A directory on disk'
        SUBSTR caseExactIA5SubstringsMatch
        EQUALITY caseExactIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )

objectclass ( 1.3.6.1.4.1.7777.1.1.1.1 NAME 'plainjoePerson'
        SUP person STRUCTURAL
        MUST (userPassword $ mail)
        MAY ( plainjoePath ) )

openldap에서 스키마 확장에 대한 부분은 openldap 사이트의 http://www.openldap.org/doc/admin23/schema.html#Extending%20Schema 에서 확인하면 된다.

오렐리 ldap admin 책에서는 95쪽을 참고한다.

현재 **회사는 예전에 ldap 에 등록한 oid가 있으며 http://www.iana.org/assignments/enterprise-numbers 에서 확인이 가능하다. 등록한 oid는 1.3.6.1.4.1.7290이다.

http://www.openldap.org/doc/admin23/schema.html#Extending%20Schema 에서 제공하는 가이드라인에 따라 구성하면 다음과 같다.
1.3.6.1.4.1.7290 example
1.3.6.1.4.1.7290.1 SNMP
1.3.6.1.4.1.7290.2 LDAP
1.3.6.1.4.1.7290.2.1 attributes
1.3.6.1.4.1.7290.2.1.1 myattributes
1.3.6.1.4.1.7290.2.2 ObjectClasses
1.3.6.1.4.1.7290.2.2.1 myObjectClasses

SSL 인증서 만들어서 여러 서비스에 활용하기

ldap에서 별도로 인증키를 만들어 사용하다가 apache 등에서 함께 이용하는 방법을 찾아보았다.
SSL 관련하여 다루어야 할 것이 여러가지 있기에 별도의 장으로 뺐다.

자체사인한 ssl 인증서 생성 스크립트

self 사인한 ssl 인증서를 생성하는 스크립트이다.

#!/bin/bash
# joon
# 자체 사인한 인증서를 생성하며 만료기간은 1825일(5년)으로 해 두었다.
# 프라이비트키는 root로 두어야하지만 ldap 사용자가 읽어야 하기에 ldap 사용자 계정으로 바꾸어주었다.
KEY_NAME='wiki.tunelinux.pe.kr'
KEY_DIRECTORY=/usr/local/direct/ssl
CA_DIRECTORY=$KEY_DIRECTORY/cacerts
PUBLIC_KEY=$CA_DIRECTORY/$KEY_NAME.crt
PRIVATE_KEY=$KEY_DIRECTORY/$KEY_NAME.key
DAYS="1825"

[ -f $PUBLIC_KEY ] && mv -fv $PUBLIC_KEY $PUBLIC_KEY.orig
[ -f $PRIVATE_KEY ] && mv -fv $PRIVATE_KEY $PRIVATE_KEY.orig

[ ! -d $KEY_DIRECTORY ] && mkdir -p $KEY_DIRECTORY
[ ! -d $CA_DIRECTORY ] && mkdir -p $CA_DIRECTORY

cd /etc/openldap
ln -s $CA_DIRECTORY .

SUBJ='/C=KR/ST=gurogu/L=seoul/O=example/OU=itservice/CN='$KEY_NAME

/usr/bin/openssl req -new -nodes -keyout $PRIVATE_KEY -x509 -days $DAYS -out $PUBLIC_KEY -subj $SUBJ

/bin/chmod 644 $PUBLIC_KEY*
/bin/chown ldap.ldap $PRIVATE_KEY
/bin/chmod 400 $PRIVATE_KEY*

/etc/init.d/ldap restart
/etc/init.d/httpd restart
/usr/sbin/cacertdir_rehash $CA_DIRECTORY

위와 같은 작업을 한후 /etc/openldap/slapd.conf 에서 다음과 같이 설정한다.

TLSCipherSuite HIGH:MEDIUM:+SSLv2
TLSCACertificateFile /usr/local/direct/ssl/cacerts/wiki.tunelinux.pe.kr.crt
TLSCertificateFile /usr/local/direct/ssl/cacerts/wiki.tunelinux.pe.kr.crt
TLSCertificateKeyFile /usr/local/direct/ssl/wiki.tunelinux.pe.kr.key

웹서버설정에서는 아래과 같이 지정한다.
/etc/httpd/conf.d/ssl.conf

SSLCertificateFile /usr/local/direct/ssl/cacerts/wiki.tunelinux.pe.kr.crt
SSLCertificateKeyFile /usr/local/direct/ssl/wiki.tunelinux.pe.kr.key

키생성하기

아래는 개인키를 mirror.key 로 인증서를 mirror.crt로 만드는 경우이다.
nodes 옵션은 서버 재시작시 비밀번호를 입력하지 않도록 하기 위해서 사용한다.
root ca를 별도로 생성하지 않고 x509 옵션을 이용하여 자체 사인하여 사용하는 것이다.
mirror.crt 가 public key 이고 자체사인한 것이기 때문에 공인받지 않은 root ca 로 생각하면 될 듯 하다.
자체인증하여 사용하므로 days는 일부러 길게 주었다.

openssl req -new -nodes -keyout mirror.key -x509 -days 1825 -out mirror.crt

cn 도메인네임은 운영하려는 서버에 해당하는 것을 넣으면 된다.

openldap 에서 이용하기

openldap에서는 위에서 만든 것을 아래와 같이 지정해준다.CA Certi 와 Certi 가 동일하다.
/etc/openldap/test 에 인증서를 놓아둔 경우이다.

TLSCACertificateFile /etc/openldap/test/mirror.crt
TLSCertificateFile /etc/openldap/test/mirror.crt
TLSCertificateKeyFile /etc/openldap/test/mirror.key

사용자 인증으로 ldap 을 사용할 경우 /etc/ldap.conf 에서 tls_cacertdir 이 /etc/openldap/cacerts 로 지정되어 있는 경우 mirror.crt 파일을 이 디렉토리로 복사해주고 cacertdir_rehash 명령을 실행해주어야 한다.

/usr/sbin/cacertdir_rehash /etc/openldap/cacerts/

apache 에서 ssl 이용하기

apache ssl 설정

apache 에서 ssl 설정은 다음과 같다. https로 테스팅을 해보기 바란다.
centos 에서 rpm으로 설치한 경우 /etc/httpd/conf.d/ssl.conf 파일을 조정한다.

SSLCertificateFile /etc/openldap/test/mirror.crt
SSLCertificateKeyFile /etc/openldap/test/mirror.key

여기에서 mirror.crt 파일은 공인인증을 받지 않았으므로 윈도우에서 crt 파일을 클릭한 경우 인증서가져오기(확장자를 .crt로 하면 됨)를 실행하여 인증서를 저장하면 된다.
그러면 웹브라우즈에서도 인증서 설치한 이후에는 편리하게 사용할 수 있다.

apache 에서 ldap인증을 사용할 경우

apache 에서 ldap 인증을 사용하는 경우에는 아래 내용이 먼저 httpd.conf에 있어야한다. CA키로 mirror.crt를 지정하는 것이다.

LDAPTrustedCA /etc/openldap/test/mirror.crt
LDAPTrustedCAType BASE64_FILE

이제 htaccess 파일에서 아래와 같이 지정을 하면 된다.

# cat .htaccess
AuthType Basic
AuthName "example Staff Only"
AuthLDAPBindDN cn=readonly,ou=admingroup,dc=example,dc=com
AuthLDAPBindPassword readonly
AuthLDAPURL ldaps://xxxx.direct.co.kr/ou=people,dc=example,dc=com?uid?sub?(objectClass=*)
require valid-user

주소록

아웃룩등의 주소록에서는 기타 설정에서 SSL사용을 체크해주면 된다.

ldapadmin 프로그램

자체서명해서 사용하면 ldapadmin 에서는 셀프사인한 root 인증서라는 주의사항이 나온다. 이것은 불편해서 그냥 사용을 해야 할 듯하다.

SSL/TLS 사용하여 php프로그래밍하기

  • LDAP의모든것2 문서에 넣은 내용이지만 관련이 있기에 여기에도 넣는다.
  • SSL/TLS에 대하여
    SSL과 TLS는 다른 부분입니다.
    오고가는 패킷을 암호화하는 것은 SSL/TLS 두가지 방법이 있습니다.

오렐리 LDAP 서적 26쪽에 나와있는 내용입니다.

  • LDAP over SSL (LDAPS - 636 port) 일반적으로 말하는 SSL입니다.
  • TLS : 389 PORT 로 암호화해서 통신하는 기능으로 RFC 2830 에서 추가된 기능이라고 합니다. 389 동일한 포트에서 암호화 되지 않은 패킷과 암호화된 패킷을 동시에 전송할 수 있는 기능입니다.
  • SSL/TLS 사용시 php로 프로그래밍을 할 경우 주의사항
    php에는 ssl 을 지원하는 636 port 로 접속할 경우 host 에 ldaps 로 지정하고 포트를 636 지정합니다. start_tls는 명시하지 않습니다. 오히려 명시하면 에러가 나지요.

TLS를 이용하는 경우는 389 PORT 자체적으로 암호화를 지원하기 때문에 389 포트를 이용합니다. PHP 의 경우는 기본적으로 프로토콜 2를 사용하기 때문에 프로토콜 3을 사용하도록 옵션을 세팅하고 호스트에서는 ldaps 가 아닌 ldap으로 지정을 합니다. 반드시 start_tls 옵션을 사용해야지요.

ldaps 와 start_tls 기능은 별개입니다.

그리고 SSL이나 TLS를 이용하는 경우 접속하려는 호스트에서 서버의 인증서가 있어야 합니다. 리눅스의 경우 /etc/openldap/cacerts 디렉토리에 ca인증서가 있으며 LDAP서버의 CA인증서를 복사해놓고 authconfig 를 이용하여 ldap 사용을 다시 지정해주어야 합니다. 이에 대해서는 openldap 에서 SSL/TLS 부분을 참고합니다.

다시 정리하면 다음과 같습니다.

  • PHP에서는 기본적으로 프로토콜 2를 사용하기 때문에 프로토콜 3을 사용하도록 옵션을 세팅
  • SSL을 사용할 경우 636 포트를 사용하고 서버는 ldaps:// 으로 지정합니다.
  • TLS를 사용할 경우 389 포트를 사용하고 서버는 ldap:// 으로 지정합니다. ldap_start_tls 를 지정해줘야 사용이 가능합니다.
  • ldap_start_tls 는 ldap 서버에 연결(connect)한후 바인드(ldap_bind) 하기전에 지정합니다.
  • 포트를 지정하지 않을 경우 SSL이냐 TLS냐에 따라 자동으로 포트를 선택합니다.

참고자료 : php 에서 start_tls 사용하기 http://kr.php.net/ldap_start_tls

  • 참고코드
    위의 검색코드와 비교해보면 됩니다. 아래는 TLS를 이용할 경우이므로 만약 SSL 636 포트를 사용하고자 할 경우에는 서버를 ldaps로 지정하고 포트를 636으로 바꾸어준다. ldap_start_tls는 지정하면 안된다.

    $target="cent3";
    
    if($target=="aaaa")
    {
            $ldaphost="ldap://aaaa.co.kr/";
            //$ldaphost="ldaps://aaaa.co.kr/";
            $ldap_port=389;
            //$ldap_port=636;
            $userdn="cn=manager,dc=co,dc=kr";
            $password="aaaaaa";
            $basedn="ou=people,dc=dc=co,dc=kr";
    }
    
    if($target=="cent3")
    {
            //$ldaphost="ldaps://localhost/";
            $ldaphost="ldap://localhost/";
            //$ldap_port=636;
            $ldap_port=389;
            $userdn="cn=manager,dc=com";
            $password="bbbbb";
            $basedn="ou=people,dc=com";
    }
    
    if($ldap_port=="")
            $ldap_port="389";
    
    // 서버접속
    $ds=ldap_connect($ldaphost,$ldap_port) or die("Could not connect to {$ldaphost}");  // must be a valid LDAP server!
    //$ds=ldap_connect($ldaphost) or die("Could not connect to {$ldaphost}");  // must be a valid LDAP server!
    if ($ds) {
       if (!ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3)) {
         fatal_error("Failed to set LDAP Protocol version to 3, TLS not supported.");
       }
    }
    
    if (!ldap_start_tls($ds)) {
        echo "failed start_tls\n";
        exit;
    }
    
    // id, password 이용하여 bind
    $r=ldap_bind($ds,$userdn,$password) or die("Bind error");
    
    // 검색할 attr 제한. 이것이 없는 경우 전체 attr을 모두 검색함. 성능을 위하여 필요한 attr만 제한하는것이 좋음
    $justthese = array("uid","dn","cn", "mail", "gidNumber","uidNumber","o","pager","shadowExpire","userpassword");
    
    

기타

apache ldap인증의 경우 실제 서버세팅

AuthLDAPBindPassword 만 실제 비밀번호를 넣으면 된다.

AuthType Basic
AuthName "joon wiki system"
AuthLDAPURL ldap://hostname:389/ou=people,dc=example,dc=co,dc=kr?uid?sub?(objectClass=*)
require valid-user
AuthLDAPBindDN cn=readonly,ou=admingroup,dc=example,dc=co,dc=kr
AuthLDAPBindPassword xxxxx

ldap 연동시 apache configure 옵션

--enable-ldap --enable-auth-ldap \
--with-ldap \