LDAP 인증

LDAP

사내 LDAP 관련 프로젝트를 진행하기 위해 스터디한 내용을 공유하고자 이 글을 작성합니다.

LDAP은 Lightweight Directory Access Protocol의 약자로, 분산 디렉터리 서비스에서 사용자, 시스템, 네트워크, 서비스, 앱 등의 정보를 공유하기 위한 오픈 프로토콜입니다.

디렉터리는 계층 구조로 구성된 레코드의 집합으로 위 정보로 구성되었습니다.

Client, Server 구조를 기반으로 하고 있습니다.

기존 Directory Protocol인 X.500은 OSI Layer 기반이기 때문에 구조가 복잡하다는 단점이 있습니다.

LDAP은 TCP/IP Layer 기반이기 때문에 X.500보다 경량화된 구조를 가졌습니다.

이로 인해 Lightweight라는 수식어가 붙습니다.

주로 사용자 정보를 중앙 집중적으로 관리하고 공유하는 데 사용합니다.

 

Directory Structure

Entry

디렉터리에 보관된 정보의 기본 단위로, Entry가 나타내는 객체(사용자)에 대한 정보를 가지고 있는 속성 집합으로 구성됩니다.

Entry의 집합은 DN(Distinguished Name)을 기반으로 DIT(Directory Information Tree)라는 계층적인 트리 구조로 구성됩니다.

 

Attribute

속성은 타입, 값으로 구성되며 값은 여러 속성으로도 구성 가능합니다.

값은 타입의 정의된 규칙에 따라 정의됩니다.

예를 들면 givenName 타입의 경우 둘 이상의 값을 가질 수 있으며, 반드시 문자열이고 대소문자 구분을 하지 않는 규칙을 가지고 있습니다.

또한, givenName 타입은 동등 일치 규칙에 따라 “John”, “JOHN”과 같은 동일한 문자를 포함할 수 없습니다.

이 밖에도 LDAP 구현체에 따라 다양한 속성이 있습니다.

dn Distinguished Name의 약자로 일종의 Entry 식별자
cn Common Name의 약자로 사용자 이름
givenName 사용자의 성을 제외한 이름
sn SurName의 약자로 사용자의 성
telephoneNumber 전화번호
mail 이메일
manager 담당자
objectClass 일종의 객체(사용자) 그룹으로,

해당 objectClass의 속성을 그대로 상속받을 수 있도록 하는 타입

Operation

LDAP 기본 명령어는 다음과 같습니다.

Bind Client와 Server 간에 인증 정보를 교환하여 인증을 수행
Unbind Client와 Server 간의 연결을 해제하여 Server가 Client를 위해 준비한 자원들을 반납

Bind의 반대가 아님

Search Entry를 조회
Modify Entry 속성의 값을 변경
Add 새로운 Entry를 추가
Delete Entry를 제거
Modify DN Entry 위치를 변경
Compare Entry 속성의 값들을 비교
Abandon 아직 완료되지 않은 요청을 중단
Extended 프로토콜에서 정의되지 않은 부가적인 Operation을 정의
StartTLS Client와 Server 간의 TLS(Transport Layer Security) 통신을 지원

종류

LDAP은 오픈 프로토콜이기 때문에 다음과 같은 여러 구현체가 존재합니다. 이 밖에도 다양한 구현체가 존재합니다.

Active Directory Microsoft가 개발한 Windows를 위한 Directory Service
Apache Directory Server Apache가 개발한 Java 기반 Open Source Directory Service
Red Hat Directory Server Red Hat이 개발한 Directory Service
Oracle Internet Directory Oracle이 개발한 Directory Service
OpenLDAP OpenLDAP Project가 개발한 Open Source Directory Service

프로젝트

개요

Spring Boot와 OpenLDAP을 활용하여 그룹 관리, 사용자 관리를 권한에 따라 사용할 수 있는 토큰 기반 REST API 서버 예제 프로젝트입니다.

개발 환경

※ 본 예제에서 LDAP은 OpenLDAP을 사용합니다.

OS macOS
Language Java(1.8 이상)
Framework Spring Boot
IDE IntelliJ IDEA Community 2020.3
LDAP Docker Docker Desktop Community 2.5.0.0
Node osixia/openldap 1.4.0 – OpenLDAP 2.4.50
LDAP Tool Apache Directory Studio 2.0.0-M15

LDAP DIT 구조

DIT 구조는 Blocko 회사(dn: dc=blocko, dc=io)를 기반으로 관리자 조직(dn: ou=admin,dc=blocko,dc=io), 사용자 조직(dn: ou=user,dc=blocko,dc=io)으로 나누어 구성하였습니다.

파선으로 되어 있는 관리자(dn: cn=admin,dc=blocko,dc=io)는 위의 관리자 조직에 속하지 않는 LDAP 관리자입니다.

관리자 ID : 8story8@blocko.io

PW : 1234

Application 관리자
사용자 ID : tester@blocko.io

PW : 4321

Application 사용자
LDAP 관리자 ID : cn=admin,dc=blocko,dc=io

PW : admin

LDAP 관리자

LDAP Tool인

Apache Directory Studio와 연동하기 위해 사용

기능

로그인 관리자, 사용자는 이메일, 비밀번호를 통해 인증을 한 뒤,

API 사용을 위한 Access Token을 발급받습니다.

그룹 등록 관리자는 그룹을 등록할 수 있습니다.
그룹 수정 관리자는 그룹을 수정할 수 있습니다.
그룹 삭제 관리자는 그룹을 삭제할 수 있습니다.
그룹 목록 조회 관리자는 등록된 모든 그룹을 조회할 수 있습니다.
그룹 상세 조회 관리자는 그룹에 속한 구성원들을 조회할 수 있습니다.
사용자 목록 조회 관리자는 모든 그룹의 사용자들을 조회할 수 있습니다.
사용자 조회 관리자는 모든 관리자, 사용자를 조회할 수 있으며 사용자는 자신만 조회할 수 있습니다.
사용자 등록 관리자, 사용자를 등록할 수 있습니다.
사용자 수정 관리자, 사용자는 자신의 이름과 비밀번호만 수정할 수 있습니다.
사용자 삭제 관리자, 사용자는 자신만 삭제할 수 있습니다.

환경 설정

LDAP 예제 프로젝트 Github를 다운로드하여 ldap 폴더에 있는 run.sh를 실행하여 OpenLDAP을 구동합니다.

 

OpenLDAP 구동 시 ldap/environment 폴더의 초기 설정 파일(init.ldif)로 위에서 설명한 DIT가 OpenLDAP에 저장됩니다.

 

DIT가 OpenLDAP에 저장되었는지 확인하기 위해 LDAP Tool인 Apache Directory Studio를 다운로드합니다.

 

OpenLDAP과 Apache Directory Studio를 연동하기 위해 다음과 같이 설정한 뒤

Check Network Parameter 클릭 → Next > 버튼을 클릭합니다.

 

OpenLDAP 관리자의 ID(cn=admin,dc=blocko,dc=io), PW(admin)로 다음과 같이 설정한 뒤

Check Authentication 클릭 → Finish 버튼을 클릭합니다.

 

OpenLDAP과 Apache Directory Studio가 정상적으로 연동이 되면 OpenLDAP에 저장된 DIT를 다음과 같이 확인할 수 있습니다.

 

IntelliJ로 LDAP 예제 프로젝트 Github의 LdapExampleApplication을 구동한 뒤

http://localhost:8080/swagger-ui.html에 접속하면 그룹 관리, 사용자 관리 API를 테스트할 수 있습니다.

 

로그인을 제외한 모든 API는 Header의 JWT를 통한 인증을 해야 사용할 수 있기 때문에 로그인 API를 통해 다음과 같이 Access Token을 발급받습니다.

 

발급받은 Access Token을 다음과 같이 설정하여 그룹, 사용자 API를 사용할 때 해당 Access Token을 통해 API에 접근할 수 있도록 합니다.

 

의존성

해당 프로젝트에서 사용한 의존성 목록은 다음과 같습니다.

spring-boot-starter-web Spring Boot Web Application 라이브러리
spring-boot-starter-security Spring Boot Security 라이브러리
spring-security-ldap Spring Security LDAP 라이브러리
jjwt JWT(Json Web Token) 라이브러리
springfox-swagger2 API Documentation 라이브러리
springfox-swagger-ui API Documentation UI 라이브러리
lombok Annotation 기반 Constructor, Getter, Setter 등 자동 완성 라이브러리
 

주요 코드

로그인

Login 엔드포인트에서 LoginForm(Email, Password)을 입력받아 LdapAuthenticationProvider로 전달하여 OpenLDAP에 인증을 한 뒤 그룹, 사용자 API를 사용하기 위한 Access Token을 발급받습니다.

인증 절차는 다음과 같습니다.

  • LdapTemplate을 통해 Email에 따른 사용자의 Email과 암호화된 Password를 OpenLDAP에서 반환받습니다.

List로 반환받는 이유는 LDAP에서 일종의 PK인 DN으로 검색하여 반환받는 것이 아니기 때문입니다.

이 부분은 추후 스터디를 통해 확인해봐야 할 것 같습니다.

  • 반환받은 암호화되어 있는 Password와 사용자가 입력한 Password를 비교하여 인증 여부를 확인합니다.
  • 인증에 성공하면 사용자 정보(권한 포함)를 OpenLDAP에서 반환받습니다.
  • 사용자 정보를 바탕으로 Access Token을 사용자에게 발급합니다.
 

그룹 등록

그룹명(group)의 존재 여부를 확인한 뒤 그룹을 OpenLDAP에 등록합니다.

이때 LdapTemplate의 bind 메서드를 사용하여 등록합니다.

(이 bind 메서드는 LDAP Bind가 아니라 LDAP Add입니다.)

등록되는 그룹 DIT는 다음과 같습니다.

dn: ou=그룹명, dc=blocko, dc=io
–        objectClass: organizationalUnit

–        ou: 그룹명

 

그룹 수정

그룹명(group), 수정될 그룹명(toBeUpdatedGroup)의 존재 여부 확인을 한 뒤 그룹명을 수정합니다.

이때 LdapTemplate의 rename 메서드를 사용하여 수정합니다.

(이 rename 메서드는 DN을 수정하므로 LDAP Modify DN입니다.)

 

그룹 삭제

그룹 삭제 시 그룹에 속한 사용자가 없어야 삭제할 수 있으므로 해당 여부를 확인한 뒤 그룹을 삭제합니다.

이때 LdapTemplate의 unbind 메서드를 사용하여 삭제합니다.

(이 unbind 메서드는 LDAP Unbind가 아니라 LDAP Delete입니다.)

 

그룹 목록 조회

OpenLDAP에서 그룹명에 해당하는 organizationUnit을 검색하여 그룹 목록을 조회합니다.

그룹 상세 조회

그룹명(group)의 존재 여부를 확인한 뒤 그룹에 대한 상세 정보(그룹에 속한 사용자 목록)를 조회합니다.

 

사용자 목록 조회

OpenLDAP에서 사용자에 해당하는 person을 검색하여 사용자 목록을 조회합니다.

 

사용자 조회

사용자 Email의 존재 여부를 확인한 뒤 사용자에 대한 상세 정보(Email, 이름)를 조회합니다.

 

사용자 등록

사용자 Email, 그룹명(group)의 존재 여부를 확인한 뒤 해당 그룹의 사용자를 OpenLDAP에 등록합니다.

이때 등록되는 DIT는 다음과 같습니다.

dn: uid=사용자 Email, ou=그룹명, dc=blocko, dc=io
–        objectClass: person

–        objectClass: simpleSecurityObject

–        objectClass: uidObject

–        cn: name

–        sn: name

–        uid: 사용자 Email

–        ou: 그룹명

 

사용자 수정

그룹명(group), 사용자 Email의 존재 여부 확인을 한 뒤 이름, 비밀번호를 수정합니다.

사용자의 속성을 수정하는 것이기 때문에 LdapTemplate의 modifyAttributes 메서드를 사용하여 수정합니다.

(이 modifyAttributes 메서드는 LDAP Modify입니다.)

 

사용자 삭제

사용자 삭제 시 그룹, 사용자 Email 존재 여부를 확인한 뒤 그룹에서 사용자를 삭제합니다.

이때 LdapTemplate의 unbind 메서드를 사용하여 삭제합니다.

(이 unbind 메서드는 LDAP Unbind가 아니라 LDAP Delete입니다.)

 

참고 자료

LDAP 예제 프로젝트 Github

OpenLDAP Github

Apache Directory Studio

Spring LDAP Overview

Spring Boot + LDAP Example Github

LDAP RFC 4511

LDAP Directory Model RFC 4512

LDAP Schema RFC 4519

Directory Service Wiki

X.500 Wiki

LDAP Wiki

이더리움 대신 아르고로 DApp 쉽게 만들기3

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다

필수 입력 사항입니다.
필수 입력 사항입니다.
유효한 이메일 주소를 입력해주세요.
You need to agree with the terms to proceed

메뉴