개요

멜론에서 ES, Kibana를 통한 통계시스템을 구축하고 있습니다. 다양한 내부사용자가 키바나를 사용할 예정이라 인증 및 권한 컨트롤에 대해 고민하고 찾아보게 되었습니다. 따라서 ES의 데이터를 및 키바나 사용권한을 컨트롤 할 수 있는 오픈소스 플러그인 살펴보았습니다.

Search Guard란?

x-pack이 모니터링을 제외하고 유료 라이센스 이기 때문에 ELK 스택을 사용하는 사용자들 사이에서 x-pack 대안기술로 무료 대체 기술에 대해 어느정도 관심이 있는듯 합니다. 이중에서 x-pack security 부분은 사실 대안이 Search Guard말고는 딱히 있는것 같지 않아 고민하게 되었습니다.

Search Guard는 엘라스틱서치 및 키바나에서 SSL 기반으로 인증 및 권한 제어를 하는 플러그인 입니다. 기본 인증은 무료로 제공하며 LDAP, 키바나 multitanency 등을 유료로 사용 할 수 있습니다.

x-pack security vs Search Guard

저는 x-pack securitySearch Guard를 모두 테스트 해보았습니다.
하지만 어느것이 더 낫다라기 보다 Search Guard는 기본인증(auth/role, 파일기반)을 무료로 사용 할 수 있는게 큰 장점입니다.

따라서, Search Guard를 빠르게 프로토타이핑 해보고 클러스터에 적용해도 괜찮다고 판단하여 멜론 분석계 클러스터에 도입 예정입니다.

SearchGuard 유의사항

SearchGuard는 TLS 적용을 반드시 하게끔 구현되어 있습니다.

Disable 기능이 없어 당황스러웠는데 이유는 SearchGuard가 TLS을 의무화 한 이유에 관한 글을 공식 블로그에 올려 설명하고 있습니다. 요점은 통계적으로 내부망 내에서의 패킷캡쳐 등으로 데이터가 탈취되는 사례도 있기 때문에 TLS을 의무적용 했다고 얘기하고 있습니다.

Search Guard 적용해보기

아래 글부터는 StandAlone ES 1대 및 키바나 1대에 Search Guard를 적용해보는 튜토리얼입니다.
아래 글부터는 편의상 존칭을 생략합니다.

ES 설정

ES 플러그인 설치

ES 플러그인을 아래와 같이 설치한다.

$ <ES directory>/bin/elasticsearch-plugin install \
  -b com.floragunn:search-guard-5:5.5.0-14

릴리즈 정보는 여기를 참고하면 된다.

SearchGuard ES 플러그인, SSL key 생성 및 설정

아래의 스크립트 실행시 사설 인증서 생성 및 elasticsearch.yml 설정이 자동으로 완료된다.

$ cd <ES directory>/plugins/search-guard-<version>/tools
$ ./install_demo_configuration.sh

ES 클러스터 시작

ES 클러스터를 시작하면 SearchGuard 관련 내용도 실행 로그에 포함되는 것을 확인 할 수 있다.

sgadmin_demo.sh 실행

아래의 스크립트를 통해 plugins/search-guard-/sgconfig의 설정 파일들을 반영한다. 간단히 말해 계정정보, role, role-mapping 정보를 수정 후 반영하는 과정이다.

아래와 같이 sgadmin_demo.sh를 생성하면 된다.

#!/bin/bash
<ES directory>/plugins/search-guard-5/tools/sgadmin.sh -arc -cn 클러스터명 -h 호스트 -p 포트 -cd <ES directory>/plugins/search-guard-5/sgconfig -cn searchguard_demo -ks <ES directory>/config/kirk.jks -ts <ES directory>/config/truststore.jks -nhnv

이후 실행해준다.

$ cd <ES directory>/plugins/search-guard-<version>/tools
$ ./sgadmin_demo.sh

계정 정보 및 Role 수정하기

plugins/search-guard-/sgconfig 하위 의 아래의 파일들을 수정하여 계정정보 및 role을 관리 할 수 있다.

유의할 점은 sg_internal_users.yml에 계정 정보를 id/pw로 기술하는데 pw는 해쉬값으로 기록한다. 이 해쉬값은 ES디렉토리/plugins/search-guard-5/tools/hash.sh를 실행하여 획득 할 수 있다.

개략적인 각 파일의 역할은 아래와 같다.

  • sg_config.yml: 인증 백엔드에 대한 설정. 기본인증(자체인증)을 사용한다면 건드릴 필요가 없지만 ldap 연동 등을 생각한다면 살펴보아야 한다.
  • sg_internal_users.yml: 사용자와 해쉬된 패스워드 값이 기술(해쉬는 tools/hash.sh로 생성가능)
  • sg_roles_mapping.yml: role을 맵핑
  • sg_action_groups.yml: 권한 그룹을 설정
  • sg_roles.yml: role 설정

권한파일 예제

테스트를 위해 새롭게 계정과 role을 만들어 맵핑해본다.

sg_internal_users.yml에 계정 정보를 추가한다.

lks21c:
  hash: $2a$12$xyoXIHR6F.D8f7enWWrf0e0TGp73UIIc7ygfPH9z7fsduSNrW7abc

sg_roles.yml에 아래와 같이 추가해준다. “only_a”라는 role을 만들었는데 뜻은 키바나는 조회 권한만 가지고 “a”라는 색인을 조회만 할 수 있는 권한이다.

READ와 같은 권한은 sg_action_groups.yml에 정의되어 있다.

only_a:
  indices:
    'a':
      '*':
        - READ
    '?kibana':
      '*':
        - READ

sg_roles_mapping.yml에 role과 계정의 맵핑을 지정해준다.

    only_a:
      users:
        - gony0

ES, SearchGuard 설치 검증하기

브라우저에서 https://localhost:9200에 접속해보면 SSL 및 인증이 정상동작하는지 확인 할 수 있다.

계정정보 확인

https://localhost:9200/_searchguard/authinfo를 통해 확인 가능하다.

키바나 설정

Search Guard 키바나 플러그인 설치

https://github.com/floragunncom/search-guard-kibana-plugin/releases에서 맞는 버전의 플러그인을 다운로드하여 아래와 같이 설치한다.

$ bin/kibana-plugin install file:///path/to/searchguard-kibana-<version>.zip

kibana.yml 설정

앞서 ES에 인증은 붙였기 때문에 아래와 같이 ES에 접속하는 계정을 명시적으로 설정해준다. 아래는 기본으로 동작하는 값으로써 상용으로 사용할때(예를 들어 회사의 클러스터)는 변경해주자.

elasticsearch.username: "kibanaserver"
elasticsearch.password: "kibanaserver"

ES가 SSL이 적용되었으므로 키바나에서 ES에 접속하는 URL을 바꾸어 준다.

elasticsearch.url: "https://localhost:9200"

사설 인증서를 사용한다면 root CA 검증을 생략하는 옵션을 적용해준다. 포스팅의 예제는 사설 인증서를 생성하였으므로 아래의 설정을 반드시 적용하여야 한다.

elasticsearch.ssl.verificationMode: none    

키바나 실행

위의 설정까지 완료했으면 키바나를 실행한다.

검증하기

위 작업까지 완료후 키바나에 접속하면 아래와 같이 Search Guard 인증페이지가 뜬다.

기본 계정인 admin/admin으로 로그인 해보면 정상 로그인이 가능하다.
또한 예제로 만든 lks21c 계정으로 접속하면 “a” 인덱스에 대한 기능을 정상 사용 할 수 있는것을 알 수 있다.

같은 계정으로 대시보드에 들어가더라도 정상 이용이 가능하다.

하지만 lks21c 계정은 조회권한만 부여해 두었으므로 대시보드 수정을 시도하면 아래와 같이 오류 및 부족한 permission을 알려준다.

추가적인 Tip으로 ES의 로그를 보면 더 자세하게 권한오류가 발생한 이유에 대해 Tracking 할 수 있다.

TransportClient 설정

아래와 같이 필요한 dependency를 추가한다.

<dependency>
     <groupId>com.floragunn</groupId>
     <artifactId>search-guard-ssl</artifactId>
     <version>5.5.0-22</version>
 </dependency>

클라이언트 설정을 아래와 같이 하면 된다.

client = new PreBuiltTransportClient(Settings.builder()
                .put("path.home", "/home/lks21c/elasticsearch-5.5.0")
                .put("cluster.name", "alyes")
                .put("searchguard.ssl.transport.enabled", true)
                .put("searchguard.ssl.transport.keystore_filepath", "es_client-keystore.jks")
                .put("searchguard.ssl.transport.keystore_password", "패스워드")
                .put("searchguard.ssl.transport.truststore_filepath", "alyes_truststore.jks")
                .put("searchguard.ssl.transport.truststore_password", "패스워드")
                .put("searchguard.ssl.transport.enforce_hostname_verification", false)
                .build(), SearchGuardSSLPlugin.class)
                .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));

끝으로 elasticsearch.yml에 아래와 같이 계정의 권한을 부여하면 된다.

searchguard.authcz.admin_dn:
  - CN=es_client,OU=client,O=client,L=Test,C=DE