> ## Content Index
> Fetch the complete content index at: https://www.popit.kr/llms.txt
> Use this file to discover other available public pages before exploring further.

# Search Guard로 ES, 키바나 인증 구축
- URL: https://www.popit.kr/elasticsearch-kibana-auth-with-search-guard/
- Published: 2017-07-09T23:00:10.000Z
- Updated: 2017-07-12T07:15:07.000Z
- Author: 광식 이
- Tags: #소프트웨어, #서비스 운영, elasticsearch, ES, 인증, 키바나, x-pack, search guard

## 개요

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

## Search Guard란?

x-pack이 모니터링을 제외하고 유료 라이센스 이기 때문에 ELK 스택을 사용하는 사용자들 사이에서 [x-pack 대안기술](https://sematext.com/blog/2017/05/22/x-pack-alternatives/?ref=popit.kr)로 무료 대체 기술에 대해 어느정도 관심이 있는듯 합니다. 이중에서 x-pack security 부분은 사실 대안이 **Search Guard**말고는 딱히 있는것 같지 않아 고민하게 되었습니다.

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

## x-pack security vs Search Guard

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

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

## SearchGuard 유의사항

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

Disable 기능이 없어 당황스러웠는데 이유는 [SearchGuard가 TLS을 의무화 한 이유에 관한 글](https://floragunn.com/search-guard-ssl-tls/?ref=popit.kr)을 공식 블로그에 올려 설명하고 있습니다. 요점은 통계적으로 내부망 내에서의 패킷캡쳐 등으로 데이터가 탈취되는 사례도 있기 때문에 TLS을 의무적용 했다고 얘기하고 있습니다.

## Search Guard 적용해보기

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

## ES 설정

### ES 플러그인 설치

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

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

릴리즈 정보는 [여기](https://github.com/floragunncom/search-guard/wiki?ref=popit.kr)를 참고하면 된다.

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

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

```sh
$ 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를 생성하면 된다.  

```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
```

```sh
$ 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에 계정 정보를 추가한다.

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

```

sg\_roles.yml에 아래와 같이 추가해준다. "only\_a"라는 role을 만들었는데 뜻은 키바나는 조회 권한만 가지고 "a"라는 색인을 조회만 할 수 있는 권한이다.**READ**와 같은 권한은 **sg\_action\_groups.yml**에 정의되어 있다.

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

sg\_roles\_mapping.yml에 role과 계정의 맵핑을 지정해준다.  

```yaml
    only_a:
      users:
        - gony0
```

### ES, SearchGuard 설치 검증하기

브라우저에서 [https://localhost:9200](https://localhost:9200/?ref=popit.kr)에 접속해보면 SSL 및 인증이 정상동작하는지 확인 할 수 있다.

### 계정정보 확인

[https://localhost:9200/\_searchguard/authinfo](https://localhost:9200/%5Fsearchguard/authinfo?ref=popit.kr)를 통해 확인 가능하다.

## 키바나 설정

### Search Guard 키바나 플러그인 설치

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

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

### kibana.yml 설정

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

```yaml
elasticsearch.username: "kibanaserver"
elasticsearch.password: "kibanaserver"

```

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

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

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

```yaml
elasticsearch.ssl.verificationMode: none
```

### 키바나 실행

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

### 검증하기

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

![](http://www.kwangsiklee.com/wp-content/uploads/2017/07/searchguard0100.png)

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

![](http://www.kwangsiklee.com/wp-content/uploads/2017/07/searchguard0200.png)

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

![](http://www.kwangsiklee.com/wp-content/uploads/2017/07/searchguard0300.png)

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

![](http://www.kwangsiklee.com/wp-content/uploads/2017/07/searchguard0400.png)

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

![](http://www.kwangsiklee.com/wp-content/uploads/2017/07/searchguard0500.png)

## TransportClient 설정

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

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

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

```java
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**에 아래와 같이 계정의 권한을 부여하면 된다.

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