-
ELK Stack의 보안Elixian의 Referenece 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에서 잡습니다.
'Elixian의 Referenece' 카테고리의 다른 글
RabbitMQ Clustering (0) 2020.06.18