Elixian의 Referenece

ELK Stack의 보안

gozalex 2020. 6. 17. 17:51

ELK Stack  보안 (feat. X-PACK)

 

ELK Stack

 

Elastic Stack 6.8 7.1부터 TLS 암호화된 통신 기능이 기본 배포 내에서 무료로 제공됩니다. 

실제로 ELK Production에 적용하면서 얻은 Lesson Learned를 공유합니다. 실제로 개발 모드에서는 아래와 같이 복잡하게 할 필요가 없습니다. 그러나 Production 으로 올라게게되면 보안 / Heap 셋팅 / Memlock 셋팅 등 자잘하게 손 대야 할 부분이 많이 생깁니다. 그 중, 보안을 적용하여 ELK Stack을 구축하는 부분을 간단하게 정리해 봅니다. 자세한 내용은 Elastic Stack 보안 설명서를 읽어보실 것을 권장합니다.

 

ELK 보안 스펙은 별도로 설정하는 것이 아니라 yml 파일에 host 주소에 loop-back(127.0.0.1)  아닌 값이 들어가면 자동으로 X-PACK Bootstrap 시작합니다.

 

또한 http.port transport.port 경우, 작성하지 않으면 default 9200/9300 잡을 것으로 예상했으나 그렇지 않았습니다. 해당 값을 넣지 않으면 아마도 elasticsearch 내부에서 http 9200~9299, transport 9300~9399 사이에 값을 사용하는  같습니다.

 

인증서는 공인된 기관의 인정서가 있는 경우, 해당 인증서를 사용하면 됩니다. 그러나 ELK 경우, 거의 내부망 (Nginx / Apache / API Server 사용하여 통신하고 ELK 직접 인터넷 망에 붙이지는 않는다.)  위치하므로 별도의 도메인을 붙여야  필요가 없습니다.

 

Elastic 아래와 같은 utility  제공합니다. 

bin/elasticsearch-certutil  사용하여 훨씬 수월하게 만들  있습니다.

 

 bin/elasticsearch-certutil cert -out config/elastic-certificates.p12 -pass "" 

 

위와 같이 p12 파일을 패스워드 없이 생성할  있습니다.

가장 간단한 방법으로 인증서를 생성할  있는 방법입니다. 다만logstash / kibana 적용하려면 crt / key 파일을 별도로 만드는 것이 좋습니다.

 

, ELK Stack 구축하려면 위의 방법 보다는 CA 파일과 인증서 / 키를 별도로 만드는 것이 좋습니다.

 

 bin/elasticsearch-certutil cert ca --pem --in instance.yml –out certs.zip

 

Instances.yml 다음과 같이 구성합니다.

 

instances:

  - name: "hb-es-node1"

     ip:

       -  "10.10.15.201"

  - name: 'hb-es-node2'

     ip:

       - "10.10.15.202"

  - name: "hb-es-node3"

     ip:

       - "10.10.15.203"

  - name: 'hb-kibana'

     ip:

       - "110.10.15.190"

  - name: 'logstash'

     ip:

       - "10.10.15.192"

 

   

/etc/hosts 파일을 사용할 경우, ip dns 변경할  있으며 ip dns   사용해도 좋습니다.

 

# yml 파일에 인스턴스 정보 추가

instances: 

- name: 'node1' 

  dns: [ 'node1.elastic.elixian.co.kr' ] 

- name: "node2" 

  dns: [ 'node2.elastic.elixian.co.kr']

- name: kibana' 

  dns: [ 'kibana.local' ] 

- name: 'logstash' 

  dns: [ 'logstash.local' ]

 

이렇게 인증 관련 파일을 생성하면  계정  비밀 번호를 생성해야 합니다.

비밀 번호는 elasticsearch에서 제공하는 별도의 util 사용합니다.

 

bin/elasticsearch-setup-passwords auto

 

bin/elasticsearch-setup-passwords interactive

 

 

Auto 경우, elasticsearch 자동으로 임의의 password 생성해 주고, interactive 경우, 사용자가 입력할  있습니다.

 

Please confirm that you would like to continue [y/N]y

 

Changed password for user apm_system

PASSWORD apm_system = KwGA9NiowJiwle9PQHqo

 

Changed password for user kibana

PASSWORD kibana = cZAdtghFDIfdgU03tDzP

 

Changed password for user logstash_system

PASSWORD logstash_system = tKoKvBacSFPjEKdShmfY

 

Changed password for user beats_system

PASSWORD beats_system = 52tCYGE846D0BtvtGsXU

 

Changed password for user remote_monitoring_user

PASSWORD remote_monitoring_user = 4L3coyUwc8DRTB7y84ze

 

Changed password for user elastic

PASSWORD elastic = z2HGfIqeAoz1SwTRmXuV

 

어디  적어줘야 합니다. 

 

중요한 것은 비밀 번호는 항상 Master Node에서 하는 것이 좋습니다.

Elasticsearch clustering으로 실행했을 , Master  군데서 비밀 번호를 만들면 다른 곳에서는 하지 않아도 됩니다.

(실제로 node2 마스터였는데 node1 비밀 번호를 설정하면 인증 실패가 나올겁니다. – 테스트하지 않아서 확실하지 않습니다.

인증 실패는 docker-compose down 하여 password 가 초기화 된 것이 원인 같다.)

 

 

다음은 elasticsearch.yml 파일의 구성입니다.

3개의 노드를 실행하고 각각의 노드는 Master / Data 속성이 true 입니다.

많은 수의 노드를 구성할 것이 아니라면 별도로 Master 노드와 Data 노드를 분리하는 것은 낭비일  있습니다. 

그리고Clustering 구축하여 Brain Split  피하기 위해서는 최소한 3개의 노드가 있어야 합니다.

 

# cluster setting

cluster.name: "hb-es-cluster"

cluster.initial_master_nodes: ["hb-es-node1", "hb-es-node2", "hb-es-node3"]

 

# node name

node.name: "hb-es-node1"

 

# host network setting

network.host: 10.10.15.201

http.port: 9200

transport.port: 9300

 

# node attribute setting

node.master: true

node.data: true

 

# detail the private IPs of your nodes:

discovery.seed_hosts: ["10.10.15.201", "10.10.15.202", "10.10.15.203"]

 

# lock memory heap

bootstrap.memory_lock: true

 

# xpack setting

xpack.security.enabled: true

 

#xpack.security.transport.ssl.verification_mode: certificate

#xpack.security.transport.ssl.keystore.path: elastic-certificates.p12

#xpack.security.transport.ssl.truststore.path: elastic-certificates.p12

 

xpack.security.transport.ssl.enabled: true

xpack.security.transport.ssl.key: /usr/share/elasticsearch/config/cert/hb-es-node1.key

xpack.security.transport.ssl.certificate: /usr/share/elasticsearch/config/cert/hb-es-node1.crt

xpack.security.transport.ssl.certificate_authorities: /usr/share/elasticsearch/config/cert/ca.crt

 

#xpack.security.http.ssl.verification_mode: certificate

#xpack.security.http.ssl.keystore.path: elastic-certificates.p12

#xpack.security.http.ssl.truststore.path: elastic-certificates.p12

 

xpack.security.http.ssl.enabled: true

xpack.security.http.ssl.key: /usr/share/elasticsearch/config/cert/hb-es-node1.key

xpack.security.http.ssl.certificate: /usr/share/elasticsearch/config/cert/hb-es-node1.crt

xpack.security.http.ssl.certificate_authorities: /usr/share/elasticsearch/config/cert/ca.crt

 

위의 YAML 파일 , 주석 처리한 부분을 확인할  있습니다.

#xpack.security.transport.ssl.verification_mode: certificate

#xpack.security.transport.ssl.keystore.path: elastic-certificates.p12

#xpack.security.transport.ssl.truststore.path: elastic-certificates.p12

이렇게 설정하면 p12 파일로 비교적 간단하게 설정을   있습니다.

 

하지만 위의 설정 코드를 logstash / kibana 넣으면 docker-compose up, 오류를 발생합니다. 

해당 설정은elasticsearch에서만 가능해 보입니다.

 

또한 logstash kibana 사이에도 속성이 미묘하게 다릅니다.

예를 들어 Logstash에서는 CA 파일만 있으면 elasticsearch TLS 통신이 가능합니다.

 


xpack.monitoring.elasticsearch.ssl.certificate_authority: /usr/share/logstash/config/cert/ca.crt

 

여기에 반 Kibana 경우, 

server.ssl.enabled: true

server.ssl.certificate: /usr/share/kibana/config/cert/hb-kibana.crt

server.ssl.key: /usr/share/kibana/config/cert/hb-kibana.key

 

elasticsearch.ssl.certificateAuthorities: [ "/usr/share/kibana/config/cert/ca.crt" ]

CA 파일 뿐만 아니라 crt / key 페어도 넣어줘야 정상적으로 연동됩니다.

 

 

 

모든 설정이 끝났다면 테스트를 해봐야 합니다.

# curl https 요청하기

curl --insecure -X GET -u elastic:xxxxxxx "https://10.10.15.202:9200?pretty"

 

curl --cacert ca.crt -u elastic: xxxxxxx 'https://node2.elastic.elixian.co.kr:9200/_cat/nodes?v'

 

 

인증서가 있는 경우, --cacert 옵션을 이용하고, 테스트의 경우에는 간단하게 –insecure 옵션을 주고 테스트 합니다.

 

 

인증 관련 작업이 마무리 되면 Elasticsearch가 운용되는 서버의 VM 설정을 해야 합니다.

설정은 Elasticsearch 홈페이지를 캡쳐했습니다.

 

vm.max_map_count=262144

RPM 등으로 설치하면 자동으로 잡아주는데 Docker로 설치할 경우, 별도로 셋팅해야 합니다.

 

셋팅은 Docker Host에서 잡습니다.