[ELK] 보안처리를 위한 ELK 스택 구축 ( Docker-compose)
이번 포스팅은 엘라스틱과 키바나에 보안접속을 할 수 있도록
추가하여, 도커 컴포즈를 사용하여 구축하는 내용에 관한 포스팅
아래 내용은 Elasticsearch with docker-compose 내용을 기반으로 작성되었습니다. (엘라스틱 공식문서)
www.elastic.co/guide/en/elastic-stack-get-started/7.8/get-started-docker.html#get-started-docker-tls
Run in Docker with TLS enabled
Gold 혹은 Platinum licesnse를 가지고 있다면 보안을 가능하게 처리할 때, TLS는 엘라스틱의 transport layer를 위해 설정이 되어야 한다. 반면에 trial license는 TLS 세팅 없이 사용이 가능하다.
docker-compose 및 설정 파일 생성
아래 설정 파일들은 elastic/stack-docs 깃허브 레파지토리에서 사용이 가능하다.
github.com/elastic/stack-docs/tree/master/docs/en/getting-started/docker
> instances.yml : 인증서를 생성해야하는 인스턴스를 식별하기 위한 파일
> .env : 엘라스틱 버전과 인증서가 생성될 위치를 지정한 환경 변수가 세팅되어있는 파일
> create-certs.yml : 도커 컴포즈 파일로써, 엘라스틱과 키비나를 위한 인증서를 생성할 컨테이너를 생성
> elastic-docker-tls.yml : 도커 컴포즈 파일로써 TLS 가 설정된 키바나 인스턴스와 3개의 엘라스틱 클러스터의 생성을 정의
instance.yml
instances:
- name: es01
dns:
- es01
- localhost
ip:
- 127.0.0.1
- name: es02
dns:
- es02
- localhost
ip:
- 127.0.0.1
- name: es03
dns:
- es03
- localhost
ip:
- 127.0.0.1
- name: 'kib01'
dns:
- kib01
- localhost
.env
COMPOSE_PROJECT_NAME=es
CERTS_DIR=/usr/share/elasticsearch/config/certificates
VERSION=7.8.0
create-certs.yml
version: '2.2'
services:
create_certs:
image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION}
container_name: create_certs
command: >
bash -c '
yum install -y -q -e 0 unzip;
if [[ ! -f /certs/bundle.zip ]]; then
bin/elasticsearch-certutil cert --silent --pem --in config/certificates/instances.yml -out /certs/bundle.zip;
unzip /certs/bundle.zip -d /certs;
fi;
chown -R 1000:0 /certs
'
working_dir: /usr/share/elasticsearch
volumes:
- certs:/certs
- .:/usr/share/elasticsearch/config/certificates
networks:
- elastic
volumes:
certs:
driver: local
networks:
elastic:
driver: bridge
elastic-docker-tls.yml
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION}
container_name: es01
environment:
- node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es02,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- xpack.license.self_generated.type=trial
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=$CERTS_DIR/es01/es01.key
- xpack.security.http.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
- xpack.security.http.ssl.certificate=$CERTS_DIR/es01/es01.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.security.transport.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
- xpack.security.transport.ssl.certificate=$CERTS_DIR/es01/es01.crt
- xpack.security.transport.ssl.key=$CERTS_DIR/es01/es01.key
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data01:/usr/share/elasticsearch/data
- certs:$CERTS_DIR
ports:
- 9200:9200
networks:
- elastic
healthcheck:
test: curl --cacert $CERTS_DIR/ca/ca.crt -s https://localhost:9200 >/dev/null; if [[ $$? == 52 ]]; then echo 0; else echo 1; fi
interval: 30s
timeout: 10s
retries: 5
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION}
container_name: es02
environment:
- node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- xpack.license.self_generated.type=trial
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=$CERTS_DIR/es02/es02.key
- xpack.security.http.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
- xpack.security.http.ssl.certificate=$CERTS_DIR/es02/es02.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.security.transport.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
- xpack.security.transport.ssl.certificate=$CERTS_DIR/es02/es02.crt
- xpack.security.transport.ssl.key=$CERTS_DIR/es02/es02.key
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data02:/usr/share/elasticsearch/data
- certs:$CERTS_DIR
networks:
- elastic
es03:
image: docker.elastic.co/elasticsearch/elasticsearch:${VERSION}
container_name: es03
environment:
- node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- xpack.license.self_generated.type=trial
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=$CERTS_DIR/es03/es03.key
- xpack.security.http.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
- xpack.security.http.ssl.certificate=$CERTS_DIR/es03/es03.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.security.transport.ssl.certificate_authorities=$CERTS_DIR/ca/ca.crt
- xpack.security.transport.ssl.certificate=$CERTS_DIR/es03/es03.crt
- xpack.security.transport.ssl.key=$CERTS_DIR/es03/es03.key
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data03:/usr/share/elasticsearch/data
- certs:$CERTS_DIR
networks:
- elastic
kib01:
image: docker.elastic.co/kibana/kibana:${VERSION}
container_name: kib01
depends_on: {"es01": {"condition": "service_healthy"}}
ports:
- 5601:5601
environment:
SERVERNAME: localhost
ELASTICSEARCH_URL: https://es01:9200
ELASTICSEARCH_HOSTS: https://es01:9200
ELASTICSEARCH_USERNAME: kibana_system
ELASTICSEARCH_PASSWORD: CHANGEME
ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES: $CERTS_DIR/ca/ca.crt
SERVER_SSL_ENABLED: "true"
SERVER_SSL_KEY: $CERTS_DIR/kib01/kib01.key
SERVER_SSL_CERTIFICATE: $CERTS_DIR/kib01/kib01.crt
volumes:
- certs:$CERTS_DIR
networks:
- elastic
volumes:
data01:
driver: local
data02:
driver: local
data03:
driver: local
certs:
driver: local
networks:
elastic:
driver: bridge
> TLS (Transport Layer Security)를 지원하기 위한 trial 라이센스를 생성하고 정의한다.
> 클라이언트 통신을 암호화하기 위해 전송 계층 보안을 사용
> 노드 간 통신을 암호화 하기 위해 전송 계층 보안을 사용
> 호스트 이름 확인을 요구하지 않고 자체 서명된 인증서 사용을 허용
도커 컴포즈 실행 과정
📌 도커 엔진에게 적어도 4 Gib의 메모리가 할당된다.
엘라스틱을 위한 인증서 생성
$ docker-compose -f create-certs.yml run --rm create_certs
클러스터 docker-compose up
$ docker-compose -f elastic-docker-tls.yml up -d
> 3개의 노드를 가진 엘라스틱 클러스터에 대해 docker-compose up으로 띄운다
> 이 시점에서, 키바나는 엘라스틱 클러스터에 연결할 수 없다. 내장 kibana_system 유저를 위한 비밀번호를 생성해야 한다. 그리고 compose file의 ELASTICSEARCH_PASSWORD를 업데이트한다. 그 후에 보안된 클러스터와 커뮤니케이션할 수 있도록 키바나를 재시작
> docker-compose up 후에 도커 컴포즈의 로그를 확인하고 싶다면 아래와 같이 입력
docker-compose logs
# 특정 컨테이너의 로그만 보고 싶다면 컨테이너 이름을 지정
docker-compose logs [컨테이너이름]
엘라스틱 패스워드 세팅
$ docker exec es01 /bin/bash -c "bin/elasticsearch-setup-passwords auto --batch --url https://es01:9200"
> elasticsearch-setup-passwordssms 내장 유저(kibana_system을 포함한)들을 위한 비밀번호를 생성해주는 도구이다
> 위 명령어를 통해 출력된 비밀번호를 따로 저장해놔야 한다.
> 그리고 키바나가 엘라스틱과 연결하기 위해 compose 파일에서 kibana_system유저에 대한 비밀번호를 설정한다
> 그리고 elasic 슈퍼바이저 유저가 키바나에 접속하고, 엘라스틱에 요청을 전송하기 위해 elastic에 대한 비밀번호가 필요한다.
아래와 같이 유저 별 비밀번호가 자동을 생성된다.
키바나 컨테이너에서 비밀번호 변경
kib01:
image: docker.elastic.co/kibana/kibana:${VERSION}
container_name: kib01
depends_on: {"es01": {"condition": "service_healthy"}}
ports:
- 5601:5601
environment:
SERVERNAME: localhost
ELASTICSEARCH_URL: https://es01:9200
ELASTICSEARCH_HOSTS: https://es01:9200
ELASTICSEARCH_USERNAME: kibana_system
ELASTICSEARCH_PASSWORD: [새로 생성된 비밀번호 입력]
ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES: $CERTS_DIR/ca/ca.crt
SERVER_SSL_ENABLED: "true"
SERVER_SSL_KEY: $CERTS_DIR/kib01/kib01.key
SERVER_SSL_CERTIFICATE: $CERTS_DIR/kib01/kib01.crt
volumes:
- certs:$CERTS_DIR
networks:
- elastic
> kibana_system에 대해 생성된 비밀번호를 ELASTICSEARCH_PASSWORD에 입력한다.
실행 중인 도커 컴포즈 종료
$ docker-compose stop
도커 컴포즈 재시작
docker-compose -f elastic-docker-tls.yml up -d
> 여기서 -f는 yml 파일을 지정할 때 사용
> -d는 백그라운도 실행을 의미함
> 기존 컨테이너는 그대로 시작하고, 변경된 kib01 컨테이너는 재생성된다.
키바나 접속
https://localhost:5601
> 키바나와 유저 브라우저 사이의 커뮤니케이션을 위해 SSL이 활성화되어 있기 때문에, 키바나는 HTTPS 프로토콜을 통해 접속해야 한다.
> 보안 설정이 잘 되었다면 아래와 같은 화면이 보인다.
> 현재는 trial license 이므로 basic license로 변경해준다.
클러스터 모니터링 설정
클러스터 모니터링 설정을 위해 Cluster 탭으로 이동 ( 아래와 같은 화면 출력 )
> 위 화면이 나오면 Turn on mornitoring 클릭
> 위 세팅까지 마치면, 아래와 같이 클러스터 모니터링 화면을 볼 수 있다.
파일로부터 세팅 값 로딩하기
컴포즈 파일에 엘라스틱과 키바나의 세팅을 지정하는 것은 시작하기에는 편리하다. 그러나 한번 경험해본 뒤에는 파일에서 세팅값을 로딩하는 것을 선호한다.
예를 들어, es01.yml을 es01 엘라스틱 노드를 위한 설정 파일로 생성하기 위해서는, 볼륨 부분에서 바인드 마운트를 생성하면 된다.
volumes:
- data01: /usr/share/elasticsearch/data
- certs:$CERTS_DIR
- ./es01.yml:/usr/share/elasticsearch/config/elasticsearch.yml
비슷하게 파일을 사용하여 키바나 세팅을 로딩하고 싶을 때는, /usr/share/kibana/config/kibana.yml를 덮어쓰기 한다.
volumes:
- certs:$CERTS_DIR
- ./kibana.yml:/usr/share/kibana/config/kibana.yml
보안이 설정된 엘라스틱 클러스터에 인덱스 생성하기
키바나 Dev Tools에서 직접 생성