개발하는 두부

Elastic Stack 또는 ELK에 Search Guard 적용하기

by 뚜부니

Search Guard는 Elastic Stack을 위한 보안 및 알림 플러그인입니다. TLS 암호화, Elasticsearch 인덱스에 대한 역할 기반 액세스 제어, document 및 Field 수준 보안 제어, 감사 로깅 및 알림 기능을 제공합니다. 또한, 저장된 데이터에 대한 액세스를 암호화, 보호 및 모니터링 하는 데 필요한 도구를 제공합니다. Search Guard는 Community Edition, Enterprise Edition, Compliance Edition이 존재하며, 여기서는 무료로 제공되는 Community Edition을 사용하여 Elastic Stack의 보안 기능을 강화하는 실습을 진행하도록 하겠습니다.

00. 실습 환경

Apache 2.0 License 내에서 사용할 수 있는 기능만 포함된 OSS 버전을 활용하여 실습하였습니다.

  • CentOS 7.9
  • Elasticsearch 7.10.2
  • Logstash 7.10.2
  • Kibana 7.10.2
  • Search Guard 53.5.0
  • Search Guard Kibana Plugin 53.0.0
  • Java 11

본 게시글에는 Elastic Stack 구축 방법에 대한 설명은 포함되어 있지 않습니다. Search Guard 설치 버전은 공식 홈페이지에서 확인해주세요. 여기서는 windows 환경에서 다운로드 받은 파일을 CentOS 서버에 업로드 하여 사용하였습니다.

01. Elasticsaerch에 적용하기

Java 설치하기

Search Guard를 사용하기 위해서는 java가 설치되어 있어야 합니다. 해당 과정은 sudo -i를 통해 관리자 모드로 변경하여 진행해주세요.

먼저, 설치할 수 있는 java 버전을 확인합니다.

yum list java*jdk-devel

그러면 다음과 같이 설치 가능한 목록이 화면에 표출됩니다.

image

이 중 java 11 버전을 설치합니다.

yum install -y java-11-openjdk-devel.x86_64

설치가 완료되면 java --version 명령어를 통해 정상적으로 설치되었는지 한 번 더 확인해주세요. 정상 설치되었다면 다음과 같은 문구가 화면에 뜹니다.

openjdk 11.0.8 2020-07-14 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.8+10-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.8+10-LTS, mixed mode, sharing)

그 다음 JAVA_HOME으로 환경 변수를 설정해줍니다.

먼저, java의 실행 파일 경로를 확인합니다.

which java

그러면 다음과 같은 링크가 뜹니다.

/usr/bin/java

해당 링크는 심볼릭 링크이므로 아래 명령어를 통해 원본 링크를 찾아줍니다.

readlink -f /bin/java

명령을 통해 찾은 원본 링크는 다음과 같습니다.

/usr/lib/jvm/java-11-openjdk-11.0.8.10-1.el7.x86_64/bin/java

원본 링크를 사용해 JAVA_HOME 환경 변수를 등록합니다.

echo "export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-11.0.8.10-1.el7.x86_64" >> /etc/profile && source /etc/profile

JAVA-HOME 환경 변수가 등록이 잘 되었는지 확인해봅시다.

echo $JAVA_HOME

설정한 path가 화면에 뜨면 정상적으로 설정이 된 것입니다. 설정이 완료되었으니, exit을 통해 관리자 모드를 종료합니다.

Search Guard TLS Tool로 인증서 생성하기

::: tip

인증서 생성은 하나의 서버에서 진행하면 됩니다. 동일한 인증서를 가지고 있어야 하기 때문에, 하나의 서버에서 생성한 다음 다른 서버에 복사해야 합니다.

저는 Elasticsearch node-1 서버에 생성하였습니다.

:::

이제 Search Guard TLS Tool를 설치 및 설정해보겠습니다.

먼저, Search Guard TLS Tool을 다운로드 받습니다. 저는 Windows 10 서버에서 공식 홈페이지에서 Search Guard TLS Tool을 클릭하여 다운로드 받은 후, CentOS 서버의 /etc/elasticsearch 내로 업로드 하였습니다.

/etc/elasticsearch에 추가한 이유는, 인증서를 elasticsearch.yml이 있는 위치에서 상대 경로로 접근하기 쉬운 위치에 두기 위해서 입니다. SearchGuard 설정을 elasticsearch.yml에 추가할 때 상대 경로로 해야 하기 때문입니다.

sudo -i를 통해 관리자 모드로 변경한 다음, CentOS 서버에 접속하여 /etc/elasticsearch로 이동합니다.

cd /etc/elasticsearch

그 다음 zip 파일을 압축 해제합니다.

unzip -d ./search-guard-tlstool search-guard-tlstool-1.9.1.zip

이 때, unzip: command not found가 발생하면 unzip을 설치한 다음 진행해주세요.

yum install unzip

설치가 완료되면, search-guard-tlstoolconfig 디렉터리로 이동합니다.

cd ./search-guard-tlstool/config

config 디렉터리를 살펴보면,

그 다음 기본적으로 제공되는 template.yml을 복사하여 TLS Tool 설정 파일을 생성합니다.

cp template.yml tlsconfig.yml

이제 tlsconfig.yml 파일을 열고 공식 홈페이지를 참고하여 내용을 수정합니다.

공식 문서에서 intermediate ca에 대해 다음과 같이 설명합니다. 그렇기에 여기서는 intermediate ca 설정은 제외하고 구성하였습니다.

In addition to the root CA you optionally also specify an intermediate CA.

수정한 tlsconfig.yml 내용은 다음과 같습니다.

ca:
  root:
    dn: CN=root, OU=monitoring, O=monitoring
    keyzise: 2048
    validitDays: 3650
    pkPassword: root-monitoring
    file: root-ca.pem

defaults:
  validitDays: 3650
  pkPassword: monitoring
  httpsEnabled: true
  reuseTransportCertificatesForHttp: true

nodes:
  - name: node-1
    dn: CN=node-1, OU=monitoring, O=monitoring
    ip: 10.0.0.1
  - name: node-2
    dn: CN=node-2, OU=monitoring, O=monitoring
    ip: 10.0.0.2
  - name: node-3
    dn: CN=node-3, OU=monitoring, O=monitoring
    ip: 10.0.0.3
  - name: node-4
    dn: CN=node-4, OU=monitoring, O=monitoring
    ip: 10.0.0.4
  - name: node-5
    dn: CN=node-5, OU=monitoring, O=monitoring
    ip: 10.0.0.5

clients:
  - name: admin
    dn: CN=admin, OU=monitoring, O=monitoring
    admin: true

httpsEnabled는 REST 계층에서 TLS를 활성화할지 입력합니다. 그리고 reuseTransportCertificatesForHttp는 REST 와 Transport에 대해 동일한 인증서를 생성할지를 입력하며, false로 설정할 경우 transport와 rest에 대한 인증서가 각각 생성됩니다.

dn을 설정할 때, CN은 중복되지 않은 고유한 이름으로 설정합니다. nodes 설정은 Elasticsearch 노드 설정에 맞게 입력하면 됩니다. 그리고 clientsname에 입력한 admin은 admin 권한을 가진 Kibana 사용자로 생성해야 합니다. Kibana 사용자 생성 관련 내용은 Kibana 설정 부분에서 다루도록 하겠습니다.

이제 인증서를 생성해보겠습니다. 참고로, 현재 위치는 /etc/elasticsearc/search-guard-tlstool/config 입니다.

# 인증서 보관할 디렉터리 생성
mkdir ../../certs
# 인증서 생성
../tools/sgtlstool.sh -c ./tlsconfig.yml -ca -crt -t ../../certs

인증서를 생성 및 저장할 디렉터리로 certs를 생성한 다음 인증서를 생성하였습니다. 만약 -t ../certs를 명령어에 입력하지 않는다면, 보관할 디렉터리를 생성하지 않아도 됩니다. 왜냐하면, default로 out이라는 디렉터리에 인증서를 생성 및 저장하기 때문입니다.

  • -c : -config, 뒤에 설정 파일 경로 입력 필수
  • -ca : -create-ca, CA 생성
  • -crt : -create-cert, 로컬 인증 기관을 통해 인증서 생성
  • -t : -target, 인증서 생성 위치 지정. (default : out)

정상적으로 생성되었는지 확인해봅시다.

# 인증서 생성한 디렉터리로 이동
cd /etc/elasticsearch/certs
# 목록 보기
ls

그러면 다음과 같이 인증서들이 생성된 것을 확인할 수 있습니다.

image

인증서가 제대로 생성되었는지 확인해봅시다.

저는 실수로 ip 필드 앞에 주석(#)을 입력하여 일부 인증서가 정상적으로 생성되어 있지 않았습니다.

../search-guard-tlstool/tools/sgtlsdiag.sh -ca ./root-ca.pem -crt ./node-1.pem

node-1.pem 인증서를 확인했을 때, 다음과 같이 표출되면 정상적으로 생성된 것입니다.

image

이제 인증서 생성이 완료되었으므로 exit 명령어를 통해 관리자 모드를 종료합니다.

그 다음 생성한 certs를 각 Elasticsearch 서버에 옮겨줍니다.

Search Guard 플러그인 설정

Elasticsearch에 Search Guard를 설치하기 전, 엘라스틱서치의 모든 노드를 중지합니다. 만약, 대규모 클러스터로 구성되어 있고 샤드 할당이 되어 있다면 노드 중지 전에 비활성화 해주세요.

sudo -i service elasticsearch stop

그 다음, 엘라스틱서치 각 노드에 Search Guard 플러그인을 설치합니다.

sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install file:///home/monitoring/search-guard-suite-plugin-7.10.2-53.5.0.zip

여기서 /usr/share/elasticsearch/bin은 일반적으로 CentOS에서 elasticsearch-plugin이 존재하는 위치이며, file:// 뒤에 있는 /home/monitoring/search-guard-suite-plugin-7.10.2-53.5.0.zip은 설치하려는 Search Guard 파일의 위치 및 zip 파일입니다.

명령어를 입력하면 다음 그림과 같은 문구를 확인할 수 있으며, Continue with installation? [y/N]에 대해 y를 입력하면 됩니다.

image

-> Installed search-guard-7과 같은 문구가 뜨면 설치가 완료된 것입니다.

설치가 완료되었다면, /etc/elasticsearch/elasticsearch.yml 파일에 Search Guard 설정을 추가합니다.
아래 내용은 node-1 서버에서 설정한 내용이며, /etc/elasticsearch/certs/node-1_elasticsearch_config_snippet.yml을 참고하여 작성했습니다.

# Disable enterprise settings to use only the community version that is free.
searchguard.enterprise_modules_enabled: false
#
# SSL/TLS
searchguard.ssl.transport.pemcert_filepath: certs/node-1.pem
searchguard.ssl.transport.pemkey_filepath: certs/node-1.key
searchguard.ssl.transport.pemkey_password: monitoring
searchguard.ssl.transport.pemtrustedcas_filepath: certs/root-ca.pem
searchguard.ssl.transport.enforce_hostname_verification: false
searchguard.ssl.transport.resolve_hostname: false
searchguard.ssl.http.enabled: true
searchguard.ssl.http.pemcert_filepath: certs/node-1.pem
searchguard.ssl.http.pemkey_filepath: certs/node-1.key
searchguard.ssl.http.pemkey_password: monitoring
searchguard.ssl.http.pemtrustedcas_filepath: certs/root-ca.pem
searchguard.nodes_dn:
- "CN=node-1,OU=monitoring,O=monitoring"
- "CN=node-2,OU=monitoring,O=monitoring"
- "CN=node-3,OU=monitoring,O=monitoring"
- "CN=node-4,OU=monitoring,O=monitoring"
- "CN=node-5,OU=monitoring,O=monitoring"
searchguard.authcz.admin_dn:
- "CN=admin,OU=monitoring,O=monitoring"

searchguard.enterprise_modules_enabled: false 설정은 SearchGuard Enterprise를 비활성화 한 것입니다. 무료 버전인 Community Edition만을 사용하기 위해서는 반드시 비활성화 해야 합니다. searchguard.ssl.transport는 SearchGuard의 SSL/TLS 설정입니다.

현재 사용하는 Elasticsearch가 OSS 버전이 아닌 경우, xpack.security.enabled: false 설정도 해야 합니다.

모든 경로는 반드시 상대 경로로 입력해주세요. 그러지 않으면, access denied이 발생합니다.

설정이 완료되었으므로 Elasticsearch를 재시작합니다.

sudo -i service elasticsearch start

sgconfig 알아보기

사용자 생성 및 권한을 부여하기 전, sgconfig 디렉터리에 존재하는 파일에 대해 간단히 살펴보도록 하겠습니다. 참고로 제가 살펴볼 sgconfig 전체 경로는 /usr/share/elasticsearch/plugins/search-guard-7/sgconfig입니다.

sg_action_groups.yml

sg_action_groups.yml은 action group에 대한 설정 파일입니다. 그리고 action group은 permission(권한)의 모음이라고 이해하면 됩니다.

  MY_ACTION_GROUP: # action group name
    reserved: false # optional. 예약어 설정 여부. (default: false)
    allowed_actions:
      - "<permission or action group>"
      - ...
    type: "index" # optional. action group 타입. index 외에 cluster, kibana 등 존재.
    description: "..." # optional. action group에 대한 설명

sg_blocks.yml

sg_blocks.yml은 화이트 리스트(verdict: allow) 또는 블랙 리스트(verdict: disallow)에 대한 설정 파일입니다.

sg_config.yml

sg_config.yml은 Search Guard 기본 설정입니다.

sg_config:
  dynamic:
    http:
      anonymous_auth_enable: false
      ...
    authc: ...
    authz: ...

여기서 dynamic.http.anonymous_auth_enable: false는 익명 인증 설정이며, 기본 설정은 false 입니다. 상세한 내용은 공식 문서를 참고하시길 바랍니다.

기본적으로 제공되는 설정 중 현재 사용하려는 community 버전에서 미지원하는 항목은 다음과 같습니다.

  • dynamic.kibana
  • dynamic.http.auth_token_provider
  • dynamic.http.authc 일부 타입 : ldap, kerberos, jwt, openid, saml, sg_auth_token
  • dynamic.http.authz 일부 타입 : ldap

그리고 필수가 아닌 필드는 다음과 같습니다.

  • dynamic.http.xff
  • dynamic.http.auth_failure_listeners : 무차별 암호 입력 방지를 위한 설정

더 자세한 설명은 공식 문서마이그레이션 관련 글 참고하시길 바랍니다.

sg_internal_users.yml

sg_internal_users.yml은 internal user database에 사용자 및 해시로 변환한 비밀번호를 설정하는 파일입니다. Search Guard에서는 BCrypt를 사용하여 비밀번호를 해시합니다. 더 상세한 내용은 공식 문서를 참고하시길 바랍니다.

username: # user name
  hash : <hashed password> # BCrypt를 사용하여 해시된 비밀번호
  search_guard_roles:
    - <rolename> # search guard role과 직접 연결
  backend_roles:
    - <backend rolename> # sg_roles_mapping.yml에서 설정한 backend_roles와 연결됨
  attributes: # Optional. 사용자에 대한 추가 정보 설정
    key: value
  description: "..." # Optional. user에 대한 설명

search_guard_rolesbackend_roles 둘 중 하나만 사용해도 되며, 사용하려는 시스템에 맞춰 설정하면 됩니다.

attributes를 사용하려면 sg_config.ymlmap_db_attrs_to_user_attrs에 추가해야 합니다. 아래 설정 외 다른 설정이 궁금하시다면, 공식 문서를 참고하시길 바랍니다.

basic_internal_auth_domain:
  http_enabled: true
  order: 1
  http_authenticator:
    type: basic
    challenge: true
  authentication_backend:
    type: internal
    config:
      map_db_attrs_to_user_attrs: 
        dbfield: mappingfield # <실제 DB에 저장될 필드명> : <매핑할 필드명> 순서로 입력.

map_db_attrs_to_user_attrs를 작성할 때, 매핑할 필드명인 mappingfield는 위에서 입력한 attributes의 key와 동일해야 합니다.

sg_roles.yml

sg_roles.yml은 역할 및 관련 권한에 대한 설정 파일입니다. 상세한 내용은 공식 문서를 참고하시길 바랍니다.

ROLE_NAME: # role name
  cluster_permissions: # cluster 수준에서 적용되는 권한
    - '<action group or single permission>'
    - ...
  index_permissions: # index 수준에서 적용되는 권한
    - index_patterns: # index 패턴 정의. 와일트 카드와 정규식 표현 사용 가능
      - <index pattern the allowed actions should be applied to>
      - ...      
      allowed_actions: # 설정한 패턴에 대해 허용할 action
        - '<action group or single permission>'
        - ...
      dls: # Community 지원 X
      fls: # Community 지원 X
    - index_patterns:
      - ...
  tenant_permissions: # Community 지원 X

sg_roles_mapping.yml

sg_roles_mapping.yml은 사용자, 호스트 등을 역할에 매핑하기 위한 파일입니다. 상세한 내용은 공식 문서를 참고하시길 바랍니다.

ROLE_NAME: # search guard role name
  users:
    - <username>
    - ...
  backend_roles:
    - <backend rolename>
    - ...
  hosts:
    - <hostname>
    - ...

만약 users 필드에서 사용자를 설정하였다면, sg_internal_users.yml에 추가하지 않아도 됩니다.

sg_tenants.yml

sg_tenants.yml은 Kibana Access 구성을 위한 tenats를 정의하는 파일입니다. Community 버전을 지원하지 않기에 상세한 설명은 넘어가도록 하겠습니다.

role 관계 이해하기

role에 대한 개념을 좀 더 이해하기 쉽도록 다음과 같이 그림으로 정리해두었습니다.

image

sg_internal_user.ymlbackend_rolessg_role_mapping.yml과 연결됩니다.
그리고 sg_role_mapping.ymlsg_role.yml과 연결됩니다.

다음과 같이 sg_role_mapping.ymlsg_internal_user.yml을 작성한 경우, devadmin이라는 이름을 가진 사용자는 admin이라는 backend_roles에 연결된 SGS_ALL_ACCESS라는 역할에 대한 권한을 가지게 됩니다.

# sg_role_mapping.yml
SGS_ALL_ACCESS:
  backend_roles:
    - "admin"

# sg_internal_user.yml
devadmin:
  hash: <password>
  backend_roles:
    - "admin"

만약, backend_roles를 거치지 않고 바로 Search Guard Role과 연결하려면 다음과 같이 sg_internal_user.yml을 설정해도 됩니다.

devadmin:
  hash: <password>
  search_guard:
    - SGS_ALL_ACCESS

user 내에서 이러한 권한에 대한 설정을 주고 싶지 않은 경우, sg_role_mapping.ymlsg_internal_user.yml을 다음과 같이 설정할 수도 있습니다.

# sg_role_mapping.yml
SGS_ALL_ACCESS:
  users:
    - "devadmin"

# sg_internal_user.yml
devadmin:
  hash: <password>

사용자 생성 및 권한 부여하기

이제 admin이라는 이름의 사용자를 생성해보도록 하겠습니다. 관리자 모드(sudo -i)로 접속해주세요.

그 전에 sgconfig.yml을 설정하도록 하겠습니다.

먼저 파일 내용 중 community 버전에서 지원하지 않는 모듈 관련 필드를 삭제하겠습니다.

  • dynamic.kibana
  • dynamic.http.auth_token_provider
  • dynamic.http.authc 일부 타입 : ldap, kerberos, jwt, openid, saml, sg_auth_token
  • dynamic.http.authz 일부 타입 : ldap

참고로, community 버전임에도 sg_auth_token과 관련된 설정이 있으면 아래와 같은 내용이 로그 파일에 계속 쌓이게 됩니다.

Unable to initialize auth domain sg_issued_jwt_auth_domain=AuthcDomain [http_enabled=false, transport_enabled=true, order=1, http_authenticator=HttpAuthenticator [challenge=false, type=sg_auth_token, config={}], authentication_backend=AuthcBackend [type=sg_auth_token, config={}], description=Authenticate via Json Web Tokens issued by Search Guard, skip_users=[]] due to ElasticsearchException[Can not load 'sg_auth_token' because enterprise modules are disabled]
org.elasticsearch.ElasticsearchException: Can not load 'sg_auth_token' because enterprise modules are disabled

지원하지 않는 필드를 삭제하면 다음과 같이 정리됩니다.

_sg_meta:
  type: "config"
  config_version: 2

sg_config:
  dynamic:
      http:
        anonymous_auth_enabled: false
        xff:
          enabled: false
          internalProxies: '192\.168\.0\.10|192\.168\.0\.11' # regex pattern
          #internalProxies: '.*' # trust all internal proxies, regex pattern
          #remoteIpHeader:  'x-forwarded-for'
      authc:
        basic_internal_auth_domain:
          description: "Authenticate via HTTP Basic against internal users database"
          http_enabled: true
          transport_enabled: true
          order: 4
          http_authenticator:
            type: basic
            challenge: true
          authentication_backend:
            type: internal
        proxy_auth_domain:
          description: "Authenticate via proxy"
          http_enabled: false
          transport_enabled: false
          order: 3
          http_authenticator:
            type: proxy
            challenge: false
            config:
              user_header: "x-proxy-user"
              roles_header: "x-proxy-roles"
          authentication_backend:
            type: noop
        clientcert_auth_domain:
          description: "Authenticate via SSL client certificates"
          http_enabled: false
          transport_enabled: false
          order: 2
          http_authenticator:
            type: clientcert
            config:
              username_attribute: cn #optional, if omitted DN becomes username
            challenge: false
          authentication_backend:
            type: noop
  #    auth_failure_listeners:
  #      ip_rate_limiting:
  #        type: ip
  #        allowed_tries: 10
  #        time_window_seconds: 3600
  #        block_expiry_seconds: 600
  #        max_blocked_clients: 100000
  #        max_tracked_clients: 100000
  #      internal_authentication_backend_limiting:
  #        type: username
  #        authentication_backend: intern
  #        allowed_tries: 10
  #        time_window_seconds: 3600
  #        block_expiry_seconds: 600
  #        max_blocked_clients: 100000
  #        max_tracked_clients: 100000

그리고 tenants 설정도 community 버전에서 지원하지 않으므로 sg_tenants.yml 파일의 내용은 모두 지워줍니다.

사용자 생성을 하기 전, 사용자에게 부여할 역할을 생성해야 합니다. Search Guard에서 기본적으로 제공되는 role을 최대한 활용하려고 합니다. 그러나 SGS_LOGSTASH 역할만으로는 logstash에서 elasticsearch에 데이터를 저장할 수 없기 때문에, sg_roles.yml 파일에 logstash를 위한 역할을 생성하도록 하겠습니다.

sg_logstash:
  cluster_permissions:
    - SGS_CLUSTER_MONITOR
    - SGS_CLUSTER_COMPOSITE_OPS
    - SGS_CLUSTER_MANAGE_INDEX_TEMPLATES
    - SGS_CLUSTER_MANAGE_ILM
    - SGS_CLUSTER_MANAGE_PIPELINES
  index_permissions:
    - index_patterns:
        - '*'
      allowed_actions:
        - "indices:admin/get"  # 추가: 인덱스 정보 조회 권한
        - "indices:admin/auto_create"  # 추가: 인덱스 자동 생성 권한
        - "indices:data/write/index"  # 추가: 데이터 쓰기(index)
        - "indices:data/write/bulk[s]"  # 추가: 데이터 쓰기(bulk)
        - "indices:admin/mapping/auto_put"  # 추가: 인덱스 매핑 자동 생성 권한
    - index_patterns:
        - 'logstash-*'
      allowed_actions:
        - SGS_CRUD
        - SGS_CREATE_INDEX
        - SGS_MANAGE
    - index_patterns:
        - '*beat*'
      allowed_actions:
        - SGS_CRUD
        - SGS_CREATE_INDEX
        - SGS_MANAGE

그 외 역할을 Search Guard에서 기본적으로 제공하는 role을 그대로 활용하여 sg_role_mapping.yml을 작성하였습니다.

SGS_ALL_ACCESS:
  reserved: true
  backend_roles:
  - "admin"

SGS_OWN_INDEX:
  reserved: false
  users:
  - "*"

sg_logstash:
  users:
  - logstash

SGS_KIBANA_USER:
  reserved: false
  backend_roles:
  - "kibanauser"

SGS_READALL:
  reserved: true
  backend_roles:
  - "readall"

SGS_MANAGE_SNAPSHOTS:
  reserved: true
  backend_roles:
  - "snapshotrestore"

SGS_KIBANA_SERVER:
  reserved: true
  users:
  - "kibanaserver"
  • SGS_ALL_ACCESS : 모든 인덱스와 모든 클러스터에 대한 권한을 부여함.
  • SGS_OWN_INDEX : 인증된 사용자의 사용자 이름을 따른 인덱스에 대한 전체 권한을 부여함.
  • SGS_KIBANA_USER : 일반 Kibana 사용자에 대한 최소 권한을 가지며, 인덱스에 대한 READ 권한은 따로 부여해주어야 함
  • SGS_READALL : 모든 인덱스에 대한 읽기 권한은 있지만 쓰기 권한은 없음
  • SGS_MANAGE_SNAPSHOTS : 스냅샷, 복원 및 리포지토리 작업에 대한 전체 권한을 부여함.
  • SGS_KIBANA_SERVER : 모든 인덱스에 대한 읽기 권한 뿐만 아니라 Kibana 대시보드, 시각화, 검색 등의 권한을 부여함.

마지막으로 sg_internal_user.yml을 작성하도록 하겠습니다. 이 때,{password}는 실제로 입력할 password를 BCrypt 변환 사이트를 통해 해시한 값으로 작성해야 합니다.

admin:
  hash: "{password}"
  reserved: true
  backend_roles:
  - "admin"
  description: "admin user"

kibanaserver:
  hash: "{password}"
  reserved: true
  description: "kibanaserver user"

logstash:
  hash: "{password}"
  reserved: false
  description: "logstash user"

설정한 내용이 적용되도록 sgadmin.sh를 실행하기 위해 tools 디렉터리로 이동합니다.
그 다음, sgadmin.sh를 실행할 수 있도록 권한을 변경합니다.

chmod +x sgadmin.sh

권한을 변경하였으면, sgadmin.sh를 실행하여 아래와 같이 PEM 인증서로 기본 구성을 적용합니다.

./sgadmin.sh -cd ../sgconfig/ -cacert /etc/elasticsearch/certs/root-ca.pem -cert /etc/elasticsearch/certs/admin.pem -key /etc/elasticsearch/certs/admin.key -keypass monitoring -nhnv -icl
  • cacert : root PEM 파일 입력
  • cert : Client의 admin 권한을 가진 PEM 파일 입력
  • key : Client의 admin 권한을 가진 KEY 파일 입력
  • keypass : Client의 admin 권한의 파일에 대한 비밀번호 입력

실행이 성공적으로 완료되면 다음과 같은 마지막에 success가 화면에 표출됩니다.

image

모든 설정이 완료되었으므로 exit 명령어를 통해 관리자 모드를 종료합니다.

정상적으로 동작하는지 curl 호출을 통해 확인해보도록 하겠습니다.

curl -k -u admin -X GET "https://localhost:9200"

위와 같이 명령어를 입력하면 admin 사용자에 대한 password를 입력하라고 뜹니다.

Enter host password for user 'admin':

password를 입력하면 다음과 같이 엘라스틱서치 정보가 화면에 표출됩니다.

{
  "name" : "node-1",
  "cluster_name" : "monitoring",
  "cluster_uuid" : "cluster_uuid",
  "version" : {
    "number" : "7.10.2",
    "build_flavor" : "oss",
    "build_type" : "rpm",
    "build_hash" : "build_hash",
    "build_date" : "2021-01-13T00:42:12.435326Z",
    "build_snapshot" : false,
    "lucene_version" : "8.7.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

02. Kibana에 적용하기

Search Guard 적용 전, Kibana를 종료합니다.

sudo systemctl stop kibana

그리고 Kibana optimization process is shaky 관련 이슈가 발생하지 않도록 node.options 파일을 수정합니다. 이 때, 메모리의 50% ~ 60% 정도로 설정합니다. 현재 사용 중인 서버의 Memory가 32GB여서 16GB(8192MB)를 할당해주었습니다.

## max size of old space in megabytes
--max-old-space-size=8192

Search Guard 적용을 위해 키바나에 Search Guard 플러그인을 설치합니다. 저는 미리 zip 파일을 서버에 업로드하여 사용하였습니다.

sudo /usr/share/kibana/bin/kibana-plugin install file:///home/monitoring/search-guard-kibana-plugin-7.10.2-53.0.0.zip --allow-root

그리고 이전에 만들었던 certadmin(client) 관련 파일과 root-ca 관련 파일을 kibana.yml이 존재하는 디렉터리에 추가합니다. 파일 구조는 다음과 같습니다.

etc
├─ certs
│ ├─ admin.key
│ ├─ admin.pem
│ ├─ root-ca.key
│ └─ root-ca.pem
├─ kibana.yml
└─ node.options

이 중 kibana.yml을 다음과 같이 수정하여 Search Guard를 적용하도록 하겠습니다.

elasticsearch.hosts: ["https://10.0.0.1:9200", "https://10.0.0.2:9200", "https://10.0.0.3:9200", "https://10.0.0.4:9200", "https://10.0.0.5:9200"]
elasticsearch.username: "kibanaserver"
elasticsearch.password: "password"
elasticsearch.ssl.verificationMode: none
  • elasticsearch.hosts : Elasticsearch에 TLS/SSL이 적용되었으므로 https라고 작성
  • elasticsearch.username : SGS_KIBANA_SERVER 권한을 가진 사용자에 대한 이름
  • elasticsearch.password : SGS_KIBANA_SERVER 권한을 가진 사용자에 대한 password
  • elasticsearch.ssl.verificationMode: none : 인증서 유효성 검사를 하지 않도록 none으로 설정

설정 변경이 완료되었으면, kibana를 실행합니다.

sudo systemctl start kibana

아래 명령어를 통해 정상 실행 되었는지 확인해봅시다.

sudo systemctl status kibana

정상 실행되면 다음과 같이 표출됩니다.

image

그리고 5601 포트로 접속해보면 아래와 같이 로그인 페이지가 화면에 뜹니다.

image

공식 문서를 참고하여 로그인 페이지를 커스텀해보도록 하겠습니다. kibana.yml에 다음 설정을 추가하여 Search Guard의 로고를 삭제해봅시다.

searchguard.basicauth.login.showbrandimage: false

그 다음 kibana를 재실행하면, 아래와 같이 로고가 삭제된 것을 확인할 수 있습니다.

image

03. Logstash 설정하기

먼저 logstash 설정 파일을 불러올 수 있도록 pipelines.yml을 설정합니다.

- pipeline.id: main
  path.config: "/etc/logstash/conf.d/main.conf"

그 다음 main.conf를 생성하고 다음과 같이 logstash를 설정합니다. input.log는 테스트를 위해 임의로 구성한 파일입니다.

input {
  file {
    path => "/etc/logstash/test/input.log"
        start_position => "beginning"
        sincedb_path => "/dev/null"
    }
}

output {
  elasticsearch {
    hosts => ["https://10.0.0.1:9200", "https://10.0.0.2:9200", "https://10.0.0.3:9200", "https://10.0.0.4:9200", "https://10.0.0.5:9200"]
    index => "test"
    user => "logstash"
    password => "logstash_password"
    ssl => true
    cacert => "/etc/logstash/root-ca.pem" # Elasticsearch path
  }
}

logstash의 각 설정에 대한 내용은 다음과 같습니다.

  • input : 입력 설정
    • file : 파일을 입력 받음 명시
      • path : 입력 받을 파일 경로
      • start_position : 파일을 불러들이는 위치
      • sincedb_path => "/dev/null" : 파일을 어디까지 읽었는지 기록하는 파일 경로이며, dev/null로 설정 시 파일을 어디까지 읽었는지 기록하지 않음
  • output : 출력 설정
    • elasticsearch : elasticsearch로 출력함을 병시
      • hosts : elasticsearch host 목록
      • index : logstash에서 elasticsearch로 출력할 때 저장할 인덱스 명
      • user : searchguard에 설정한 logstash 사용자 명
      • password : searchguard에 설정한 logstash 사용자의 패스워드
      • ssl => true : elasticsearch와의 통신을 https로 하기 위해 true로 설정
      • cacert : root-ca.pem이 위치하는 경로 (root-ca.pem은 이전에 생성한 파일 업로드)

설정을 완료한 다음 logstash를 실행합니다.

sudo systemctl start logstash

그 다음 Kibana > DevTools에 접속하여 인덱스가 생성되었는지 확인해보기 위해 아래 명령어를 입력합니다.

GET _cat/indices

image


참고

블로그의 정보

개발하는 두부

뚜부니

활동하기