LogstashExample1: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
Строка 207: Строка 207:
 
}
 
}
 
</PRE>
 
</PRE>
В результате сообщение будет разобрано на поля - но в этом случае в поле host
+
В результате сообщение будет разобрано на поля - но в этом случае в поле host
  +
<PRE>
  +
"host": {
  +
"hostname": "elk.domain.tld",
  +
"id": "ec2385ad84aeea5eb425460c41a5b866",
  +
"os": {
  +
"type": "linux",
  +
"codename": "focal",
  +
"name": "Ubuntu",
  +
"version": "20.04.2 LTS (Focal Fossa)",
  +
"kernel": "5.4.0-1045-aws",
  +
"platform": "ubuntu",
  +
"family": "debian"
  +
},
  +
</PRE>
  +
будет записан заголовок HOST что не овсем то что надо
  +
  +
=Пример с дебагом=
  +
Усложняем - добавляем максимальное количесво информации в логи
  +
==Nginx==
  +
Пишем все что возможно: https://noname.com.ua/mediawiki/index.php/Nginx_Log_Post
  +
<PRE>
  +
  +
</PRE>
  +
<PRE>
  +
server {
  +
listen 443 ssl;
  +
root /var/www/backend;
  +
server_name elk.domain.tld;
  +
access_log /var/log/nginx/elk.domain.tld-access.log.ssl nginxlog_json;
  +
error_log /var/log/nginx/elk.domain.tld-error.log.ssl;
  +
client_max_body_size 500M;
  +
keepalive_timeout 0;
  +
ssl_certificate ...;
  +
ssl_certificate_key ...;
  +
  +
lua_need_request_body on;
  +
  +
set $response_body "";
  +
body_filter_by_lua '
  +
local response_body = string.sub(ngx.arg[1], 1, 1000)
  +
ngx.ctx.buffered = (ngx.ctx.buffered or "") .. response_body
  +
if ngx.arg[2] then
  +
ngx.var.response_body = ngx.ctx.buffered
  +
end
  +
';
  +
  +
set_by_lua_block $request_headers{
  +
local h = ngx.req.get_headers()
  +
local request_headers_all = ""
  +
for k, v in pairs(h) do
  +
local rowtext = ""
  +
rowtext = string.format(" %s='%s' ", k, v)
  +
request_headers_all = request_headers_all .. rowtext
  +
  +
end
  +
return request_headers_all
  +
}
  +
...
  +
</PRE>

Версия 14:31, 8 августа 2021

Пример

Это продолжение статьи https://noname.com.ua/mediawiki/index.php?title=Logstash

nginx

Отправка логов nginx в Elastic (один из вариантов)
Тут рассматривается самый простой случай - когда Filebeat не делает преобразований Nginx умеет писать логи в Json

Как логгировать хедеры https://stackoverflow.com/questions/24380123/how-to-log-all-headers-in-nginx

log_format nginxlog_json escape=json
    '{ "timestamp": "$time_iso8601", '
    '"remote_addr": "$remote_addr", '
    '"body_bytes_sent": $body_bytes_sent, '
    '"request": "$request", '
    '"request_method": "$request_method", '
    '"request_time": $request_time, '
    '"response_status": $status, '
    '"upstream_status": $upstream_status,'
    '"upstream_response_time": $upstream_response_time,'
    '"upstream_connect_time": $upstream_connect_time,'
    '"upstream_header_time": $upstream_header_time,'
    '"upstream_addr": "$upstream_addr",'
    '"host": "$host",'
    '"http_x_forwarded_for": "$http_x_forwarded_for",'
    '"http_referrer": "$http_referer", '
    '"http_user_agent": "$http_user_agent", '
    '"http_version": "$server_protocol", '
    '"nginx_access": true }';

В лог попадает:

tail -1 /var/log/nginx/access.log.ssl   | jq .
{
  "timestamp": "2021-08-08T08:47:59+00:00",
  "remote_addr": "159.224.49.4",
  "body_bytes_sent": 361,
  "request": "POST /internal/bsearch HTTP/1.1",
  "request_method": "POST",
  "request_time": 0.152,
  "response_status": 200,
  "upstream_status": 200,
  "upstream_response_time": 0.028,
  "upstream_connect_time": 0,
  "upstream_header_time": 0.028,
  "upstream_addr": "127.0.0.1:5601",
  "host": "elk.domain.tld",
  "http_x_forwarded_for": "",
  "http_referrer": "https://elk.domain.tld/app/discover",
  "http_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15",
  "http_version": "HTTP/1.1",
  "nginx_access": true
}

Filebeat

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/nginx/elk.domain.tld-access.log.ssl
  exclude_files: ['\.gz$']
filebeat.config.modules:
  reload.enabled: false
setup.template.settings:
  index.number_of_shards: 1
setup.kibana:
output.logstash:
  hosts: ["elk.domain.tld:5400"]
  ssl.certificate_authorities: ["/etc/elk-certs/elk-ssl.crt"]
  ssl.certificate: "/etc/elk-certs/elk-ssl.crt"
  ssl.key: "/etc/elk-certs/elk-ssl.key"
processors:
  - add_host_metadata:
      when.not.contains.tags: forwarded
  - add_cloud_metadata: ~
  - add_docker_metadata: ~
  - add_kubernetes_metadata: ~
logging.level: debug
logging.selectors: ["*"]

В примере мониторится всего один файл (исключение очевидно лишнее)
Результат пересылается на удаленный хост в Logstash Важно Сертификат должен соответствовать хостнейму - тут нельзя указать IP адрес

hosts: ["elk.domain.tld:5400"]

Logstash

Базовый пример без преобразований

Минимальный конфиг - слушать Filebeat на порту 5400 (без сертификата - не будет работать)
Результат - писать в файл без всяких преобразований

input {
    beats {
        port => 5400
        ssl => true
        ssl_certificate_authorities => ["/etc/elk-certs/elk-ssl.crt"]
        ssl_certificate => "/etc/elk-certs/elk-ssl.crt"
        ssl_key => "/etc/elk-certs/elk-ssl.key"
        ssl_verify_mode => "force_peer"
    }
}
output {
    file {
        flush_interval => 5
            gzip => false
            path => "/var/log/logstash/logstash_debug.log"
    }
}

Результат записи в файл не удовлетворительный

root@elk:/var/log/logstash# tail -1 logstash_debug.log  | jq .

Сообщение не было разобрано на поля

{
  "message": "{ \"timestamp\": \"2021-08-08T09:20:47+00:00\", \"remote_addr\": \"61.219.11.151\", \"body_bytes_sent\": 163, \"request\": \"GET / HTTP/1.1\", \"request_method\": \"GET\", \"request_time\": 0.213, \"response_status\": 400, \"upstream_status\": ,\"upstream_response_time\": ,\"upstream_connect_time\": ,\"upstream_header_time\": ,\"upstream_addr\": \"\",\"host\": \"elk.arturhaunt.ninja\",\"http_x_forwarded_for\": \"\",\"http_referrer\": \"\", \"http_user_agent\": \"\", \"http_version\": \"HTTP/1.1\", \"nginx_access\": true }",
  "cloud": {
    "availability_zone": "us-east-1f",
    "region": "us-east-1",
    "instance": {
      "id": "i-075866580c26fd42c"
    },
    "service": {
      "name": "EC2"
    },
    "machine": {
      "type": "t3.large"
    },
    "image": {
      "id": "ami-09e67e426f25ce0d7"
    },
    "account": {
      "id": "543591064633"
    },
    "provider": "aws"
  },
  "@timestamp": "2021-08-08T09:20:52.684Z",
  "agent": {
    "hostname": "elk.domain.tld",
    "id": "aef24fda-f14c-40cf-a388-fa0af443f5d7",
    "type": "filebeat",
    "version": "7.14.0",
    "ephemeral_id": "c53f02a8-0b37-4dae-a3c7-cbf03eabca6a",
    "name": "elk.arturhaunt.ninja"
  },
  "@version": "1",
  "log": {
    "offset": 4126,
    "file": {
      "path": "/var/log/nginx/elk.domain.tld-access.log.ssl"
    }
  },
  "host": {
    "hostname": "elk.domain.tld",
    "id": "ec2385ad84aeea5eb425460c41a5b866",
    "os": {
      "type": "linux",
      "codename": "focal",
      "name": "Ubuntu",
      "version": "20.04.2 LTS (Focal Fossa)",
      "kernel": "5.4.0-1045-aws",
      "platform": "ubuntu",
      "family": "debian"
    },
    "ip": [
      "172.31.91.220",
      "fe80::14b5:eff:feac:ae79"
    ],
    "name": "elk.domain.tld",
    "mac": [
      "16:b5:0e:ac:ae:79"
    ],
    "architecture": "x86_64",
    "containerized": false
  },
  "input": {
    "type": "log"
  },
  "ecs": {
    "version": "1.10.0"
  },
  "tags": [
    "beats_input_codec_plain_applied"
  ]
}

Базовый пример с JSON

Для того что бы разобрать на поля JSON

filter {
  json {
    source => "message"
  }
}

В результате сообщение будет разобрано на поля - но в этом случае в поле host

  "host": {
    "hostname": "elk.domain.tld",
    "id": "ec2385ad84aeea5eb425460c41a5b866",
    "os": {
      "type": "linux",
      "codename": "focal",
      "name": "Ubuntu",
      "version": "20.04.2 LTS (Focal Fossa)",
      "kernel": "5.4.0-1045-aws",
      "platform": "ubuntu",
      "family": "debian"
    },

будет записан заголовок HOST что не овсем то что надо

Пример с дебагом

Усложняем - добавляем максимальное количесво информации в логи

Nginx

Пишем все что возможно: https://noname.com.ua/mediawiki/index.php/Nginx_Log_Post


    server {
        listen 443 ssl;
        root /var/www/backend;
        server_name elk.domain.tld;
        access_log /var/log/nginx/elk.domain.tld-access.log.ssl nginxlog_json;
        error_log /var/log/nginx/elk.domain.tld-error.log.ssl;
        client_max_body_size 500M;
        keepalive_timeout 0;
        ssl_certificate     ...;
        ssl_certificate_key ...;

        lua_need_request_body on;

        set $response_body "";
        body_filter_by_lua '
            local response_body = string.sub(ngx.arg[1], 1, 1000)
            ngx.ctx.buffered = (ngx.ctx.buffered or "") .. response_body
            if ngx.arg[2] then
                ngx.var.response_body = ngx.ctx.buffered
            end
        ';

        set_by_lua_block $request_headers{
            local h = ngx.req.get_headers()
            local request_headers_all = ""
            for k, v in pairs(h) do
                local rowtext = ""
                rowtext = string.format(" %s='%s' ", k, v)
                request_headers_all = request_headers_all .. rowtext

            end
            return request_headers_all
        }
...