Veremos a partir de agora como aplicar controle de acesso no elasticsearch, utilizando um plugin opensource, bem como configurar um período de retenção.

Ativar apenas a autenticação é simples. Para limitar o acesso a interface do kibana, o comum tem sido configurar um webserver autenticado como proxy reverso. Neste caso, é fácil encontrar documentações envolvendo integração com o nginx, por exemplo. Também encontrei ajustes granulares via nginx, mas não gostei (gera uma complexidade desnecessária e fora de propósito).

Para controlar acesso de forma granular e exportar o dashboard, no formato pdf, o time de desenvolvimento do elasticsearch defende a utilização do plugin x-pack. Trata-se de uma solução eficiente e fácil de instalar. Infelizmente, o pacote disponível para download livremente é trial (30 dias). A solução é comercial.

Pesquisando por soluções alternativas, encontramos o Searchguard. A instalação não foi tão simples e alguns problemas nos fizeram abandonar. Assim como no x-pack, existe um plugin para o elasticsearch e outro para o kibana. A versão do plugin para o kibana ainda é Alpha. E, nos testes realizados, recebemos mensagens de erro interno na chamada de algumas funções.

A segunda alternativa que encontramos, conhecida como Readonly Rest, foi a mais simples, eficiente e atende a demanda da maioria dos administradores. Além disto, o plugin é disponibilizado sob licença GPL 3,

Demonstraremos uma configuração simples, supondo que duas filiais exportarão os logs de seus servidores proxy (peers) para a matriz, e forneceremos acesso ao dashboard limitando a visão apenas ao segmento de rede que fazem parte – impedindo que uma filial visualize os logs da outra.

Disponibilizei para download um pacote com os arquivos essenciais de configuração:
elk-readonlyrest.tar


Instalação e configuração do plugin ReadonlyREST no servidor

Não instale a versão readonlyrest-1.13.0_es5.1.2.zip. Preferencialmente, opte pelo download disponível na página oficial ou instale a versão avaliada na demonstração.

1. Instalação do plugin

/usr/share/elasticsearch/bin/elasticsearch-plugin install file:///diretorio/do/dowload/readonlyrest-1.13.0_es5.1.2.zip

2. Alteração em /etc/elasticsearch/elasticsearch.yml

Para que este layout funcione, cada filial informará um document-type único que será definido como index no servidor logstash (repare nos índices em negrito).

readonlyrest:
    enable: true
    response_if_req_forbidden: <h1>Forbidden</h1>
    access_control_rules:

    - name: Kibana Server
      type: allow
      auth_key: kibana:kibana

    - name: Logstash
      type: allow
      hosts: ["127.0.0.1"]
      auth_key: logstash:logstash


    # Grupos
    - name: Grupo filial 1
      type: allow
      accept_x-forwarded-for_header: true
      kibana_access: ro
      actions: ["indices:data/read/*", "indices:admin/mappings/get", "indices:admin/mappings/fields/get*"]
      indices: ["<no-index>", "logstash-squid-filial1*", ".kibana*", "default"]
      groups: ["grpfilial1"]

    - name: Grupo filial 2
      type: allow
      accept_x-forwarded-for_header: true
      kibana_access: ro
      actions: ["indices:data/read/*", "indices:admin/mappings/get", "indices:admin/mappings/fields/get*"]
      indices: ["<no-index>", "logstash-squid-filial2*", ".kibana*", "default"]
      groups: ["grpfilial2"]

    users:

    - username: filial1
      auth_key: filial1:senh@fili@l1
      groups: ["grpfilial1"]

    - username: filial2
      auth_key: filial2:senh@fili@l2
      groups: ["grpfilial2"]

Em caso de dúvidas, consulte os links:
https://github.com/sscarduzio/elasticsearch-readonlyrest-plugin
https://github.com/sscarduzio/elasticsearch-readonlyrest-plugin/wiki/Supported-Rules

3. Reiniciando o serviço (systemctl ou service)

systemctl restart elasticsearch


Configuração do servidor Logstash

Após reiniciar o serviço elasticsearch, qualquer conexão será validada. Portanto, informe uma conta de usuário válida no bloco “output” (usuário logstash).

O índice foi redefinido como “logstash-%{type}-%{+YYYY.MM.dd}” para diferenciar os dados por origem (document-type) e identificar o dia corrente (para controlar o período de retenção).

1. Alteração em /etc/logstash/conf.d/squid.conf

input {
  beats {
      host => "ip_servidor_logstash"
      port => 5044
      ssl => false
  }
}

filter {
  if [type] =~ /(squid|squid-*)/ {
    grok {

      break_on_match => true
      match => [ "message", "%{NUMBER:timestamp}\s+%{NUMBER:response_time} %{IPORHOST:src_ip} %{WORD:squid_request_status}/%{NUMBER:http_status_code} %{NUMBER:reply_size_include_header:int} %{WORD:http_method} %{WORD:http_protocol}://%{HOSTNAME:dst_host}:%{NUMBER:tcp.port}%{NOTSPACE:request_url} %{NOTSPACE:user} %{WORD:squid}/(?:-|%{IP:dst_ip}) %{NOTSPACE:content_type}" ]

      match => [ "message", "%{NUMBER:timestamp}\s+%{NUMBER:response_time} %{IPORHOST:src_ip} %{WORD:squid_request_status}/%{NUMBER:http_status_code} %{NUMBER:reply_size_include_header:int} %{WORD:http_method} %{WORD:http_protocol}://%{HOSTNAME:dst_host}%{NOTSPACE:request_url} %{NOTSPACE:user} %{WORD:squid}/(?:-|%{IP:dst_ip}) %{NOTSPACE:content_type}" ]

      match => [ "message", "%{NUMBER:timestamp}\s+%{NUMBER:response_time} %{IPORHOST:src_ip} %{WORD:squid_request_status}/%{NUMBER:http_status_code} %{NUMBER:reply_size_include_header:int} %{WORD:http_method} %{HOSTNAME:dst_host}:%{NUMBER:tcp.port} %{NOTSPACE:user} %{WORD:squid}/(?:-|%{IP:dst_ip}) %{NOTSPACE:content_type}" ]

      add_tag => ["squid"]
    }

    geoip {
      source => "dst_ip"
    }
  }
}

output {
  elasticsearch {
    hosts => localhost
    ssl => false
    flush_size => 1000
      index => "logstash-%{type}-%{+YYYY.MM.dd}"

      user => logstash
      password => logstash
  }
}

2. Reiniciando o serviço (systemctl ou service)

systemctl restart logstash


Configuração do servidor Kibana

Para autenticar, configure a conta definida em “Kibana Server“. Vale lembrar que, de acordo com a configuração demonstrada, o usuário kibana terá acesso irrestrito ao ambiente. “O mesmo se aplica ao usuário logstash, desde que o endereço IP de origem seja local (127.0.0.1)”.

A opção elasticsearch.preserveHost foi definida como false para permitir o envio do IP de origem no header x-forwarded-for, possibilitando aplicar filtros por IP no plugin readonlyrest.

Pela interface do Kibana, crie cada index em “Management->Index Patterns->Add New“. Ou seja, em “index name or pattern” cadastre “logstash-squid-filial1-*” e repita o processo para cada filial. O botão “Create” ficará disponível desde que já exista um índice válido no elasticsearch.

1. Alteração em /etc/kibana/kibana.yml

# Specifies the address to which the Kibana server will bind. IP addresses and host names are both valid values.
# The default is 'localhost', which usually means remote machines will not be able to connect.
# To allow connections from remote users, set this parameter to a non-loopback address.
server.host: "0.0.0.0"
...
# The URL of the Elasticsearch instance to use for all your queries.
elasticsearch.url: "http://localhost:9200"

# When this setting’s value is true Kibana uses the hostname specified in the server.host
# setting. When the value of this setting is false, Kibana uses the hostname of the host
# that connects to this Kibana instance.
#elasticsearch.preserveHost: true
elasticsearch.preserveHost: false
...
# If your Elasticsearch is protected with basic authentication, these settings provide
# the username and password that the Kibana server uses to perform maintenance on the Kibana
# index at startup. Your Kibana users still need to authenticate with Elasticsearch, which
# is proxied through the Kibana server.
elasticsearch.username: "kibana"
elasticsearch.password: "kibana"
...

2. Reiniciando o serviço (systemctl ou service)

systemctl restart kibana


Configuração dos agentes Filebeat

Há apenas uma mudança significativa no arquivo /etc/filebeat/filebeat.yml. Ajuste o conteúdo de document-type de cada filial. Na primeira, configure como squid-filial1 e, na segunda, squid-filial2.

1. Alteração em /etc/filebeat/filebeat.yml

...
# Each - is a prospector. Most options can be set at the prospector level, so
# you can use different prospectors for various configurations.
# Below are the prospector specific configurations.

- input_type: log

  # Paths that should be crawled and fetched. Glob based paths.
  paths:
    - /var/log/squid/access.log

  document_type: squid-filial1
  ...

2. Reiniciando o serviço (systemctl ou service)

systemctl restart filebeat


Configuração do período de retenção no servidor Elasticsearch

O controle de retenção será feito através da ferramenta Curator. A configuração base do Curator será definida no arquivo config.yml. Nele, configuraremos os parâmetros de conexão com o elasticsearch. Já a definição das ações (como remoção de index) será definida em action.yml.

Em nosso exemplo, o período de retenção será configurado para 1 ano (365 dias).

Se desejar consultar os índices disponíveis, utilize o comando:

curl -u logstash 'localhost:9200/_cat/indices?v'

1. Instalação da ferramenta Curator

sudo echo "deb http://packages.elastic.co/curator/4/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-5.x.list
sudo apt-get update

#Instalação do serviço
apt-get install elasticsearch-curator
mkdir /etc/curator

2. Configuração da ferramenta Curator

Definição do arquivo /etc/curator/config.yml

---
# Remember, leave a key empty if there is no value.  None will be a string,
# not a Python "NoneType"
client:
  hosts:
    - 127.0.0.1
  port: 9200
  url_prefix:
  use_ssl: False
  certificate:
  client_cert:
  client_key:
  ssl_no_validate: False
  http_auth: logstash:logstash
  timeout: 30
  master_only: False

logging:
  loglevel: INFO
  logfile:
  logformat: default
  blacklist: ['elasticsearch', 'urllib3']

Definição do arquivo /etc/curator/action.yml

---
# Remember, leave a key empty if there is no value.  None will be a string,
# not a Python "NoneType"
#
# Also remember that all examples have 'disable_action' set to True.  If you
# want to use this action as a template, be sure to set this to False after
# copying it.
actions:
  1:
    action: delete_indices
    description: >-
      Delete indices older than 365 days (based on index name), for logstash-
      prefixed indices. Ignore the error if the filter does not result in an
      actionable list of indices (ignore_empty_list) and exit cleanly.
    options:
      ignore_empty_list: True
      timeout_override:
      continue_if_exception: False
      disable_action: False
    filters:
    - filtertype: pattern
      kind: prefix
      value: logstash-squid-
      exclude:
    - filtertype: age
      source: name
      direction: older
      timestring: '%Y.%m.%d'
      unit: days
      unit_count: 365
      exclude:

3. Execução da ferramenta Curator

– Para automatizar o processo, inclua uma chamada no cron (diário)

curator --config /etc/curator/config.yml /etc/curator/action.yml