Active Directory와 LDAP는 같은 것이 아니다. Active Directory Domain Services(AD DS)는 사용자·컴퓨터·그룹과 정책을 관리하는 디렉터리 서비스이고, LDAP는 그 디렉터리를 조회하고 수정하는 데 사용하는 프로토콜이다. Windows 도메인 로그온에는 Kerberos·NTLM, 이름과 서비스 탐색에는 DNS 등 다른 프로토콜도 함께 관여한다.
“LDAP로 Active Directory에 로그인한다”는 표현은 상황을 빠르게 말할 때는 편하지만, 장애와 보안을 다룰 때는 어느 단계에서 어떤 프로토콜을 쓰는지 분리해야 한다.
AD DS, LDAP, Kerberos는 각각 무엇인가
| 구성 요소 | 역할 | 대표 질문 |
|---|---|---|
| AD DS | 객체·관계·정책을 보관하고 도메인 서비스를 제공 | 사용자는 어느 그룹에 속하는가? 이 컴퓨터는 어느 도메인에 가입했는가? |
| LDAP | 디렉터리의 객체를 검색·읽기·수정하고 bind하는 프로토콜 | 이 base DN 아래에서 조건에 맞는 사용자를 찾아 달라 |
| Kerberos | ticket을 이용한 네트워크 인증 프로토콜 | 이 사용자가 해당 서비스에 인증됐음을 어떻게 증명할까? |
| DNS | 도메인 컨트롤러와 Kerberos·LDAP 서비스 위치 탐색 | 어느 domain controller로 연결해야 하는가? |
| Group Policy | 도메인에 속한 사용자·컴퓨터 설정 관리 | 어떤 보안·운영 설정을 일괄 적용할까? |
AD DS는 LDAP를 지원하지만 LDAP만으로 구성되지 않는다. 반대로 OpenLDAP 같은 다른 디렉터리 서비스도 LDAP를 제공할 수 있다. 따라서 “LDAP 서버”라는 말만으로 AD DS의 도메인 가입, Group Policy, Kerberos 동작까지 기대하면 안 된다.
LDAP에서 실제로 다루는 데이터
LDAP 디렉터리는 항목(entry)을 계층적으로 관리한다. 각 항목에는 이름과 여러 속성이 있다.
- DN(Distinguished Name): 항목의 전체 위치. 예:
CN=Kim,OU=People,DC=example,DC=com - RDN(Relative Distinguished Name): 같은 부모 아래에서 항목을 구분하는 이름
- attribute:
cn,mail,memberOf처럼 항목이 가진 값 - objectClass: 해당 항목이 가져야 하거나 가질 수 있는 속성을 정하는 schema 규칙
- base DN과 scope: 검색을 시작할 위치와 현재 항목·한 단계·전체 하위 중 어디까지 볼지 정하는 범위
- filter: 반환할 항목을 좁히는 조건
AD DS에는 sAMAccountName, userPrincipalName, objectGUID처럼 AD 환경에서 자주 쓰는 속성이 있다. 표준 LDAP 속성과 제품별 schema를 구분하고, 애플리케이션이 실제로 필요한 속성만 요청해야 한다.
LDAP bind가 곧 애플리케이션 권한 부여는 아니다
LDAP bind는 LDAP 연결에서 사용할 인증 상태를 만든다. 익명 bind, 이름·비밀번호를 쓰는 simple bind, SASL을 이용한 방식 등이 있다. bind가 성공했다고 해서 사용자가 애플리케이션의 관리자라는 뜻은 아니다.
인증과 권한을 세 층으로 나누면 혼동이 줄어든다.
- LDAP 인증 상태: 이 연결이 어느 identity로 directory operation을 수행하는가?
- 디렉터리 접근 제어: 그 identity가 어떤 객체와 속성을 읽거나 수정할 수 있는가?
- 애플리케이션 권한 부여: 조회한 사용자·그룹을 서비스의 reader, operator, admin 중 어디에 연결하는가?
예를 들어 사용자의 비밀번호 bind가 성공해도, 애플리케이션은 허용된 그룹과 계정 상태를 별도로 확인해야 한다. 반대로 검색용 service identity에는 사용자 비밀번호나 민감한 속성을 수정할 권한이 없어야 한다.
Windows 로그온은 왜 LDAP만으로 설명할 수 없나
도메인에 가입한 Windows 환경의 통합 인증은 일반적으로 Kerberos를 우선 사용하고 조건에 따라 NTLM이 관여한다. LDAP는 사용자·그룹·컴퓨터 객체를 찾거나 directory operation을 수행하는 데 쓰인다.
client
├─ DNS: domain controller와 service 위치 탐색
├─ Kerberos/NTLM: 사용자 또는 service 인증
└─ LDAP: directory 객체와 속성 조회·변경
│
▼
Active Directory Domain Services
웹 애플리케이션이 직접 username과 password를 받아 LDAP bind하는 방식은 이 Windows 통합 로그온과도 다르다. 새 애플리케이션이라면 조직의 identity provider가 제공하는 OIDC나 SAML을 먼저 검토하고, AD DS·LDAP 직접 연동은 legacy protocol이나 명확한 directory 조회 요구가 있을 때 선택하는 편이 경계를 관리하기 쉽다.
직접 LDAP를 연동해야 한다면 지킬 기준
1. 평문 simple bind를 사용하지 않는다
비밀번호를 사용하는 simple bind는 TLS로 보호되지 않으면 credential과 directory data를 노출할 수 있다. LDAPS 또는 StartTLS 중 조직이 정한 방식을 쓰고 다음을 확인한다.
- server certificate의 hostname과 신뢰 체인 검증
- 허용할 TLS version과 cipher policy
- 인증서 만료·교체 시나리오
- timeout과 여러 domain controller failover
- AD DS의 LDAP signing·channel binding 정책과 client 호환성
인증서 검증을 끄는 옵션은 연결 장애를 잠시 숨길 뿐, 중간자 공격 가능성을 만든다.
2. 검색 identity와 권한을 최소화한다
검색용 계정에는 필요한 OU와 속성에 대한 read 권한만 준다. 애플리케이션 설정 파일이나 소스 코드에 비밀번호를 고정하지 말고, 승인된 secret 전달 경로와 rotation 절차를 둔다. directory administrator 계정을 application bind에 사용하는 것은 피한다.
3. 검색 범위와 filter를 고정한다
사용자 입력을 문자열로 이어 붙인 filter는 LDAP injection으로 이어질 수 있다. 예를 들어 다음은 구조를 보여 주는 템플릿일 뿐이다.
base DN: OU=People,DC=example,DC=com
filter: (&(objectCategory=person)(objectClass=user)(sAMAccountName={escaped_value}))
attrs: objectGUID, userPrincipalName, memberOf
{escaped_value}에는 RFC 4515 규칙을 구현한 library의 filter escaping 함수를 적용해야 한다. DN을 만들 때는 filter escaping이 아니라 DN 전용 escaping 규칙을 사용한다. base DN, scope, 반환 attribute와 최대 결과 수도 애플리케이션이 통제해야 한다.
4. 표시 이름 대신 안정된 식별자를 저장한다
cn이나 email은 바뀔 수 있다. AD DS의 immutable identifier와 애플리케이션 내부 user ID를 연결하고, 표시용 속성은 동기화 가능한 값으로 취급한다. group 이름을 role로 바꿀 때도 rename, nested group, 탈퇴와 계정 비활성화가 어떻게 반영되는지 정해야 한다.
5. 실패를 세분화해 관측한다
사용자 화면에는 계정 존재 여부가 드러나지 않는 일반적인 인증 실패를 반환하더라도, 운영 지표에서는 다음을 구분할 필요가 있다.
- DNS·network timeout
- TLS handshake·certificate 검증 실패
- bind credential 거부
- 검색 결과 0건·복수 건
- directory access denied
- group mapping 실패
- 모든 domain controller 연결 실패
비밀번호, bind DN 전체, 민감한 attribute나 원본 filter를 log에 남기지 않는다.
배포 전에 확인할 테스트
정상 계정 하나로 로그인되는지만 보면 부족하다.
- 잘못된 비밀번호와 존재하지 않는 사용자
- 잠김·비활성·만료된 계정
*,(,), 역슬래시가 포함된 입력- 인증서 만료·신뢰 실패
- domain controller 한 대의 장애와 timeout
- group 추가·제거·중첩·이름 변경
- 검색 계정의 권한 축소와 secret rotation
- LDAP 장애 중 기존 session을 어떻게 처리할지
핵심은 AD DS를 “LDAP로 로그인하는 database”로 줄여 보지 않는 것이다. directory 조회, 인증 프로토콜, 전송 보호, 애플리케이션 권한 부여를 각각 분리하면 연동 방식과 장애 지점을 훨씬 정확하게 설명할 수 있다.
Jenkins·Argo CD·Keycloak·OpenLDAP SSO와 RBAC는 LDAP identity를 OIDC application과 연결할 때의 인증·권한 경계를 더 구체적으로 다룬다. Domain controller 탐색의 기반이 되는 이름 해석은 DNS resolver와 authoritative server의 역할에서 이어서 볼 수 있다.
참고 자료
'배움과 성장 > 네트워크·보안' 카테고리의 다른 글
| HTTP Keep-Alive: HTTP/1.1 지속 연결과 HTTP/2·3 연결 재사용 (0) | 2024.12.03 |
|---|---|
| Istio mTLS 설정: Auto mTLS·PeerAuthentication STRICT·검증 순서 (2) | 2024.09.11 |
| 버퍼 오버플로란: 경계 밖 쓰기 원인과 C 코드 예방·검증 (2) | 2024.08.28 |
| HMAC 키 배포 설계: 공유 비밀을 어디까지 노출할 것인가 (0) | 2024.08.26 |
| JWT와 HMAC 검증: HS256 키·alg·claim을 안전하게 다루는 법 (0) | 2024.08.26 |
댓글