OpenLDAP 호스트 접근 제어 구현 가이드

1. 호스트 제어 구현 방식

OpenLDAP에서 호스트 접근 제어를 구현하는 방법은 두 가지가 있다. 첫 번째는 시스템의 access 모듈을 활용하는 방식으로, 사용자 로그인 제한을 구현할 수 있지만 설정이 복잡하고 유연성이 부족하다. 두 번째는 OpenLDAP 서버 측에서 스키마와 오브젝트 클래스를 정의하고 사용자 엔트리 속성을 추가한 후, 클라이언트 설정과 결합하는 방식이다. 이 방법은 관리 측면에서简便하고 유연성이 높다.

2. Linux-PAM 모듈을 활용한 제어

2.1 Linux-PAM 아키텍처

기본적으로 UNIX/Linux 시스템에 로그인할 때, PAM(Pluggable Authentication Modules) 모듈이 사용자의 신원 검증과 비밀번호 확인을 담당한다. Linux-PAM의 구성은 다음과 같다:
+----------------+
| application: X |
+----------------+       /  +----------+     +================+
| authentication-[---->--\--] Linux-   |--<--| PAM config file|
|       +        [----<--/--]   PAM    |     |================|
|[conversation()][--+    \  |          |     | X auth .. a.so |
+----------------+  |    /  +-n--n-----+     | X auth .. b.so |
|                |  |       __|  |           |           _____/
|  service user  |  A      |     |           |____,-----'
|                |  |      V     A
+----------------+  +------|-----|---------+ -----+------+
                     +---u-----u----+    |      |      |
                     |   auth....   |--[ a ]--[ b ]--[ c ]
                     +--------------+
                     |   acct....   |--[ b ]--[ d ]
                     +--------------+
                     |   password   |--[ b ]--[ c ]
                     +--------------+
                     |   session    |--[ e ]--[ c ]
                     +--------------+

2.2 PAM 설정 파일 문법

PAM 설정 파일 경로:
$ ls /etc/pam.conf # 구버전
$ ls /etc/pam.d/*  # 신버전
PAM 모듈 경로:
$ ls /lib64/security/  # x86_64
$ ls /lib/security/    # x86_32
기본 시스템 설정 파일:
/etc/pam.d/system-auth

3. Access 제어를 통한 사용자 관리 실습

3.1 pam_access 모듈 기능 개요

pam_access 모듈은 특정 머신에 대한 로그인 접근을 제어하는 역할을 한다. 기본적으로 /etc/security/access.conf 파일을 참조하여 다양한 접근 제어를 적용한다. access.conf 파일이 작동하려면 /etc/pam.d/login 파일에 pam_access.so 모듈이 로드되어 있어야 한다.

3.2 Access 설정 문법

pam_access.so 모듈은 access.conf 파일에 정의된 조건에 따라 인증을 처리한다. 설정 형식은 다음과 같다:
permission: user: origin
각 파라미터 의미: - permission: "+"는 허용, "-"는 거부. EXCEPT 키워드를 활용하면 전체 거부 후 일부 허용 가능 - user: 허용 또는 거부할 사용자 또는 그룹. "all"은 모든 사용자 지정 - origin: 로그인 대상 위치로, local(로컬), console(콘솔), all(전체), 네트워크 주소 등 지정 가능

3.3 실제 설정 적용

pam_access.so 모듈 로드 제한이 필요한 클라이언트 머신에서 /etc/pam.d/sshd 파일을 편집한다. account 섹션의 최상위에 다음 내용을 추가한다:
[root@dir01 ~]# vim /etc/pam.d/sshd
#%PAM-1.0
auth       required     pam_sepermit.so
auth       substack     password-auth
auth       include      postlogin
-auth      optional     pam_reauthorize.so prepare
account    required     pam_access.so  # 새로 추가하는 account는 최상위에 위치해야 함
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
접근 규칙 설정
[root@server01 ~]# vim /etc/security/access.conf
-:testuser1:ALL         # testuser1 사용자의 server01.example.com 접근 차단
검증
[root@server01 ~]# ssh testuser1@192.168.1.132
testuser1@192.168.1.132's password: 
Permission denied, please try again.

[root@server01 ~]# tail /var/log/secure
Apr 23 00:02:01 server01 sshd[38953]: fatal: Access denied for user testuser5 by PAM account configuration [preauth]
Apr 24 22:27:33 server01 sshd[46999]: Accepted password for root from 192.168.1.1 port 1366 ssh2
Apr 24 22:27:33 server01 sshd[46999]: pam_unix(sshd:session): session opened for user root by (uid=0)
Apr 24 22:37:34 server01 sshd[47514]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=server01.example.com  user=testuser1
여러 사용자의 접근을 관리하려면 OpenLDAP 서버에서 해당 사용자를 특정 그룹에 포함시킨 후, access.conf에서 그룹 단위로 제어를 설정하면 된다. 모든 인증 정보는 OpenLDAP 서버에서 조회된다. 4. OpenLDAP 서버 측 호스트 제어 규칙 OpenLDAP 서버에서는 커스텀 모듈과 호스트 설정을 통해 사용자별 로그인 권한을 세밀하게 제어할 수 있다.

4.1 olcModuleList 객체 정의

# olcModuleList 객체 확인 (기존 module{0}.ldif 파일이 있으면 생략 가능)
$ cat << EOF | ldapadd -Y EXTERNAL -H ldapi:///
dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
EOF

4.2 모듈 경로 추가

$ cat << EOF | ldapadd -Y EXTERNAL -H ldapi:///
dn: cn=module{0},cn=config
changetype: modify
add: olcModulePath
olcModulePath: /usr/lib64/openldap/
EOF

4.3 호스트 제어 모듈 로드

[root@dir01 ~]# cat << EOF | ldapmodify -c -Y EXTERNAL -Q -H ldapi:///
dn: cn=module{0},cn=config
add: olcModuleLoad
olcModuleLoad: dynlist.la
EOF
modifying entry "cn=module{0},cn=config"

4.4 호스트 오브젝트 클래스 정의

[root@dir01 ~]# cat << EOF | ldapadd -Y EXTERNAL -H ldapi:///
dn: olcOverlay=dynlist,olcDatabase={2}hdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcDynamicList
olcOverlay: dynlist
olcDlAttrSet: inetOrgPerson labeledURI
EOF

4.5 ldapns 스키마 정의

[root@dir01 ~]# cat << EOF | ldapadd -Y EXTERNAL -H ldapi:///
dn: cn=ldapns,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: ldapns
olcAttributeTypes: {0}( 1.3.6.1.4.1.5322.17.2.1 NAME 'authorizedService' DESC 'IANA GSS-API authorized service name' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
olcAttributeTypes: {1}( 1.3.6.1.4.1.5322.17.2.2 NAME 'loginStatus' DESC 'Currently logged in sessions for a user' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch ORDERING caseIgnoreOrderingMatch SYNTAX OMsDirectoryString )
olcObjectClasses: {0}( 1.3.6.1.4.1.5322.17.1.1 NAME 'authorizedServiceObject' DESC 'Auxiliary object class for adding authorizedService attribute' SUP top AUXILIARY MAY authorizedService )
olcObjectClasses: {1}( 1.3.6.1.4.1.5322.17.1.2 NAME 'hostObject' DESC 'Auxiliary object class for adding host attribute' SUP top AUXILIARY MAY host )
olcObjectClasses: {2}( 1.3.6.1.4.1.5322.17.1.3 NAME 'loginStatusObject' DESC 'Auxiliary object class for login status attribute' SUP top AUXILIARY MAY loginStatus )
EOF

4.6 호스트 그룹 정의

호스트 그룹(ou)을 구성하여 효율적인 관리 가능한다. servers OU 하에 apphost와 dbahost 서브 OU를 생성하고, 각각的应用 시스템과 데이터베이스 시스템을 분류한다. 예를 들어, 앱 사용자는 JBOSS, Tomcat, Nginx, OpenStack 등 앱 서버와 Cacti, Nagios, Zabbix 같은 모니터링 시스템에만 접근 가능하도록 하고, DB 사용자는 Oracle, MySQL, MariaDB 등 데이터베이스 서버만 접근하도록 제한할 수 있다.
[root@dir01 ~]# cat << EOF | ldapadd -x -D "cn=admin,dc=dir01,dc=example,dc=com" -w password123 -H ldap://dir01.example.com
dn: ou=servers,dc=dir01,dc=example,dc=com
objectClass: organizationalUnit
ou: servers

dn: ou=apphost,ou=servers,dc=dir01,dc=example,dc=com
objectClass: organizationalUnit
objectClass: hostObject
ou: apphost
host: server01.example.com
EOF
OU 생성 시 hostObject 클래스를 적용하고 host 속성에 호스트 정보를 지정하여 apphost 그룹에 server01.example.com을 포함시킨다.

4.7 사용자 그룹 및 사용자 정의

사용자를 특정 그룹에 할당하여 그룹 단위로 호스트 접근을 제어한다. 예: appgroup 그룹과 appuser1 사용자 그룹 추가
cat << EOF | ldapadd -x -D "cn=admin,dc=dir01,dc=example,dc=com" -w password123 -H ldap://dir01.example.com
dn: cn=appgroup,ou=Group,dc=dir01,dc=example,dc=com
objectClass: posixGroup
cn: appgroup
gidNumber: 10010
EOF
사용자 추가 및 호스트 연결
[root@dir01 ~]# cat add_user.ldif
dn: uid=appuser1,ou=People,dc=dir01,dc=example,dc=com
uid: appuser1
cn: appuser1
sn: app
objectClass: person
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
objectClass: inetOrgPerson
userPassword: password123
shadowLastChange: 19096
shadowMin: 0
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 1010
gidNumber: 10010
homeDirectory: /home/appuser1
labeledURI: ldap:///ou=apphost,ou=servers,dc=dir01,dc=example,dc=com?host

[root@dir01 ~]# ldapadd -x -D "cn=admin,dc=dir01,dc=example,dc=com" -w password123 -H ldap://dir01.example.com -f add_user.ldif
검증
[root@dir01 ~]# ldapsearch -x -D "cn=admin,dc=dir01,dc=example,dc=com" -w password123 -H ldap://dir01.example.com -b "uid=appuser1,ou=People,dc=dir01,dc=example,dc=com"
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# appuser1, People, dir01.example.com
dn: uid=appuser1,ou=People,dc=dir01,dc=example,dc=com
uid: appuser1
cn: appuser1
sn: app
objectClass: person
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
objectClass: inetOrgPerson
userPassword:: e1NTSEF9STZZcjZhV0FOdTh6UkpUNEV5eVB2Y3dGUzNmeCtRMnU=
shadowLastChange: 19096
shadowMin: 0
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 1010
gidNumber: 10010
homeDirectory: /home/appuser1
labeledURI: ldap:///ou=apphost,ou=servers,dc=dir01,dc=example,dc=com?host
host: server01.example.com

[root@dir01 ~]# ldapsearch -x -D "cn=admin,dc=dir01,dc=example,dc=com" -w password123 -H ldap://dir01.example.com "host=server01.example.com"
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: host=server01.example.com
# requesting: ALL
#

# jboss, People, dir01.example.com
dn: uid=jboss,ou=People,dc=dir01,dc=example,dc=com
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
cn: jboss
uid: jboss
uidNumber: 20006
gidNumber: 10005
userPassword:: amJvc3M=
homeDirectory: /home/jboss
loginShell: /bin/bash
host: server01.example.com

# apphost, servers, dir01.example.com
dn: ou=apphost,ou=servers,dc=dir01,dc=example,dc=com
objectClass: organizationalUnit
objectClass: hostObject
ou: apphost
host: server01.example.com

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

4.8 인덱스 추가

[root@dir01 ~]# grep olcDbIndex /etc/openldap/slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif
[root@dir01 ~]# cat << EOF | ldapadd -Y EXTERNAL -H ldapi:///
dn: olcDatabase={2}hdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: host eq
EOF

5. 클라이언트에서 LDAP 호스트 제어 규칙 활성화

CentOS 6
$ cat >> /etc/pam_ldap.conf << EOF
pam_check_host_attr yes
EOF
CentOS 7
cat >> /etc/nslcd.conf << EOF
pam_authz_search (&(objectClass=posixAccount)(uid=\$username)(|(host=\$hostname)(host=\$fqdn)(host=\\\*)))
EOF

$ systemctl restart nslcd

태그: openldap ldap authentication pam access-control

6월 5일 20:10에 게시됨