Active Directory 처럼 "계정 사용 안 함" 체크 하나로 끝나는 기능이 OpenLDAP 에는 없다. 무엇을 막고 싶은지에 따라 방법이 달라진다.
| 목표 | 방법 |
|---|---|
| LDAP 바인드 자체를 막는다 (웹 로그인 포함) | userPassword 잠금 또는 ppolicy 잠금 |
| 리눅스 OS 로그인만 막는다 | shadowExpire · loginShell |
| 기간이 지나면 자동으로 막는다 | ppolicy 의 비밀번호 만료 |
| 다음 로그인 때 비밀번호를 바꾸게 한다 | pwdReset |
핵심은 애플리케이션이 무엇을 보느냐다. 웹 애플리케이션 대부분은 simple bind 성공 여부만 보고 shadowExpire 같은 POSIX 속성은 읽지 않는다. 그래서 shadowExpire 만 걸어 두고 "비활성화했다"고 생각하면 웹 로그인은 그대로 열려 있다.
dn: uid=testuser,ou=people,dc=example,dc=com
changetype: modify
replace: userPassword
userPassword: {SSHA}!disabled
해시 형식으로 해석되지 않는 값을 넣으면 어떤 비밀번호로도 바인드가 성립하지 않는다. ! 만 넣거나 {CRYPT}* 를 쓰는 관행도 같은 원리다.
ldapmodify -x -D "cn=admin,dc=example,dc=com" -W -f disable.ldif
ldapwhoami -x -D "uid=testuser,ou=people,dc=example,dc=com" -W # 실패해야 정상
단순하고 확실하지만 원래 비밀번호가 사라진다. 복직 · 오작동 대비가 필요하면 아래 ppolicy 잠금을 쓰거나, 기존 해시를 별도 속성에 보관하는 절차를 운영 문서로 남긴다.
정책 기반으로 다루려면 ppolicy 오버레이를 올린다.
# 모듈 적재
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy.la
# 오버레이 등록
dn: olcOverlay=ppolicy,olcDatabase={2}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcPPolicyConfig
olcOverlay: ppolicy
olcPPolicyDefault: cn=default,ou=policies,dc=example,dc=com
olcPPolicyHashCleartext: TRUE
# 정책 항목
dn: cn=default,ou=policies,dc=example,dc=com
objectClass: top
objectClass: device
objectClass: pwdPolicy
cn: default
pwdAttribute: userPassword
pwdMaxAge: 7776000
pwdExpireWarning: 604800
pwdInHistory: 5
pwdMinLength: 12
pwdLockout: TRUE
pwdMaxFailure: 5
pwdLockoutDuration: 900
pwdFailureCountInterval: 900
pwdGraceAuthNLimit: 0
pwdAttribute: userPassword 는 필수다. 값 단위는 초이며 pwdMaxAge: 7776000 은 90일이다.
특정 계정만 즉시 잠그려면 pwdAccountLockedTime 을 넣는다.
dn: uid=testuser,ou=people,dc=example,dc=com
changetype: modify
replace: pwdAccountLockedTime
pwdAccountLockedTime: 000001010000Z
이 값은 "잠긴 시각"이며 과거 시각을 넣어 사실상 영구 잠금으로 쓴다. 해제는 속성을 지우면 된다.
dn: uid=testuser,ou=people,dc=example,dc=com
changetype: modify
delete: pwdAccountLockedTime
pwdReset: TRUE 는 다음 바인드 때 비밀번호 변경을 요구한다. 클라이언트가 Password Modify 확장 연산을 지원해야 사용자 경험이 매끄럽다. 지원하지 않는 애플리케이션에서는 그냥 로그인 실패로 보인다.
dn: uid=testuser,ou=people,dc=example,dc=com
changetype: modify
replace: shadowExpire
shadowExpire: 1
shadowExpire 는 1970-01-01 부터의 일수이며 오늘보다 작으면 만료다. 항목에 objectClass: shadowAccount 가 있어야 하고, SSSD 가 shadow 정책을 평가하도록 설정돼 있어야 한다.
# /etc/sssd/sssd.conf
[domain/example.com]
ldap_pwd_policy = shadow
ldap_account_expire_policy = shadow
access_provider = ldap
ldap_access_order = expire
셸만 막는 방법도 있다.
replace: loginShell
loginShell: /sbin/nologin
이것은 SSH 접속만 막는다. LDAP 바인드를 쓰는 웹 로그인에는 아무 영향이 없다.
애플리케이션 쪽 설정으로 특정 상태의 계정을 아예 검색 대상에서 빼는 방법도 있다. 서버를 고치지 않아도 되어 가장 빨리 적용된다.
# 애플리케이션의 user filter
(&(objectClass=posixAccount)(!(employeeType=disabled)))
# SSSD
ldap_access_filter = (!(employeeType=disabled))
대신 애플리케이션마다 따로 설정해야 하며, 설정을 빠뜨린 서비스에서는 여전히 로그인된다. 확실한 차단은 서버 쪽(바인드 차단)이다.
운영 관례는 다음과 같다.
userPassword 잠금 또는 ppolicy 잠금).ou=DisabledUsers 같은 별도 트리로 이동, 이후 정책에 따라 삭제.즉시 삭제하면 파일 소유권이 숫자 UID 로 남고 감사 추적이 끊긴다. 잠금 → 보관 → 삭제 순서를 권한다.
userPassword 보호 규칙.