commit dac9a1e3f44e1ee487d3d1b2a6c4a74f7477c2f9 Author: Magnus Root Date: Tue Feb 24 11:30:35 2026 +0300 Work version diff --git a/.ansible/.lock b/.ansible/.lock new file mode 100644 index 0000000..e69de29 diff --git a/.gitea/workflows/yamllint_and_pass_check.yml b/.gitea/workflows/yamllint_and_pass_check.yml new file mode 100644 index 0000000..81eb41c --- /dev/null +++ b/.gitea/workflows/yamllint_and_pass_check.yml @@ -0,0 +1,26 @@ +--- +name: YAML Lint + +on: [push] + +jobs: + yamllint: + runs-on: ubuntu-yamllint + steps: + - name: Checkout linting + uses: actions/checkout@v4 + + - name: Run yamllint with auto-detected config + run: | + yamllint -c .yamllint . + gitleaks: + runs-on: ubuntu-yamllint + steps: + - name: Checkout passwords leaks + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Run gitleaks + run: gitleaks detect --source . --verbose +... diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d74e21 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode/ diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 0000000..2268f80 --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,7 @@ +[extend] +useDefault = true + +[allowlist] +paths = [ +# '''roles/logs_settings_on_ptaf/templates/filebeat.yml.j2''', +] \ No newline at end of file diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..e68c28f --- /dev/null +++ b/.yamllint @@ -0,0 +1,11 @@ +--- +extends: default + +ignore: | + roles/filebeat_install/files/fields.yml + .gitea/workflows/yamllint.yml + +rules: + line-length: + max: 180 +... diff --git a/README.md b/README.md new file mode 100755 index 0000000..354ac3c --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# waf_playbooks + +Репозиторий для всех задач решаемых на WAF с помощью ansible. + +Все изменения должны делаться в новых ветках и потом мерджиться в master. + +При пуше коммитов в гит происходит проверка кода на соответствие правилам оформления кода с помощью `yamllint`, а также проверка на утечки с помощью `gitleaks`. Если проверка не будет пройдена, то не будет возможности смёрджить изменения в основную ветку. Так что если ваш коммит н еможет пройти какую-либо проверку, то можно запустить проверку этими же инструментами локально и найти в чём проблема. + +## Dockerfile для yamllint и gitleaks +```bash +FROM docker.gitea.com/runner-images:ubuntu-latest + +RUN apt-get update && \ + apt-get install -y yamllint && \ + apt-get install -y wget && \ + wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.4/gitleaks_8.18.4_linux_x64.tar.gz && \ + tar -xzf gitleaks_8.18.4_linux_x64.tar.gz && \ + mv gitleaks /usr/local/bin/ && \ + rm gitleaks_8.18.4_linux_x64.tar.gz && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* +``` + +## Docker-compose.yml для yamllint и gitleaks +```bash +version: '3' +services: + act_runner: + image: gitea/act_runner:latest + privileged: true + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./runner_data:/data + environment: + - GITEA_INSTANCE_URL=https://svc-git.cirex.ru + - GITEA_RUNNER_REGISTRATION_TOKEN=EQcod + - GITEA_RUNNER_NAME=my-docker-runner + - GITEA_RUNNER_LABELS=ubuntu-yamllint:docker://ubuntu-yamllint:latest,ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest,ubuntu-22.04:docker://docker.gitea.com/runner-images:ubuntu-22.04 + restart: unless-stopped +``` diff --git a/ansible.cfg b/ansible.cfg new file mode 100755 index 0000000..7864beb --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,30 @@ +[defaults] +inventory = ./inventory/hosts.yml +host_key_checking = False +pipelining = True +forks = 10 +strategy = free +stdout_callback = default +callback_whitelist = default +callback_default_result_format = yaml +remote_user = ansible +python_interpreter = /usr/bin/python3 +gathering = smart +fact_caching_timeoout = 86400 +fact_caching = jsonfile +fact_caching_connection = /tmp/ansible_fact_cache + +[privilege_escalation] +become = True +become_method = sudo +become_user = root + +[persistent_connections] +pipelining = True + +[ssh_connection] +ssh_args = -o ControlMaster=auto -o ControlPersist=60s +retries = 3 + +[logging] +log_path = /var/log/ansible.log diff --git a/inventory/group_vars/AZ1.yml b/inventory/group_vars/AZ1.yml new file mode 100755 index 0000000..d72212f --- /dev/null +++ b/inventory/group_vars/AZ1.yml @@ -0,0 +1,4 @@ +--- +gray_gateway: +white_gateway: +... diff --git a/inventory/group_vars/AZ2.yml b/inventory/group_vars/AZ2.yml new file mode 100755 index 0000000..d72212f --- /dev/null +++ b/inventory/group_vars/AZ2.yml @@ -0,0 +1,4 @@ +--- +gray_gateway: +white_gateway: +... diff --git a/inventory/group_vars/PD101.yml b/inventory/group_vars/PD101.yml new file mode 100644 index 0000000..d72212f --- /dev/null +++ b/inventory/group_vars/PD101.yml @@ -0,0 +1,4 @@ +--- +gray_gateway: +white_gateway: +... diff --git a/inventory/group_vars/PD201.yml b/inventory/group_vars/PD201.yml new file mode 100644 index 0000000..d72212f --- /dev/null +++ b/inventory/group_vars/PD201.yml @@ -0,0 +1,4 @@ +--- +gray_gateway: +white_gateway: +... diff --git a/inventory/group_vars/prod.yml b/inventory/group_vars/prod.yml new file mode 100755 index 0000000..c93cd17 --- /dev/null +++ b/inventory/group_vars/prod.yml @@ -0,0 +1,159 @@ +--- +api_sp_token: +db_user: +db_password: +telegram_bot_token: +git_token: +telegram_chat_id: +grafana_api_token: +db_name: test_info +username_on_new_hosts: user +install_ssh_pass: +timezone: "Europe/Moscow" +ntp_servers: + - + - +dns_servers: + - + - +need_support_soft: + - xrdp + - tree + - mc + - wget + - gpg + - python3 + - ansible + - git + - apt-transport-https + - ca-certificates + - curl + - apt-utils + - gnupg2 +xrdp_pass: +primary_db_host: '10.10.10.8' +secondary_db_host: '10.10.10.5' +arch_version: amd64 +ubuntu_codename: noble +zabbix_version: "7.0" +zabbix_server: "10.10.20.5" +zabbix_port: "10050" +zabbix_hostname: system.hostname +ubuntu_version: "24.04" +compose_version: 2.39.3 +iptables_version: 1.8.10-3ubuntu2 +docker_agent_version: '4.1.6.409465' +docker_image: ptaf-core-nginx-agent:release-{{ docker_agent_version }} +local_directory_docker_image: /home/install/ptaf-core-nginx-agent_release-{{ docker_agent_version }}.tar +magos_bin: "/usr/local/bin/magos" +number_of_worker_processes: 4 +number_of_worker_connections: 64000 +sysctl_params: + net.core.netdev_max_backlog: 10000 + net.core.somaxconn: 262144 + net.ipv4.tcp_syncookies: 1 + net.ipv4.tcp_max_syn_backlog: 262144 + net.ipv4.tcp_max_tw_buckets: 720000 + net.ipv4.tcp_timestamps: 1 + net.ipv4.tcp_tw_reuse: 1 + net.ipv4.tcp_fin_timeout: 30 + net.ipv4.tcp_keepalive_time: 1800 + net.ipv4.tcp_keepalive_probes: 7 + net.ipv4.tcp_keepalive_intvl: 30 + net.core.wmem_max: 33554432 + net.core.rmem_max: 33554432 + net.core.rmem_default: 8388608 + net.core.wmem_default: 4194394 + net.ipv4.tcp_rmem: "4096 8388608 16777216" + net.ipv4.tcp_wmem: "4096 4194394 16777216" + net.ipv4.ip_local_port_range: "1024 65535" + net.netfilter.nf_conntrack_max: 1048576 +antibot_networks: + - + - +waf_networks: + - + - +need_soft: + - tree + - mc + - ncdu + - chrony + - sqlite3 + - python3-pip + - postgresql-client-common + - postgresql-client-16 + - mtr + - traceroute + - angie-module-njs +user_list: + - username: + home_dir: + key_file: + - username: + home_dir: + key_file: +need_install_firewall: true +app_config: + Test_service: + # По умолчанию пусто. Если надо добавить, то добалять адрес с : на конце + LISTEN_IP: + TENANT_NAME: "Test_service" + CONTAINER_NUMBERS: 1 + # Есть ли настройки без кастомов + USUAL_SETTINGS: true + # Здесь и далее указывается только то у чего нет кастомных настроек. + # Ни апстирмов, ни портов, ни server. + SID_NUMBERS: + - 11111 + - 11111 + - 11111 + # Приложения в тенанте. Подставляются в шаблоны в апстримы и имена логов + APP_IN_TENANT_NAMES: + - "test_1_ru" + - "test_2_ru" + - "test_3_ru" + # Приложения в тенанте. Подставляются в server_name. + # Если их несколько для одного приложения, то пишутся в одну строку + SERVER_NAMES_FOR_APPS: + - "test.1.ru" + - "test.2.ru" + - "test.3.ru" + # Адреса ориджинов. Подставляются в апстримы + UPSTREAM_IPS: + - 91.206.126.155 + - 91.206.126.36 + - 91.206.126.162 + # Группировка ориджинов на случай, если в апстриме больше одного адреса + UPSTREAM_GROUPS: + - ips: "{{ app_config[app].UPSTREAM_IPS[:1] }}" + # Приложения в тенанте. Подставляются в шаблоны в апстримы и имена логов + suffix: "test_1_ru" + - ips: "{{ app_config[app].UPSTREAM_IPS[1:2] }}" + suffix: "test_2_ru" + - ips: "{{ app_config[app].UPSTREAM_IPS[2:3] }}" + suffix: "test_3_ru" + # Есть ли кастомные правила для PT AF Nginx или кастомные locations + CUSTOM_CONFIG_PTAF_NGINX_NEED: false + # Есть ли кастомные изменения в upstream PT AF Nginx + CUSTOM_CONFIG_PTAF_NGINX_UPSTREAM_NEED: false + # Есть ли кастомные правила для Angie или кастомные locations + CUSTOM_CONFIG_ANGIE_NEED: false + # Есть ли кастомные изменения в upstream Angie + CUSTOM_CONFIG_ANGIE_UPSTREAM_NEED: false + # Есть ли кастомные порты + CUSTOM_PORTS_NEED: false + # Есть ли кастомные настройки апстримов Angie для кастомных портов + CUSTOM_CONFIG_ANGIE_UPSTREAM_NEED_WITH_CUSTOM_PORTS: false + # Есть ли кастомные настройки апстримов PT AF Nginx для кастомных портов + CUSTOM_CONFIG_PTAF_NGINX_UPSTREAM_NEED_WITH_CUSTOM_PORTS: false + # Есть ли кастомные правила Angie + CUSTOM_CONFIG_ANGIE_NEED_WITH_CUSTOM_PORTS: false + # Есть ли кастомные правила PT AF Nginx + CUSTOM_CONFIG_PTAF_NGINX_NEED_WITH_CUSTOM_PORTS: false + # Есть ли кастом в location. Не может быть без CUSTOM_CONFIG_ANGIE_NEED:true + CUSTOM_LOCATIONS_NEED: false + # Нужна ли отгрузка логов заказчику + FLUENT_BIT_NEED: false + CONNECTION_STRING: +... diff --git a/inventory/hosts.yml b/inventory/hosts.yml new file mode 100755 index 0000000..00fc58a --- /dev/null +++ b/inventory/hosts.yml @@ -0,0 +1,20 @@ +--- +all: + children: + prod: + children: + PTAF: + children: + AZ1: + hosts: + WAF--AZ1-test01: + ansible_host: 10.10.10.4 + WAF--AZ1-test02: + ansible_host: 10.10.10.5 + AZ2: + hosts: + WAF-AZ2-test01: + ansible_host: 10.10.11.4 + WAF-AZ2-test02: + ansible_host: 10.10.11.5 +... diff --git a/roles/auspex/defaults/main.yml b/roles/auspex/defaults/main.yml new file mode 100644 index 0000000..3f475f1 --- /dev/null +++ b/roles/auspex/defaults/main.yml @@ -0,0 +1,3 @@ +--- +auspex_bin: "/usr/local/bin/auspex" +... diff --git a/roles/auspex/tasks/main.yml b/roles/auspex/tasks/main.yml new file mode 100644 index 0000000..160b047 --- /dev/null +++ b/roles/auspex/tasks/main.yml @@ -0,0 +1,82 @@ +--- +- name: Copy auspex from cloud + ansible.builtin.get_url: + url: "" + dest: "{{ auspex_bin }}" + owner: root + group: root + mode: '0744' + timeout: 60 + force: true + retries: 3 + delay: 10 + +- name: Create cron task for auspex cert checker + ansible.builtin.cron: + name: "Run auspex cert checker" + minute: "0" + hour: "9" + day: "*" + month: "*" + weekday: "*" + job: "{{ auspex_bin }} -c" + user: root + +- name: Create cron task for auspex port checker + ansible.builtin.cron: + name: "Run auspex port checker" + minute: "*/16" + hour: "*" + day: "*" + month: "*" + weekday: "*" + job: "{{ auspex_bin }} -p" + user: root + +- name: Create cron task for auspex match checker + ansible.builtin.cron: + name: "Run auspex match checker" + minute: "*/11" + hour: "*" + day: "*" + month: "*" + weekday: "*" + job: "{{ auspex_bin }} -m" + user: root + +- name: Create cron task for auspex logs checker + ansible.builtin.cron: + name: "Run auspex logs checker" + minute: "*/30" + hour: "*" + day: "*" + month: "*" + weekday: "*" + job: "{{ auspex_bin }} -l" + user: root + +- name: Copy auspex on and off scripts + ansible.builtin.template: + src: "{{ item }}" + dest: "/usr/local/bin/{{ (item | basename).removesuffix('.j2') }}" + owner: root + group: root + mode: '0744' + loop: "{{ query('fileglob', 'templates/*.sh.j2') }}" + +- name: Create directory /etc/auspex + ansible.builtin.file: + path: /etc/auspex + state: directory + owner: root + group: root + mode: '0755' + +- name: Create .env + ansible.builtin.template: + src: auspex.env.j2 + dest: /etc/auspex/auspex.env + owner: root + group: root + mode: '0600' +... diff --git a/roles/auspex/templates/auspex.env.j2 b/roles/auspex/templates/auspex.env.j2 new file mode 100644 index 0000000..a0d14dd --- /dev/null +++ b/roles/auspex/templates/auspex.env.j2 @@ -0,0 +1,22 @@ +TELEGRAM_BOT_TOKEN={{ telegram_bot_token }} +TELEGRAM_CHAT_ID={{ telegram_chat_id }} +DB_USER={{ db_user }} +DB_PASSWORD={{ db_password }} +DB_NAME=waf_info +DB_PORT=5432 +PRIMARY_DB_HOST=10.100.10.8 +SECONDARY_DB_HOST=10.100.13.5 +PTAF_BASE_DIR=/home/install/ptaf +ANGIE_CONF_DIR=/etc/angie/http.d +SSL_DIR=/etc/ssl +NGINX_CONFIG_GLOB=/home/install/conf/ptaf-nginx/*/*/*/*.conf +STATE_FILE_PATH=/tmp/port_checker_state.json +LOG_DIR=/var/log/ptaf_nginx +CERT_CRITICAL_DAYS=3 +CERT_WARNING_DAYS=15 +CERT_INFO_DAYS=30 +LOG_STALE_MINUTES=61 +CHECK_TIMEOUT_SEC=10 +MAX_RETRIES=3 +RETRY_DELAY_SEC=2 +MAX_WORKERS=10 \ No newline at end of file diff --git a/roles/auspex/templates/auspex_l_off.sh.j2 b/roles/auspex/templates/auspex_l_off.sh.j2 new file mode 100644 index 0000000..cab4746 --- /dev/null +++ b/roles/auspex/templates/auspex_l_off.sh.j2 @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для комментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/30 * * * * {{ auspex_bin }} -l" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в незакомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка найдена и не закомментирована - комментируем её + echo "$CURRENT_CRON" | sed "s|^\(${ESCAPED_LINE}\)|#\1|" | crontab - + echo "Строка закомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка уже закомментирована + echo "Строка уже закомментирована, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/auspex/templates/auspex_l_on.sh.j2 b/roles/auspex/templates/auspex_l_on.sh.j2 new file mode 100644 index 0000000..401ba34 --- /dev/null +++ b/roles/auspex/templates/auspex_l_on.sh.j2 @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для раскомментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/30 * * * * {{ auspex_bin }} -l" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в закомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка найдена и закомментирована - раскомментируем её + echo "$CURRENT_CRON" | sed "s|^#\(${ESCAPED_LINE}\)|\1|" | crontab - + echo "Строка раскомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка уже раскомментирована + echo "Строка уже активна, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/auspex/templates/auspex_m_off.sh.j2 b/roles/auspex/templates/auspex_m_off.sh.j2 new file mode 100644 index 0000000..2e779b0 --- /dev/null +++ b/roles/auspex/templates/auspex_m_off.sh.j2 @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для комментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/11 * * * * {{ auspex_bin }} -m" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в незакомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка найдена и не закомментирована - комментируем её + echo "$CURRENT_CRON" | sed "s|^\(${ESCAPED_LINE}\)|#\1|" | crontab - + echo "Строка закомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка уже закомментирована + echo "Строка уже закомментирована, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/auspex/templates/auspex_m_on.sh.j2 b/roles/auspex/templates/auspex_m_on.sh.j2 new file mode 100644 index 0000000..2a36217 --- /dev/null +++ b/roles/auspex/templates/auspex_m_on.sh.j2 @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для раскомментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/11 * * * * {{ auspex_bin }} -m" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в закомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка найдена и закомментирована - раскомментируем её + echo "$CURRENT_CRON" | sed "s|^#\(${ESCAPED_LINE}\)|\1|" | crontab - + echo "Строка раскомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка уже раскомментирована + echo "Строка уже активна, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/auspex/templates/auspex_p_off.sh.j2 b/roles/auspex/templates/auspex_p_off.sh.j2 new file mode 100644 index 0000000..131baa3 --- /dev/null +++ b/roles/auspex/templates/auspex_p_off.sh.j2 @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для комментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/11 * * * * {{ auspex_bin }} -p" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в незакомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка найдена и не закомментирована - комментируем её + echo "$CURRENT_CRON" | sed "s|^\(${ESCAPED_LINE}\)|#\1|" | crontab - + echo "Строка закомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка уже закомментирована + echo "Строка уже закомментирована, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/auspex/templates/auspex_p_on.sh.j2 b/roles/auspex/templates/auspex_p_on.sh.j2 new file mode 100644 index 0000000..ef0bb98 --- /dev/null +++ b/roles/auspex/templates/auspex_p_on.sh.j2 @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для раскомментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/11 * * * * {{ auspex_bin }} -p" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в закомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка найдена и закомментирована - раскомментируем её + echo "$CURRENT_CRON" | sed "s|^#\(${ESCAPED_LINE}\)|\1|" | crontab - + echo "Строка раскомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка уже раскомментирована + echo "Строка уже активна, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/auspex_l_off/README.md b/roles/auspex_l_off/README.md new file mode 100644 index 0000000..d0bd16b --- /dev/null +++ b/roles/auspex_l_off/README.md @@ -0,0 +1,3 @@ +# Auspex logs off + +Отключение проверки свежести логов diff --git a/roles/auspex_l_off/tasks/main.yml b/roles/auspex_l_off/tasks/main.yml new file mode 100644 index 0000000..3b58dd7 --- /dev/null +++ b/roles/auspex_l_off/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: Check utils + ansible.builtin.stat: + path: /usr/local/bin/auspex + register: utils_stat + +- name: Auspex logs check off + ansible.builtin.command: /usr/local/bin/auspex_l_off.sh + register: result + when: utils_stat.stat.exists and utils_stat.stat.executable + +- name: Show result + ansible.builtin.debug: + var: result.stdout + when: utils_stat.stat.exists +... diff --git a/roles/auspex_l_on/tasks/README.md b/roles/auspex_l_on/tasks/README.md new file mode 100644 index 0000000..803f79d --- /dev/null +++ b/roles/auspex_l_on/tasks/README.md @@ -0,0 +1,3 @@ +# Auspex logs on + +Включение проверки свежести логов diff --git a/roles/auspex_l_on/tasks/main.yml b/roles/auspex_l_on/tasks/main.yml new file mode 100644 index 0000000..056c95b --- /dev/null +++ b/roles/auspex_l_on/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: Check utils + ansible.builtin.stat: + path: /usr/local/bin/auspex + register: utils_stat + +- name: Auspex logs check on + ansible.builtin.command: /usr/local/bin/auspex_l_on.sh + register: result + when: utils_stat.stat.exists and utils_stat.stat.executable + +- name: Show result + ansible.builtin.debug: + var: result.stdout + when: utils_stat.stat.exists +... diff --git a/roles/auspex_m_off/README.md b/roles/auspex_m_off/README.md new file mode 100644 index 0000000..fdc3bc9 --- /dev/null +++ b/roles/auspex_m_off/README.md @@ -0,0 +1,3 @@ +# Auspex match off + +Отключение проверки связности Angie и Docker diff --git a/roles/auspex_m_off/tasks/main.yml b/roles/auspex_m_off/tasks/main.yml new file mode 100644 index 0000000..d493b64 --- /dev/null +++ b/roles/auspex_m_off/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: Check utils + ansible.builtin.stat: + path: /usr/local/bin/auspex + register: utils_stat + +- name: Auspex match off + ansible.builtin.command: /usr/local/bin/auspex_m_off.sh + register: result + when: utils_stat.stat.exists and utils_stat.stat.executable + +- name: Show result + ansible.builtin.debug: + var: result.stdout + when: utils_stat.stat.exists +... diff --git a/roles/auspex_m_on/README.md b/roles/auspex_m_on/README.md new file mode 100644 index 0000000..3f30201 --- /dev/null +++ b/roles/auspex_m_on/README.md @@ -0,0 +1,3 @@ +# Auspex logs on + +Включение проверки связности Angie и Docker diff --git a/roles/auspex_m_on/tasks/main.yml b/roles/auspex_m_on/tasks/main.yml new file mode 100644 index 0000000..655ff26 --- /dev/null +++ b/roles/auspex_m_on/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: Check utils + ansible.builtin.stat: + path: /usr/local/bin/auspex + register: utils_stat + +- name: Auspex match on + ansible.builtin.command: /usr/local/bin/auspex_m_on.sh + register: result + when: utils_stat.stat.exists and utils_stat.stat.executable + +- name: Show result + ansible.builtin.debug: + var: result.stdout + when: utils_stat.stat.exists +... diff --git a/roles/auspex_p_off/README.md b/roles/auspex_p_off/README.md new file mode 100644 index 0000000..28b997d --- /dev/null +++ b/roles/auspex_p_off/README.md @@ -0,0 +1,3 @@ +# Auspex ports off + +Отключение проверки доступности портов diff --git a/roles/auspex_p_off/tasks/main.yml b/roles/auspex_p_off/tasks/main.yml new file mode 100644 index 0000000..48c22d8 --- /dev/null +++ b/roles/auspex_p_off/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: Check utils + ansible.builtin.stat: + path: /usr/local/bin/auspex + register: utils_stat + +- name: Port checker off + ansible.builtin.command: /usr/local/bin/auspex_p_off.sh + register: result + when: utils_stat.stat.exists and utils_stat.stat.executable + +- name: Show result + ansible.builtin.debug: + var: result.stdout + when: utils_stat.stat.exists +... diff --git a/roles/auspex_p_on/README.md b/roles/auspex_p_on/README.md new file mode 100644 index 0000000..5324efd --- /dev/null +++ b/roles/auspex_p_on/README.md @@ -0,0 +1,3 @@ +# Auspex ports on + +Включение проверки доступности портов diff --git a/roles/auspex_p_on/tasks/main.yml b/roles/auspex_p_on/tasks/main.yml new file mode 100644 index 0000000..5c347a8 --- /dev/null +++ b/roles/auspex_p_on/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: Check utils + ansible.builtin.stat: + path: /usr/local/bin/auspex + register: utils_stat + +- name: Port checker on + ansible.builtin.command: /usr/local/bin/auspex_p_on.sh + register: result + when: utils_stat.stat.exists and utils_stat.stat.executable + +- name: Show result + ansible.builtin.debug: + var: result.stdout + when: utils_stat.stat.exists +... diff --git a/roles/certs_settings/README.md b/roles/certs_settings/README.md new file mode 100644 index 0000000..ffcc937 --- /dev/null +++ b/roles/certs_settings/README.md @@ -0,0 +1,9 @@ +# Certs_settings + +Роль для раскатки SSL-сертификатов. + +Если нужно добавить сертификаты для стороннего АнтиДДОС, то можно просто положить их в папку files рядом с сертами SP. + +Если нужно добавить сертификаты для mtls, то в директории *files* есть директория mtls, туда и нужно положить сертификаты. + +НЕ ЗАБЫВАЙТЕ называть сертификаты так, чтобы было понятно к чему они принадлежат, а также шифровать их через ansible-vault. diff --git a/roles/certs_settings/handlers/main.yml b/roles/certs_settings/handlers/main.yml new file mode 100644 index 0000000..6963225 --- /dev/null +++ b/roles/certs_settings/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Reload angie + service: + name: "angie" + state: reloaded +... diff --git a/roles/certs_settings/tasks/main.yml b/roles/certs_settings/tasks/main.yml new file mode 100644 index 0000000..808da2c --- /dev/null +++ b/roles/certs_settings/tasks/main.yml @@ -0,0 +1,41 @@ +--- +- name: Copy antiddos cert + ansible.builtin.copy: + src: "{{ item }}" + dest: /etc/ssl/certs/ + owner: root + group: root + mode: '0644' + loop: "{{ lookup('fileglob', 'files/*.crt', 'files/*.cer', 'files/*.pem', wantlist=True) }}" + notify: Reload angie + +- name: Copy antiddos key + ansible.builtin.copy: + src: "{{ item }}" + dest: /etc/ssl/private/ + owner: root + group: root + mode: '0644' + loop: "{{ lookup('fileglob', 'files/*.key', wantlist=True) }}" + notify: Reload angie + +- name: Copy mtls certs + ansible.builtin.copy: + src: "{{ item }}" + dest: /etc/ssl/mtls/ + owner: root + group: root + mode: '0644' + loop: "{{ lookup('fileglob', 'files/mtls/*.crt', 'files/mtls/*.cer', 'files/mtls/*.pem', wantlist=True) }}" + notify: Reload angie + +- name: Copy mtls keys + ansible.builtin.copy: + src: "{{ item }}" + dest: /etc/ssl/mtls/ + owner: root + group: root + mode: '0644' + loop: "{{ lookup('fileglob', 'files/mtls/*.key', wantlist=True) }}" + notify: Reload angie +... diff --git a/roles/chrony_install/README.md b/roles/chrony_install/README.md new file mode 100755 index 0000000..b99fbc8 --- /dev/null +++ b/roles/chrony_install/README.md @@ -0,0 +1,4 @@ +# Роль для установки и настройки Chrony для синхрониации времени + +В `defaults/main` нужно указать нужную временную зону и адреса NTP-серверов. +Далее роль проверит и при необходимости установит Chrony и внесёт настройки в файл `/etc/chrony/chrony.conf` diff --git a/roles/chrony_install/tasks/main.yml b/roles/chrony_install/tasks/main.yml new file mode 100755 index 0000000..6a09538 --- /dev/null +++ b/roles/chrony_install/tasks/main.yml @@ -0,0 +1,25 @@ +--- +- name: Chrony install + ansible.builtin.apt: + name: chrony + state: present + +- name: Timezone settings + ansible.builtin.timezone: + name: "{{ timezone }}" + +- name: Chrony settings + ansible.builtin.template: + src: chrony.conf.j2 + dest: /etc/chrony/chrony.conf + owner: root + group: root + mode: '0644' + +- name: Chrony enable + ansible.builtin.service: + name: chronyd + state: restarted + enabled: true + ignore_errors: "{{ ansible_check_mode }}" +... diff --git a/roles/chrony_install/templates/chrony.conf.j2 b/roles/chrony_install/templates/chrony.conf.j2 new file mode 100755 index 0000000..0a75cac --- /dev/null +++ b/roles/chrony_install/templates/chrony.conf.j2 @@ -0,0 +1,3 @@ +{% for server in ntp_servers %} +server {{ server }} iburst +{% endfor %} diff --git a/roles/different_need_soft_install/README.md b/roles/different_need_soft_install/README.md new file mode 100755 index 0000000..edf666f --- /dev/null +++ b/roles/different_need_soft_install/README.md @@ -0,0 +1 @@ +# Роль для установки различного необходимого софта diff --git a/roles/different_need_soft_install/files/angie.conf b/roles/different_need_soft_install/files/angie.conf new file mode 100755 index 0000000..c223db8 --- /dev/null +++ b/roles/different_need_soft_install/files/angie.conf @@ -0,0 +1,73 @@ +user angie; +worker_processes auto; +worker_rlimit_nofile 65536; + +error_log /var/log/angie/error.log notice; +pid /run/angie.pid; + +load_module modules/ngx_http_js_module.so; + +events { + worker_connections 65536; +} + + +http { + server_names_hash_bucket_size 128; + include /etc/angie/mime.types; + default_type application/octet-stream; + + js_path /etc/angie/njs/; + js_import main from host_transform.js; + + log_format waf escape=json + '{' + '"SID":$http_x_sid,' + '"server_name":"$server_name",' + '"app_name":"$host",' + '"proxyed_to":"$upstream_addr",' + '"upstream_status":"$upstream_status",' + '"upstream_response_length":"$upstream_response_length",' + '"upstream_response_time":"$upstream_response_time",' + '"upstream_bytes_sent":"$upstream_bytes_sent",' + '"server_port":$server_port,' + '"server_addr":"$server_addr",' + '"server_protocol":"$server_protocol",' + '"remote_addr":"$remote_addr",' + '"response_status_code":$status,' + '"response_body_bytes_sent":$body_bytes_sent,' + '"http_x_forwarded_for":"$http_x_forwarded_for",' + '"uri":"$uri",' + '"http_user_agent":"$http_user_agent",' + '"query_string":"$query_string",' + '"request_method":"$request_method",' + '"request_time":$request_time,' + '"@timestamp":"$time_iso8601"' + '}'; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + log_format extended '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" rt="$request_time" ' + '"$http_user_agent" "$http_x_forwarded_for" ' + 'h="$host" sn="$server_name" ru="$request_uri" u="$uri" ' + 'ucs="$upstream_cache_status" ua="$upstream_addr" us="$upstream_status" ' + 'uct="$upstream_connect_time" urt="$upstream_response_time"'; + + access_log /var/log/angie/access.log waf; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/angie/http.d/*.conf; +} + +#stream { +# include /etc/angie/stream.d/*.conf; +#} \ No newline at end of file diff --git a/roles/different_need_soft_install/files/angie_00-default.conf b/roles/different_need_soft_install/files/angie_00-default.conf new file mode 100644 index 0000000..c30aa0a --- /dev/null +++ b/roles/different_need_soft_install/files/angie_00-default.conf @@ -0,0 +1,22 @@ +# Default server для порта 80 - отбрасывает неизвестные запросы +server { + listen 80 default_server; + server_name _; + + # Возвращаем 444 (закрываем соединение без ответа) + return 444; + + # Или можно вернуть 403/404: + # return 403 "Access denied"; +} + +# Default server для порта 443 +server { + listen 443 ssl; + server_name _; + + ssl_certificate /etc/ssl/certs/sp.crt; + ssl_certificate_key /etc/ssl/private/sp.key; + + return 444; +} \ No newline at end of file diff --git a/roles/different_need_soft_install/files/docker_network.json b/roles/different_need_soft_install/files/docker_network.json new file mode 100755 index 0000000..ac4f992 --- /dev/null +++ b/roles/different_need_soft_install/files/docker_network.json @@ -0,0 +1,13 @@ +{ + "bip": "172.17.0.1/24", + "default-address-pools": [ + { + "base": "172.18.0.0/16", + "size": 24 + }, + { + "base": "172.19.0.0/16", + "size": 24 + } + ] +} diff --git a/roles/different_need_soft_install/files/host_transform.js b/roles/different_need_soft_install/files/host_transform.js new file mode 100644 index 0000000..68df47c --- /dev/null +++ b/roles/different_need_soft_install/files/host_transform.js @@ -0,0 +1,6 @@ +function sanitizeHost(r) { + var host = r.headersIn.Host || ''; + return host.replace(/_/g, '-'); +} + +export default { sanitizeHost }; \ No newline at end of file diff --git a/roles/different_need_soft_install/files/portainer_docker_compose.yml b/roles/different_need_soft_install/files/portainer_docker_compose.yml new file mode 100755 index 0000000..bd614a6 --- /dev/null +++ b/roles/different_need_soft_install/files/portainer_docker_compose.yml @@ -0,0 +1,20 @@ +--- +services: + portainer: + container_name: portainer + image: portainer/portainer-ce:lts + restart: always + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /home/install/portainer/portainer_data:/data + ports: + - 29443:9443 + +volumes: + portainer_data: + name: portainer_data + +networks: + default: + name: portainer_network +... diff --git a/roles/different_need_soft_install/tasks/angie_install.yml b/roles/different_need_soft_install/tasks/angie_install.yml new file mode 100755 index 0000000..0255d24 --- /dev/null +++ b/roles/different_need_soft_install/tasks/angie_install.yml @@ -0,0 +1,63 @@ +--- +- name: Download GPG Angie key + ansible.builtin.get_url: + url: https://angie.software/keys/angie-signing.gpg + dest: /etc/apt/trusted.gpg.d/angie-signing.gpg + mode: '0644' + +- name: Create sources.list for Angie + ansible.builtin.template: + src: "templates/angie.list.j2" + dest: "/etc/apt/sources.list.d/angie.list" + register: angie_gpg_result + +- name: Update cache + ansible.builtin.apt: + update_cache: true + when: angie_gpg_result.changed + +- name: Install Angie + ansible.builtin.apt: + name: angie + state: present + ignore_errors: "{{ ansible_check_mode }}" + +- name: Change angie.conf + ansible.builtin.copy: + src: files/angie.conf + dest: /etc/angie/angie.conf + mode: '0644' + owner: root + group: root + +- name: Create njs dir + ansible.builtin.file: + path: /etc/angie/njs/ + state: directory + mode: '0755' + owner: root + group: root + +- name: Angie njs copy + ansible.builtin.copy: + src: files/host_transform.js + dest: /etc/angie/njs/host_transform.js + mode: '0644' + owner: root + group: root + +- name: Angie default route copy + ansible.builtin.copy: + src: files/angie_00-default.conf + dest: /etc/angie/http.d/00-default.conf + mode: '0644' + owner: root + group: root + +- name: Start and enable Angie service + ansible.builtin.systemd: + name: angie + state: started + enabled: true + ignore_errors: "{{ ansible_check_mode }}" +... diff --git a/roles/different_need_soft_install/tasks/lazydocker_install.yml b/roles/different_need_soft_install/tasks/lazydocker_install.yml new file mode 100644 index 0000000..2091ae8 --- /dev/null +++ b/roles/different_need_soft_install/tasks/lazydocker_install.yml @@ -0,0 +1,13 @@ +--- +- name: Copy lazydocker from cloud + ansible.builtin.get_url: + url: "" + dest: "/usr/local/bin/lazydocker" + owner: root + group: root + mode: '0744' + timeout: 60 + retries: 3 + delay: 10 + when: inventory_hostname is match("^PTAF") +... diff --git a/roles/different_need_soft_install/tasks/main.yml b/roles/different_need_soft_install/tasks/main.yml new file mode 100755 index 0000000..9d41331 --- /dev/null +++ b/roles/different_need_soft_install/tasks/main.yml @@ -0,0 +1,25 @@ +--- +- name: Soft from Ubuntu repo + ansible.builtin.include_tasks: soft_from_ubuntu_repo.yml + +- name: Angie install + ansible.builtin.include_tasks: angie_install.yml + when: inventory_hostname is match("^PTAF") + +- name: Need soft install + ansible.builtin.include_tasks: need_soft_install.yml + +- name: Portainer run + ansible.builtin.include_tasks: portainer_install.yml + when: inventory_hostname is match("^PTAF") + +- name: Zabbix install + ansible.builtin.include_tasks: zabbix_install.yml + +- name: Lazydocker install + ansible.builtin.include_tasks: lazydocker_install.yml + +- name: Logrotate settings + ansible.builtin.include_role: + name: logrotate_settings +... diff --git a/roles/different_need_soft_install/tasks/need_soft_install.yml b/roles/different_need_soft_install/tasks/need_soft_install.yml new file mode 100755 index 0000000..49bf6b7 --- /dev/null +++ b/roles/different_need_soft_install/tasks/need_soft_install.yml @@ -0,0 +1,96 @@ +--- +- name: Install prerequisites + ansible.builtin.apt: + name: + - ca-certificates + - curl + - software-properties-common + - gnupg + state: present + +- name: Install iptables + ansible.builtin.apt: + name: iptables={{ iptables_version }} + state: present + when: inventory_hostname is match("^PTAF") + +- name: Docker install + block: + - name: Download GPG Docker key + ansible.builtin.get_url: + url: https://download.docker.com/linux/ubuntu/gpg + dest: /etc/apt/keyrings/docker.asc + mode: '0644' + + - name: Create sources.list for Docker + ansible.builtin.template: + src: "templates/docker.list.j2" + dest: "/etc/apt/sources.list.d/docker.list" + register: docker_gpg_result + + - name: Update cache + ansible.builtin.apt: + update_cache: true + when: docker_gpg_result.changed + + - name: Install Docker + ansible.builtin.apt: + name: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-buildx-plugin + - docker-compose-plugin + state: present + register: docker_install_result + ignore_errors: "{{ ansible_check_mode }}" + + - name: Install Docker Compose + ansible.builtin.get_url: + # yamllint disable-line rule:line-length + url: https://github.com/docker/compose/releases/download/v{{ compose_version }}/docker-compose-Linux-x86_64 + dest: /usr/local/bin/docker-compose + mode: '0755' + register: compose_install_result + + - name: Copy docker network settings + ansible.builtin.copy: + src: files/docker_network.json + dest: /etc/docker/daemon.json + owner: root + group: root + mode: '0644' + register: docker_install_result + + - name: Add system users to docker group + ansible.builtin.user: + name: "{{ item }}" + groups: docker + append: true + with_items: + - zabbix + - install + ignore_errors: "{{ ansible_check_mode }}" + + - name: Add TB users to docker group + ansible.builtin.user: + name: "{{ item.username }}" + groups: docker + append: true + with_items: "{{ user_list }}" + ignore_errors: "{{ ansible_check_mode }}" + when: inventory_hostname is match("^PTAF") + +- name: Check need restart docker + ansible.builtin.set_fact: + # yamllint disable-line rule:line-length + need_restart: "{{ docker_install_result is changed or compose_install_result is changed }}" + when: inventory_hostname is match("^PTAF") + +- name: Restart Docker service + ansible.builtin.systemd: + name: docker + state: restarted + when: need_restart + ignore_errors: "{{ ansible_check_mode }}" +... diff --git a/roles/different_need_soft_install/tasks/portainer_install.yml b/roles/different_need_soft_install/tasks/portainer_install.yml new file mode 100755 index 0000000..306bcf3 --- /dev/null +++ b/roles/different_need_soft_install/tasks/portainer_install.yml @@ -0,0 +1,25 @@ +--- +- name: Create need dir + ansible.builtin.file: + path: /home/install/portainer + state: directory + mode: '0755' + owner: root + group: root + +- name: Download portainer docker compose file + ansible.builtin.copy: + src: files/portainer_docker_compose.yml + dest: /home/install/portainer/docker-compose.yml + mode: '0644' + owner: root + group: root + ignore_errors: "{{ ansible_check_mode }}" + +- name: Run Docker compose + community.docker.docker_compose_v2: + project_src: /home/install/portainer/ + files: + - docker-compose.yml + ignore_errors: true +... diff --git a/roles/different_need_soft_install/tasks/soft_from_ubuntu_repo.yml b/roles/different_need_soft_install/tasks/soft_from_ubuntu_repo.yml new file mode 100755 index 0000000..85435e1 --- /dev/null +++ b/roles/different_need_soft_install/tasks/soft_from_ubuntu_repo.yml @@ -0,0 +1,8 @@ +--- +- name: Install different soft + ansible.builtin.apt: + name: "{{ item }}" + state: present + with_items: "{{ need_soft }}" + ignore_errors: true +... diff --git a/roles/different_need_soft_install/tasks/zabbix_install.yml b/roles/different_need_soft_install/tasks/zabbix_install.yml new file mode 100755 index 0000000..572add3 --- /dev/null +++ b/roles/different_need_soft_install/tasks/zabbix_install.yml @@ -0,0 +1,15 @@ +--- +- name: Pull and run Zabbix Agent container + community.docker.docker_container: + name: zabbix-agent-{{ zabbix_version }} + image: zabbix/zabbix-agent:{{ zabbix_version }}-ubuntu-latest + state: started + restart_policy: always + env: + ZBX_SERVER_HOST: "{{ zabbix_server }}" + ZBX_LISTENPORT: "{{ zabbix_port }}" + ZBX_HOSTNAMEITEM: "{{ zabbix_hostname }}" + ports: + - "10050:10050" + ignore_errors: true +... diff --git a/roles/different_need_soft_install/templates/angie.list.j2 b/roles/different_need_soft_install/templates/angie.list.j2 new file mode 100755 index 0000000..553c654 --- /dev/null +++ b/roles/different_need_soft_install/templates/angie.list.j2 @@ -0,0 +1 @@ +deb https://download.angie.software/angie/ubuntu/{{ ubuntu_version }} {{ ubuntu_codename }} main \ No newline at end of file diff --git a/roles/different_need_soft_install/templates/docker.list.j2 b/roles/different_need_soft_install/templates/docker.list.j2 new file mode 100755 index 0000000..64459db --- /dev/null +++ b/roles/different_need_soft_install/templates/docker.list.j2 @@ -0,0 +1 @@ +deb [arch={{ arch_version }} signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu {{ ubuntu_codename }} stable \ No newline at end of file diff --git a/roles/dns_settings/README.md b/roles/dns_settings/README.md new file mode 100755 index 0000000..d3f478f --- /dev/null +++ b/roles/dns_settings/README.md @@ -0,0 +1,4 @@ +# Роль для настройки DNS-серверов + +В `defaults/main` указываются dns-серверы на которые будет обращаться хост. +Далее роль подкидывает на хост заполненный шаблон по пути `/etc/resolv.conf` и перезагружает службу. diff --git a/roles/dns_settings/tasks/main.yml b/roles/dns_settings/tasks/main.yml new file mode 100755 index 0000000..1f0fc7c --- /dev/null +++ b/roles/dns_settings/tasks/main.yml @@ -0,0 +1,14 @@ +--- +- name: New resolv conf upload + ansible.builtin.template: + src: resolv.conf.j2 + dest: /etc/resolv.conf + owner: root + group: root + mode: '0644' + +- name: Restart systemd-resolved + ansible.builtin.systemd: + name: systemd-resolved + state: restarted +... diff --git a/roles/dns_settings/templates/resolv.conf.j2 b/roles/dns_settings/templates/resolv.conf.j2 new file mode 100755 index 0000000..24bd666 --- /dev/null +++ b/roles/dns_settings/templates/resolv.conf.j2 @@ -0,0 +1,5 @@ +{% for server in dns_servers %} +nameserver {{ server }} +{% endfor %} +options edns0 trust-ad +search . \ No newline at end of file diff --git a/roles/filebeat_install/README.md b/roles/filebeat_install/README.md new file mode 100755 index 0000000..918de89 --- /dev/null +++ b/roles/filebeat_install/README.md @@ -0,0 +1,8 @@ +# Роль для настройки access логов nginx и angie по одному шаблону + +Во время работы роли происходит следующее: + +1. Проверяется какой веб-сервер используется; +2. На основе полученных данных в нужные файлы подкидывается форма `access`-логов; +3. В конфигурационные файлы добавляется указание использовать нужную форму; +4. Устанавливается и запускается `filebeat`. diff --git a/roles/filebeat_install/defaults/main.yml b/roles/filebeat_install/defaults/main.yml new file mode 100755 index 0000000..cff19d3 --- /dev/null +++ b/roles/filebeat_install/defaults/main.yml @@ -0,0 +1,3 @@ +--- +filebeat_install_filebeat_password: +... diff --git a/roles/filebeat_install/files/fields.yml b/roles/filebeat_install/files/fields.yml new file mode 100755 index 0000000..a2ee89b --- /dev/null +++ b/roles/filebeat_install/files/fields.yml @@ -0,0 +1,9581 @@ +--- +# WARNING! Do not edit this file directly, it was generated by the ECS project, +# based on ECS version 1.8.0. +# Please visit https://github.com/elastic/ecs to suggest changes to ECS fields. + +- key: ecs + title: ECS + description: ECS Fields. + fields: + - name: '@timestamp' + level: core + required: true + type: date + description: 'Date/time when the event originated. + + This is the date/time extracted from the event, typically representing when + the event was generated by the source. + + If the event source has no original timestamp, this value is typically populated + by the first time the event was received by the pipeline. + + Required field for all events.' + example: '2016-05-23T08:05:34.853Z' + - name: labels + level: core + type: object + object_type: keyword + description: 'Custom key/value pairs. + + Can be used to add meta information to events. Should not contain nested objects. + All values are stored as keyword. + + Example: `docker` and `k8s` labels.' + example: '{"application": "foo-bar", "env": "production"}' + - name: message + level: core + type: text + description: 'For log events the message field contains the log message, optimized + for viewing in a log viewer. + + For structured logs without an original message field, other fields can be concatenated + to form a human-readable summary of the event. + + If multiple messages exist, they can be combined into one message.' + example: Hello World + - name: tags + level: core + type: keyword + ignore_above: 1024 + description: List of keywords used to tag each event. + example: '["production", "env2"]' + - name: agent + title: Agent + group: 2 + description: 'The agent fields contain the data about the software entity, if + any, that collects, detects, or observes events on a host, or takes measurements + on a host. + + Examples include Beats. Agents may also run on observers. ECS agent.* fields + shall be populated with details of the agent running on the host or observer + where the event happened or the measurement was taken.' + footnote: 'Examples: In the case of Beats for logs, the agent.name is filebeat. + For APM, it is the agent running in the app/service. The agent information does + not change if data is sent through queuing systems like Kafka, Redis, or processing + systems such as Logstash or APM Server.' + type: group + fields: + - name: build.original + level: core + type: keyword + ignore_above: 1024 + description: 'Extended build information for the agent. + + This field is intended to contain any build information that a data source + may provide, no specific formatting is required.' + example: metricbeat version 7.6.0 (amd64), libbeat 7.6.0 [6a23e8f8f30f5001ba344e4e54d8d9cb82cb107c + built 2020-02-05 23:10:10 +0000 UTC] + default_field: false + - name: ephemeral_id + level: extended + type: keyword + ignore_above: 1024 + description: 'Ephemeral identifier of this agent (if one exists). + + This id normally changes across restarts, but `agent.id` does not.' + example: 8a4f500f + - name: id + level: core + type: keyword + ignore_above: 1024 + description: 'Unique identifier of this agent (if one exists). + + Example: For Beats this would be beat.id.' + example: 8a4f500d + - name: name + level: core + type: keyword + ignore_above: 1024 + description: 'Custom name of the agent. + + This is a name that can be given to an agent. This can be helpful if for example + two Filebeat instances are running on the same host but a human readable separation + is needed on which Filebeat instance data is coming from. + + If no name is given, the name is often left empty.' + example: foo + - name: type + level: core + type: keyword + ignore_above: 1024 + description: 'Type of the agent. + + The agent type always stays the same and should be given by the agent used. + In case of Filebeat the agent would always be Filebeat also if two Filebeat + instances are run on the same machine.' + example: filebeat + - name: version + level: core + type: keyword + ignore_above: 1024 + description: Version of the agent. + example: 6.0.0-rc2 + - name: as + title: Autonomous System + group: 2 + description: An autonomous system (AS) is a collection of connected Internet Protocol + (IP) routing prefixes under the control of one or more network operators on + behalf of a single administrative entity or domain that presents a common, clearly + defined routing policy to the internet. + type: group + fields: + - name: number + level: extended + type: long + description: Unique number allocated to the autonomous system. The autonomous + system number (ASN) uniquely identifies each network on the Internet. + example: 15169 + - name: organization.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Organization name. + example: Google LLC + - name: client + title: Client + group: 2 + description: 'A client is defined as the initiator of a network connection for + events regarding sessions, connections, or bidirectional flow records. + + For TCP events, the client is the initiator of the TCP connection that sends + the SYN packet(s). For other protocols, the client is generally the initiator + or requestor in the network transaction. Some systems use the term "originator" + to refer the client in TCP connections. The client fields describe details about + the system acting as the client in the network event. Client fields are usually + populated in conjunction with server fields. Client fields are generally not + populated for packet-level events. + + Client / server representations can add semantic context to an exchange, which + is helpful to visualize the data in certain situations. If your context falls + in that category, you should still ensure that source and destination are filled + appropriately.' + type: group + fields: + - name: address + level: extended + type: keyword + ignore_above: 1024 + description: 'Some event client addresses are defined ambiguously. The event + will sometimes list an IP, a domain or a unix socket. You should always store + the raw address in the `.address` field. + + Then it should be duplicated to `.ip` or `.domain`, depending on which one + it is.' + - name: as.number + level: extended + type: long + description: Unique number allocated to the autonomous system. The autonomous + system number (ASN) uniquely identifies each network on the Internet. + example: 15169 + - name: as.organization.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Organization name. + example: Google LLC + - name: bytes + level: core + type: long + format: bytes + description: Bytes sent from the client to the server. + example: 184 + - name: domain + level: core + type: keyword + ignore_above: 1024 + description: Client domain. + - name: geo.city_name + level: core + type: keyword + ignore_above: 1024 + description: City name. + example: Montreal + - name: geo.continent_name + level: core + type: keyword + ignore_above: 1024 + description: Name of the continent. + example: North America + - name: geo.country_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Country ISO code. + example: CA + - name: geo.country_name + level: core + type: keyword + ignore_above: 1024 + description: Country name. + example: Canada + - name: geo.location + level: core + type: geo_point + description: Longitude and latitude. + example: '{ "lon": -73.614830, "lat": 45.505918 }' + - name: geo.name + level: extended + type: keyword + ignore_above: 1024 + description: 'User-defined description of a location, at the level of granularity + they care about. + + Could be the name of their data centers, the floor number, if this describes + a local physical entity, city names. + + Not typically used in automated geolocation.' + example: boston-dc + - name: geo.region_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Region ISO code. + example: CA-QC + - name: geo.region_name + level: core + type: keyword + ignore_above: 1024 + description: Region name. + example: Quebec + - name: ip + level: core + type: ip + description: IP address of the client (IPv4 or IPv6). + - name: mac + level: core + type: keyword + ignore_above: 1024 + description: MAC address of the client. + - name: nat.ip + level: extended + type: ip + description: 'Translated IP of source based NAT sessions (e.g. internal client + to internet). + + Typically connections traversing load balancers, firewalls, or routers.' + - name: nat.port + level: extended + type: long + format: string + description: 'Translated port of source based NAT sessions (e.g. internal client + to internet). + + Typically connections traversing load balancers, firewalls, or routers.' + - name: packets + level: core + type: long + description: Packets sent from the client to the server. + example: 12 + - name: port + level: core + type: long + format: string + description: Port of the client. + - name: registered_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The highest registered client domain, stripped of the subdomain. + + For example, the registered domain for "foo.example.com" is "example.com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last two labels will not work well for TLDs such as "co.uk".' + example: example.com + - name: subdomain + level: extended + type: keyword + ignore_above: 1024 + description: 'The subdomain portion of a fully qualified domain name includes + all of the names except the host name under the registered_domain. In a partially + qualified domain, or if the the qualification level of the full name cannot + be determined, subdomain contains all of the names below the registered domain. + + For example the subdomain portion of "www.east.mydomain.co.uk" is "east". + If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", + the subdomain field should contain "sub2.sub1", with no trailing period.' + example: east + default_field: false + - name: top_level_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The effective top level domain (eTLD), also known as the domain + suffix, is the last part of the domain name. For example, the top level domain + for example.com is "com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last label will not work well for effective TLDs such as "co.uk".' + example: co.uk + - name: user.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the user is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.email + level: extended + type: keyword + ignore_above: 1024 + description: User email address. + - name: user.full_name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: User's full name, if available. + example: Albert Einstein + - name: user.group.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.group.id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + - name: user.group.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + - name: user.hash + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique user hash to correlate information for a user in anonymized + form. + + Useful if `user.id` or `user.name` contain confidential information and cannot + be used.' + - name: user.id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier of the user. + - name: user.name + level: core + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Short name or login of the user. + example: albert + - name: user.roles + level: extended + type: keyword + ignore_above: 1024 + description: Array of user roles at the time of the event. + example: '["kibana_admin", "reporting_user"]' + default_field: false + - name: cloud + title: Cloud + group: 2 + description: Fields related to the cloud or infrastructure the events are coming + from. + footnote: 'Examples: If Metricbeat is running on an EC2 host and fetches data + from its host, the cloud info contains the data about this machine. If Metricbeat + runs on a remote machine outside the cloud and fetches data from a service running + in the cloud, the field contains cloud data from the machine the service is + running on.' + type: group + fields: + - name: account.id + level: extended + type: keyword + ignore_above: 1024 + description: 'The cloud account or organization id used to identify different + entities in a multi-tenant environment. + + Examples: AWS account id, Google Cloud ORG Id, or other unique identifier.' + example: 666777888999 + - name: account.name + level: extended + type: keyword + ignore_above: 1024 + description: 'The cloud account name or alias used to identify different entities + in a multi-tenant environment. + + Examples: AWS account name, Google Cloud ORG display name.' + example: elastic-dev + default_field: false + - name: availability_zone + level: extended + type: keyword + ignore_above: 1024 + description: Availability zone in which this host is running. + example: us-east-1c + - name: instance.id + level: extended + type: keyword + ignore_above: 1024 + description: Instance ID of the host machine. + example: i-1234567890abcdef0 + - name: instance.name + level: extended + type: keyword + ignore_above: 1024 + description: Instance name of the host machine. + - name: machine.type + level: extended + type: keyword + ignore_above: 1024 + description: Machine type of the host machine. + example: t2.medium + - name: project.id + level: extended + type: keyword + ignore_above: 1024 + description: 'The cloud project identifier. + + Examples: Google Cloud Project id, Azure Project id.' + example: my-project + default_field: false + - name: project.name + level: extended + type: keyword + ignore_above: 1024 + description: 'The cloud project name. + + Examples: Google Cloud Project name, Azure Project name.' + example: my project + default_field: false + - name: provider + level: extended + type: keyword + ignore_above: 1024 + description: Name of the cloud provider. Example values are aws, azure, gcp, + or digitalocean. + example: aws + - name: region + level: extended + type: keyword + ignore_above: 1024 + description: Region in which this host is running. + example: us-east-1 + - name: code_signature + title: Code Signature + group: 2 + description: These fields contain information about binary code signatures. + type: group + fields: + - name: exists + level: core + type: boolean + description: Boolean to capture if a signature is present. + example: 'true' + default_field: false + - name: status + level: extended + type: keyword + ignore_above: 1024 + description: 'Additional information about the certificate status. + + This is useful for logging cryptographic errors with the certificate validity + or trust status. Leave unpopulated if the validity or trust of the certificate + was unchecked.' + example: ERROR_UNTRUSTED_ROOT + default_field: false + - name: subject_name + level: core + type: keyword + ignore_above: 1024 + description: Subject name of the code signer + example: Microsoft Corporation + default_field: false + - name: trusted + level: extended + type: boolean + description: 'Stores the trust status of the certificate chain. + + Validating the trust of the certificate chain may be complicated, and this + field should only be populated by tools that actively check the status.' + example: 'true' + default_field: false + - name: valid + level: extended + type: boolean + description: 'Boolean to capture if the digital signature is verified against + the binary content. + + Leave unpopulated if a certificate was unchecked.' + example: 'true' + default_field: false + - name: container + title: Container + group: 2 + description: 'Container fields are used for meta information about the specific + container that is the source of information. + + These fields help correlate data based containers from any runtime.' + type: group + fields: + - name: id + level: core + type: keyword + ignore_above: 1024 + description: Unique container id. + - name: image.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the image the container was built on. + - name: image.tag + level: extended + type: keyword + ignore_above: 1024 + description: Container image tags. + - name: labels + level: extended + type: object + object_type: keyword + description: Image labels. + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Container name. + - name: runtime + level: extended + type: keyword + ignore_above: 1024 + description: Runtime managing this container. + example: docker + - name: destination + title: Destination + group: 2 + description: 'Destination fields capture details about the receiver of a network + exchange/packet. These fields are populated from a network event, packet, or + other event containing details of a network transaction. + + Destination fields are usually populated in conjunction with source fields. + The source and destination fields are considered the baseline and should always + be filled if an event contains source and destination details from a network + transaction. If the event also contains identification of the client and server + roles, then the client and server fields should also be populated.' + type: group + fields: + - name: address + level: extended + type: keyword + ignore_above: 1024 + description: 'Some event destination addresses are defined ambiguously. The + event will sometimes list an IP, a domain or a unix socket. You should always + store the raw address in the `.address` field. + + Then it should be duplicated to `.ip` or `.domain`, depending on which one + it is.' + - name: as.number + level: extended + type: long + description: Unique number allocated to the autonomous system. The autonomous + system number (ASN) uniquely identifies each network on the Internet. + example: 15169 + - name: as.organization.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Organization name. + example: Google LLC + - name: bytes + level: core + type: long + format: bytes + description: Bytes sent from the destination to the source. + example: 184 + - name: domain + level: core + type: keyword + ignore_above: 1024 + description: Destination domain. + - name: geo.city_name + level: core + type: keyword + ignore_above: 1024 + description: City name. + example: Montreal + - name: geo.continent_name + level: core + type: keyword + ignore_above: 1024 + description: Name of the continent. + example: North America + - name: geo.country_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Country ISO code. + example: CA + - name: geo.country_name + level: core + type: keyword + ignore_above: 1024 + description: Country name. + example: Canada + - name: geo.location + level: core + type: geo_point + description: Longitude and latitude. + example: '{ "lon": -73.614830, "lat": 45.505918 }' + - name: geo.name + level: extended + type: keyword + ignore_above: 1024 + description: 'User-defined description of a location, at the level of granularity + they care about. + + Could be the name of their data centers, the floor number, if this describes + a local physical entity, city names. + + Not typically used in automated geolocation.' + example: boston-dc + - name: geo.region_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Region ISO code. + example: CA-QC + - name: geo.region_name + level: core + type: keyword + ignore_above: 1024 + description: Region name. + example: Quebec + - name: ip + level: core + type: ip + description: IP address of the destination (IPv4 or IPv6). + - name: mac + level: core + type: keyword + ignore_above: 1024 + description: MAC address of the destination. + - name: nat.ip + level: extended + type: ip + description: 'Translated ip of destination based NAT sessions (e.g. internet + to private DMZ) + + Typically used with load balancers, firewalls, or routers.' + - name: nat.port + level: extended + type: long + format: string + description: 'Port the source session is translated to by NAT Device. + + Typically used with load balancers, firewalls, or routers.' + - name: packets + level: core + type: long + description: Packets sent from the destination to the source. + example: 12 + - name: port + level: core + type: long + format: string + description: Port of the destination. + - name: registered_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The highest registered destination domain, stripped of the subdomain. + + For example, the registered domain for "foo.example.com" is "example.com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last two labels will not work well for TLDs such as "co.uk".' + example: example.com + - name: subdomain + level: extended + type: keyword + ignore_above: 1024 + description: 'The subdomain portion of a fully qualified domain name includes + all of the names except the host name under the registered_domain. In a partially + qualified domain, or if the the qualification level of the full name cannot + be determined, subdomain contains all of the names below the registered domain. + + For example the subdomain portion of "www.east.mydomain.co.uk" is "east". + If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", + the subdomain field should contain "sub2.sub1", with no trailing period.' + example: east + default_field: false + - name: top_level_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The effective top level domain (eTLD), also known as the domain + suffix, is the last part of the domain name. For example, the top level domain + for example.com is "com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last label will not work well for effective TLDs such as "co.uk".' + example: co.uk + - name: user.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the user is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.email + level: extended + type: keyword + ignore_above: 1024 + description: User email address. + - name: user.full_name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: User's full name, if available. + example: Albert Einstein + - name: user.group.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.group.id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + - name: user.group.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + - name: user.hash + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique user hash to correlate information for a user in anonymized + form. + + Useful if `user.id` or `user.name` contain confidential information and cannot + be used.' + - name: user.id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier of the user. + - name: user.name + level: core + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Short name or login of the user. + example: albert + - name: user.roles + level: extended + type: keyword + ignore_above: 1024 + description: Array of user roles at the time of the event. + example: '["kibana_admin", "reporting_user"]' + default_field: false + - name: dll + title: DLL + group: 2 + description: 'These fields contain information about code libraries dynamically + loaded into processes. + + + Many operating systems refer to "shared code libraries" with different names, + but this field set refers to all of the following: + + * Dynamic-link library (`.dll`) commonly used on Windows + + * Shared Object (`.so`) commonly used on Unix-like operating systems + + * Dynamic library (`.dylib`) commonly used on macOS' + type: group + fields: + - name: code_signature.exists + level: core + type: boolean + description: Boolean to capture if a signature is present. + example: 'true' + default_field: false + - name: code_signature.status + level: extended + type: keyword + ignore_above: 1024 + description: 'Additional information about the certificate status. + + This is useful for logging cryptographic errors with the certificate validity + or trust status. Leave unpopulated if the validity or trust of the certificate + was unchecked.' + example: ERROR_UNTRUSTED_ROOT + default_field: false + - name: code_signature.subject_name + level: core + type: keyword + ignore_above: 1024 + description: Subject name of the code signer + example: Microsoft Corporation + default_field: false + - name: code_signature.trusted + level: extended + type: boolean + description: 'Stores the trust status of the certificate chain. + + Validating the trust of the certificate chain may be complicated, and this + field should only be populated by tools that actively check the status.' + example: 'true' + default_field: false + - name: code_signature.valid + level: extended + type: boolean + description: 'Boolean to capture if the digital signature is verified against + the binary content. + + Leave unpopulated if a certificate was unchecked.' + example: 'true' + default_field: false + - name: hash.md5 + level: extended + type: keyword + ignore_above: 1024 + description: MD5 hash. + default_field: false + - name: hash.sha1 + level: extended + type: keyword + ignore_above: 1024 + description: SHA1 hash. + default_field: false + - name: hash.sha256 + level: extended + type: keyword + ignore_above: 1024 + description: SHA256 hash. + default_field: false + - name: hash.sha512 + level: extended + type: keyword + ignore_above: 1024 + description: SHA512 hash. + default_field: false + - name: name + level: core + type: keyword + ignore_above: 1024 + description: 'Name of the library. + + This generally maps to the name of the file on disk.' + example: kernel32.dll + default_field: false + - name: path + level: extended + type: keyword + ignore_above: 1024 + description: Full file path of the library. + example: C:\Windows\System32\kernel32.dll + default_field: false + - name: pe.architecture + level: extended + type: keyword + ignore_above: 1024 + description: CPU architecture target for the file. + example: x64 + default_field: false + - name: pe.company + level: extended + type: keyword + ignore_above: 1024 + description: Internal company name of the file, provided at compile-time. + example: Microsoft Corporation + default_field: false + - name: pe.description + level: extended + type: keyword + ignore_above: 1024 + description: Internal description of the file, provided at compile-time. + example: Paint + default_field: false + - name: pe.file_version + level: extended + type: keyword + ignore_above: 1024 + description: Internal version of the file, provided at compile-time. + example: 6.3.9600.17415 + default_field: false + - name: pe.imphash + level: extended + type: keyword + ignore_above: 1024 + description: 'A hash of the imports in a PE file. An imphash -- or import hash + -- can be used to fingerprint binaries even after recompilation or other code-level + transformations have occurred, which would change more traditional hash values. + + Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html.' + example: 0c6803c4e922103c4dca5963aad36ddf + default_field: false + - name: pe.original_file_name + level: extended + type: keyword + ignore_above: 1024 + description: Internal name of the file, provided at compile-time. + example: MSPAINT.EXE + default_field: false + - name: pe.product + level: extended + type: keyword + ignore_above: 1024 + description: Internal product name of the file, provided at compile-time. + example: "Microsoft\xAE Windows\xAE Operating System" + default_field: false + - name: dns + title: DNS + group: 2 + description: 'Fields describing DNS queries and answers. + + DNS events should either represent a single DNS query prior to getting answers + (`dns.type:query`) or they should represent a full exchange and contain the + query details as well as all of the answers that were provided for this query + (`dns.type:answer`).' + type: group + fields: + - name: answers + level: extended + type: object + description: 'An array containing an object for each answer section returned + by the server. + + The main keys that should be present in these objects are defined by ECS. + Records that have more information may contain more keys than what ECS defines. + + Not all DNS data sources give all details about DNS answers. At minimum, answer + objects must contain the `data` key. If more information is available, map + as much of it to ECS as possible, and add any additional fields to the answer + objects as custom fields.' + - name: answers.class + level: extended + type: keyword + ignore_above: 1024 + description: The class of DNS data contained in this resource record. + example: IN + - name: answers.data + level: extended + type: keyword + ignore_above: 1024 + description: 'The data describing the resource. + + The meaning of this data depends on the type and class of the resource record.' + example: 10.10.10.10 + - name: answers.name + level: extended + type: keyword + ignore_above: 1024 + description: 'The domain name to which this resource record pertains. + + If a chain of CNAME is being resolved, each answer''s `name` should be the + one that corresponds with the answer''s `data`. It should not simply be the + original `question.name` repeated.' + example: www.example.com + - name: answers.ttl + level: extended + type: long + description: The time interval in seconds that this resource record may be cached + before it should be discarded. Zero values mean that the data should not be + cached. + example: 180 + - name: answers.type + level: extended + type: keyword + ignore_above: 1024 + description: The type of data contained in this resource record. + example: CNAME + - name: header_flags + level: extended + type: keyword + ignore_above: 1024 + description: 'Array of 2 letter DNS header flags. + + Expected values are: AA, TC, RD, RA, AD, CD, DO.' + example: '["RD", "RA"]' + - name: id + level: extended + type: keyword + ignore_above: 1024 + description: The DNS packet identifier assigned by the program that generated + the query. The identifier is copied to the response. + example: 62111 + - name: op_code + level: extended + type: keyword + ignore_above: 1024 + description: The DNS operation code that specifies the kind of query in the + message. This value is set by the originator of a query and copied into the + response. + example: QUERY + - name: question.class + level: extended + type: keyword + ignore_above: 1024 + description: The class of records being queried. + example: IN + - name: question.name + level: extended + type: keyword + ignore_above: 1024 + description: 'The name being queried. + + If the name field contains non-printable characters (below 32 or above 126), + those characters should be represented as escaped base 10 integers (\DDD). + Back slashes and quotes should be escaped. Tabs, carriage returns, and line + feeds should be converted to \t, \r, and \n respectively.' + example: www.example.com + - name: question.registered_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The highest registered domain, stripped of the subdomain. + + For example, the registered domain for "foo.example.com" is "example.com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last two labels will not work well for TLDs such as "co.uk".' + example: example.com + - name: question.subdomain + level: extended + type: keyword + ignore_above: 1024 + description: 'The subdomain is all of the labels under the registered_domain. + + If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", + the subdomain field should contain "sub2.sub1", with no trailing period.' + example: www + - name: question.top_level_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The effective top level domain (eTLD), also known as the domain + suffix, is the last part of the domain name. For example, the top level domain + for example.com is "com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last label will not work well for effective TLDs such as "co.uk".' + example: co.uk + - name: question.type + level: extended + type: keyword + ignore_above: 1024 + description: The type of record being queried. + example: AAAA + - name: resolved_ip + level: extended + type: ip + description: 'Array containing all IPs seen in `answers.data`. + + The `answers` array can be difficult to use, because of the variety of data + formats it can contain. Extracting all IP addresses seen in there to `dns.resolved_ip` + makes it possible to index them as IP addresses, and makes them easier to + visualize and query for.' + example: '["10.10.10.10", "10.10.10.11"]' + - name: response_code + level: extended + type: keyword + ignore_above: 1024 + description: The DNS response code. + example: NOERROR + - name: type + level: extended + type: keyword + ignore_above: 1024 + description: 'The type of DNS event captured, query or answer. + + If your source of DNS events only gives you DNS queries, you should only create + dns events of type `dns.type:query`. + + If your source of DNS events gives you answers as well, you should create + one event per query (optionally as soon as the query is seen). And a second + event containing all query details as well as an array of answers.' + example: answer + - name: ecs + title: ECS + group: 2 + description: Meta-information specific to ECS. + type: group + fields: + - name: version + level: core + required: true + type: keyword + ignore_above: 1024 + description: 'ECS version this event conforms to. `ecs.version` is a required + field and must exist in all events. + + When querying across multiple indices -- which may conform to slightly different + ECS versions -- this field lets integrations adjust to the schema version + of the events.' + example: 1.0.0 + - name: error + title: Error + group: 2 + description: 'These fields can represent errors of any kind. + + Use them for errors that happen while fetching events or in cases where the + event itself contains an error.' + type: group + fields: + - name: code + level: core + type: keyword + ignore_above: 1024 + description: Error code describing the error. + - name: id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier for the error. + - name: message + level: core + type: text + description: Error message. + - name: stack_trace + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: The stack trace of this error in plain text. + index: false + - name: type + level: extended + type: keyword + ignore_above: 1024 + description: The type of the error, for example the class name of the exception. + example: java.lang.NullPointerException + - name: event + title: Event + group: 2 + description: 'The event fields are used for context information about the log + or metric event itself. + + A log is defined as an event containing details of something that happened. + Log events must include the time at which the thing happened. Examples of log + events include a process starting on a host, a network packet being sent from + a source to a destination, or a network connection between a client and a server + being initiated or closed. A metric is defined as an event containing one or + more numerical measurements and the time at which the measurement was taken. + Examples of metric events include memory pressure measured on a host and device + temperature. See the `event.kind` definition in this section for additional + details about metric and state events.' + type: group + fields: + - name: action + level: core + type: keyword + ignore_above: 1024 + description: 'The action captured by the event. + + This describes the information in the event. It is more specific than `event.category`. + Examples are `group-add`, `process-started`, `file-created`. The value is + normally defined by the implementer.' + example: user-password-change + - name: category + level: core + type: keyword + ignore_above: 1024 + description: 'This is one of four ECS Categorization Fields, and indicates the + second level in the ECS category hierarchy. + + `event.category` represents the "big buckets" of ECS categories. For example, + filtering on `event.category:process` yields all events relating to process + activity. This field is closely related to `event.type`, which is used as + a subcategory. + + This field is an array. This will allow proper categorization of some events + that fall in multiple categories.' + example: authentication + - name: code + level: extended + type: keyword + ignore_above: 1024 + description: 'Identification code for this event, if one exists. + + Some event sources use event codes to identify messages unambiguously, regardless + of message language or wording adjustments over time. An example of this is + the Windows Event ID.' + example: 4648 + - name: created + level: core + type: date + description: 'event.created contains the date/time when the event was first + read by an agent, or by your pipeline. + + This field is distinct from @timestamp in that @timestamp typically contain + the time extracted from the original event. + + In most situations, these two timestamps will be slightly different. The difference + can be used to calculate the delay between your source generating an event, + and the time when your agent first processed it. This can be used to monitor + your agent''s or pipeline''s ability to keep up with your event source. + + In case the two timestamps are identical, @timestamp should be used.' + example: '2016-05-23T08:05:34.857Z' + - name: dataset + level: core + type: keyword + ignore_above: 1024 + description: 'Name of the dataset. + + If an event source publishes more than one type of log or events (e.g. access + log, error log), the dataset is used to specify which one the event comes + from. + + It''s recommended but not required to start the dataset name with the module + name, followed by a dot, then the dataset name.' + example: apache.access + - name: duration + level: core + type: long + format: duration + input_format: nanoseconds + output_format: asMilliseconds + output_precision: 1 + description: 'Duration of the event in nanoseconds. + + If event.start and event.end are known this value should be the difference + between the end and start time.' + - name: end + level: extended + type: date + description: event.end contains the date when the event ended or when the activity + was last observed. + - name: hash + level: extended + type: keyword + ignore_above: 1024 + description: Hash (perhaps logstash fingerprint) of raw field to be able to + demonstrate log integrity. + example: 123456789012345678901234567890ABCD + - name: id + level: core + type: keyword + ignore_above: 1024 + description: Unique ID to describe the event. + example: 8a4f500d + - name: ingested + level: core + type: date + description: 'Timestamp when an event arrived in the central data store. + + This is different from `@timestamp`, which is when the event originally occurred. It''s + also different from `event.created`, which is meant to capture the first time + an agent saw the event. + + In normal conditions, assuming no tampering, the timestamps should chronologically + look like this: `@timestamp` < `event.created` < `event.ingested`.' + example: '2016-05-23T08:05:35.101Z' + default_field: false + - name: kind + level: core + type: keyword + ignore_above: 1024 + description: 'This is one of four ECS Categorization Fields, and indicates the + highest level in the ECS category hierarchy. + + `event.kind` gives high-level information about what type of information the + event contains, without being specific to the contents of the event. For example, + values of this field distinguish alert events from metric events. + + The value of this field can be used to inform how these kinds of events should + be handled. They may warrant different retention, different access control, + it may also help understand whether the data coming in at a regular interval + or not.' + example: alert + - name: module + level: core + type: keyword + ignore_above: 1024 + description: 'Name of the module this data is coming from. + + If your monitoring agent supports the concept of modules or plugins to process + events of a given source (e.g. Apache logs), `event.module` should contain + the name of this module.' + example: apache + - name: original + level: core + type: keyword + ignore_above: 1024 + description: 'Raw text message of entire event. Used to demonstrate log integrity. + + This field is not indexed and doc_values are disabled. It cannot be searched, + but it can be retrieved from `_source`. If users wish to override this and + index this field, consider using the wildcard data type.' + example: Sep 19 08:26:10 host CEF:0|Security| threatmanager|1.0|100| + worm successfully stopped|10|src=10.0.0.1 dst=2.1.2.2spt=1232 + index: false + - name: outcome + level: core + type: keyword + ignore_above: 1024 + description: 'This is one of four ECS Categorization Fields, and indicates the + lowest level in the ECS category hierarchy. + + `event.outcome` simply denotes whether the event represents a success or a + failure from the perspective of the entity that produced the event. + + Note that when a single transaction is described in multiple events, each + event may populate different values of `event.outcome`, according to their + perspective. + + Also note that in the case of a compound event (a single event that contains + multiple logical events), this field should be populated with the value that + best captures the overall success or failure from the perspective of the event + producer. + + Further note that not all events will have an associated outcome. For example, + this field is generally not populated for metric events, events with `event.type:info`, + or any events for which an outcome does not make logical sense.' + example: success + - name: provider + level: extended + type: keyword + ignore_above: 1024 + description: 'Source of the event. + + Event transports such as Syslog or the Windows Event Log typically mention + the source of an event. It can be the name of the software that generated + the event (e.g. Sysmon, httpd), or of a subsystem of the operating system + (kernel, Microsoft-Windows-Security-Auditing).' + example: kernel + - name: reason + level: extended + type: keyword + ignore_above: 1024 + description: 'Reason why this event happened, according to the source. + + This describes the why of a particular action or outcome captured in the event. + Where `event.action` captures the action from the event, `event.reason` describes + why that action was taken. For example, a web proxy with an `event.action` + which denied the request may also populate `event.reason` with the reason + why (e.g. `blocked site`).' + example: Terminated an unexpected process + default_field: false + - name: reference + level: extended + type: keyword + ignore_above: 1024 + description: 'Reference URL linking to additional information about this event. + + This URL links to a static definition of this event. Alert events, indicated + by `event.kind:alert`, are a common use case for this field.' + example: https://system.example.com/event/#0001234 + default_field: false + - name: risk_score + level: core + type: float + description: Risk score or priority of the event (e.g. security solutions). + Use your system's original value here. + - name: risk_score_norm + level: extended + type: float + description: 'Normalized risk score or priority of the event, on a scale of + 0 to 100. + + This is mainly useful if you use more than one system that assigns risk scores, + and you want to see a normalized value across all systems.' + - name: sequence + level: extended + type: long + format: string + description: 'Sequence number of the event. + + The sequence number is a value published by some event sources, to make the + exact ordering of events unambiguous, regardless of the timestamp precision.' + - name: severity + level: core + type: long + format: string + description: 'The numeric severity of the event according to your event source. + + What the different severity values mean can be different between sources and + use cases. It''s up to the implementer to make sure severities are consistent + across events from the same source. + + The Syslog severity belongs in `log.syslog.severity.code`. `event.severity` + is meant to represent the severity according to the event source (e.g. firewall, + IDS). If the event source does not publish its own severity, you may optionally + copy the `log.syslog.severity.code` to `event.severity`.' + example: 7 + - name: start + level: extended + type: date + description: event.start contains the date when the event started or when the + activity was first observed. + - name: timezone + level: extended + type: keyword + ignore_above: 1024 + description: 'This field should be populated when the event''s timestamp does + not include timezone information already (e.g. default Syslog timestamps). + It''s optional otherwise. + + Acceptable timezone formats are: a canonical ID (e.g. "Europe/Amsterdam"), + abbreviated (e.g. "EST") or an HH:mm differential (e.g. "-05:00").' + - name: type + level: core + type: keyword + ignore_above: 1024 + description: 'This is one of four ECS Categorization Fields, and indicates the + third level in the ECS category hierarchy. + + `event.type` represents a categorization "sub-bucket" that, when used along + with the `event.category` field values, enables filtering events down to a + level appropriate for single visualization. + + This field is an array. This will allow proper categorization of some events + that fall in multiple event types.' + - name: url + level: extended + type: keyword + ignore_above: 1024 + description: 'URL linking to an external system to continue investigation of + this event. + + This URL links to another system where in-depth investigation of the specific + occurrence of this event can take place. Alert events, indicated by `event.kind:alert`, + are a common use case for this field.' + example: https://mysystem.example.com/alert/5271dedb-f5b0-4218-87f0-4ac4870a38fe + default_field: false + - name: file + title: File + group: 2 + description: 'A file is defined as a set of information that has been created + on, or has existed on a filesystem. + + File objects can be associated with host events, network events, and/or file + events (e.g., those produced by File Integrity Monitoring [FIM] products or + services). File fields provide details about the affected file associated with + the event or metric.' + type: group + fields: + - name: accessed + level: extended + type: date + description: 'Last time the file was accessed. + + Note that not all filesystems keep track of access time.' + - name: attributes + level: extended + type: keyword + ignore_above: 1024 + description: 'Array of file attributes. + + Attributes names will vary by platform. Here''s a non-exhaustive list of values + that are expected in this field: archive, compressed, directory, encrypted, + execute, hidden, read, readonly, system, write.' + example: '["readonly", "system"]' + default_field: false + - name: code_signature.exists + level: core + type: boolean + description: Boolean to capture if a signature is present. + example: 'true' + default_field: false + - name: code_signature.status + level: extended + type: keyword + ignore_above: 1024 + description: 'Additional information about the certificate status. + + This is useful for logging cryptographic errors with the certificate validity + or trust status. Leave unpopulated if the validity or trust of the certificate + was unchecked.' + example: ERROR_UNTRUSTED_ROOT + default_field: false + - name: code_signature.subject_name + level: core + type: keyword + ignore_above: 1024 + description: Subject name of the code signer + example: Microsoft Corporation + default_field: false + - name: code_signature.trusted + level: extended + type: boolean + description: 'Stores the trust status of the certificate chain. + + Validating the trust of the certificate chain may be complicated, and this + field should only be populated by tools that actively check the status.' + example: 'true' + default_field: false + - name: code_signature.valid + level: extended + type: boolean + description: 'Boolean to capture if the digital signature is verified against + the binary content. + + Leave unpopulated if a certificate was unchecked.' + example: 'true' + default_field: false + - name: created + level: extended + type: date + description: 'File creation time. + + Note that not all filesystems store the creation time.' + - name: ctime + level: extended + type: date + description: 'Last time the file attributes or metadata changed. + + Note that changes to the file content will update `mtime`. This implies `ctime` + will be adjusted at the same time, since `mtime` is an attribute of the file.' + - name: device + level: extended + type: keyword + ignore_above: 1024 + description: Device that is the source of the file. + example: sda + - name: directory + level: extended + type: keyword + ignore_above: 1024 + description: Directory where the file is located. It should include the drive + letter, when appropriate. + example: /home/alice + - name: drive_letter + level: extended + type: keyword + ignore_above: 1 + description: 'Drive letter where the file is located. This field is only relevant + on Windows. + + The value should be uppercase, and not include the colon.' + example: C + default_field: false + - name: extension + level: extended + type: keyword + ignore_above: 1024 + description: 'File extension, excluding the leading dot. + + Note that when the file name has multiple extensions (example.tar.gz), only + the last one should be captured ("gz", not "tar.gz").' + example: png + - name: gid + level: extended + type: keyword + ignore_above: 1024 + description: Primary group ID (GID) of the file. + example: '1001' + - name: group + level: extended + type: keyword + ignore_above: 1024 + description: Primary group name of the file. + example: alice + - name: hash.md5 + level: extended + type: keyword + ignore_above: 1024 + description: MD5 hash. + - name: hash.sha1 + level: extended + type: keyword + ignore_above: 1024 + description: SHA1 hash. + - name: hash.sha256 + level: extended + type: keyword + ignore_above: 1024 + description: SHA256 hash. + - name: hash.sha512 + level: extended + type: keyword + ignore_above: 1024 + description: SHA512 hash. + - name: inode + level: extended + type: keyword + ignore_above: 1024 + description: Inode representing the file in the filesystem. + example: '256383' + - name: mime_type + level: extended + type: keyword + ignore_above: 1024 + description: MIME type should identify the format of the file or stream of bytes + using https://www.iana.org/assignments/media-types/media-types.xhtml[IANA + official types], where possible. When more than one type is applicable, the + most specific type should be used. + default_field: false + - name: mode + level: extended + type: keyword + ignore_above: 1024 + description: Mode of the file in octal representation. + example: '0640' + - name: mtime + level: extended + type: date + description: Last time the file content was modified. + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the file including the extension, without the directory. + example: example.png + - name: owner + level: extended + type: keyword + ignore_above: 1024 + description: File owner's username. + example: alice + - name: path + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Full path to the file, including the file name. It should include + the drive letter, when appropriate. + example: /home/alice/example.png + - name: pe.architecture + level: extended + type: keyword + ignore_above: 1024 + description: CPU architecture target for the file. + example: x64 + default_field: false + - name: pe.company + level: extended + type: keyword + ignore_above: 1024 + description: Internal company name of the file, provided at compile-time. + example: Microsoft Corporation + default_field: false + - name: pe.description + level: extended + type: keyword + ignore_above: 1024 + description: Internal description of the file, provided at compile-time. + example: Paint + default_field: false + - name: pe.file_version + level: extended + type: keyword + ignore_above: 1024 + description: Internal version of the file, provided at compile-time. + example: 6.3.9600.17415 + default_field: false + - name: pe.imphash + level: extended + type: keyword + ignore_above: 1024 + description: 'A hash of the imports in a PE file. An imphash -- or import hash + -- can be used to fingerprint binaries even after recompilation or other code-level + transformations have occurred, which would change more traditional hash values. + + Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html.' + example: 0c6803c4e922103c4dca5963aad36ddf + default_field: false + - name: pe.original_file_name + level: extended + type: keyword + ignore_above: 1024 + description: Internal name of the file, provided at compile-time. + example: MSPAINT.EXE + default_field: false + - name: pe.product + level: extended + type: keyword + ignore_above: 1024 + description: Internal product name of the file, provided at compile-time. + example: "Microsoft\xAE Windows\xAE Operating System" + default_field: false + - name: size + level: extended + type: long + description: 'File size in bytes. + + Only relevant when `file.type` is "file".' + example: 16384 + - name: target_path + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Target path for symlinks. + - name: type + level: extended + type: keyword + ignore_above: 1024 + description: File type (file, dir, or symlink). + example: file + - name: uid + level: extended + type: keyword + ignore_above: 1024 + description: The user ID (UID) or security identifier (SID) of the file owner. + example: '1001' + - name: x509.alternative_names + level: extended + type: keyword + ignore_above: 1024 + description: List of subject alternative names (SAN). Name types vary by certificate + authority and certificate type but commonly contain IP addresses, DNS names + (and wildcards), and email addresses. + example: '*.elastic.co' + default_field: false + - name: x509.issuer.common_name + level: extended + type: keyword + ignore_above: 1024 + description: List of common name (CN) of issuing certificate authority. + example: Example SHA2 High Assurance Server CA + default_field: false + - name: x509.issuer.country + level: extended + type: keyword + ignore_above: 1024 + description: List of country (C) codes + example: US + default_field: false + - name: x509.issuer.distinguished_name + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of issuing certificate authority. + example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance + Server CA + default_field: false + - name: x509.issuer.locality + level: extended + type: keyword + ignore_above: 1024 + description: List of locality names (L) + example: Mountain View + default_field: false + - name: x509.issuer.organization + level: extended + type: keyword + ignore_above: 1024 + description: List of organizations (O) of issuing certificate authority. + example: Example Inc + default_field: false + - name: x509.issuer.organizational_unit + level: extended + type: keyword + ignore_above: 1024 + description: List of organizational units (OU) of issuing certificate authority. + example: www.example.com + default_field: false + - name: x509.issuer.state_or_province + level: extended + type: keyword + ignore_above: 1024 + description: List of state or province names (ST, S, or P) + example: California + default_field: false + - name: x509.not_after + level: extended + type: date + description: Time at which the certificate is no longer considered valid. + example: 2020-07-16 03:15:39+00:00 + default_field: false + - name: x509.not_before + level: extended + type: date + description: Time at which the certificate is first considered valid. + example: 2019-08-16 01:40:25+00:00 + default_field: false + - name: x509.public_key_algorithm + level: extended + type: keyword + ignore_above: 1024 + description: Algorithm used to generate the public key. + example: RSA + default_field: false + - name: x509.public_key_curve + level: extended + type: keyword + ignore_above: 1024 + description: The curve used by the elliptic curve public key algorithm. This + is algorithm specific. + example: nistp521 + default_field: false + - name: x509.public_key_exponent + level: extended + type: long + description: Exponent used to derive the public key. This is algorithm specific. + example: 65537 + index: false + default_field: false + - name: x509.public_key_size + level: extended + type: long + description: The size of the public key space in bits. + example: 2048 + default_field: false + - name: x509.serial_number + level: extended + type: keyword + ignore_above: 1024 + description: Unique serial number issued by the certificate authority. For consistency, + if this value is alphanumeric, it should be formatted without colons and uppercase + characters. + example: 55FBB9C7DEBF09809D12CCAA + default_field: false + - name: x509.signature_algorithm + level: extended + type: keyword + ignore_above: 1024 + description: Identifier for certificate signature algorithm. We recommend using + names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. + example: SHA256-RSA + default_field: false + - name: x509.subject.common_name + level: extended + type: keyword + ignore_above: 1024 + description: List of common names (CN) of subject. + example: shared.global.example.net + default_field: false + - name: x509.subject.country + level: extended + type: keyword + ignore_above: 1024 + description: List of country (C) code + example: US + default_field: false + - name: x509.subject.distinguished_name + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of the certificate subject entity. + example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net + default_field: false + - name: x509.subject.locality + level: extended + type: keyword + ignore_above: 1024 + description: List of locality names (L) + example: San Francisco + default_field: false + - name: x509.subject.organization + level: extended + type: keyword + ignore_above: 1024 + description: List of organizations (O) of subject. + example: Example, Inc. + default_field: false + - name: x509.subject.organizational_unit + level: extended + type: keyword + ignore_above: 1024 + description: List of organizational units (OU) of subject. + default_field: false + - name: x509.subject.state_or_province + level: extended + type: keyword + ignore_above: 1024 + description: List of state or province names (ST, S, or P) + example: California + default_field: false + - name: x509.version_number + level: extended + type: keyword + ignore_above: 1024 + description: Version of x509 format. + example: 3 + default_field: false + - name: geo + title: Geo + group: 2 + description: 'Geo fields can carry data about a specific location related to an + event. + + This geolocation information can be derived from techniques such as Geo IP, + or be user-supplied.' + type: group + fields: + - name: city_name + level: core + type: keyword + ignore_above: 1024 + description: City name. + example: Montreal + - name: continent_name + level: core + type: keyword + ignore_above: 1024 + description: Name of the continent. + example: North America + - name: country_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Country ISO code. + example: CA + - name: country_name + level: core + type: keyword + ignore_above: 1024 + description: Country name. + example: Canada + - name: location + level: core + type: geo_point + description: Longitude and latitude. + example: '{ "lon": -73.614830, "lat": 45.505918 }' + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: 'User-defined description of a location, at the level of granularity + they care about. + + Could be the name of their data centers, the floor number, if this describes + a local physical entity, city names. + + Not typically used in automated geolocation.' + example: boston-dc + - name: region_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Region ISO code. + example: CA-QC + - name: region_name + level: core + type: keyword + ignore_above: 1024 + description: Region name. + example: Quebec + - name: group + title: Group + group: 2 + description: The group fields are meant to represent groups that are relevant + to the event. + type: group + fields: + - name: domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + - name: hash + title: Hash + group: 2 + description: 'The hash fields represent different hash algorithms and their values. + + Field names for common hashes (e.g. MD5, SHA1) are predefined. Add fields for + other hashes by lowercasing the hash algorithm name and using underscore separators + as appropriate (snake case, e.g. sha3_512).' + type: group + fields: + - name: md5 + level: extended + type: keyword + ignore_above: 1024 + description: MD5 hash. + - name: sha1 + level: extended + type: keyword + ignore_above: 1024 + description: SHA1 hash. + - name: sha256 + level: extended + type: keyword + ignore_above: 1024 + description: SHA256 hash. + - name: sha512 + level: extended + type: keyword + ignore_above: 1024 + description: SHA512 hash. + - name: host + title: Host + group: 2 + description: 'A host is defined as a general computing instance. + + ECS host.* fields should be populated with details about the host on which the + event happened, or from which the measurement was taken. Host types include + hardware, virtual machines, Docker containers, and Kubernetes nodes.' + type: group + fields: + - name: architecture + level: core + type: keyword + ignore_above: 1024 + description: Operating system architecture. + example: x86_64 + - name: domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the domain of which the host is a member. + + For example, on Windows this could be the host''s Active Directory domain + or NetBIOS domain name. For Linux this could be the domain of the host''s + LDAP provider.' + example: CONTOSO + default_field: false + - name: geo.city_name + level: core + type: keyword + ignore_above: 1024 + description: City name. + example: Montreal + - name: geo.continent_name + level: core + type: keyword + ignore_above: 1024 + description: Name of the continent. + example: North America + - name: geo.country_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Country ISO code. + example: CA + - name: geo.country_name + level: core + type: keyword + ignore_above: 1024 + description: Country name. + example: Canada + - name: geo.location + level: core + type: geo_point + description: Longitude and latitude. + example: '{ "lon": -73.614830, "lat": 45.505918 }' + - name: geo.name + level: extended + type: keyword + ignore_above: 1024 + description: 'User-defined description of a location, at the level of granularity + they care about. + + Could be the name of their data centers, the floor number, if this describes + a local physical entity, city names. + + Not typically used in automated geolocation.' + example: boston-dc + - name: geo.region_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Region ISO code. + example: CA-QC + - name: geo.region_name + level: core + type: keyword + ignore_above: 1024 + description: Region name. + example: Quebec + - name: hostname + level: core + type: keyword + ignore_above: 1024 + description: 'Hostname of the host. + + It normally contains what the `hostname` command returns on the host machine.' + - name: id + level: core + type: keyword + ignore_above: 1024 + description: 'Unique host id. + + As hostname is not always unique, use values that are meaningful in your environment. + + Example: The current usage of `beat.name`.' + - name: ip + level: core + type: ip + description: Host ip addresses. + - name: mac + level: core + type: keyword + ignore_above: 1024 + description: Host mac addresses. + - name: name + level: core + type: keyword + ignore_above: 1024 + description: 'Name of the host. + + It can contain what `hostname` returns on Unix systems, the fully qualified + domain name, or a name specified by the user. The sender decides which value + to use.' + - name: os.family + level: extended + type: keyword + ignore_above: 1024 + description: OS family (such as redhat, debian, freebsd, windows). + example: debian + - name: os.full + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, including the version or code name. + example: Mac OS Mojave + - name: os.kernel + level: extended + type: keyword + ignore_above: 1024 + description: Operating system kernel version as a raw string. + example: 4.4.0-112-generic + - name: os.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, without the version. + example: Mac OS X + - name: os.platform + level: extended + type: keyword + ignore_above: 1024 + description: Operating system platform (such centos, ubuntu, windows). + example: darwin + - name: os.type + level: extended + type: keyword + ignore_above: 1024 + description: 'Use the `os.type` field to categorize the operating system into + one of the broad commercial families. + + One of these following values should be used (lowercase): linux, macos, unix, + windows. + + If the OS you''re dealing with is not in the list, the field should not be + populated. Please let us know by opening an issue with ECS, to propose its + addition.' + example: macos + default_field: false + - name: os.version + level: extended + type: keyword + ignore_above: 1024 + description: Operating system version as a raw string. + example: 10.14.1 + - name: type + level: core + type: keyword + ignore_above: 1024 + description: 'Type of host. + + For Cloud providers this can be the machine type like `t2.medium`. If vm, + this could be the container, for example, or other information meaningful + in your environment.' + - name: uptime + level: extended + type: long + description: Seconds the host has been up. + example: 1325 + - name: user.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the user is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.email + level: extended + type: keyword + ignore_above: 1024 + description: User email address. + - name: user.full_name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: User's full name, if available. + example: Albert Einstein + - name: user.group.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.group.id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + - name: user.group.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + - name: user.hash + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique user hash to correlate information for a user in anonymized + form. + + Useful if `user.id` or `user.name` contain confidential information and cannot + be used.' + - name: user.id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier of the user. + - name: user.name + level: core + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Short name or login of the user. + example: albert + - name: user.roles + level: extended + type: keyword + ignore_above: 1024 + description: Array of user roles at the time of the event. + example: '["kibana_admin", "reporting_user"]' + default_field: false + - name: http + title: HTTP + group: 2 + description: Fields related to HTTP activity. Use the `url` field set to store + the url of the request. + type: group + fields: + - name: request.body.bytes + level: extended + type: long + format: bytes + description: Size in bytes of the request body. + example: 887 + - name: request.body.content + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: The full HTTP request body. + example: Hello world + - name: request.bytes + level: extended + type: long + format: bytes + description: Total size in bytes of the request (body and headers). + example: 1437 + - name: request.method + level: extended + type: keyword + ignore_above: 1024 + description: 'HTTP request method. + + Prior to ECS 1.6.0 the following guidance was provided: + + "The field value must be normalized to lowercase for querying." + + As of ECS 1.6.0, the guidance is deprecated because the original case of the + method may be useful in anomaly detection. Original case will be mandated + in ECS 2.0.0' + example: GET, POST, PUT, PoST + - name: request.mime_type + level: extended + type: keyword + ignore_above: 1024 + description: 'Mime type of the body of the request. + + This value must only be populated based on the content of the request body, + not on the `Content-Type` header. Comparing the mime type of a request with + the request''s Content-Type header can be helpful in detecting threats or + misconfigured clients.' + example: image/gif + default_field: false + - name: request.referrer + level: extended + type: keyword + ignore_above: 1024 + description: Referrer for this HTTP request. + example: https://blog.example.com/ + - name: response.body.bytes + level: extended + type: long + format: bytes + description: Size in bytes of the response body. + example: 887 + - name: response.body.content + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: The full HTTP response body. + example: Hello world + - name: response.bytes + level: extended + type: long + format: bytes + description: Total size in bytes of the response (body and headers). + example: 1437 + - name: response.mime_type + level: extended + type: keyword + ignore_above: 1024 + description: 'Mime type of the body of the response. + + This value must only be populated based on the content of the response body, + not on the `Content-Type` header. Comparing the mime type of a response with + the response''s Content-Type header can be helpful in detecting misconfigured + servers.' + example: image/gif + default_field: false + - name: response.status_code + level: extended + type: long + format: string + description: HTTP response status code. + example: 404 + - name: version + level: extended + type: keyword + ignore_above: 1024 + description: HTTP version. + example: 1.1 + - name: interface + title: Interface + group: 2 + description: The interface fields are used to record ingress and egress interface + information when reported by an observer (e.g. firewall, router, load balancer) + in the context of the observer handling a network connection. In the case of + a single observer interface (e.g. network sensor on a span port) only the observer.ingress + information should be populated. + type: group + fields: + - name: alias + level: extended + type: keyword + ignore_above: 1024 + description: Interface alias as reported by the system, typically used in firewall + implementations for e.g. inside, outside, or dmz logical interface naming. + example: outside + default_field: false + - name: id + level: extended + type: keyword + ignore_above: 1024 + description: Interface ID as reported by an observer (typically SNMP interface + ID). + example: 10 + default_field: false + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Interface name as reported by the system. + example: eth0 + default_field: false + - name: log + title: Log + group: 2 + description: 'Details about the event''s logging mechanism or logging transport. + + The log.* fields are typically populated with details about the logging mechanism + used to create and/or transport the event. For example, syslog details belong + under `log.syslog.*`. + + The details specific to your event source are typically not logged under `log.*`, + but rather in `event.*` or in other ECS fields.' + type: group + fields: + - name: file.path + level: extended + type: keyword + ignore_above: 1024 + description: 'Full path to the log file this event came from, including the + file name. It should include the drive letter, when appropriate. + + If the event wasn''t read from a log file, do not populate this field.' + example: /var/log/fun-times.log + default_field: false + - name: level + level: core + type: keyword + ignore_above: 1024 + description: 'Original log level of the log event. + + If the source of the event provides a log level or textual severity, this + is the one that goes in `log.level`. If your source doesn''t specify one, + you may put your event transport''s severity here (e.g. Syslog severity). + + Some examples are `warn`, `err`, `i`, `informational`.' + example: error + - name: logger + level: core + type: keyword + ignore_above: 1024 + description: The name of the logger inside an application. This is usually the + name of the class which initialized the logger, or can be a custom name. + example: org.elasticsearch.bootstrap.Bootstrap + - name: origin.file.line + level: extended + type: integer + description: The line number of the file containing the source code which originated + the log event. + example: 42 + - name: origin.file.name + level: extended + type: keyword + ignore_above: 1024 + description: 'The name of the file containing the source code which originated + the log event. + + Note that this field is not meant to capture the log file. The correct field + to capture the log file is `log.file.path`.' + example: Bootstrap.java + - name: origin.function + level: extended + type: keyword + ignore_above: 1024 + description: The name of the function or method which originated the log event. + example: init + - name: original + level: core + type: keyword + ignore_above: 1024 + description: 'This is the original log message and contains the full log message + before splitting it up in multiple parts. + + In contrast to the `message` field which can contain an extracted part of + the log message, this field contains the original, full log message. It can + have already some modifications applied like encoding or new lines removed + to clean up the log message. + + This field is not indexed and doc_values are disabled so it can''t be queried + but the value can be retrieved from `_source`.' + example: Sep 19 08:26:10 localhost My log + index: false + - name: syslog + level: extended + type: object + description: The Syslog metadata of the event, if the event was transmitted + via Syslog. Please see RFCs 5424 or 3164. + - name: syslog.facility.code + level: extended + type: long + format: string + description: 'The Syslog numeric facility of the log event, if available. + + According to RFCs 5424 and 3164, this value should be an integer between 0 + and 23.' + example: 23 + - name: syslog.facility.name + level: extended + type: keyword + ignore_above: 1024 + description: The Syslog text-based facility of the log event, if available. + example: local7 + - name: syslog.priority + level: extended + type: long + format: string + description: 'Syslog numeric priority of the event, if available. + + According to RFCs 5424 and 3164, the priority is 8 * facility + severity. + This number is therefore expected to contain a value between 0 and 191.' + example: 135 + - name: syslog.severity.code + level: extended + type: long + description: 'The Syslog numeric severity of the log event, if available. + + If the event source publishing via Syslog provides a different numeric severity + value (e.g. firewall, IDS), your source''s numeric severity should go to `event.severity`. + If the event source does not specify a distinct severity, you can optionally + copy the Syslog severity to `event.severity`.' + example: 3 + - name: syslog.severity.name + level: extended + type: keyword + ignore_above: 1024 + description: 'The Syslog numeric severity of the log event, if available. + + If the event source publishing via Syslog provides a different severity value + (e.g. firewall, IDS), your source''s text severity should go to `log.level`. + If the event source does not specify a distinct severity, you can optionally + copy the Syslog severity to `log.level`.' + example: Error + - name: network + title: Network + group: 2 + description: 'The network is defined as the communication path over which a host + or network event happens. + + The network.* fields should be populated with details about the network activity + associated with an event.' + type: group + fields: + - name: application + level: extended + type: keyword + ignore_above: 1024 + description: 'A name given to an application level protocol. This can be arbitrarily + assigned for things like microservices, but also apply to things like skype, + icq, facebook, twitter. This would be used in situations where the vendor + or service can be decoded such as from the source/dest IP owners, ports, or + wire format. + + The field value must be normalized to lowercase for querying. See the documentation + section "Implementing ECS".' + example: aim + - name: bytes + level: core + type: long + format: bytes + description: 'Total bytes transferred in both directions. + + If `source.bytes` and `destination.bytes` are known, `network.bytes` is their + sum.' + example: 368 + - name: community_id + level: extended + type: keyword + ignore_above: 1024 + description: 'A hash of source and destination IPs and ports, as well as the + protocol used in a communication. This is a tool-agnostic standard to identify + flows. + + Learn more at https://github.com/corelight/community-id-spec.' + example: 1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0= + - name: direction + level: core + type: keyword + ignore_above: 1024 + description: "Direction of the network traffic.\nRecommended values are:\n \ + \ * ingress\n * egress\n * inbound\n * outbound\n * internal\n * external\n\ + \ * unknown\n\nWhen mapping events from a host-based monitoring context,\ + \ populate this field from the host's point of view, using the values \"ingress\"\ + \ or \"egress\".\nWhen mapping events from a network or perimeter-based monitoring\ + \ context, populate this field from the point of view of the network perimeter,\ + \ using the values \"inbound\", \"outbound\", \"internal\" or \"external\"\ + .\nNote that \"internal\" is not crossing perimeter boundaries, and is meant\ + \ to describe communication between two hosts within the perimeter. Note also\ + \ that \"external\" is meant to describe traffic between two hosts that are\ + \ external to the perimeter. This could for example be useful for ISPs or\ + \ VPN service providers." + example: inbound + - name: forwarded_ip + level: core + type: ip + description: Host IP address when the source IP address is the proxy. + example: 192.1.1.2 + - name: iana_number + level: extended + type: keyword + ignore_above: 1024 + description: IANA Protocol Number (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml). + Standardized list of protocols. This aligns well with NetFlow and sFlow related + logs which use the IANA Protocol Number. + example: 6 + - name: inner + level: extended + type: object + description: Network.inner fields are added in addition to network.vlan fields + to describe the innermost VLAN when q-in-q VLAN tagging is present. Allowed + fields include vlan.id and vlan.name. Inner vlan fields are typically used + when sending traffic with multiple 802.1q encapsulations to a network sensor + (e.g. Zeek, Wireshark.) + default_field: false + - name: inner.vlan.id + level: extended + type: keyword + ignore_above: 1024 + description: VLAN ID as reported by the observer. + example: 10 + default_field: false + - name: inner.vlan.name + level: extended + type: keyword + ignore_above: 1024 + description: Optional VLAN name as reported by the observer. + example: outside + default_field: false + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Name given by operators to sections of their network. + example: Guest Wifi + - name: packets + level: core + type: long + description: 'Total packets transferred in both directions. + + If `source.packets` and `destination.packets` are known, `network.packets` + is their sum.' + example: 24 + - name: protocol + level: core + type: keyword + ignore_above: 1024 + description: 'L7 Network protocol name. ex. http, lumberjack, transport protocol. + + The field value must be normalized to lowercase for querying. See the documentation + section "Implementing ECS".' + example: http + - name: transport + level: core + type: keyword + ignore_above: 1024 + description: 'Same as network.iana_number, but instead using the Keyword name + of the transport layer (udp, tcp, ipv6-icmp, etc.) + + The field value must be normalized to lowercase for querying. See the documentation + section "Implementing ECS".' + example: tcp + - name: type + level: core + type: keyword + ignore_above: 1024 + description: 'In the OSI Model this would be the Network Layer. ipv4, ipv6, + ipsec, pim, etc + + The field value must be normalized to lowercase for querying. See the documentation + section "Implementing ECS".' + example: ipv4 + - name: vlan.id + level: extended + type: keyword + ignore_above: 1024 + description: VLAN ID as reported by the observer. + example: 10 + default_field: false + - name: vlan.name + level: extended + type: keyword + ignore_above: 1024 + description: Optional VLAN name as reported by the observer. + example: outside + default_field: false + - name: observer + title: Observer + group: 2 + description: 'An observer is defined as a special network, security, or application + device used to detect, observe, or create network, security, or application-related + events and metrics. + + This could be a custom hardware appliance or a server that has been configured + to run special network, security, or application software. Examples include + firewalls, web proxies, intrusion detection/prevention systems, network monitoring + sensors, web application firewalls, data loss prevention systems, and APM servers. + The observer.* fields shall be populated with details of the system, if any, + that detects, observes and/or creates a network, security, or application event + or metric. Message queues and ETL components used in processing events or metrics + are not considered observers in ECS.' + type: group + fields: + - name: egress + level: extended + type: object + description: Observer.egress holds information like interface number and name, + vlan, and zone information to classify egress traffic. Single armed monitoring + such as a network sensor on a span port should only use observer.ingress + to categorize traffic. + default_field: false + - name: egress.interface.alias + level: extended + type: keyword + ignore_above: 1024 + description: Interface alias as reported by the system, typically used in firewall + implementations for e.g. inside, outside, or dmz logical interface naming. + example: outside + default_field: false + - name: egress.interface.id + level: extended + type: keyword + ignore_above: 1024 + description: Interface ID as reported by an observer (typically SNMP interface + ID). + example: 10 + default_field: false + - name: egress.interface.name + level: extended + type: keyword + ignore_above: 1024 + description: Interface name as reported by the system. + example: eth0 + default_field: false + - name: egress.vlan.id + level: extended + type: keyword + ignore_above: 1024 + description: VLAN ID as reported by the observer. + example: 10 + default_field: false + - name: egress.vlan.name + level: extended + type: keyword + ignore_above: 1024 + description: Optional VLAN name as reported by the observer. + example: outside + default_field: false + - name: egress.zone + level: extended + type: keyword + ignore_above: 1024 + description: Network zone of outbound traffic as reported by the observer to + categorize the destination area of egress traffic, e.g. Internal, External, + DMZ, HR, Legal, etc. + example: Public_Internet + default_field: false + - name: geo.city_name + level: core + type: keyword + ignore_above: 1024 + description: City name. + example: Montreal + - name: geo.continent_name + level: core + type: keyword + ignore_above: 1024 + description: Name of the continent. + example: North America + - name: geo.country_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Country ISO code. + example: CA + - name: geo.country_name + level: core + type: keyword + ignore_above: 1024 + description: Country name. + example: Canada + - name: geo.location + level: core + type: geo_point + description: Longitude and latitude. + example: '{ "lon": -73.614830, "lat": 45.505918 }' + - name: geo.name + level: extended + type: keyword + ignore_above: 1024 + description: 'User-defined description of a location, at the level of granularity + they care about. + + Could be the name of their data centers, the floor number, if this describes + a local physical entity, city names. + + Not typically used in automated geolocation.' + example: boston-dc + - name: geo.region_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Region ISO code. + example: CA-QC + - name: geo.region_name + level: core + type: keyword + ignore_above: 1024 + description: Region name. + example: Quebec + - name: hostname + level: core + type: keyword + ignore_above: 1024 + description: Hostname of the observer. + - name: ingress + level: extended + type: object + description: Observer.ingress holds information like interface number and name, + vlan, and zone information to classify ingress traffic. Single armed monitoring + such as a network sensor on a span port should only use observer.ingress + to categorize traffic. + default_field: false + - name: ingress.interface.alias + level: extended + type: keyword + ignore_above: 1024 + description: Interface alias as reported by the system, typically used in firewall + implementations for e.g. inside, outside, or dmz logical interface naming. + example: outside + default_field: false + - name: ingress.interface.id + level: extended + type: keyword + ignore_above: 1024 + description: Interface ID as reported by an observer (typically SNMP interface + ID). + example: 10 + default_field: false + - name: ingress.interface.name + level: extended + type: keyword + ignore_above: 1024 + description: Interface name as reported by the system. + example: eth0 + default_field: false + - name: ingress.vlan.id + level: extended + type: keyword + ignore_above: 1024 + description: VLAN ID as reported by the observer. + example: 10 + default_field: false + - name: ingress.vlan.name + level: extended + type: keyword + ignore_above: 1024 + description: Optional VLAN name as reported by the observer. + example: outside + default_field: false + - name: ingress.zone + level: extended + type: keyword + ignore_above: 1024 + description: Network zone of incoming traffic as reported by the observer to + categorize the source area of ingress traffic. e.g. internal, External, DMZ, + HR, Legal, etc. + example: DMZ + default_field: false + - name: ip + level: core + type: ip + description: IP addresses of the observer. + - name: mac + level: core + type: keyword + ignore_above: 1024 + description: MAC addresses of the observer + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: 'Custom name of the observer. + + This is a name that can be given to an observer. This can be helpful for example + if multiple firewalls of the same model are used in an organization. + + If no custom name is needed, the field can be left empty.' + example: 1_proxySG + - name: os.family + level: extended + type: keyword + ignore_above: 1024 + description: OS family (such as redhat, debian, freebsd, windows). + example: debian + - name: os.full + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, including the version or code name. + example: Mac OS Mojave + - name: os.kernel + level: extended + type: keyword + ignore_above: 1024 + description: Operating system kernel version as a raw string. + example: 4.4.0-112-generic + - name: os.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, without the version. + example: Mac OS X + - name: os.platform + level: extended + type: keyword + ignore_above: 1024 + description: Operating system platform (such centos, ubuntu, windows). + example: darwin + - name: os.type + level: extended + type: keyword + ignore_above: 1024 + description: 'Use the `os.type` field to categorize the operating system into + one of the broad commercial families. + + One of these following values should be used (lowercase): linux, macos, unix, + windows. + + If the OS you''re dealing with is not in the list, the field should not be + populated. Please let us know by opening an issue with ECS, to propose its + addition.' + example: macos + default_field: false + - name: os.version + level: extended + type: keyword + ignore_above: 1024 + description: Operating system version as a raw string. + example: 10.14.1 + - name: product + level: extended + type: keyword + ignore_above: 1024 + description: The product name of the observer. + example: s200 + - name: serial_number + level: extended + type: keyword + ignore_above: 1024 + description: Observer serial number. + - name: type + level: core + type: keyword + ignore_above: 1024 + description: 'The type of the observer the data is coming from. + + There is no predefined list of observer types. Some examples are `forwarder`, + `firewall`, `ids`, `ips`, `proxy`, `poller`, `sensor`, `APM server`.' + example: firewall + - name: vendor + level: core + type: keyword + ignore_above: 1024 + description: Vendor name of the observer. + example: Symantec + - name: version + level: core + type: keyword + ignore_above: 1024 + description: Observer version. + - name: organization + title: Organization + group: 2 + description: 'The organization fields enrich data with information about the company + or entity the data is associated with. + + These fields help you arrange or filter data stored in an index by one or multiple + organizations.' + type: group + fields: + - name: id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the organization. + - name: name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Organization name. + - name: os + title: Operating System + group: 2 + description: The OS fields contain information about the operating system. + type: group + fields: + - name: family + level: extended + type: keyword + ignore_above: 1024 + description: OS family (such as redhat, debian, freebsd, windows). + example: debian + - name: full + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, including the version or code name. + example: Mac OS Mojave + - name: kernel + level: extended + type: keyword + ignore_above: 1024 + description: Operating system kernel version as a raw string. + example: 4.4.0-112-generic + - name: name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, without the version. + example: Mac OS X + - name: platform + level: extended + type: keyword + ignore_above: 1024 + description: Operating system platform (such centos, ubuntu, windows). + example: darwin + - name: type + level: extended + type: keyword + ignore_above: 1024 + description: 'Use the `os.type` field to categorize the operating system into + one of the broad commercial families. + + One of these following values should be used (lowercase): linux, macos, unix, + windows. + + If the OS you''re dealing with is not in the list, the field should not be + populated. Please let us know by opening an issue with ECS, to propose its + addition.' + example: macos + default_field: false + - name: version + level: extended + type: keyword + ignore_above: 1024 + description: Operating system version as a raw string. + example: 10.14.1 + - name: package + title: Package + group: 2 + description: These fields contain information about an installed software package. + It contains general information about a package, such as name, version or size. + It also contains installation details, such as time or location. + type: group + fields: + - name: architecture + level: extended + type: keyword + ignore_above: 1024 + description: Package architecture. + example: x86_64 + - name: build_version + level: extended + type: keyword + ignore_above: 1024 + description: 'Additional information about the build version of the installed + package. + + For example use the commit SHA of a non-released package.' + example: 36f4f7e89dd61b0988b12ee000b98966867710cd + default_field: false + - name: checksum + level: extended + type: keyword + ignore_above: 1024 + description: Checksum of the installed package for verification. + example: 68b329da9893e34099c7d8ad5cb9c940 + - name: description + level: extended + type: keyword + ignore_above: 1024 + description: Description of the package. + example: Open source programming language to build simple/reliable/efficient + software. + - name: install_scope + level: extended + type: keyword + ignore_above: 1024 + description: Indicating how the package was installed, e.g. user-local, global. + example: global + - name: installed + level: extended + type: date + description: Time when package was installed. + - name: license + level: extended + type: keyword + ignore_above: 1024 + description: 'License under which the package was released. + + Use a short name, e.g. the license identifier from SPDX License List where + possible (https://spdx.org/licenses/).' + example: Apache License 2.0 + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Package name + example: go + - name: path + level: extended + type: keyword + ignore_above: 1024 + description: Path where the package is installed. + example: /usr/local/Cellar/go/1.12.9/ + - name: reference + level: extended + type: keyword + ignore_above: 1024 + description: Home page or reference URL of the software in this package, if + available. + example: https://golang.org + default_field: false + - name: size + level: extended + type: long + format: string + description: Package size in bytes. + example: 62231 + - name: type + level: extended + type: keyword + ignore_above: 1024 + description: 'Type of package. + + This should contain the package file type, rather than the package manager + name. Examples: rpm, dpkg, brew, npm, gem, nupkg, jar.' + example: rpm + default_field: false + - name: version + level: extended + type: keyword + ignore_above: 1024 + description: Package version + example: 1.12.9 + - name: pe + title: PE Header + group: 2 + description: These fields contain Windows Portable Executable (PE) metadata. + type: group + fields: + - name: architecture + level: extended + type: keyword + ignore_above: 1024 + description: CPU architecture target for the file. + example: x64 + default_field: false + - name: company + level: extended + type: keyword + ignore_above: 1024 + description: Internal company name of the file, provided at compile-time. + example: Microsoft Corporation + default_field: false + - name: description + level: extended + type: keyword + ignore_above: 1024 + description: Internal description of the file, provided at compile-time. + example: Paint + default_field: false + - name: file_version + level: extended + type: keyword + ignore_above: 1024 + description: Internal version of the file, provided at compile-time. + example: 6.3.9600.17415 + default_field: false + - name: imphash + level: extended + type: keyword + ignore_above: 1024 + description: 'A hash of the imports in a PE file. An imphash -- or import hash + -- can be used to fingerprint binaries even after recompilation or other code-level + transformations have occurred, which would change more traditional hash values. + + Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html.' + example: 0c6803c4e922103c4dca5963aad36ddf + default_field: false + - name: original_file_name + level: extended + type: keyword + ignore_above: 1024 + description: Internal name of the file, provided at compile-time. + example: MSPAINT.EXE + default_field: false + - name: product + level: extended + type: keyword + ignore_above: 1024 + description: Internal product name of the file, provided at compile-time. + example: "Microsoft\xAE Windows\xAE Operating System" + default_field: false + - name: process + title: Process + group: 2 + description: 'These fields contain information about a process. + + These fields can help you correlate metrics information with a process id/name + from a log message. The `process.pid` often stays in the metric itself and + is copied to the global field for correlation.' + type: group + fields: + - name: args + level: extended + type: keyword + ignore_above: 1024 + description: 'Array of process arguments, starting with the absolute path to + the executable. + + May be filtered to protect sensitive information.' + example: '["/usr/bin/ssh", "-l", "user", "10.0.0.16"]' + - name: args_count + level: extended + type: long + description: 'Length of the process.args array. + + This field can be useful for querying or performing bucket analysis on how + many arguments were provided to start a process. More arguments may be an + indication of suspicious activity.' + example: 4 + default_field: false + - name: code_signature.exists + level: core + type: boolean + description: Boolean to capture if a signature is present. + example: 'true' + default_field: false + - name: code_signature.status + level: extended + type: keyword + ignore_above: 1024 + description: 'Additional information about the certificate status. + + This is useful for logging cryptographic errors with the certificate validity + or trust status. Leave unpopulated if the validity or trust of the certificate + was unchecked.' + example: ERROR_UNTRUSTED_ROOT + default_field: false + - name: code_signature.subject_name + level: core + type: keyword + ignore_above: 1024 + description: Subject name of the code signer + example: Microsoft Corporation + default_field: false + - name: code_signature.trusted + level: extended + type: boolean + description: 'Stores the trust status of the certificate chain. + + Validating the trust of the certificate chain may be complicated, and this + field should only be populated by tools that actively check the status.' + example: 'true' + default_field: false + - name: code_signature.valid + level: extended + type: boolean + description: 'Boolean to capture if the digital signature is verified against + the binary content. + + Leave unpopulated if a certificate was unchecked.' + example: 'true' + default_field: false + - name: command_line + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: 'Full command line that started the process, including the absolute + path to the executable, and all arguments. + + Some arguments may be filtered to protect sensitive information.' + example: /usr/bin/ssh -l user 10.0.0.16 + default_field: false + - name: entity_id + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique identifier for the process. + + The implementation of this is specified by the data source, but some examples + of what could be used here are a process-generated UUID, Sysmon Process GUIDs, + or a hash of some uniquely identifying components of a process. + + Constructing a globally unique identifier is a common practice to mitigate + PID reuse as well as to identify a specific process over time, across multiple + monitored hosts.' + example: c2c455d9f99375d + default_field: false + - name: executable + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Absolute path to the process executable. + example: /usr/bin/ssh + - name: exit_code + level: extended + type: long + description: 'The exit code of the process, if this is a termination event. + + The field should be absent if there is no exit code for the event (e.g. process + start).' + example: 137 + default_field: false + - name: hash.md5 + level: extended + type: keyword + ignore_above: 1024 + description: MD5 hash. + - name: hash.sha1 + level: extended + type: keyword + ignore_above: 1024 + description: SHA1 hash. + - name: hash.sha256 + level: extended + type: keyword + ignore_above: 1024 + description: SHA256 hash. + - name: hash.sha512 + level: extended + type: keyword + ignore_above: 1024 + description: SHA512 hash. + - name: name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: 'Process name. + + Sometimes called program name or similar.' + example: ssh + - name: parent.args + level: extended + type: keyword + ignore_above: 1024 + description: 'Array of process arguments, starting with the absolute path to + the executable. + + May be filtered to protect sensitive information.' + example: '["/usr/bin/ssh", "-l", "user", "10.0.0.16"]' + default_field: false + - name: parent.args_count + level: extended + type: long + description: 'Length of the process.args array. + + This field can be useful for querying or performing bucket analysis on how + many arguments were provided to start a process. More arguments may be an + indication of suspicious activity.' + example: 4 + default_field: false + - name: parent.code_signature.exists + level: core + type: boolean + description: Boolean to capture if a signature is present. + example: 'true' + default_field: false + - name: parent.code_signature.status + level: extended + type: keyword + ignore_above: 1024 + description: 'Additional information about the certificate status. + + This is useful for logging cryptographic errors with the certificate validity + or trust status. Leave unpopulated if the validity or trust of the certificate + was unchecked.' + example: ERROR_UNTRUSTED_ROOT + default_field: false + - name: parent.code_signature.subject_name + level: core + type: keyword + ignore_above: 1024 + description: Subject name of the code signer + example: Microsoft Corporation + default_field: false + - name: parent.code_signature.trusted + level: extended + type: boolean + description: 'Stores the trust status of the certificate chain. + + Validating the trust of the certificate chain may be complicated, and this + field should only be populated by tools that actively check the status.' + example: 'true' + default_field: false + - name: parent.code_signature.valid + level: extended + type: boolean + description: 'Boolean to capture if the digital signature is verified against + the binary content. + + Leave unpopulated if a certificate was unchecked.' + example: 'true' + default_field: false + - name: parent.command_line + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: 'Full command line that started the process, including the absolute + path to the executable, and all arguments. + + Some arguments may be filtered to protect sensitive information.' + example: /usr/bin/ssh -l user 10.0.0.16 + default_field: false + - name: parent.entity_id + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique identifier for the process. + + The implementation of this is specified by the data source, but some examples + of what could be used here are a process-generated UUID, Sysmon Process GUIDs, + or a hash of some uniquely identifying components of a process. + + Constructing a globally unique identifier is a common practice to mitigate + PID reuse as well as to identify a specific process over time, across multiple + monitored hosts.' + example: c2c455d9f99375d + default_field: false + - name: parent.executable + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: Absolute path to the process executable. + example: /usr/bin/ssh + default_field: false + - name: parent.exit_code + level: extended + type: long + description: 'The exit code of the process, if this is a termination event. + + The field should be absent if there is no exit code for the event (e.g. process + start).' + example: 137 + default_field: false + - name: parent.hash.md5 + level: extended + type: keyword + ignore_above: 1024 + description: MD5 hash. + default_field: false + - name: parent.hash.sha1 + level: extended + type: keyword + ignore_above: 1024 + description: SHA1 hash. + default_field: false + - name: parent.hash.sha256 + level: extended + type: keyword + ignore_above: 1024 + description: SHA256 hash. + default_field: false + - name: parent.hash.sha512 + level: extended + type: keyword + ignore_above: 1024 + description: SHA512 hash. + default_field: false + - name: parent.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: 'Process name. + + Sometimes called program name or similar.' + example: ssh + default_field: false + - name: parent.pe.architecture + level: extended + type: keyword + ignore_above: 1024 + description: CPU architecture target for the file. + example: x64 + default_field: false + - name: parent.pe.company + level: extended + type: keyword + ignore_above: 1024 + description: Internal company name of the file, provided at compile-time. + example: Microsoft Corporation + default_field: false + - name: parent.pe.description + level: extended + type: keyword + ignore_above: 1024 + description: Internal description of the file, provided at compile-time. + example: Paint + default_field: false + - name: parent.pe.file_version + level: extended + type: keyword + ignore_above: 1024 + description: Internal version of the file, provided at compile-time. + example: 6.3.9600.17415 + default_field: false + - name: parent.pe.imphash + level: extended + type: keyword + ignore_above: 1024 + description: 'A hash of the imports in a PE file. An imphash -- or import hash + -- can be used to fingerprint binaries even after recompilation or other code-level + transformations have occurred, which would change more traditional hash values. + + Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html.' + example: 0c6803c4e922103c4dca5963aad36ddf + default_field: false + - name: parent.pe.original_file_name + level: extended + type: keyword + ignore_above: 1024 + description: Internal name of the file, provided at compile-time. + example: MSPAINT.EXE + default_field: false + - name: parent.pe.product + level: extended + type: keyword + ignore_above: 1024 + description: Internal product name of the file, provided at compile-time. + example: "Microsoft\xAE Windows\xAE Operating System" + default_field: false + - name: parent.pgid + level: extended + type: long + format: string + description: Identifier of the group of processes the process belongs to. + default_field: false + - name: parent.pid + level: core + type: long + format: string + description: Process id. + example: 4242 + default_field: false + - name: parent.ppid + level: extended + type: long + format: string + description: Parent process' pid. + example: 4241 + default_field: false + - name: parent.start + level: extended + type: date + description: The time the process started. + example: '2016-05-23T08:05:34.853Z' + default_field: false + - name: parent.thread.id + level: extended + type: long + format: string + description: Thread ID. + example: 4242 + default_field: false + - name: parent.thread.name + level: extended + type: keyword + ignore_above: 1024 + description: Thread name. + example: thread-0 + default_field: false + - name: parent.title + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: 'Process title. + + The proctitle, some times the same as process name. Can also be different: + for example a browser setting its title to the web page currently opened.' + default_field: false + - name: parent.uptime + level: extended + type: long + description: Seconds the process has been up. + example: 1325 + default_field: false + - name: parent.working_directory + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: The working directory of the process. + example: /home/alice + default_field: false + - name: pe.architecture + level: extended + type: keyword + ignore_above: 1024 + description: CPU architecture target for the file. + example: x64 + default_field: false + - name: pe.company + level: extended + type: keyword + ignore_above: 1024 + description: Internal company name of the file, provided at compile-time. + example: Microsoft Corporation + default_field: false + - name: pe.description + level: extended + type: keyword + ignore_above: 1024 + description: Internal description of the file, provided at compile-time. + example: Paint + default_field: false + - name: pe.file_version + level: extended + type: keyword + ignore_above: 1024 + description: Internal version of the file, provided at compile-time. + example: 6.3.9600.17415 + default_field: false + - name: pe.imphash + level: extended + type: keyword + ignore_above: 1024 + description: 'A hash of the imports in a PE file. An imphash -- or import hash + -- can be used to fingerprint binaries even after recompilation or other code-level + transformations have occurred, which would change more traditional hash values. + + Learn more at https://www.fireeye.com/blog/threat-research/2014/01/tracking-malware-import-hashing.html.' + example: 0c6803c4e922103c4dca5963aad36ddf + default_field: false + - name: pe.original_file_name + level: extended + type: keyword + ignore_above: 1024 + description: Internal name of the file, provided at compile-time. + example: MSPAINT.EXE + default_field: false + - name: pe.product + level: extended + type: keyword + ignore_above: 1024 + description: Internal product name of the file, provided at compile-time. + example: "Microsoft\xAE Windows\xAE Operating System" + default_field: false + - name: pgid + level: extended + type: long + format: string + description: Identifier of the group of processes the process belongs to. + - name: pid + level: core + type: long + format: string + description: Process id. + example: 4242 + - name: ppid + level: extended + type: long + format: string + description: Parent process' pid. + example: 4241 + - name: start + level: extended + type: date + description: The time the process started. + example: '2016-05-23T08:05:34.853Z' + - name: thread.id + level: extended + type: long + format: string + description: Thread ID. + example: 4242 + - name: thread.name + level: extended + type: keyword + ignore_above: 1024 + description: Thread name. + example: thread-0 + - name: title + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: 'Process title. + + The proctitle, some times the same as process name. Can also be different: + for example a browser setting its title to the web page currently opened.' + - name: uptime + level: extended + type: long + description: Seconds the process has been up. + example: 1325 + - name: working_directory + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: The working directory of the process. + example: /home/alice + - name: registry + title: Registry + group: 2 + description: Fields related to Windows Registry operations. + type: group + fields: + - name: data.bytes + level: extended + type: keyword + ignore_above: 1024 + description: 'Original bytes written with base64 encoding. + + For Windows registry operations, such as SetValueEx and RegQueryValueEx, this + corresponds to the data pointed by `lp_data`. This is optional but provides + better recoverability and should be populated for REG_BINARY encoded values.' + example: ZQBuAC0AVQBTAAAAZQBuAAAAAAA= + default_field: false + - name: data.strings + level: core + type: keyword + ignore_above: 1024 + description: 'Content when writing string types. + + Populated as an array when writing string data to the registry. For single + string registry types (REG_SZ, REG_EXPAND_SZ), this should be an array with + one string. For sequences of string with REG_MULTI_SZ, this array will be + variable length. For numeric data, such as REG_DWORD and REG_QWORD, this should + be populated with the decimal representation (e.g `"1"`).' + example: '["C:\rta\red_ttp\bin\myapp.exe"]' + default_field: false + - name: data.type + level: core + type: keyword + ignore_above: 1024 + description: Standard registry type for encoding contents + example: REG_SZ + default_field: false + - name: hive + level: core + type: keyword + ignore_above: 1024 + description: Abbreviated name for the hive. + example: HKLM + default_field: false + - name: key + level: core + type: keyword + ignore_above: 1024 + description: Hive-relative path of keys. + example: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\winword.exe + default_field: false + - name: path + level: core + type: keyword + ignore_above: 1024 + description: Full path, including hive, key and value + example: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution + Options\winword.exe\Debugger + default_field: false + - name: value + level: core + type: keyword + ignore_above: 1024 + description: Name of the value written. + example: Debugger + default_field: false + - name: related + title: Related + group: 2 + description: 'This field set is meant to facilitate pivoting around a piece of + data. + + Some pieces of information can be seen in many places in an ECS event. To facilitate + searching for them, store an array of all seen values to their corresponding + field in `related.`. + + A concrete example is IP addresses, which can be under host, observer, source, + destination, client, server, and network.forwarded_ip. If you append all IPs + to `related.ip`, you can then search for a given IP trivially, no matter where + it appeared, by querying `related.ip:192.0.2.15`.' + type: group + fields: + - name: hash + level: extended + type: keyword + ignore_above: 1024 + description: All the hashes seen on your event. Populating this field, then + using it to search for hashes can help in situations where you're unsure what + the hash algorithm is (and therefore which key name to search). + default_field: false + - name: hosts + level: extended + type: keyword + ignore_above: 1024 + description: All hostnames or other host identifiers seen on your event. Example + identifiers include FQDNs, domain names, workstation names, or aliases. + default_field: false + - name: ip + level: extended + type: ip + description: All of the IPs seen on your event. + - name: user + level: extended + type: keyword + ignore_above: 1024 + description: All the user names seen on your event. + default_field: false + - name: rule + title: Rule + group: 2 + description: 'Rule fields are used to capture the specifics of any observer or + agent rules that generate alerts or other notable events. + + Examples of data sources that would populate the rule fields include: network + admission control platforms, network or host IDS/IPS, network firewalls, web + application firewalls, url filters, endpoint detection and response (EDR) systems, + etc.' + type: group + fields: + - name: author + level: extended + type: keyword + ignore_above: 1024 + description: Name, organization, or pseudonym of the author or authors who created + the rule used to generate this event. + example: '["Star-Lord"]' + default_field: false + - name: category + level: extended + type: keyword + ignore_above: 1024 + description: A categorization value keyword used by the entity using the rule + for detection of this event. + example: Attempted Information Leak + default_field: false + - name: description + level: extended + type: keyword + ignore_above: 1024 + description: The description of the rule generating the event. + example: Block requests to public DNS over HTTPS / TLS protocols + default_field: false + - name: id + level: extended + type: keyword + ignore_above: 1024 + description: A rule ID that is unique within the scope of an agent, observer, + or other entity using the rule for detection of this event. + example: 101 + default_field: false + - name: license + level: extended + type: keyword + ignore_above: 1024 + description: Name of the license under which the rule used to generate this + event is made available. + example: Apache 2.0 + default_field: false + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: The name of the rule or signature generating the event. + example: BLOCK_DNS_over_TLS + default_field: false + - name: reference + level: extended + type: keyword + ignore_above: 1024 + description: 'Reference URL to additional information about the rule used to + generate this event. + + The URL can point to the vendor''s documentation about the rule. If that''s + not available, it can also be a link to a more general page describing this + type of alert.' + example: https://en.wikipedia.org/wiki/DNS_over_TLS + default_field: false + - name: ruleset + level: extended + type: keyword + ignore_above: 1024 + description: Name of the ruleset, policy, group, or parent category in which + the rule used to generate this event is a member. + example: Standard_Protocol_Filters + default_field: false + - name: uuid + level: extended + type: keyword + ignore_above: 1024 + description: A rule ID that is unique within the scope of a set or group of + agents, observers, or other entities using the rule for detection of this + event. + example: 1100110011 + default_field: false + - name: version + level: extended + type: keyword + ignore_above: 1024 + description: The version / revision of the rule being used for analysis. + example: 1.1 + default_field: false + - name: server + title: Server + group: 2 + description: 'A Server is defined as the responder in a network connection for + events regarding sessions, connections, or bidirectional flow records. + + For TCP events, the server is the receiver of the initial SYN packet(s) of the + TCP connection. For other protocols, the server is generally the responder in + the network transaction. Some systems actually use the term "responder" to refer + the server in TCP connections. The server fields describe details about the + system acting as the server in the network event. Server fields are usually + populated in conjunction with client fields. Server fields are generally not + populated for packet-level events. + + Client / server representations can add semantic context to an exchange, which + is helpful to visualize the data in certain situations. If your context falls + in that category, you should still ensure that source and destination are filled + appropriately.' + type: group + fields: + - name: address + level: extended + type: keyword + ignore_above: 1024 + description: 'Some event server addresses are defined ambiguously. The event + will sometimes list an IP, a domain or a unix socket. You should always store + the raw address in the `.address` field. + + Then it should be duplicated to `.ip` or `.domain`, depending on which one + it is.' + - name: as.number + level: extended + type: long + description: Unique number allocated to the autonomous system. The autonomous + system number (ASN) uniquely identifies each network on the Internet. + example: 15169 + - name: as.organization.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Organization name. + example: Google LLC + - name: bytes + level: core + type: long + format: bytes + description: Bytes sent from the server to the client. + example: 184 + - name: domain + level: core + type: keyword + ignore_above: 1024 + description: Server domain. + - name: geo.city_name + level: core + type: keyword + ignore_above: 1024 + description: City name. + example: Montreal + - name: geo.continent_name + level: core + type: keyword + ignore_above: 1024 + description: Name of the continent. + example: North America + - name: geo.country_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Country ISO code. + example: CA + - name: geo.country_name + level: core + type: keyword + ignore_above: 1024 + description: Country name. + example: Canada + - name: geo.location + level: core + type: geo_point + description: Longitude and latitude. + example: '{ "lon": -73.614830, "lat": 45.505918 }' + - name: geo.name + level: extended + type: keyword + ignore_above: 1024 + description: 'User-defined description of a location, at the level of granularity + they care about. + + Could be the name of their data centers, the floor number, if this describes + a local physical entity, city names. + + Not typically used in automated geolocation.' + example: boston-dc + - name: geo.region_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Region ISO code. + example: CA-QC + - name: geo.region_name + level: core + type: keyword + ignore_above: 1024 + description: Region name. + example: Quebec + - name: ip + level: core + type: ip + description: IP address of the server (IPv4 or IPv6). + - name: mac + level: core + type: keyword + ignore_above: 1024 + description: MAC address of the server. + - name: nat.ip + level: extended + type: ip + description: 'Translated ip of destination based NAT sessions (e.g. internet + to private DMZ) + + Typically used with load balancers, firewalls, or routers.' + - name: nat.port + level: extended + type: long + format: string + description: 'Translated port of destination based NAT sessions (e.g. internet + to private DMZ) + + Typically used with load balancers, firewalls, or routers.' + - name: packets + level: core + type: long + description: Packets sent from the server to the client. + example: 12 + - name: port + level: core + type: long + format: string + description: Port of the server. + - name: registered_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The highest registered server domain, stripped of the subdomain. + + For example, the registered domain for "foo.example.com" is "example.com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last two labels will not work well for TLDs such as "co.uk".' + example: example.com + - name: subdomain + level: extended + type: keyword + ignore_above: 1024 + description: 'The subdomain portion of a fully qualified domain name includes + all of the names except the host name under the registered_domain. In a partially + qualified domain, or if the the qualification level of the full name cannot + be determined, subdomain contains all of the names below the registered domain. + + For example the subdomain portion of "www.east.mydomain.co.uk" is "east". + If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", + the subdomain field should contain "sub2.sub1", with no trailing period.' + example: east + default_field: false + - name: top_level_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The effective top level domain (eTLD), also known as the domain + suffix, is the last part of the domain name. For example, the top level domain + for example.com is "com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last label will not work well for effective TLDs such as "co.uk".' + example: co.uk + - name: user.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the user is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.email + level: extended + type: keyword + ignore_above: 1024 + description: User email address. + - name: user.full_name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: User's full name, if available. + example: Albert Einstein + - name: user.group.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.group.id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + - name: user.group.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + - name: user.hash + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique user hash to correlate information for a user in anonymized + form. + + Useful if `user.id` or `user.name` contain confidential information and cannot + be used.' + - name: user.id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier of the user. + - name: user.name + level: core + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Short name or login of the user. + example: albert + - name: user.roles + level: extended + type: keyword + ignore_above: 1024 + description: Array of user roles at the time of the event. + example: '["kibana_admin", "reporting_user"]' + default_field: false + - name: service + title: Service + group: 2 + description: 'The service fields describe the service for or from which the data + was collected. + + These fields help you find and correlate logs for a specific service and version.' + type: group + fields: + - name: ephemeral_id + level: extended + type: keyword + ignore_above: 1024 + description: 'Ephemeral identifier of this service (if one exists). + + This id normally changes across restarts, but `service.id` does not.' + example: 8a4f500f + - name: id + level: core + type: keyword + ignore_above: 1024 + description: 'Unique identifier of the running service. If the service is comprised + of many nodes, the `service.id` should be the same for all nodes. + + This id should uniquely identify the service. This makes it possible to correlate + logs and metrics for one specific service, no matter which particular node + emitted the event. + + Note that if you need to see the events from one specific host of the service, + you should filter on that `host.name` or `host.id` instead.' + example: d37e5ebfe0ae6c4972dbe9f0174a1637bb8247f6 + - name: name + level: core + type: keyword + ignore_above: 1024 + description: 'Name of the service data is collected from. + + The name of the service is normally user given. This allows for distributed + services that run on multiple hosts to correlate the related instances based + on the name. + + In the case of Elasticsearch the `service.name` could contain the cluster + name. For Beats the `service.name` is by default a copy of the `service.type` + field if no name is specified.' + example: elasticsearch-metrics + - name: node.name + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of a service node. + + This allows for two nodes of the same service running on the same host to + be differentiated. Therefore, `service.node.name` should typically be unique + across nodes of a given service. + + In the case of Elasticsearch, the `service.node.name` could contain the unique + node name within the Elasticsearch cluster. In cases where the service doesn''t + have the concept of a node name, the host name or container name can be used + to distinguish running instances that make up this service. If those do not + provide uniqueness (e.g. multiple instances of the service running on the + same host) - the node name can be manually set.' + example: instance-0000000016 + - name: state + level: core + type: keyword + ignore_above: 1024 + description: Current state of the service. + - name: type + level: core + type: keyword + ignore_above: 1024 + description: 'The type of the service data is collected from. + + The type can be used to group and correlate logs and metrics from one service + type. + + Example: If logs or metrics are collected from Elasticsearch, `service.type` + would be `elasticsearch`.' + example: elasticsearch + - name: version + level: core + type: keyword + ignore_above: 1024 + description: 'Version of the service the data was collected from. + + This allows to look at a data set only for a specific version of a service.' + example: 3.2.4 + - name: source + title: Source + group: 2 + description: 'Source fields capture details about the sender of a network exchange/packet. + These fields are populated from a network event, packet, or other event containing + details of a network transaction. + + Source fields are usually populated in conjunction with destination fields. + The source and destination fields are considered the baseline and should always + be filled if an event contains source and destination details from a network + transaction. If the event also contains identification of the client and server + roles, then the client and server fields should also be populated.' + type: group + fields: + - name: address + level: extended + type: keyword + ignore_above: 1024 + description: 'Some event source addresses are defined ambiguously. The event + will sometimes list an IP, a domain or a unix socket. You should always store + the raw address in the `.address` field. + + Then it should be duplicated to `.ip` or `.domain`, depending on which one + it is.' + - name: as.number + level: extended + type: long + description: Unique number allocated to the autonomous system. The autonomous + system number (ASN) uniquely identifies each network on the Internet. + example: 15169 + - name: as.organization.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Organization name. + example: Google LLC + - name: bytes + level: core + type: long + format: bytes + description: Bytes sent from the source to the destination. + example: 184 + - name: domain + level: core + type: keyword + ignore_above: 1024 + description: Source domain. + - name: geo.city_name + level: core + type: keyword + ignore_above: 1024 + description: City name. + example: Montreal + - name: geo.continent_name + level: core + type: keyword + ignore_above: 1024 + description: Name of the continent. + example: North America + - name: geo.country_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Country ISO code. + example: CA + - name: geo.country_name + level: core + type: keyword + ignore_above: 1024 + description: Country name. + example: Canada + - name: geo.location + level: core + type: geo_point + description: Longitude and latitude. + example: '{ "lon": -73.614830, "lat": 45.505918 }' + - name: geo.name + level: extended + type: keyword + ignore_above: 1024 + description: 'User-defined description of a location, at the level of granularity + they care about. + + Could be the name of their data centers, the floor number, if this describes + a local physical entity, city names. + + Not typically used in automated geolocation.' + example: boston-dc + - name: geo.region_iso_code + level: core + type: keyword + ignore_above: 1024 + description: Region ISO code. + example: CA-QC + - name: geo.region_name + level: core + type: keyword + ignore_above: 1024 + description: Region name. + example: Quebec + - name: ip + level: core + type: ip + description: IP address of the source (IPv4 or IPv6). + - name: mac + level: core + type: keyword + ignore_above: 1024 + description: MAC address of the source. + - name: nat.ip + level: extended + type: ip + description: 'Translated ip of source based NAT sessions (e.g. internal client + to internet) + + Typically connections traversing load balancers, firewalls, or routers.' + - name: nat.port + level: extended + type: long + format: string + description: 'Translated port of source based NAT sessions. (e.g. internal client + to internet) + + Typically used with load balancers, firewalls, or routers.' + - name: packets + level: core + type: long + description: Packets sent from the source to the destination. + example: 12 + - name: port + level: core + type: long + format: string + description: Port of the source. + - name: registered_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The highest registered source domain, stripped of the subdomain. + + For example, the registered domain for "foo.example.com" is "example.com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last two labels will not work well for TLDs such as "co.uk".' + example: example.com + - name: subdomain + level: extended + type: keyword + ignore_above: 1024 + description: 'The subdomain portion of a fully qualified domain name includes + all of the names except the host name under the registered_domain. In a partially + qualified domain, or if the the qualification level of the full name cannot + be determined, subdomain contains all of the names below the registered domain. + + For example the subdomain portion of "www.east.mydomain.co.uk" is "east". + If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", + the subdomain field should contain "sub2.sub1", with no trailing period.' + example: east + default_field: false + - name: top_level_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The effective top level domain (eTLD), also known as the domain + suffix, is the last part of the domain name. For example, the top level domain + for example.com is "com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last label will not work well for effective TLDs such as "co.uk".' + example: co.uk + - name: user.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the user is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.email + level: extended + type: keyword + ignore_above: 1024 + description: User email address. + - name: user.full_name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: User's full name, if available. + example: Albert Einstein + - name: user.group.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: user.group.id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + - name: user.group.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + - name: user.hash + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique user hash to correlate information for a user in anonymized + form. + + Useful if `user.id` or `user.name` contain confidential information and cannot + be used.' + - name: user.id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier of the user. + - name: user.name + level: core + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Short name or login of the user. + example: albert + - name: user.roles + level: extended + type: keyword + ignore_above: 1024 + description: Array of user roles at the time of the event. + example: '["kibana_admin", "reporting_user"]' + default_field: false + - name: threat + title: Threat + group: 2 + description: "Fields to classify events and alerts according to a threat taxonomy\ + \ such as the MITRE ATT&CK\xAE framework.\nThese fields are for users to classify\ + \ alerts from all of their sources (e.g. IDS, NGFW, etc.) within a common taxonomy.\ + \ The threat.tactic.* are meant to capture the high level category of the threat\ + \ (e.g. \"impact\"). The threat.technique.* fields are meant to capture which\ + \ kind of approach is used by this detected threat, to accomplish the goal (e.g.\ + \ \"endpoint denial of service\")." + type: group + fields: + - name: framework + level: extended + type: keyword + ignore_above: 1024 + description: Name of the threat framework used to further categorize and classify + the tactic and technique of the reported threat. Framework classification + can be provided by detecting systems, evaluated at ingest time, or retrospectively + tagged to events. + example: MITRE ATT&CK + - name: tactic.id + level: extended + type: keyword + ignore_above: 1024 + description: "The id of tactic used by this threat. You can use a MITRE ATT&CK\xAE\ + \ tactic, for example. (ex. https://attack.mitre.org/tactics/TA0002/ )" + example: TA0002 + - name: tactic.name + level: extended + type: keyword + ignore_above: 1024 + description: "Name of the type of tactic used by this threat. You can use a\ + \ MITRE ATT&CK\xAE tactic, for example. (ex. https://attack.mitre.org/tactics/TA0002/)" + example: Execution + - name: tactic.reference + level: extended + type: keyword + ignore_above: 1024 + description: "The reference url of tactic used by this threat. You can use a\ + \ MITRE ATT&CK\xAE tactic, for example. (ex. https://attack.mitre.org/tactics/TA0002/\ + \ )" + example: https://attack.mitre.org/tactics/TA0002/ + - name: technique.id + level: extended + type: keyword + ignore_above: 1024 + description: "The id of technique used by this threat. You can use a MITRE ATT&CK\xAE\ + \ technique, for example. (ex. https://attack.mitre.org/techniques/T1059/)" + example: T1059 + - name: technique.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: "The name of technique used by this threat. You can use a MITRE\ + \ ATT&CK\xAE technique, for example. (ex. https://attack.mitre.org/techniques/T1059/)" + example: Command and Scripting Interpreter + - name: technique.reference + level: extended + type: keyword + ignore_above: 1024 + description: "The reference url of technique used by this threat. You can use\ + \ a MITRE ATT&CK\xAE technique, for example. (ex. https://attack.mitre.org/techniques/T1059/)" + example: https://attack.mitre.org/techniques/T1059/ + - name: technique.subtechnique.id + level: extended + type: keyword + ignore_above: 1024 + description: "The full id of subtechnique used by this threat. You can use a\ + \ MITRE ATT&CK\xAE subtechnique, for example. (ex. https://attack.mitre.org/techniques/T1059/001/)" + example: T1059.001 + default_field: false + - name: technique.subtechnique.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: "The name of subtechnique used by this threat. You can use a MITRE\ + \ ATT&CK\xAE subtechnique, for example. (ex. https://attack.mitre.org/techniques/T1059/001/)" + example: PowerShell + default_field: false + - name: technique.subtechnique.reference + level: extended + type: keyword + ignore_above: 1024 + description: "The reference url of subtechnique used by this threat. You can\ + \ use a MITRE ATT&CK\xAE subtechnique, for example. (ex. https://attack.mitre.org/techniques/T1059/001/)" + example: https://attack.mitre.org/techniques/T1059/001/ + default_field: false + - name: tls + title: TLS + group: 2 + description: Fields related to a TLS connection. These fields focus on the TLS + protocol itself and intentionally avoids in-depth analysis of the related x.509 + certificate files. + type: group + fields: + - name: cipher + level: extended + type: keyword + ignore_above: 1024 + description: String indicating the cipher used during the current connection. + example: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + default_field: false + - name: client.certificate + level: extended + type: keyword + ignore_above: 1024 + description: PEM-encoded stand-alone certificate offered by the client. This + is usually mutually-exclusive of `client.certificate_chain` since this value + also exists in that list. + example: MII... + default_field: false + - name: client.certificate_chain + level: extended + type: keyword + ignore_above: 1024 + description: Array of PEM-encoded certificates that make up the certificate + chain offered by the client. This is usually mutually-exclusive of `client.certificate` + since that value should be the first certificate in the chain. + example: '["MII...", "MII..."]' + default_field: false + - name: client.hash.md5 + level: extended + type: keyword + ignore_above: 1024 + description: Certificate fingerprint using the MD5 digest of DER-encoded version + of certificate offered by the client. For consistency with other hash values, + this value should be formatted as an uppercase hash. + example: 0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC + default_field: false + - name: client.hash.sha1 + level: extended + type: keyword + ignore_above: 1024 + description: Certificate fingerprint using the SHA1 digest of DER-encoded version + of certificate offered by the client. For consistency with other hash values, + this value should be formatted as an uppercase hash. + example: 9E393D93138888D288266C2D915214D1D1CCEB2A + default_field: false + - name: client.hash.sha256 + level: extended + type: keyword + ignore_above: 1024 + description: Certificate fingerprint using the SHA256 digest of DER-encoded + version of certificate offered by the client. For consistency with other hash + values, this value should be formatted as an uppercase hash. + example: 0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0 + default_field: false + - name: client.issuer + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name of subject of the issuer of the x.509 certificate + presented by the client. + example: CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com + default_field: false + - name: client.ja3 + level: extended + type: keyword + ignore_above: 1024 + description: A hash that identifies clients based on how they perform an SSL/TLS + handshake. + example: d4e5b18d6b55c71272893221c96ba240 + default_field: false + - name: client.not_after + level: extended + type: date + description: Date/Time indicating when client certificate is no longer considered + valid. + example: '2021-01-01T00:00:00.000Z' + default_field: false + - name: client.not_before + level: extended + type: date + description: Date/Time indicating when client certificate is first considered + valid. + example: '1970-01-01T00:00:00.000Z' + default_field: false + - name: client.server_name + level: extended + type: keyword + ignore_above: 1024 + description: Also called an SNI, this tells the server which hostname to which + the client is attempting to connect to. When this value is available, it should + get copied to `destination.domain`. + example: www.elastic.co + default_field: false + - name: client.subject + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name of subject of the x.509 certificate presented + by the client. + example: CN=myclient, OU=Documentation Team, DC=example, DC=com + default_field: false + - name: client.supported_ciphers + level: extended + type: keyword + ignore_above: 1024 + description: Array of ciphers offered by the client during the client hello. + example: '["TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", + "..."]' + default_field: false + - name: client.x509.alternative_names + level: extended + type: keyword + ignore_above: 1024 + description: List of subject alternative names (SAN). Name types vary by certificate + authority and certificate type but commonly contain IP addresses, DNS names + (and wildcards), and email addresses. + example: '*.elastic.co' + default_field: false + - name: client.x509.issuer.common_name + level: extended + type: keyword + ignore_above: 1024 + description: List of common name (CN) of issuing certificate authority. + example: Example SHA2 High Assurance Server CA + default_field: false + - name: client.x509.issuer.country + level: extended + type: keyword + ignore_above: 1024 + description: List of country (C) codes + example: US + default_field: false + - name: client.x509.issuer.distinguished_name + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of issuing certificate authority. + example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance + Server CA + default_field: false + - name: client.x509.issuer.locality + level: extended + type: keyword + ignore_above: 1024 + description: List of locality names (L) + example: Mountain View + default_field: false + - name: client.x509.issuer.organization + level: extended + type: keyword + ignore_above: 1024 + description: List of organizations (O) of issuing certificate authority. + example: Example Inc + default_field: false + - name: client.x509.issuer.organizational_unit + level: extended + type: keyword + ignore_above: 1024 + description: List of organizational units (OU) of issuing certificate authority. + example: www.example.com + default_field: false + - name: client.x509.issuer.state_or_province + level: extended + type: keyword + ignore_above: 1024 + description: List of state or province names (ST, S, or P) + example: California + default_field: false + - name: client.x509.not_after + level: extended + type: date + description: Time at which the certificate is no longer considered valid. + example: 2020-07-16 03:15:39+00:00 + default_field: false + - name: client.x509.not_before + level: extended + type: date + description: Time at which the certificate is first considered valid. + example: 2019-08-16 01:40:25+00:00 + default_field: false + - name: client.x509.public_key_algorithm + level: extended + type: keyword + ignore_above: 1024 + description: Algorithm used to generate the public key. + example: RSA + default_field: false + - name: client.x509.public_key_curve + level: extended + type: keyword + ignore_above: 1024 + description: The curve used by the elliptic curve public key algorithm. This + is algorithm specific. + example: nistp521 + default_field: false + - name: client.x509.public_key_exponent + level: extended + type: long + description: Exponent used to derive the public key. This is algorithm specific. + example: 65537 + index: false + default_field: false + - name: client.x509.public_key_size + level: extended + type: long + description: The size of the public key space in bits. + example: 2048 + default_field: false + - name: client.x509.serial_number + level: extended + type: keyword + ignore_above: 1024 + description: Unique serial number issued by the certificate authority. For consistency, + if this value is alphanumeric, it should be formatted without colons and uppercase + characters. + example: 55FBB9C7DEBF09809D12CCAA + default_field: false + - name: client.x509.signature_algorithm + level: extended + type: keyword + ignore_above: 1024 + description: Identifier for certificate signature algorithm. We recommend using + names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. + example: SHA256-RSA + default_field: false + - name: client.x509.subject.common_name + level: extended + type: keyword + ignore_above: 1024 + description: List of common names (CN) of subject. + example: shared.global.example.net + default_field: false + - name: client.x509.subject.country + level: extended + type: keyword + ignore_above: 1024 + description: List of country (C) code + example: US + default_field: false + - name: client.x509.subject.distinguished_name + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of the certificate subject entity. + example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net + default_field: false + - name: client.x509.subject.locality + level: extended + type: keyword + ignore_above: 1024 + description: List of locality names (L) + example: San Francisco + default_field: false + - name: client.x509.subject.organization + level: extended + type: keyword + ignore_above: 1024 + description: List of organizations (O) of subject. + example: Example, Inc. + default_field: false + - name: client.x509.subject.organizational_unit + level: extended + type: keyword + ignore_above: 1024 + description: List of organizational units (OU) of subject. + default_field: false + - name: client.x509.subject.state_or_province + level: extended + type: keyword + ignore_above: 1024 + description: List of state or province names (ST, S, or P) + example: California + default_field: false + - name: client.x509.version_number + level: extended + type: keyword + ignore_above: 1024 + description: Version of x509 format. + example: 3 + default_field: false + - name: curve + level: extended + type: keyword + ignore_above: 1024 + description: String indicating the curve used for the given cipher, when applicable. + example: secp256r1 + default_field: false + - name: established + level: extended + type: boolean + description: Boolean flag indicating if the TLS negotiation was successful and + transitioned to an encrypted tunnel. + default_field: false + - name: next_protocol + level: extended + type: keyword + ignore_above: 1024 + description: String indicating the protocol being tunneled. Per the values in + the IANA registry (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids), + this string should be lower case. + example: http/1.1 + default_field: false + - name: resumed + level: extended + type: boolean + description: Boolean flag indicating if this TLS connection was resumed from + an existing TLS negotiation. + default_field: false + - name: server.certificate + level: extended + type: keyword + ignore_above: 1024 + description: PEM-encoded stand-alone certificate offered by the server. This + is usually mutually-exclusive of `server.certificate_chain` since this value + also exists in that list. + example: MII... + default_field: false + - name: server.certificate_chain + level: extended + type: keyword + ignore_above: 1024 + description: Array of PEM-encoded certificates that make up the certificate + chain offered by the server. This is usually mutually-exclusive of `server.certificate` + since that value should be the first certificate in the chain. + example: '["MII...", "MII..."]' + default_field: false + - name: server.hash.md5 + level: extended + type: keyword + ignore_above: 1024 + description: Certificate fingerprint using the MD5 digest of DER-encoded version + of certificate offered by the server. For consistency with other hash values, + this value should be formatted as an uppercase hash. + example: 0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC + default_field: false + - name: server.hash.sha1 + level: extended + type: keyword + ignore_above: 1024 + description: Certificate fingerprint using the SHA1 digest of DER-encoded version + of certificate offered by the server. For consistency with other hash values, + this value should be formatted as an uppercase hash. + example: 9E393D93138888D288266C2D915214D1D1CCEB2A + default_field: false + - name: server.hash.sha256 + level: extended + type: keyword + ignore_above: 1024 + description: Certificate fingerprint using the SHA256 digest of DER-encoded + version of certificate offered by the server. For consistency with other hash + values, this value should be formatted as an uppercase hash. + example: 0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0 + default_field: false + - name: server.issuer + level: extended + type: keyword + ignore_above: 1024 + description: Subject of the issuer of the x.509 certificate presented by the + server. + example: CN=Example Root CA, OU=Infrastructure Team, DC=example, DC=com + default_field: false + - name: server.ja3s + level: extended + type: keyword + ignore_above: 1024 + description: A hash that identifies servers based on how they perform an SSL/TLS + handshake. + example: 394441ab65754e2207b1e1b457b3641d + default_field: false + - name: server.not_after + level: extended + type: date + description: Timestamp indicating when server certificate is no longer considered + valid. + example: '2021-01-01T00:00:00.000Z' + default_field: false + - name: server.not_before + level: extended + type: date + description: Timestamp indicating when server certificate is first considered + valid. + example: '1970-01-01T00:00:00.000Z' + default_field: false + - name: server.subject + level: extended + type: keyword + ignore_above: 1024 + description: Subject of the x.509 certificate presented by the server. + example: CN=www.example.com, OU=Infrastructure Team, DC=example, DC=com + default_field: false + - name: server.x509.alternative_names + level: extended + type: keyword + ignore_above: 1024 + description: List of subject alternative names (SAN). Name types vary by certificate + authority and certificate type but commonly contain IP addresses, DNS names + (and wildcards), and email addresses. + example: '*.elastic.co' + default_field: false + - name: server.x509.issuer.common_name + level: extended + type: keyword + ignore_above: 1024 + description: List of common name (CN) of issuing certificate authority. + example: Example SHA2 High Assurance Server CA + default_field: false + - name: server.x509.issuer.country + level: extended + type: keyword + ignore_above: 1024 + description: List of country (C) codes + example: US + default_field: false + - name: server.x509.issuer.distinguished_name + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of issuing certificate authority. + example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance + Server CA + default_field: false + - name: server.x509.issuer.locality + level: extended + type: keyword + ignore_above: 1024 + description: List of locality names (L) + example: Mountain View + default_field: false + - name: server.x509.issuer.organization + level: extended + type: keyword + ignore_above: 1024 + description: List of organizations (O) of issuing certificate authority. + example: Example Inc + default_field: false + - name: server.x509.issuer.organizational_unit + level: extended + type: keyword + ignore_above: 1024 + description: List of organizational units (OU) of issuing certificate authority. + example: www.example.com + default_field: false + - name: server.x509.issuer.state_or_province + level: extended + type: keyword + ignore_above: 1024 + description: List of state or province names (ST, S, or P) + example: California + default_field: false + - name: server.x509.not_after + level: extended + type: date + description: Time at which the certificate is no longer considered valid. + example: 2020-07-16 03:15:39+00:00 + default_field: false + - name: server.x509.not_before + level: extended + type: date + description: Time at which the certificate is first considered valid. + example: 2019-08-16 01:40:25+00:00 + default_field: false + - name: server.x509.public_key_algorithm + level: extended + type: keyword + ignore_above: 1024 + description: Algorithm used to generate the public key. + example: RSA + default_field: false + - name: server.x509.public_key_curve + level: extended + type: keyword + ignore_above: 1024 + description: The curve used by the elliptic curve public key algorithm. This + is algorithm specific. + example: nistp521 + default_field: false + - name: server.x509.public_key_exponent + level: extended + type: long + description: Exponent used to derive the public key. This is algorithm specific. + example: 65537 + index: false + default_field: false + - name: server.x509.public_key_size + level: extended + type: long + description: The size of the public key space in bits. + example: 2048 + default_field: false + - name: server.x509.serial_number + level: extended + type: keyword + ignore_above: 1024 + description: Unique serial number issued by the certificate authority. For consistency, + if this value is alphanumeric, it should be formatted without colons and uppercase + characters. + example: 55FBB9C7DEBF09809D12CCAA + default_field: false + - name: server.x509.signature_algorithm + level: extended + type: keyword + ignore_above: 1024 + description: Identifier for certificate signature algorithm. We recommend using + names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. + example: SHA256-RSA + default_field: false + - name: server.x509.subject.common_name + level: extended + type: keyword + ignore_above: 1024 + description: List of common names (CN) of subject. + example: shared.global.example.net + default_field: false + - name: server.x509.subject.country + level: extended + type: keyword + ignore_above: 1024 + description: List of country (C) code + example: US + default_field: false + - name: server.x509.subject.distinguished_name + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of the certificate subject entity. + example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net + default_field: false + - name: server.x509.subject.locality + level: extended + type: keyword + ignore_above: 1024 + description: List of locality names (L) + example: San Francisco + default_field: false + - name: server.x509.subject.organization + level: extended + type: keyword + ignore_above: 1024 + description: List of organizations (O) of subject. + example: Example, Inc. + default_field: false + - name: server.x509.subject.organizational_unit + level: extended + type: keyword + ignore_above: 1024 + description: List of organizational units (OU) of subject. + default_field: false + - name: server.x509.subject.state_or_province + level: extended + type: keyword + ignore_above: 1024 + description: List of state or province names (ST, S, or P) + example: California + default_field: false + - name: server.x509.version_number + level: extended + type: keyword + ignore_above: 1024 + description: Version of x509 format. + example: 3 + default_field: false + - name: version + level: extended + type: keyword + ignore_above: 1024 + description: Numeric part of the version parsed from the original string. + example: '1.2' + default_field: false + - name: version_protocol + level: extended + type: keyword + ignore_above: 1024 + description: Normalized lowercase protocol name parsed from original string. + example: tls + default_field: false + - name: span.id + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique identifier of the span within the scope of its trace. + + A span represents an operation within a transaction, such as a request to another + service, or a database query.' + example: 3ff9a8981b7ccd5a + default_field: false + - name: trace.id + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique identifier of the trace. + + A trace groups multiple events like transactions that belong together. For example, + a user request handled by multiple inter-connected services.' + example: 4bf92f3577b34da6a3ce929d0e0e4736 + - name: transaction.id + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique identifier of the transaction within the scope of its trace. + + A transaction is the highest level of work measured within a service, such as + a request to a server.' + example: 00f067aa0ba902b7 + - name: url + title: URL + group: 2 + description: URL fields provide support for complete or partial URLs, and supports + the breaking down into scheme, domain, path, and so on. + type: group + fields: + - name: domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Domain of the url, such as "www.elastic.co". + + In some cases a URL may refer to an IP and/or port directly, without a domain + name. In this case, the IP address would go to the `domain` field. + + If the URL contains a literal IPv6 address enclosed by `[` and `]` (IETF RFC + 2732), the `[` and `]` characters should also be captured in the `domain` + field.' + example: www.elastic.co + - name: extension + level: extended + type: keyword + ignore_above: 1024 + description: 'The field contains the file extension from the original request + url, excluding the leading dot. + + The file extension is only set if it exists, as not every url has a file extension. + + The leading period must not be included. For example, the value must be "png", + not ".png". + + Note that when the file name has multiple extensions (example.tar.gz), only + the last one should be captured ("gz", not "tar.gz").' + example: png + - name: fragment + level: extended + type: keyword + ignore_above: 1024 + description: 'Portion of the url after the `#`, such as "top". + + The `#` is not part of the fragment.' + - name: full + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: If full URLs are important to your use case, they should be stored + in `url.full`, whether this field is reconstructed or present in the event + source. + example: https://www.elastic.co:443/search?q=elasticsearch#top + - name: original + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: 'Unmodified original url as seen in the event source. + + Note that in network monitoring, the observed URL may be a full URL, whereas + in access logs, the URL is often just represented as a path. + + This field is meant to represent the URL as it was observed, complete or not.' + example: https://www.elastic.co:443/search?q=elasticsearch#top or /search?q=elasticsearch + - name: password + level: extended + type: keyword + ignore_above: 1024 + description: Password of the request. + - name: path + level: extended + type: keyword + ignore_above: 1024 + description: Path of the request, such as "/search". + - name: port + level: extended + type: long + format: string + description: Port of the request, such as 443. + example: 443 + - name: query + level: extended + type: keyword + ignore_above: 1024 + description: 'The query field describes the query string of the request, such + as "q=elasticsearch". + + The `?` is excluded from the query string. If a URL contains no `?`, there + is no query field. If there is a `?` but no query, the query field exists + with an empty string. The `exists` query can be used to differentiate between + the two cases.' + - name: registered_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The highest registered url domain, stripped of the subdomain. + + For example, the registered domain for "foo.example.com" is "example.com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last two labels will not work well for TLDs such as "co.uk".' + example: example.com + - name: scheme + level: extended + type: keyword + ignore_above: 1024 + description: 'Scheme of the request, such as "https". + + Note: The `:` is not part of the scheme.' + example: https + - name: subdomain + level: extended + type: keyword + ignore_above: 1024 + description: 'The subdomain portion of a fully qualified domain name includes + all of the names except the host name under the registered_domain. In a partially + qualified domain, or if the the qualification level of the full name cannot + be determined, subdomain contains all of the names below the registered domain. + + For example the subdomain portion of "www.east.mydomain.co.uk" is "east". + If the domain has multiple levels of subdomain, such as "sub2.sub1.example.com", + the subdomain field should contain "sub2.sub1", with no trailing period.' + example: east + default_field: false + - name: top_level_domain + level: extended + type: keyword + ignore_above: 1024 + description: 'The effective top level domain (eTLD), also known as the domain + suffix, is the last part of the domain name. For example, the top level domain + for example.com is "com". + + This value can be determined precisely with a list like the public suffix + list (http://publicsuffix.org). Trying to approximate this by simply taking + the last label will not work well for effective TLDs such as "co.uk".' + example: co.uk + - name: username + level: extended + type: keyword + ignore_above: 1024 + description: Username of the request. + - name: user + title: User + group: 2 + description: 'The user fields describe information about the user that is relevant + to the event. + + Fields can have one entry or multiple entries. If a user has more than one id, + provide an array that includes all of them.' + type: group + fields: + - name: changes.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the user is a member of. + + For example, an LDAP or Active Directory domain name.' + default_field: false + - name: changes.email + level: extended + type: keyword + ignore_above: 1024 + description: User email address. + default_field: false + - name: changes.full_name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: User's full name, if available. + example: Albert Einstein + default_field: false + - name: changes.group.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + default_field: false + - name: changes.group.id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + default_field: false + - name: changes.group.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + default_field: false + - name: changes.hash + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique user hash to correlate information for a user in anonymized + form. + + Useful if `user.id` or `user.name` contain confidential information and cannot + be used.' + default_field: false + - name: changes.id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier of the user. + default_field: false + - name: changes.name + level: core + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: Short name or login of the user. + example: albert + default_field: false + - name: changes.roles + level: extended + type: keyword + ignore_above: 1024 + description: Array of user roles at the time of the event. + example: '["kibana_admin", "reporting_user"]' + default_field: false + - name: domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the user is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: effective.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the user is a member of. + + For example, an LDAP or Active Directory domain name.' + default_field: false + - name: effective.email + level: extended + type: keyword + ignore_above: 1024 + description: User email address. + default_field: false + - name: effective.full_name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: User's full name, if available. + example: Albert Einstein + default_field: false + - name: effective.group.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + default_field: false + - name: effective.group.id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + default_field: false + - name: effective.group.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + default_field: false + - name: effective.hash + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique user hash to correlate information for a user in anonymized + form. + + Useful if `user.id` or `user.name` contain confidential information and cannot + be used.' + default_field: false + - name: effective.id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier of the user. + default_field: false + - name: effective.name + level: core + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: Short name or login of the user. + example: albert + default_field: false + - name: effective.roles + level: extended + type: keyword + ignore_above: 1024 + description: Array of user roles at the time of the event. + example: '["kibana_admin", "reporting_user"]' + default_field: false + - name: email + level: extended + type: keyword + ignore_above: 1024 + description: User email address. + - name: full_name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: User's full name, if available. + example: Albert Einstein + - name: group.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + - name: group.id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + - name: group.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + - name: hash + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique user hash to correlate information for a user in anonymized + form. + + Useful if `user.id` or `user.name` contain confidential information and cannot + be used.' + - name: id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier of the user. + - name: name + level: core + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Short name or login of the user. + example: albert + - name: roles + level: extended + type: keyword + ignore_above: 1024 + description: Array of user roles at the time of the event. + example: '["kibana_admin", "reporting_user"]' + default_field: false + - name: target.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the user is a member of. + + For example, an LDAP or Active Directory domain name.' + default_field: false + - name: target.email + level: extended + type: keyword + ignore_above: 1024 + description: User email address. + default_field: false + - name: target.full_name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: User's full name, if available. + example: Albert Einstein + default_field: false + - name: target.group.domain + level: extended + type: keyword + ignore_above: 1024 + description: 'Name of the directory the group is a member of. + + For example, an LDAP or Active Directory domain name.' + default_field: false + - name: target.group.id + level: extended + type: keyword + ignore_above: 1024 + description: Unique identifier for the group on the system/platform. + default_field: false + - name: target.group.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the group. + default_field: false + - name: target.hash + level: extended + type: keyword + ignore_above: 1024 + description: 'Unique user hash to correlate information for a user in anonymized + form. + + Useful if `user.id` or `user.name` contain confidential information and cannot + be used.' + default_field: false + - name: target.id + level: core + type: keyword + ignore_above: 1024 + description: Unique identifier of the user. + default_field: false + - name: target.name + level: core + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: Short name or login of the user. + example: albert + default_field: false + - name: target.roles + level: extended + type: keyword + ignore_above: 1024 + description: Array of user roles at the time of the event. + example: '["kibana_admin", "reporting_user"]' + default_field: false + - name: user_agent + title: User agent + group: 2 + description: 'The user_agent fields normally come from a browser request. + + They often show up in web service logs coming from the parsed user agent string.' + type: group + fields: + - name: device.name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the device. + example: iPhone + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Name of the user agent. + example: Safari + - name: original + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: Unparsed user_agent string. + example: Mozilla/5.0 (iPhone; CPU iPhone OS 12_1 like Mac OS X) AppleWebKit/605.1.15 + (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1 + - name: os.family + level: extended + type: keyword + ignore_above: 1024 + description: OS family (such as redhat, debian, freebsd, windows). + example: debian + - name: os.full + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, including the version or code name. + example: Mac OS Mojave + - name: os.kernel + level: extended + type: keyword + ignore_above: 1024 + description: Operating system kernel version as a raw string. + example: 4.4.0-112-generic + - name: os.name + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + default_field: false + description: Operating system name, without the version. + example: Mac OS X + - name: os.platform + level: extended + type: keyword + ignore_above: 1024 + description: Operating system platform (such centos, ubuntu, windows). + example: darwin + - name: os.type + level: extended + type: keyword + ignore_above: 1024 + description: 'Use the `os.type` field to categorize the operating system into + one of the broad commercial families. + + One of these following values should be used (lowercase): linux, macos, unix, + windows. + + If the OS you''re dealing with is not in the list, the field should not be + populated. Please let us know by opening an issue with ECS, to propose its + addition.' + example: macos + default_field: false + - name: os.version + level: extended + type: keyword + ignore_above: 1024 + description: Operating system version as a raw string. + example: 10.14.1 + - name: version + level: extended + type: keyword + ignore_above: 1024 + description: Version of the user agent. + example: 12.0 + - name: vlan + title: VLAN + group: 2 + description: 'The VLAN fields are used to identify 802.1q tag(s) of a packet, + as well as ingress and egress VLAN associations of an observer in relation to + a specific packet or connection. + + Network.vlan fields are used to record a single VLAN tag, or the outer tag in + the case of q-in-q encapsulations, for a packet or connection as observed, typically + provided by a network sensor (e.g. Zeek, Wireshark) passively reporting on traffic. + + Network.inner VLAN fields are used to report inner q-in-q 802.1q tags (multiple + 802.1q encapsulations) as observed, typically provided by a network sensor (e.g. + Zeek, Wireshark) passively reporting on traffic. Network.inner VLAN fields should + only be used in addition to network.vlan fields to indicate q-in-q tagging. + + Observer.ingress and observer.egress VLAN values are used to record observer + specific information when observer events contain discrete ingress and egress + VLAN information, typically provided by firewalls, routers, or load balancers.' + type: group + fields: + - name: id + level: extended + type: keyword + ignore_above: 1024 + description: VLAN ID as reported by the observer. + example: 10 + default_field: false + - name: name + level: extended + type: keyword + ignore_above: 1024 + description: Optional VLAN name as reported by the observer. + example: outside + default_field: false + - name: vulnerability + title: Vulnerability + group: 2 + description: The vulnerability fields describe information about a vulnerability + that is relevant to an event. + type: group + fields: + - name: category + level: extended + type: keyword + ignore_above: 1024 + description: 'The type of system or architecture that the vulnerability affects. + These may be platform-specific (for example, Debian or SUSE) or general (for + example, Database or Firewall). For example (https://qualysguard.qualys.com/qwebhelp/fo_portal/knowledgebase/vulnerability_categories.htm[Qualys + vulnerability categories]) + + This field must be an array.' + example: '["Firewall"]' + default_field: false + - name: classification + level: extended + type: keyword + ignore_above: 1024 + description: The classification of the vulnerability scoring system. For example + (https://www.first.org/cvss/) + example: CVSS + default_field: false + - name: description + level: extended + type: keyword + ignore_above: 1024 + multi_fields: + - name: text + type: text + norms: false + description: The description of the vulnerability that provides additional context + of the vulnerability. For example (https://cve.mitre.org/about/faqs.html#cve_entry_descriptions_created[Common + Vulnerabilities and Exposure CVE description]) + example: In macOS before 2.12.6, there is a vulnerability in the RPC... + default_field: false + - name: enumeration + level: extended + type: keyword + ignore_above: 1024 + description: The type of identifier used for this vulnerability. For example + (https://cve.mitre.org/about/) + example: CVE + default_field: false + - name: id + level: extended + type: keyword + ignore_above: 1024 + description: The identification (ID) is the number portion of a vulnerability + entry. It includes a unique identification number for the vulnerability. For + example (https://cve.mitre.org/about/faqs.html#what_is_cve_id)[Common Vulnerabilities + and Exposure CVE ID] + example: CVE-2019-00001 + default_field: false + - name: reference + level: extended + type: keyword + ignore_above: 1024 + description: A resource that provides additional information, context, and mitigations + for the identified vulnerability. + example: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6111 + default_field: false + - name: report_id + level: extended + type: keyword + ignore_above: 1024 + description: The report or scan identification number. + example: 20191018.0001 + default_field: false + - name: scanner.vendor + level: extended + type: keyword + ignore_above: 1024 + description: The name of the vulnerability scanner vendor. + example: Tenable + default_field: false + - name: score.base + level: extended + type: float + description: 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe. + + Base scores cover an assessment for exploitability metrics (attack vector, + complexity, privileges, and user interaction), impact metrics (confidentiality, + integrity, and availability), and scope. For example (https://www.first.org/cvss/specification-document)' + example: 5.5 + default_field: false + - name: score.environmental + level: extended + type: float + description: 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe. + + Environmental scores cover an assessment for any modified Base metrics, confidentiality, + integrity, and availability requirements. For example (https://www.first.org/cvss/specification-document)' + example: 5.5 + default_field: false + - name: score.temporal + level: extended + type: float + description: 'Scores can range from 0.0 to 10.0, with 10.0 being the most severe. + + Temporal scores cover an assessment for code maturity, remediation level, + and confidence. For example (https://www.first.org/cvss/specification-document)' + default_field: false + - name: score.version + level: extended + type: keyword + ignore_above: 1024 + description: 'The National Vulnerability Database (NVD) provides qualitative + severity rankings of "Low", "Medium", and "High" for CVSS v2.0 base score + ranges in addition to the severity ratings for CVSS v3.0 as they are defined + in the CVSS v3.0 specification. + + CVSS is owned and managed by FIRST.Org, Inc. (FIRST), a US-based non-profit + organization, whose mission is to help computer security incident response + teams across the world. For example (https://nvd.nist.gov/vuln-metrics/cvss)' + example: 2.0 + default_field: false + - name: severity + level: extended + type: keyword + ignore_above: 1024 + description: The severity of the vulnerability can help with metrics and internal + prioritization regarding remediation. For example (https://nvd.nist.gov/vuln-metrics/cvss) + example: Critical + default_field: false + - name: x509 + title: x509 Certificate + group: 2 + description: 'This implements the common core fields for x509 certificates. This + information is likely logged with TLS sessions, digital signatures found in + executable binaries, S/MIME information in email bodies, or analysis of files + on disk. + + When the certificate relates to a file, use the fields at `file.x509`. When + hashes of the DER-encoded certificate are available, the `hash` data set should + be populated as well (e.g. `file.hash.sha256`). + + Events that contain certificate information about network connections, should + use the x509 fields under the relevant TLS fields: `tls.server.x509` and/or + `tls.client.x509`.' + type: group + fields: + - name: alternative_names + level: extended + type: keyword + ignore_above: 1024 + description: List of subject alternative names (SAN). Name types vary by certificate + authority and certificate type but commonly contain IP addresses, DNS names + (and wildcards), and email addresses. + example: '*.elastic.co' + default_field: false + - name: issuer.common_name + level: extended + type: keyword + ignore_above: 1024 + description: List of common name (CN) of issuing certificate authority. + example: Example SHA2 High Assurance Server CA + default_field: false + - name: issuer.country + level: extended + type: keyword + ignore_above: 1024 + description: List of country (C) codes + example: US + default_field: false + - name: issuer.distinguished_name + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of issuing certificate authority. + example: C=US, O=Example Inc, OU=www.example.com, CN=Example SHA2 High Assurance + Server CA + default_field: false + - name: issuer.locality + level: extended + type: keyword + ignore_above: 1024 + description: List of locality names (L) + example: Mountain View + default_field: false + - name: issuer.organization + level: extended + type: keyword + ignore_above: 1024 + description: List of organizations (O) of issuing certificate authority. + example: Example Inc + default_field: false + - name: issuer.organizational_unit + level: extended + type: keyword + ignore_above: 1024 + description: List of organizational units (OU) of issuing certificate authority. + example: www.example.com + default_field: false + - name: issuer.state_or_province + level: extended + type: keyword + ignore_above: 1024 + description: List of state or province names (ST, S, or P) + example: California + default_field: false + - name: not_after + level: extended + type: date + description: Time at which the certificate is no longer considered valid. + example: 2020-07-16 03:15:39+00:00 + default_field: false + - name: not_before + level: extended + type: date + description: Time at which the certificate is first considered valid. + example: 2019-08-16 01:40:25+00:00 + default_field: false + - name: public_key_algorithm + level: extended + type: keyword + ignore_above: 1024 + description: Algorithm used to generate the public key. + example: RSA + default_field: false + - name: public_key_curve + level: extended + type: keyword + ignore_above: 1024 + description: The curve used by the elliptic curve public key algorithm. This + is algorithm specific. + example: nistp521 + default_field: false + - name: public_key_exponent + level: extended + type: long + description: Exponent used to derive the public key. This is algorithm specific. + example: 65537 + index: false + default_field: false + - name: public_key_size + level: extended + type: long + description: The size of the public key space in bits. + example: 2048 + default_field: false + - name: serial_number + level: extended + type: keyword + ignore_above: 1024 + description: Unique serial number issued by the certificate authority. For consistency, + if this value is alphanumeric, it should be formatted without colons and uppercase + characters. + example: 55FBB9C7DEBF09809D12CCAA + default_field: false + - name: signature_algorithm + level: extended + type: keyword + ignore_above: 1024 + description: Identifier for certificate signature algorithm. We recommend using + names found in Go Lang Crypto library. See https://github.com/golang/go/blob/go1.14/src/crypto/x509/x509.go#L337-L353. + example: SHA256-RSA + default_field: false + - name: subject.common_name + level: extended + type: keyword + ignore_above: 1024 + description: List of common names (CN) of subject. + example: shared.global.example.net + default_field: false + - name: subject.country + level: extended + type: keyword + ignore_above: 1024 + description: List of country (C) code + example: US + default_field: false + - name: subject.distinguished_name + level: extended + type: keyword + ignore_above: 1024 + description: Distinguished name (DN) of the certificate subject entity. + example: C=US, ST=California, L=San Francisco, O=Example, Inc., CN=shared.global.example.net + default_field: false + - name: subject.locality + level: extended + type: keyword + ignore_above: 1024 + description: List of locality names (L) + example: San Francisco + default_field: false + - name: subject.organization + level: extended + type: keyword + ignore_above: 1024 + description: List of organizations (O) of subject. + example: Example, Inc. + default_field: false + - name: subject.organizational_unit + level: extended + type: keyword + ignore_above: 1024 + description: List of organizational units (OU) of subject. + default_field: false + - name: subject.state_or_province + level: extended + type: keyword + ignore_above: 1024 + description: List of state or province names (ST, S, or P) + example: California + default_field: false + - name: version_number + level: extended + type: keyword + ignore_above: 1024 + description: Version of x509 format. + example: 3 + default_field: false +- key: beat + anchor: beat-common + title: Beat + description: > + Contains common beat fields available in all event types. + fields: + - name: agent.hostname + type: keyword + description: > + Deprecated - use agent.name or agent.id to identify an agent. + Hostname of the agent. + + - name: beat.timezone + type: alias + path: event.timezone + migration: true + + - name: fields + type: object + object_type: keyword + description: > + Contains user configurable fields. + + - name: beat.name + type: alias + path: host.name + migration: true + + - name: beat.hostname + type: alias + path: agent.hostname + migration: true + + - name: timeseries.instance + type: keyword + description: Time series instance id +- key: cloud + title: Cloud provider metadata + description: > + Metadata from cloud providers added by the add_cloud_metadata processor. + fields: + + - name: cloud.image.id + example: ami-abcd1234 + description: > + Image ID for the cloud instance. + + # Alias for old fields + - name: meta.cloud.provider + type: alias + path: cloud.provider + migration: true + + - name: meta.cloud.instance_id + type: alias + path: cloud.instance.id + migration: true + + - name: meta.cloud.instance_name + type: alias + path: cloud.instance.name + migration: true + + - name: meta.cloud.machine_type + type: alias + path: cloud.machine.type + migration: true + + - name: meta.cloud.availability_zone + type: alias + path: cloud.availability_zone + migration: true + + - name: meta.cloud.project_id + type: alias + path: cloud.project.id + migration: true + + - name: meta.cloud.region + type: alias + path: cloud.region + migration: true + + +- key: docker + title: Docker + description: > + Docker stats collected from Docker. + short_config: false + anchor: docker-processor + fields: + - name: docker + type: group + fields: + - name: container.id + type: alias + path: container.id + migration: true + + - name: container.image + type: alias + path: container.image.name + migration: true + + - name: container.name + type: alias + path: container.name + migration: true + + - name: container.labels # TODO: How to map these? + type: object + object_type: keyword + description: > + Image labels. +- key: host + title: Host + description: > + Info collected for the host machine. + anchor: host-processor + fields: + + # ECS fields are in fields.ecs.yml. + # These are the non-ECS fields. + - name: host + type: group + fields: + + - name: containerized + type: boolean + description: > + If the host is a container. + + - name: os.build + type: keyword + example: "18D109" + description: > + OS build information. + + - name: os.codename + type: keyword + example: "stretch" + description: > + OS codename, if any. +- key: kubernetes + title: Kubernetes + description: > + Kubernetes metadata added by the kubernetes processor + short_config: false + anchor: kubernetes-processor + fields: + - name: kubernetes + type: group + fields: + - name: pod.name + type: keyword + description: > + Kubernetes pod name + + - name: pod.uid + type: keyword + description: > + Kubernetes Pod UID + + - name: namespace + type: keyword + description: > + Kubernetes namespace + + - name: node.name + type: keyword + description: > + Kubernetes node name + + - name: node.hostname + type: keyword + description: > + Kubernetes hostname as reported by the node’s kernel + + - name: labels.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes labels map + + - name: annotations.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes annotations map + + - name: service.selectors.* + type: object + object_type: keyword + object_type_mapping_type: "*" + description: > + Kubernetes Service selectors map + + - name: replicaset.name + type: keyword + description: > + Kubernetes replicaset name + + - name: deployment.name + type: keyword + description: > + Kubernetes deployment name + + - name: statefulset.name + type: keyword + description: > + Kubernetes statefulset name + + - name: container.name + type: keyword + description: > + Kubernetes container name + + - name: container.image + type: keyword + description: > + Kubernetes container image +- key: process + title: Process + description: > + Process metadata fields + fields: + - name: process + type: group + fields: + - name: exe + type: alias + path: process.executable + migration: true +- key: jolokia-autodiscover + title: Jolokia Discovery autodiscover provider + description: > + Metadata from Jolokia Discovery added by the jolokia provider. + fields: + - name: jolokia.agent.version + type: keyword + description: > + Version number of jolokia agent. + - name: jolokia.agent.id + type: keyword + description: > + Each agent has a unique id which can be either provided during startup of the agent in form of a configuration parameter or being autodetected. If autodected, the id has several parts: The IP, the process id, hashcode of the agent and its type. + - name: jolokia.server.product + type: keyword + description: > + The container product if detected. + - name: jolokia.server.version + type: keyword + description: > + The container's version (if detected). + - name: jolokia.server.vendor + type: keyword + description: > + The vendor of the container the agent is running in. + - name: jolokia.url + type: keyword + description: > + The URL how this agent can be contacted. + - name: jolokia.secured + type: boolean + description: > + Whether the agent was configured for authentication or not. +- key: log + title: Log file content + description: > + Contains log file lines. + fields: + + - name: log.source.address + type: keyword + required: false + description: > + Source address from which the log event was read / sent from. + + - name: log.offset + type: long + required: false + description: > + The file offset the reported line starts at. + + - name: stream + type: keyword + required: false + description: > + Log stream when reading container logs, can be 'stdout' or 'stderr' + + - name: input.type + required: true + description: > + The input type from which the event was generated. This field is set to the value specified + for the `type` option in the input section of the Filebeat config file. + + - name: syslog.facility + type: long + required: false + description: > + The facility extracted from the priority. + + - name: syslog.priority + type: long + required: false + description: > + The priority of the syslog event. + + - name: syslog.severity_label + type: keyword + required: false + description: > + The human readable severity. + + - name: syslog.facility_label + type: keyword + required: false + description: > + The human readable facility. + + - name: process.program + type: keyword + required: false + description: > + The name of the program. + + - name: log.flags + description: > + This field contains the flags of the event. + + - name: http.response.content_length + type: alias + path: http.response.body.bytes + migration: true + + - name: user_agent + type: group + fields: + - name: os + type: group + fields: + - name: full_name + type: keyword + + - name: fileset.name + type: keyword + description: > + The Filebeat fileset that generated this event. + + - name: fileset.module + type: alias + path: event.module + migration: true + + - name: read_timestamp + type: alias + path: event.created + migration: true + + - name: docker.attrs + type: object + object_type: keyword + description: > + docker.attrs contains labels and environment variables written by docker's JSON File logging driver. + These fields are only available when they are configured in the logging driver options. + + - name: icmp.code + type: keyword + description: > + ICMP code. + + - name: icmp.type + type: keyword + description: > + ICMP type. + + - name: igmp.type + type: keyword + description: > + IGMP type. + + + - name: azure + type: group + fields: + - name: eventhub + type: keyword + description: > + Name of the eventhub. + - name: offset + type: long + description: > + The offset. + - name: enqueued_time + type: date + description: > + The enqueued time. + - name: partition_id + type: long + description: > + The partition id. + - name: consumer_group + type: keyword + description: > + The consumer group. + - name: sequence_number + type: long + description: > + The sequence number. + + + - name: kafka + type: group + fields: + - name: topic + type: keyword + description: > + Kafka topic + + - name: partition + type: long + description: > + Kafka partition number + + - name: offset + type: long + description: > + Kafka offset of this message + + - name: key + type: keyword + description: > + Kafka key, corresponding to the Kafka value stored in the message + + - name: block_timestamp + type: date + description: > + Kafka outer (compressed) block timestamp + + - name: headers + type: array + description: > + An array of Kafka header strings for this message, in the form + ": ". +- key: apache + title: "Apache" + description: > + Apache Module + short_config: true + fields: + - name: apache2 + type: group + description: > + Aliases for backward compatibility with old apache2 fields + fields: + - name: access + type: group + fields: + - name: remote_ip + type: alias + path: source.address + migration: true + - name: ssl.protocol + type: alias + path: apache.access.ssl.protocol + migration: true + - name: ssl.cipher + type: alias + path: apache.access.ssl.cipher + migration: true + - name: body_sent.bytes + type: alias + path: http.response.body.bytes + migration: true + - name: user_name + type: alias + path: user.name + migration: true + - name: method + type: alias + path: http.request.method + migration: true + - name: url + type: alias + path: url.original + migration: true + - name: http_version + type: alias + path: http.version + migration: true + - name: response_code + type: alias + path: http.response.status_code + migration: true + - name: referrer + type: alias + path: http.request.referrer + migration: true + - name: agent + type: alias + path: user_agent.original + migration: true + + - name: user_agent + type: group + fields: + - name: device + type: alias + path: user_agent.device.name + migration: true + - name: name + type: alias + path: user_agent.name + migration: true + - name: os + type: alias + path: user_agent.os.full_name + migration: true + - name: os_name + type: alias + path: user_agent.os.name + migration: true + - name: original + type: alias + path: user_agent.original + migration: true + - name: geoip + type: group + fields: + - name: continent_name + type: alias + path: source.geo.continent_name + migration: true + - name: country_iso_code + type: alias + path: source.geo.country_iso_code + migration: true + - name: location + type: alias + path: source.geo.location + migration: true + - name: region_name + type: alias + path: source.geo.region_name + migration: true + - name: city_name + type: alias + path: source.geo.city_name + migration: true + - name: region_iso_code + type: alias + path: source.geo.region_iso_code + migration: true + - name: error + type: group + fields: + - name: level + type: alias + path: log.level + migration: true + - name: message + type: alias + path: message + migration: true + - name: pid + type: alias + path: process.pid + migration: true + - name: tid + type: alias + path: process.thread.id + migration: true + - name: module + type: alias + path: apache.error.module + migration: true + + + - name: apache + type: group + description: > + Apache fields. + fields: + - name: access + type: group + description: > + Contains fields for the Apache HTTP Server access logs. + fields: + - name: ssl.protocol + type: keyword + description: > + SSL protocol version. + + - name: ssl.cipher + type: keyword + description: > + SSL cipher name. + - name: error + type: group + description: > + Fields from the Apache error logs. + fields: + - name: module + type: keyword + description: > + The module producing the logged message. +- key: auditd + title: "Auditd" + description: > + Module for parsing auditd logs. + short_config: true + fields: + + - name: user + type: group + fields: + + - name: terminal + type: keyword + description: > + Terminal or tty device on which the user is performing the observed activity. + + - name: audit + type: group + fields: + - name: id + type: keyword + description: > + One or multiple unique identifiers of the user. + - name: name + type: keyword + example: albert + description: > + Short name or login of the user. + + - name: group.id + type: keyword + description: > + Unique identifier for the group on the system/platform. + - name: group.name + type: keyword + description: > + Name of the group. + + + - name: filesystem + type: group + fields: + - name: id + type: keyword + description: > + One or multiple unique identifiers of the user. + - name: name + type: keyword + example: albert + description: > + Short name or login of the user. + - name: group.id + type: keyword + description: > + Unique identifier for the group on the system/platform. + - name: group.name + type: keyword + description: > + Name of the group. + + - name: owner + type: group + fields: + - name: id + type: keyword + description: > + One or multiple unique identifiers of the user. + - name: name + type: keyword + example: albert + description: > + Short name or login of the user. + - name: group.id + type: keyword + description: > + Unique identifier for the group on the system/platform. + - name: group.name + type: keyword + description: > + Name of the group. + + - name: saved + type: group + fields: + - name: id + type: keyword + description: > + One or multiple unique identifiers of the user. + - name: name + type: keyword + example: albert + description: > + Short name or login of the user. + - name: group.id + type: keyword + description: > + Unique identifier for the group on the system/platform. + - name: group.name + type: keyword + description: > + Name of the group. + + - name: auditd + type: group + description: > + Fields from the auditd logs. + fields: + - name: log + type: group + description: > + Fields from the Linux audit log. Not all fields are documented here because + they are dynamic and vary by audit event type. + fields: + - name: old_auid + description: > + For login events this is the old audit ID used for the user prior to + this login. + - name: new_auid + description: > + For login events this is the new audit ID. The audit ID can be used to + trace future events to the user even if their identity changes (like + becoming root). + - name: old_ses + description: > + For login events this is the old session ID used for the user prior to + this login. + - name: new_ses + description: > + For login events this is the new session ID. It can be used to tie a + user to future events by session ID. + - name: sequence + type: long + description: > + The audit event sequence number. + - name: items + description: > + The number of items in an event. + - name: item + description: > + The item field indicates which item out of the total number of items. + This number is zero-based; a value of 0 means it is the first item. + - name: tty + type: keyword + definition: > + TTY udevice the user is running programs on. + - name: a0 + description: > + The first argument to the system call. + - name: addr + type: ip + definition: > + Remote address that the user is connecting from. + - name: rport + type: long + definition: > + Remote port number. + - name: laddr + type: ip + definition: > + Local network address. + - name: lport + type: long + definition: > + Local port number. + + - name: acct + type: alias + path: user.name + migration: true + - name: pid + type: alias + path: process.pid + migration: true + - name: ppid + type: alias + path: process.ppid + migration: true + - name: res + type: alias + path: event.outcome + migration: true + - name: record_type + type: alias + path: event.action + migration: true + - name: geoip + type: group + fields: + - name: continent_name + type: alias + path: source.geo.continent_name + migration: true + - name: country_iso_code + type: alias + path: source.geo.country_iso_code + migration: true + - name: location + type: alias + path: source.geo.location + migration: true + - name: region_name + type: alias + path: source.geo.region_name + migration: true + - name: city_name + type: alias + path: source.geo.city_name + migration: true + - name: region_iso_code + type: alias + path: source.geo.region_iso_code + migration: true + + # Fields below were not defined in 6.x but were still being populated. + - name: arch + type: alias + path: host.architecture + migration: true + - name: gid + type: alias + path: user.group.id + migration: true + - name: uid + type: alias + path: user.id + migration: true + - name: agid + type: alias + path: user.audit.group.id + migration: true + - name: auid + type: alias + path: user.audit.id + migration: true + - name: fsgid + type: alias + path: user.filesystem.group.id + migration: true + - name: fsuid + type: alias + path: user.filesystem.id + migration: true + - name: egid + type: alias + path: user.effective.group.id + migration: true + - name: euid + type: alias + path: user.effective.id + migration: true + - name: sgid + type: alias + path: user.saved.group.id + migration: true + - name: suid + type: alias + path: user.saved.id + migration: true + - name: ogid + type: alias + path: user.owner.group.id + migration: true + - name: ouid + type: alias + path: user.owner.id + migration: true + - name: comm + type: alias + path: process.name + migration: true + - name: exe + type: alias + path: process.executable + migration: true + - name: terminal + type: alias + path: user.terminal + migration: true + - name: msg + type: alias + path: message + migration: true + - name: src + type: alias + path: source.address + migration: true + - name: dst + type: alias + path: destination.address + migration: true +- key: elasticsearch + title: "Elasticsearch" + description: > + elasticsearch Module + fields: + - name: elasticsearch + type: group + description: > + fields: + - name: component + description: "Elasticsearch component from where the log event originated" + example: "o.e.c.m.MetaDataCreateIndexService" + type: keyword + - name: cluster.uuid + description: "UUID of the cluster" + example: "GmvrbHlNTiSVYiPf8kxg9g" + type: keyword + - name: cluster.name + description: "Name of the cluster" + example: "docker-cluster" + type: keyword + - name: node.id + description: "ID of the node" + example: "DSiWcTyeThWtUXLB9J0BMw" + type: keyword + - name: node.name + description: "Name of the node" + example: "vWNJsZ3" + type: keyword + - name: index.name + description: "Index name" + example: "filebeat-test-input" + type: keyword + - name: index.id + description: "Index id" + example: "aOGgDwbURfCV57AScqbCgw" + type: keyword + - name: shard.id + description: "Id of the shard" + example: "0" + type: keyword + - name: audit + type: group + fields: + - name: layer + description: "The layer from which this event originated: rest, transport or ip_filter" + example: "rest" + type: keyword + - name: event_type + description: "The type of event that occurred: anonymous_access_denied, authentication_failed, access_denied, access_granted, connection_granted, connection_denied, tampered_request, run_as_granted, run_as_denied" + example: "access_granted" + type: keyword + - name: origin.type + description: "Where the request originated: rest (request originated from a REST API request), transport (request was received on the transport channel), local_node (the local node issued the request)" + example: "local_node" + type: keyword + - name: realm + description: "The authentication realm the authentication was validated against" + example": "default_file" + type: keyword + - name: user.realm + description: "The user's authentication realm, if authenticated" + example": "active_directory" + type: keyword + - name: user.roles + description: "Roles to which the principal belongs" + example: [ "kibana_admin", "beats_admin" ] + type: keyword + - name: user.run_as.name + type: keyword + - name: user.run_as.realm + type: keyword + - name: component + type: keyword + - name: action + description: "The name of the action that was executed" + example: "cluster:monitor/main" + type: keyword + - name: url.params + description: "REST URI parameters" + example: "{username=jacknich2}" + - name: indices + description: "Indices accessed by action" + example: [ "foo-2019.01.04", "foo-2019.01.03", "foo-2019.01.06" ] + type: keyword + - name: request.id + description: "Unique ID of request" + example: "WzL_kb6VSvOhAq0twPvHOQ" + type: keyword + - name: request.name + description: "The type of request that was executed" + example: "ClearScrollRequest" + type: keyword + - name: request_body + type: alias + path: http.request.body.content + migration: true + - name: origin_address + type: alias + path: source.ip + migration: true + - name: uri + type: alias + path: url.original + migration: true + - name: principal + type: alias + path: user.name + migration: true + - name: message + type: text + - name: invalidate.apikeys.owned_by_authenticated_user + type: boolean + - name: deprecation + type: group + description: > + fields: + - name: gc + type: group + description: > + GC fileset fields. + fields: + - name: phase + type: group + description: > + Fields specific to GC phase. + fields: + - name: name + type: keyword + description: > + Name of the GC collection phase. + - name: duration_sec + type: float + description: > + Collection phase duration according to the Java virtual machine. + - name: scrub_symbol_table_time_sec + type: float + description: > + Pause time in seconds cleaning up symbol tables. + - name: scrub_string_table_time_sec + type: float + description: > + Pause time in seconds cleaning up string tables. + - name: weak_refs_processing_time_sec + type: float + description: > + Time spent processing weak references in seconds. + - name: parallel_rescan_time_sec + type: float + description: > + Time spent in seconds marking live objects while application is stopped. + - name: class_unload_time_sec + type: float + description: > + Time spent unloading unused classes in seconds. + - name: cpu_time + type: group + description: > + Process CPU time spent performing collections. + fields: + - name: user_sec + type: float + description: > + CPU time spent outside the kernel. + - name: sys_sec + type: float + description: > + CPU time spent inside the kernel. + - name: real_sec + type: float + description: > + Total elapsed CPU time spent to complete the collection from start to finish. + - name: jvm_runtime_sec + type: float + description: > + The time from JVM start up in seconds, as a floating point number. + - name: threads_total_stop_time_sec + type: float + description: > + Garbage collection threads total stop time seconds. + - name: stopping_threads_time_sec + type: float + description: > + Time took to stop threads seconds. + - name: tags + type: keyword + description: > + GC logging tags. + - name: heap + type: group + description: > + Heap allocation and total size. + fields: + - name: size_kb + type: integer + description: > + Total heap size in kilobytes. + - name: used_kb + type: integer + description: > + Used heap in kilobytes. + - name: old_gen + type: group + description: > + Old generation occupancy and total size. + fields: + - name: size_kb + type: integer + description: > + Total size of old generation in kilobytes. + - name: used_kb + type: integer + description: > + Old generation occupancy in kilobytes. + - name: young_gen + type: group + description: > + Young generation occupancy and total size. + fields: + - name: size_kb + type: integer + description: > + Total size of young generation in kilobytes. + - name: used_kb + type: integer + description: > + Young generation occupancy in kilobytes. + - name: server + description: "Server log file" + type: group + fields: + - name: stacktrace + description": Stack trace in case of errors + index: false + - name: gc + description: "GC log" + type: group + fields: + - name: young + description: "Young GC" + example: "" + type: group + fields: + - name: one + description: "" + example: "" + type: long + - name: two + description: "" + example: "" + type: long + - name: overhead_seq + description: "Sequence number" + example: 3449992 + type: long + - name: collection_duration.ms + description: "Time spent in GC, in milliseconds" + example: 1600 + type: float + - name: observation_duration.ms + description: "Total time over which collection was observed, in milliseconds" + example: 1800 + type: float + - name: slowlog + description: "Slowlog events from Elasticsearch" + example: "[2018-06-29T10:06:14,933][INFO ][index.search.slowlog.query] [v_VJhjV] [metricbeat-6.3.0-2018.06.26][0] took[4.5ms], took_millis[4], total_hits[19435], types[], stats[], search_type[QUERY_THEN_FETCH], total_shards[1], source[{\"query\":{\"match_all\":{\"boost\":1.0}}}]," + type: group + fields: + - name: logger + description: "Logger name" + example: "index.search.slowlog.fetch" + type: keyword + - name: took + description: "Time it took to execute the query" + example: "300ms" + type: keyword + - name: types + description: "Types" + example: "" + type: keyword + - name: stats + description: "Stats groups" + example: "group1" + type: keyword + - name: search_type + description: "Search type" + example: "QUERY_THEN_FETCH" + type: keyword + - name: source_query + description: "Slow query" + example: "{\"query\":{\"match_all\":{\"boost\":1.0}}}" + type: keyword + - name: extra_source + description: "Extra source information" + example: "" + type: keyword + - name: total_hits + description: "Total hits" + example: 42 + type: keyword + - name: total_shards + description: "Total queried shards" + example: 22 + type: keyword + - name: routing + description: "Routing" + example: "s01HZ2QBk9jw4gtgaFtn" + type: keyword + - name: id + description: Id + example: "" + type: keyword + - name: type + description: "Type" + example: "doc" + type: keyword + - name: source + description: Source of document that was indexed + type: keyword +- key: haproxy + title: "HAProxy" + description: > + haproxy Module + fields: + - name: haproxy + type: group + description: > + fields: + + - name: frontend_name + description: Name of the frontend (or listener) which received and processed the connection. + + - name: backend_name + description: Name of the backend (or listener) which was selected to manage the connection to the server. + + - name: server_name + description: Name of the last server to which the connection was sent. + + - name: total_waiting_time_ms + description: Total time in milliseconds spent waiting in the various queues + type: long + + - name: connection_wait_time_ms + description: Total time in milliseconds spent waiting for the connection to establish to the final server + type: long + + - name: bytes_read + description: Total number of bytes transmitted to the client when the log is emitted. + type: long + + - name: time_queue + description: Total time in milliseconds spent waiting in the various queues. + type: long + + - name: time_backend_connect + description: Total time in milliseconds spent waiting for the connection to establish to the final server, including retries. + type: long + + - name: server_queue + description: Total number of requests which were processed before this one in the server queue. + type: long + + - name: backend_queue + description: Total number of requests which were processed before this one in the backend's global queue. + type: long + + - name: bind_name + description: Name of the listening address which received the connection. + + - name: error_message + description: Error message logged by HAProxy in case of error. + type: text + + - name: source + type: keyword + description: The HAProxy source of the log + + - name: termination_state + description: Condition the session was in when the session ended. + + - name: mode + type: keyword + description: mode that the frontend is operating (TCP or HTTP) + + - name: connections + description: Contains various counts of connections active in the process. + type: group + fields: + - name: active + description: Total number of concurrent connections on the process when the session was logged. + type: long + + - name: frontend + description: Total number of concurrent connections on the frontend when the session was logged. + type: long + + - name: backend + description: Total number of concurrent connections handled by the backend when the session was logged. + type: long + + - name: server + description: Total number of concurrent connections still active on the server when the session was logged. + type: long + + - name: retries + description: Number of connection retries experienced by this session when trying to connect to the server. + type: long + + - name: client + description: Information about the client doing the request + type: group + fields: + - name: ip + type: alias + path: source.address + migration: true + - name: port + type: alias + path: source.port + migration: true + + - name: process_name + type: alias + path: process.name + migration: true + + - name: pid + type: alias + path: process.pid + migration: true + + - name: destination + description: Destination information + type: group + fields: + - name: port + type: alias + path: destination.port + migration: true + - name: ip + type: alias + path: destination.ip + migration: true + + - name: geoip + type: group + description: > + Contains GeoIP information gathered based on the client.ip field. + Only present if the GeoIP Elasticsearch plugin is available and + used. + fields: + - name: continent_name + type: alias + path: source.geo.continent_name + migration: true + - name: country_iso_code + type: alias + path: source.geo.country_iso_code + migration: true + - name: location + type: alias + path: source.geo.location + migration: true + - name: region_name + type: alias + path: source.geo.region_name + migration: true + - name: city_name + type: alias + path: source.geo.city_name + migration: true + - name: region_iso_code + type: alias + path: source.geo.region_iso_code + migration: true + - name: http + description: Please add description + type: group + fields: + + - name: response + description: Fields related to the HTTP response + type: group + fields: + - name: captured_cookie + description: > + Optional "name=value" entry indicating that the client had this cookie in the response. + + - name: captured_headers + description: > + List of headers captured in the response due to the presence of the "capture response header" statement in the frontend. + type: keyword + + - name: status_code + type: alias + path: http.response.status_code + migration: true + + - name: request + description: Fields related to the HTTP request + type: group + fields: + - name: captured_cookie + description: > + Optional "name=value" entry indicating that the server has returned a cookie with its request. + + - name: captured_headers + description: > + List of headers captured in the request due to the presence of the "capture request header" statement in the frontend. + type: keyword + + - name: raw_request_line + description: Complete HTTP request line, including the method, request and HTTP version string. + type: keyword + + - name: time_wait_without_data_ms + description: Total time in milliseconds spent waiting for the server to send a full HTTP response, not counting data. + type: long + + - name: time_wait_ms + description: Total time in milliseconds spent waiting for a full HTTP request from the client (not counting body) after the first byte was received. + type: long + + - name: tcp + description: TCP log format + type: group + fields: + - name: connection_waiting_time_ms + type: long + description: Total time in milliseconds elapsed between the accept and the last close +- key: icinga + title: "Icinga" + description: > + Icinga Module + fields: + - name: icinga + type: group + description: > + fields: + - name: debug + type: group + description: > + Contains fields for the Icinga debug logs. + fields: + - name: facility + type: keyword + description: > + Specifies what component of Icinga logged the message. + + - name: severity + type: alias + path: log.level + migration: true + - name: message + type: alias + path: message + migration: true + - name: main + type: group + description: > + Contains fields for the Icinga main logs. + fields: + - name: facility + type: keyword + description: > + Specifies what component of Icinga logged the message. + + - name: severity + type: alias + path: log.level + migration: true + - name: message + type: alias + path: message + migration: true + - name: startup + type: group + description: > + Contains fields for the Icinga startup logs. + fields: + - name: facility + type: keyword + description: > + Specifies what component of Icinga logged the message. + + - name: severity + type: alias + path: log.level + migration: true + - name: message + type: alias + path: message + migration: true +- key: iis + title: "IIS" + description: > + Module for parsing IIS log files. + fields: + - name: iis + type: group + description: > + Fields from IIS log files. + fields: + + - name: access + type: group + description: > + Contains fields for IIS access logs. + fields: + - name: sub_status + type: long + description: > + The HTTP substatus code. + - name: win32_status + type: long + description: > + The Windows status code. + - name: site_name + type: keyword + description: > + The site name and instance number. + - name: server_name + type: keyword + description: > + The name of the server on which the log file entry was generated. + - name: cookie + type: keyword + description: > + The content of the cookie sent or received, if any. + + - name: body_received.bytes + type: alias + path: http.request.body.bytes + migration: true + - name: body_sent.bytes + type: alias + path: http.response.body.bytes + migration: true + - name: server_ip + type: alias + path: destination.address + migration: true + - name: method + type: alias + path: http.request.method + migration: true + - name: url + type: alias + path: url.path + migration: true + - name: query_string + type: alias + path: url.query + migration: true + - name: port + type: alias + path: destination.port + migration: true + - name: user_name + type: alias + path: user.name + migration: true + - name: remote_ip + type: alias + path: source.address + migration: true + - name: referrer + type: alias + path: http.request.referrer + migration: true + - name: response_code + type: alias + path: http.response.status_code + migration: true + - name: http_version + type: alias + path: http.version + migration: true + - name: hostname + type: alias + path: host.hostname + migration: true + - name: user_agent + type: group + fields: + - name: device + type: alias + path: user_agent.device.name + migration: true + - name: name + type: alias + path: user_agent.name + migration: true + - name: os + type: alias + path: user_agent.os.full_name + migration: true + - name: os_name + type: alias + path: user_agent.os.name + migration: true + - name: original + type: alias + path: user_agent.original + migration: true + - name: geoip + type: group + fields: + - name: continent_name + type: alias + path: source.geo.continent_name + migration: true + - name: country_iso_code + type: alias + path: source.geo.country_iso_code + migration: true + - name: location + type: alias + path: source.geo.location + migration: true + - name: region_name + type: alias + path: source.geo.region_name + migration: true + - name: city_name + type: alias + path: source.geo.city_name + migration: true + - name: region_iso_code + type: alias + path: source.geo.region_iso_code + migration: true + - name: error + type: group + description: > + Contains fields for IIS error logs. + fields: + - name: reason_phrase + type: keyword + description: > + The HTTP reason phrase. + - name: queue_name + type: keyword + description: > + The IIS application pool name. + + - name: remote_ip + type: alias + path: source.address + migration: true + - name: remote_port + type: alias + path: source.port + migration: true + - name: server_ip + type: alias + path: destination.address + migration: true + - name: server_port + type: alias + path: destination.port + migration: true + - name: http_version + type: alias + path: http.version + migration: true + - name: method + type: alias + path: http.request.method + migration: true + - name: url + type: alias + path: url.original + migration: true + - name: response_code + type: alias + path: http.response.status_code + migration: true + - name: geoip + type: group + fields: + - name: continent_name + type: alias + path: source.geo.continent_name + migration: true + - name: country_iso_code + type: alias + path: source.geo.country_iso_code + migration: true + - name: location + type: alias + path: source.geo.location + migration: true + - name: region_name + type: alias + path: source.geo.region_name + migration: true + - name: city_name + type: alias + path: source.geo.city_name + migration: true + - name: region_iso_code + type: alias + path: source.geo.region_iso_code + migration: true +- key: kafka + title: "Kafka" + description: > + Kafka module + fields: + - name: kafka + type: group + description: > + fields: + - name: log + type: group + description: > + Kafka log lines. + fields: + - name: level + type: alias + path: log.level + migration: true + - name: message + type: alias + path: message + migration: true + + - name: component + type: keyword + description: > + Component the log is coming from. + - name: class + type: keyword + description: > + Java class the log is coming from. + - name: thread + type: keyword + description: > + Thread name the log is coming from. + - name: trace + type: group + description: > + Trace in the log line. + fields: + - name: class + type: keyword + description: > + Java class the trace is coming from. + - name: message + type: text + description: > + Message part of the trace. +- key: kibana + title: "kibana" + description: > + kibana Module + fields: + - name: kibana + type: group + description: > + Module for parsing Kibana logs. + fields: + - name: session_id + description: The ID of the user session associated with this event. Each login attempt results in a unique session id. + example: "123e4567-e89b-12d3-a456-426614174000" + type: keyword + - name: space_id + description: "The id of the space associated with this event." + example: "default" + type: keyword + - name: saved_object.type + description: "The type of the saved object associated with this event." + example: "dashboard" + type: keyword + - name: saved_object.id + description: "The id of the saved object associated with this event." + example: "6295bdd0-0a0e-11e7-825f-6748cda7d858" + type: keyword + - name: add_to_spaces + description: "The set of space ids that a saved object was shared to." + example: "['default', 'marketing']" + type: keyword + - name: delete_from_spaces + description: "The set of space ids that a saved object was removed from." + example: "['default', 'marketing']" + type: keyword + - name: authentication_provider + description: "The authentication provider associated with a login event." + example: "basic1" + type: keyword + - name: authentication_type + description: "The authentication provider type associated with a login event." + example: "basic" + type: keyword + - name: authentication_realm + description: "The Elasticsearch authentication realm name which fulfilled a login event." + example: "native" + type: keyword + - name: lookup_realm + description: "The Elasticsearch lookup realm which fulfilled a login event." + example: "native" + type: keyword + - name: log + type: group + description: > + Kafka log lines. + fields: + - name: tags + type: keyword + description: > + Kibana logging tags. + - name: state + type: keyword + description: > + Current state of Kibana. + - name: meta + type: object + object_type: keyword + + - name: kibana.log.meta.req.headers.referer + type: alias + path: http.request.referrer + migration: true + - name: kibana.log.meta.req.referer + type: alias + path: http.request.referrer + migration: true + - name: kibana.log.meta.req.headers.user-agent + type: alias + path: user_agent.original + migration: true + - name: kibana.log.meta.req.remoteAddress + type: alias + path: source.address + migration: true + - name: kibana.log.meta.req.url + type: alias + path: url.original + migration: true + - name: kibana.log.meta.statusCode + type: alias + path: http.response.status_code + migration: true + - name: kibana.log.meta.method + type: alias + path: http.request.method + migration: true +- key: logstash + title: "logstash" + description: > + logstash Module + fields: + - name: logstash + type: group + description: > + fields: + - name: log + title: "Logstash" + type: group + description: > + Fields from the Logstash logs. + fields: + - name: module + type: keyword + description: > + The module or class where the event originate. + - name: thread + type: keyword + description: > + Information about the running thread where the log originate. + multi_fields: + - name: text + type: text + - name: log_event + type: object + description: > + key and value debugging information. + - name: log_event.action + type: keyword + - name: pipeline_id + type: keyword + example: main + description: > + The ID of the pipeline. + + - name: message + type: alias + path: message + migration: true + - name: level + type: alias + path: log.level + migration: true + - name: slowlog + type: group + description: > + slowlog + fields: + - name: module + type: keyword + description: > + The module or class where the event originate. + - name: thread + type: keyword + description: > + Information about the running thread where the log originate. + multi_fields: + - name: text + type: text + - name: event + type: keyword + description: > + Raw dump of the original event + multi_fields: + - name: text + type: text + - name: plugin_name + type: keyword + description: > + Name of the plugin + - name: plugin_type + type: keyword + description: > + Type of the plugin: Inputs, Filters, Outputs or Codecs. + - name: took_in_millis + type: long + description: > + Execution time for the plugin in milliseconds. + - name: plugin_params + type: keyword + description: > + String value of the plugin configuration + multi_fields: + - name: text + type: text + - name: plugin_params_object + type: object + description: > + key -> value of the configuration used by the plugin. + - name: level + type: alias + path: log.level + migration: true + - name: took_in_nanos + type: alias + path: event.duration + migration: true +- key: mongodb + title: "mongodb" + description: > + Module for parsing MongoDB log files. + fields: + - name: mongodb + type: group + description: > + Fields from MongoDB logs. + fields: + - name: log + type: group + description: > + Contains fields from MongoDB logs. + fields: + - name: component + description: > + Functional categorization of message + example: COMMAND + type: keyword + - name: context + description: > + Context of message + example: initandlisten + type: keyword + + - name: severity + type: alias + path: log.level + migration: true + - name: message + type: alias + path: message + migration: true +- key: mysql + title: "MySQL" + description: > + Module for parsing the MySQL log files. + short_config: true + fields: + - name: mysql + type: group + description: > + Fields from the MySQL log files. + fields: + - name: thread_id + type: long + description: > + The connection or thread ID for the query. + - name: error + type: group + description: > + Contains fields from the MySQL error logs. + fields: + - name: thread_id + type: alias + path: mysql.thread_id + migration: true + - name: level + type: alias + path: log.level + migration: true + - name: message + type: alias + path: message + migration: true + - name: slowlog + type: group + description: > + Contains fields from the MySQL slow logs. + fields: + - name: lock_time.sec + type: float + description: > + The amount of time the query waited for the lock to be available. The + value is in seconds, as a floating point number. + - name: rows_sent + type: long + description: > + The number of rows returned by the query. + - name: rows_examined + type: long + description: > + The number of rows scanned by the query. + - name: rows_affected + type: long + description: > + The number of rows modified by the query. + - name: bytes_sent + type: long + format: bytes + description: > + The number of bytes sent to client. + - name: bytes_received + type: long + format: bytes + description: > + The number of bytes received from client. + - name: query + description: > + The slow query. + - name: id + type: alias + path: mysql.thread_id + migration: true + - name: schema + type: keyword + description: > + The schema where the slow query was executed. + - name: current_user + type: keyword + description: > + Current authenticated user, used to determine access privileges. Can differ from the value for user. + - name: last_errno + type: keyword + description: > + Last SQL error seen. + - name: killed + type: keyword + description: > + Code of the reason if the query was killed. + + - name: query_cache_hit + type: boolean + description: > + Whether the query cache was hit. + - name: tmp_table + type: boolean + description: > + Whether a temporary table was used to resolve the query. + - name: tmp_table_on_disk + type: boolean + description: > + Whether the query needed temporary tables on disk. + - name: tmp_tables + type: long + description: > + Number of temporary tables created for this query + - name: tmp_disk_tables + type: long + description: > + Number of temporary tables created on disk for this query. + - name: tmp_table_sizes + type: long + format: bytes + description: + Size of temporary tables created for this query. + - name: filesort + type: boolean + description: > + Whether filesort optimization was used. + - name: filesort_on_disk + type: boolean + description: > + Whether filesort optimization was used and it needed temporary tables on disk. + - name: priority_queue + type: boolean + description: > + Whether a priority queue was used for filesort. + - name: full_scan + type: boolean + description: > + Whether a full table scan was needed for the slow query. + - name: full_join + type: boolean + description: > + Whether a full join was needed for the slow query (no indexes were used for joins). + - name: merge_passes + type: long + description: > + Number of merge passes executed for the query. + - name: sort_merge_passes + type: long + description: > + Number of merge passes that the sort algorithm has had to do. + - name: sort_range_count + type: long + description: > + Number of sorts that were done using ranges. + - name: sort_rows + type: long + description: > + Number of sorted rows. + - name: sort_scan_count + type: long + description: > + Number of sorts that were done by scanning the table. + - name: log_slow_rate_type + type: keyword + description: > + Type of slow log rate limit, it can be `session` if the rate limit + is applied per session, or `query` if it applies per query. + - name: log_slow_rate_limit + type: keyword + description: > + Slow log rate limit, a value of 100 means that one in a hundred queries + or sessions are being logged. + - name: read_first + type: long + description: > + The number of times the first entry in an index was read. + - name: read_last + type: long + description: > + The number of times the last key in an index was read. + - name: read_key + type: long + description: > + The number of requests to read a row based on a key. + - name: read_next + type: long + description: > + The number of requests to read the next row in key order. + - name: read_prev + type: long + description: > + The number of requests to read the previous row in key order. + - name: read_rnd + type: long + description: > + The number of requests to read a row based on a fixed position. + - name: read_rnd_next + type: long + description: > + The number of requests to read the next row in the data file. + + # https://www.percona.com/doc/percona-server/5.7/diagnostics/slow_extended.html + - name: innodb + type: group + description: > + Contains fields relative to InnoDB engine + fields: + - name: trx_id + type: keyword + description: > + Transaction ID + - name: io_r_ops + type: long + description: > + Number of page read operations. + - name: io_r_bytes + type: long + format: bytes + description: > + Bytes read during page read operations. + - name: io_r_wait.sec + type: long + description: > + How long it took to read all needed data from storage. + - name: rec_lock_wait.sec + type: long + description: > + How long the query waited for locks. + - name: queue_wait.sec + type: long + description: > + How long the query waited to enter the InnoDB queue and to be executed once + in the queue. + - name: pages_distinct + type: long + description: > + Approximated count of pages accessed to execute the query. + + - name: user + type: alias + path: user.name + migration: true + - name: host + type: alias + path: source.domain + migration: true + - name: ip + type: alias + path: source.ip + migration: true + +- key: nats + title: "NATS" + description: > + Module for parsing NATS log files. + release: beta + fields: + - name: nats + type: group + description: > + Fields from NATS logs. + fields: + - name: log + type: group + description: > + Nats log files + release: beta + fields: + - name: client + type: group + description: > + Fields from NATS logs client. + fields: + - name: id + type: integer + description: > + The id of the client + - name: msg + type: group + description: > + Fields from NATS logs message. + fields: + - name: bytes + type: long + format: bytes + description: > + Size of the payload in bytes + - name: type + type: keyword + description: > + The protocol message type + - name: subject + type: keyword + description: > + Subject name this message was received on + - name: sid + type: integer + description: > + The unique alphanumeric subscription ID of the subject + - name: reply_to + type: keyword + description: > + The inbox subject on which the publisher is listening for responses + - name: max_messages + type: integer + description: > + An optional number of messages to wait for before automatically unsubscribing + - name: error.message + type: text + description: > + Details about the error occurred + - name: queue_group + type: text + description: > + The queue group which subscriber will join +- key: nginx + title: "Nginx" + description: > + Module for parsing the Nginx log files. + short_config: true + fields: + - name: nginx + type: group + description: > + Fields from the Nginx log files. + fields: + - name: access + type: group + description: > + Contains fields for the Nginx access logs. + fields: + - name: remote_ip_list + type: array + description: > + An array of remote IP addresses. It is a list because it is common to include, besides the client + IP address, IP addresses from headers like `X-Forwarded-For`. + Real source IP is restored to `source.ip`. + + - name: body_sent.bytes + type: alias + path: http.response.body.bytes + migration: true + - name: user_name + type: alias + path: user.name + migration: true + - name: method + type: alias + path: http.request.method + migration: true + - name: url + type: alias + path: url.original + migration: true + - name: http_version + type: alias + path: http.version + migration: true + - name: response_code + type: alias + path: http.response.status_code + migration: true + - name: referrer + type: alias + path: http.request.referrer + migration: true + - name: agent + type: alias + path: user_agent.original + migration: true + + - name: user_agent + type: group + fields: + - name: device + type: alias + path: user_agent.device.name + migration: true + - name: name + type: alias + path: user_agent.name + migration: true + - name: os + type: alias + path: user_agent.os.full_name + migration: true + - name: os_name + type: alias + path: user_agent.os.name + migration: true + - name: original + type: alias + path: user_agent.original + migration: true + + - name: geoip + type: group + fields: + - name: continent_name + type: alias + path: source.geo.continent_name + migration: true + - name: country_iso_code + type: alias + path: source.geo.country_iso_code + migration: true + - name: location + type: alias + path: source.geo.location + migration: true + - name: region_name + type: alias + path: source.geo.region_name + migration: true + - name: city_name + type: alias + path: source.geo.city_name + migration: true + - name: region_iso_code + type: alias + path: source.geo.region_iso_code + migration: true + - name: error + type: group + description: > + Contains fields for the Nginx error logs. + fields: + - name: connection_id + type: long + description: > + Connection identifier. + + - name: level + type: alias + path: log.level + migration: true + - name: pid + type: alias + path: process.pid + migration: true + - name: tid + type: alias + path: process.thread.id + migration: true + - name: message + type: alias + path: message + migration: true + - name: ingress_controller + type: group + description: > + Contains fields for the Ingress Nginx controller access logs. + fields: + - name: remote_ip_list + type: array + description: > + An array of remote IP addresses. It is a list because it is common to include, besides the client + IP address, IP addresses from headers like `X-Forwarded-For`. + Real source IP is restored to `source.ip`. + + # ingress-controller specific fields + - name: upstream_address_list + type: keyword + description: > + An array of the upstream addresses. It is a list because it is common that several upstream servers + were contacted during request processing. + - name: upstream.response.length_list + type: keyword + description: > + An array of upstream response lengths. It is a list because it is common that several upstream servers + were contacted during request processing. + - name: upstream.response.time_list + type: keyword + description: > + An array of upstream response durations. It is a list because it is common that several upstream servers + were contacted during request processing. + - name: upstream.response.status_code_list + type: keyword + description: > + An array of upstream response status codes. It is a list because it is common that several upstream servers + were contacted during request processing. + - name: http.request.length + type: long + format: bytes + description: > + The request length (including request line, header, and request body) + - name: http.request.time + type: double + format: duration + description: > + Time elapsed since the first bytes were read from the client + - name: upstream.name + type: keyword + description: > + The name of the upstream. + - name: upstream.alternative_name + type: keyword + description: > + The name of the alternative upstream. + - name: upstream.response.length + type: long + format: bytes + description: > + The length of the response obtained from the upstream server. If several servers were contacted during request process, + the summary of the multiple response lengths is stored. + - name: upstream.response.time + type: double + format: duration + description: > + The time spent on receiving the response from the upstream as seconds with millisecond resolution. + If several servers were contacted during request process, the summary of the multiple response times is stored. + - name: upstream.response.status_code + type: long + description: > + The status code of the response obtained from the upstream server. If several servers were contacted during + request process, only the status code of the response from the last one is stored in this field. + - name: upstream.ip + type: ip + description: > + The IP address of the upstream server. If several servers were contacted during request process, + only the last one is stored in this field. + - name: upstream.port + type: long + description: > + The port of the upstream server. If several servers were contacted during request process, + only the last one is stored in this field. + - name: http.request.id + type: keyword + description: > + The randomly generated ID of the request + + - name: body_sent.bytes + type: alias + path: http.response.body.bytes + migration: true + - name: user_name + type: alias + path: user.name + migration: true + - name: method + type: alias + path: http.request.method + migration: true + - name: url + type: alias + path: url.original + migration: true + - name: http_version + type: alias + path: http.version + migration: true + - name: response_code + type: alias + path: http.response.status_code + migration: true + - name: referrer + type: alias + path: http.request.referrer + migration: true + - name: agent + type: alias + path: user_agent.original + migration: true + + - name: user_agent + type: group + fields: + - name: device + type: alias + path: user_agent.device.name + migration: true + - name: name + type: alias + path: user_agent.name + migration: true + - name: os + type: alias + path: user_agent.os.full_name + migration: true + - name: os_name + type: alias + path: user_agent.os.name + migration: true + - name: original + type: alias + path: user_agent.original + migration: true + + - name: geoip + type: group + fields: + - name: continent_name + type: alias + path: source.geo.continent_name + migration: true + - name: country_iso_code + type: alias + path: source.geo.country_iso_code + migration: true + - name: location + type: alias + path: source.geo.location + migration: true + - name: region_name + type: alias + path: source.geo.region_name + migration: true + - name: city_name + type: alias + path: source.geo.city_name + migration: true + - name: region_iso_code + type: alias + path: source.geo.region_iso_code + migration: true +- key: osquery + title: "Osquery" + description: > + Fields exported by the `osquery` module + fields: + - name: osquery + type: group + description: > + fields: + - name: result + type: group + description: > + Common fields exported by the result metricset. + fields: + - name: name + type: keyword + description: > + The name of the query that generated this event. + - name: action + type: keyword + description: > + For incremental data, marks whether the entry was added + or removed. It can be one of "added", "removed", or "snapshot". + - name: host_identifier + type: keyword + description: > + The identifier for the host on which the osquery agent is running. + Normally the hostname. + - name: unix_time + type: long + description: > + Unix timestamp of the event, in seconds since the epoch. Used for computing the `@timestamp` column. + - name: calendar_time + type: keyword + description: > + String representation of the collection time, as formatted by osquery. +- key: pensando + title: Pensando + description: > + pensando Module + fields: + - name: pensando + type: group + description: > + Fields from Pensando logs. + fields: + - name: dfw + type: group + release: beta + default_field: false + description: > + Fields for Pensando DFW + fields: + - name: action + type: keyword + description: > + Action on the flow. + - name: app_id + type: integer + description: > + Application ID + - name: destination_address + type: keyword + description: > + Address of destination. + - name: destination_port + type: integer + description: > + Port of destination. + - name: direction + type: keyword + description: > + Direction of the flow + - name: protocol + type: keyword + description: > + Protocol of the flow + - name: rule_id + type: keyword + description: > + Rule ID that was matched. + - name: session_id + type: integer + description: > + Session ID of the flow + - name: session_state + type: keyword + description: > + Session state of the flow. + - name: source_address + type: keyword + description: > + Source address of the flow. + - name: source_port + type: integer + description: > + Source port of the flow. + - name: timestamp + type: date + description: > + Timestamp of the log. +- key: postgresql + title: "PostgreSQL" + description: > + Module for parsing the PostgreSQL log files. + short_config: true + fields: + - name: postgresql + type: group + description: > + Fields from PostgreSQL logs. + fields: + - name: log + type: group + description: > + Fields from the PostgreSQL log files. + fields: + - name: timestamp + deprecated: 7.3.0 + description: > + The timestamp from the log line. + - name: core_id + type: alias + path: postgresql.log.session_line_number + description: > + Core id. (deprecated, there is no core_id in PostgreSQL logs, this is actually session_line_number). + deprecated: 8.0.0 + - name: client_addr + example: "127.0.0.1" + description: > + Host where the connection originated from. + - name: client_port + example: "59700" + description: > + Port where the connection originated from. + - name: session_id + description: > + PostgreSQL session. + example: "5ff1dd98.22" + - name: session_line_number + type: long + description: > + Line number inside a session. (%l in `log_line_prefix`). + - name: database + example: "postgres" + description: > + Name of database. + - name: query + example: "SELECT * FROM users;" + description: > + Query statement. In the case of CSV parse, look at command_tag to get more context. + - name: query_step + example: "parse" + description: > + Statement step when using extended query protocol (one of statement, parse, bind or execute). + - name: query_name + example: "pdo_stmt_00000001" + description: > + Name given to a query when using extended query protocol. If it is "", or not present, + this field is ignored. + - name: command_tag + example: "SELECT" + description: > + Type of session's current command. + The complete list can be found at: src/include/tcop/cmdtaglist.h + - name: session_start_time + type: date + description: > + Time when this session started. + - name: virtual_transaction_id + description: > + Backend local transaction id. + - name: transaction_id + type: long + description: > + The id of current transaction. + - name: sql_state_code + # This code is not a number. + type: keyword + description: > + State code returned by Postgres (if any). + See also https://www.postgresql.org/docs/current/errcodes-appendix.html + - name: detail + description: > + More information about the message, parameters in case of a parametrized query. + e.g. 'Role \"user\" does not exist.', 'parameters: $1 = 42', etc. + - name: hint + description: > + A possible solution to solve an error. + - name: internal_query + description: > + Internal query that led to the error (if any). + - name: internal_query_pos + type: long + description: > + Character count of the internal query (if any). + - name: context + description: > + Error context. + - name: query_pos + type: long + description: > + Character count of the error position (if any). + - name: location + description: > + Location of the error in the PostgreSQL source code (if log_error_verbosity is set to verbose). + - name: application_name + description: > + Name of the application of this event. It is defined by the client. + - name: backend_type + example: "client backend" + description: > + Type of backend of this event. + Possible types are autovacuum launcher, autovacuum worker, logical replication launcher, + logical replication worker, parallel worker, background writer, client backend, checkpointer, + startup, walreceiver, walsender and walwriter. + In addition, background workers registered by extensions may have additional types. + + - name: error.code + type: alias + path: postgresql.log.sql_state_code + description: > + Error code returned by Postgres (if any). + Deprecated: errors can have letters. Use sql_state_code instead. + deprecated: 8.0.0 + + - name: timezone + type: alias + path: event.timezone + migration: true + - name: user + type: alias + path: user.name + migration: true + - name: level + type: alias + example: "LOG" + description: > + Valid values are DEBUG5, DEBUG4, DEBUG3, DEBUG2, DEBUG1, INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. + path: log.level + migration: true + - name: message + type: alias + path: message + migration: true +- key: redis + title: "Redis" + description: > + Redis Module + fields: + - name: redis + type: group + description: > + fields: + - name: log + type: group + description: > + Redis log files + fields: + - name: role + type: keyword + description: > + The role of the Redis instance. Can be one of `master`, `slave`, `child` (for RDF/AOF writing child), + or `sentinel`. + + - name: pid + type: alias + path: process.pid + migration: true + - name: level + type: alias + path: log.level + migration: true + - name: message + type: alias + path: message + migration: true + - name: slowlog + type: group + description: > + Slow logs are retrieved from Redis via a network connection. + fields: + - name: cmd + type: keyword + description: > + The command executed. + - name: duration.us + type: long + description: > + How long it took to execute the command in microseconds. + - name: id + type: long + description: > + The ID of the query. + - name: key + type: keyword + description: > + The key on which the command was executed. + - name: args + type: keyword + description: > + The arguments with which the command was called. +- key: santa + title: "Google Santa" + description: > + Santa Module + fields: + - name: santa + type: group + description: > + fields: + + - name: action + type: keyword + example: EXEC + description: Action + + - name: decision + type: keyword + example: ALLOW + description: Decision that santad took. + + - name: reason + type: keyword + example: CERT + description: Reason for the decsision. + + - name: mode + type: keyword + example: M + description: Operating mode of Santa. + + - name: disk + type: group + description: Fields for DISKAPPEAR actions. + fields: + - name: volume + description: The volume name. + + - name: bus + description: The disk bus protocol. + + - name: serial + description: The disk serial number. + + - name: bsdname + example: disk1s3 + description: The disk BSD name. + + - name: model + example: APPLE SSD SM0512L + description: The disk model. + + - name: fs + example: apfs + description: The disk volume kind (filesystem type). + + - name: mount + description: The disk volume path. + + - name: certificate.common_name + type: keyword + description: Common name from code signing certificate. + + - name: certificate.sha256 + type: keyword + description: SHA256 hash of code signing certificate. +- key: system + title: "System" + description: > + Module for parsing system log files. + short_config: true + fields: + - name: system + type: group + description: > + Fields from the system log files. + fields: + - name: auth + type: group + description: > + Fields from the Linux authorization logs. + fields: + - name: timestamp + type: alias + path: '@timestamp' + migration: true + - name: hostname + type: alias + path: host.hostname + migration: true + - name: program + type: alias + path: process.name + migration: true + - name: pid + type: alias + path: process.pid + migration: true + - name: message + type: alias + path: message + migration: true + - name: user + type: alias + path: user.name + migration: true + + - name: ssh + type: group + fields: + - name: method + description: > + The SSH authentication method. Can be one of "password" or "publickey". + - name: signature + description: > + The signature of the client public key. + - name: dropped_ip + type: ip + description: > + The client IP from SSH connections that are open and immediately dropped. + + - name: event + example: Accepted + description: > + The SSH event as found in the logs (Accepted, Invalid, Failed, etc.) + + - name: ip + type: alias + path: source.ip + migration: true + - name: port + type: alias + path: source.port + migration: true + + - name: geoip + type: group + fields: + - name: continent_name + type: alias + path: source.geo.continent_name + migration: true + - name: country_iso_code + type: alias + path: source.geo.country_iso_code + migration: true + - name: location + type: alias + path: source.geo.location + migration: true + - name: region_name + type: alias + path: source.geo.region_name + migration: true + - name: city_name + type: alias + path: source.geo.city_name + migration: true + - name: region_iso_code + type: alias + path: source.geo.region_iso_code + migration: true + + - name: sudo + type: group + description: > + Fields specific to events created by the `sudo` command. + fields: + - name: error + example: user NOT in sudoers + description: > + The error message in case the sudo command failed. + - name: tty + description: > + The TTY where the sudo command is executed. + - name: pwd + description: > + The current directory where the sudo command is executed. + - name: user + example: root + description: > + The target user to which the sudo command is switching. + - name: command + description: > + The command executed via sudo. + + - name: useradd + type: group + description: > + Fields specific to events created by the `useradd` command. + fields: + - name: home + description: + The home folder for the new user. + - name: shell + description: + The default shell for the new user. + + - name: name + type: alias + path: user.name + migration: true + - name: uid + type: alias + path: user.id + migration: true + - name: gid + type: alias + path: group.id + migration: true + + - name: groupadd + type: group + description: > + Fields specific to events created by the `groupadd` command. + fields: + - name: name + type: alias + path: group.name + migration: true + - name: gid + type: alias + path: group.id + migration: true + - name: syslog + type: group + description: > + Contains fields from the syslog system logs. + fields: + - name: timestamp + type: alias + path: '@timestamp' + migration: true + - name: hostname + type: alias + path: host.hostname + migration: true + - name: program + type: alias + path: process.name + migration: true + - name: pid + type: alias + path: process.pid + migration: true + - name: message + type: alias + path: message + migration: true +- key: traefik + title: "Traefik" + description: > + Module for parsing the Traefik log files. + fields: + - name: traefik + type: group + description: > + Fields from the Traefik log files. + fields: + - name: access + type: group + description: > + Contains fields for the Traefik access logs. + fields: + - name: user_identifier + type: keyword + description: > + Is the RFC 1413 identity of the client + - name: request_count + type: long + description: > + The number of requests + - name: frontend_name + type: keyword + description: > + The name of the frontend used + - name: backend_url + type: keyword + description: + The url of the backend where request is forwarded + + - name: body_sent.bytes + type: alias + path: http.response.body.bytes + migration: true + - name: remote_ip + type: alias + path: source.address + migration: true + - name: user_name + type: alias + path: user.name + migration: true + - name: method + type: alias + path: http.request.method + migration: true + - name: url + type: alias + path: url.original + migration: true + - name: http_version + type: alias + path: http.version + migration: true + - name: response_code + type: alias + path: http.response.status_code + migration: true + - name: referrer + type: alias + path: http.request.referrer + migration: true + - name: agent + type: alias + path: user_agent.original + migration: true + + - name: user_agent + type: group + fields: + - name: device + type: alias + path: user_agent.device.name + - name: name + type: alias + path: user_agent.name + - name: os + type: alias + path: user_agent.os.full_name + - name: os_name + type: alias + path: user_agent.os.name + - name: original + type: alias + path: user_agent.original + + - name: geoip + type: group + fields: + - name: continent_name + type: alias + path: source.geo.continent_name + - name: country_iso_code + type: alias + path: source.geo.country_iso_code + - name: location + type: alias + path: source.geo.location + - name: region_name + type: alias + path: source.geo.region_name + - name: city_name + type: alias + path: source.geo.city_name + - name: region_iso_code + type: alias + path: source.geo.region_iso_code + +- key: ptaf + title: "PTAF Nginx Access Logs" + description: "Fields for PTAF Nginx access logs" + fields: + - name: site + type: keyword + + - name: server + type: keyword + + - name: proxyed_to + type: keyword + + - name: upstream_status + type: integer + + - name: dest_port + type: integer + + - name: dest_ip + type: ip + + - name: src + type: ip + + - name: user + type: keyword + + - name: time_local + type: date # ← ТОЛЬКО type: date, БЕЗ format! + + - name: protocol + type: keyword + + - name: status + type: integer + + - name: bytes_out + type: long + + - name: bytes_in + type: long + + - name: http_referer + type: keyword + ignore_above: 2048 + + - name: http_user_agent + type: text + fields: + keyword: + type: keyword + ignore_above: 1024 + + - name: http_x_forwarded_for + type: ip + + - name: uri_query + type: keyword + ignore_above: 4096 + + - name: uri_path + type: keyword + + - name: http_method + type: keyword + + - name: response_time + type: float + + - name: cookie + type: text + index: false + + - name: request_time + type: float + + - name: http_content_type + type: keyword + + - name: log_type + type: keyword + + - name: service + type: keyword +... diff --git a/roles/filebeat_install/tasks/main.yml b/roles/filebeat_install/tasks/main.yml new file mode 100755 index 0000000..38c16b6 --- /dev/null +++ b/roles/filebeat_install/tasks/main.yml @@ -0,0 +1,46 @@ +--- +- name: Check if filebeat is installed + ansible.builtin.command: dpkg -s filebeat + register: filebeat_check + changed_when: false + failed_when: false + +- name: Install filebeat + ansible.builtin.apt: + # yamllint disable-line rule:line-length + deb: "" + when: filebeat_check.rc != 0 + +- name: Make backups + ansible.builtin.copy: + src: "/etc/filebeat/{{ item }}" + dest: "/etc/filebeat/{{ item | basename }}.bak" + remote_src: true + with_items: + - filebeat.yml + - fields.yml + ignore_errors: "{{ ansible_check_mode }}" + +- name: Add new filebeat conf + ansible.builtin.template: + src: templates/filebeat.yml.j2 + dest: /etc/filebeat/filebeat.yml + owner: root + group: root + mode: '0644' + +- name: Add new fields conf + ansible.builtin.template: + src: files/fields.yml + dest: /etc/filebeat/fields.yml + owner: root + group: root + mode: '0644' + +- name: Enable filebeat + ansible.builtin.service: + name: filebeat + state: restarted + enabled: true + ignore_errors: "{{ ansible_check_mode }}" +... diff --git a/roles/filebeat_install/templates/filebeat.yml.j2 b/roles/filebeat_install/templates/filebeat.yml.j2 new file mode 100755 index 0000000..e0ff1b1 --- /dev/null +++ b/roles/filebeat_install/templates/filebeat.yml.j2 @@ -0,0 +1,472 @@ +filebeat.inputs: + +- type: log + enabled: true + id: nginx-access + paths: + - /var/log/ptaf_nginx/*/*/*access.log + - /var/log/ptaf_nginx/*/*/*access.log.1 + json: + keys_under_root: true + overwrite_keys: true + add_error_key: true + fields: + log_type: access + fields_under_root: true + +- type: filestream + id: nginx-error + enabled: true + paths: + - /var/log/ptaf_nginx/*/*/*error.log + - /var/log/ptaf_nginx/*/*/*error.log.1 + fields: + log_type: "error" + fields_under_root: true + +- type: filestream + id: angie-error + enabled: true + paths: + - /var/log/angie/*error.log + - /var/log/angie/*error.log.1 + + fields: + log_type: "angie-error" + fields_under_root: true + +setup.ilm.enabled: false + +setup.template.enabled: false +setup.template.name: "ptaf" +setup.template.pattern: "ptaf-*" + +# Отключаем автоматическое создание индексов +setup.dashboards.enabled: false + +output.elasticsearch: + enabled: true +# Array of hosts to connect to. + hosts: ["https://10.10.10.23:9200", "https://10.10.10.24:9200"] + username: "vector" + password: {{ filebeat_install_filebeat_password }} +#Вывод в консоль +#output.console: + # codec.json: + # pretty: true + + #SSL configuration for HTTPS + ssl: + verification_mode: none # Отключаем проверку сертификата + +# Индексы для разных типов логов + indices: + - index: "ptaf-access-%{+yyyy.MM.dd}" + when: + equals: + log_type: "access" + + - index: "ptaf-error-%{+yyyy.MM.dd}" + when: + equals: + log_type: "error" + + - index: "ptaf-angie-error-%{+yyyy.MM.dd}" + when: + equals: + log_type: "angie-error" + +seccomp: + enabled: false + +processors: + - script: + lang: javascript + source: | + function process(event) { + // Обработка upstream_response_time + var responseTime = event.Get("upstream_response_time"); + if (responseTime && typeof responseTime === 'string') { + var values = responseTime.split(","); + if (values.length > 0) { + var lastValue = values[values.length - 1].trim(); + var numValue = parseFloat(lastValue); + if (!isNaN(numValue)) { + event.Put("upstream_response_time_digital", numValue); + } + } + } + + // Обработка upstream_status + var upstreamStatus = event.Get("upstream_status"); + if (upstreamStatus && typeof upstreamStatus === 'string') { + var statusValues = upstreamStatus.split(","); + if (statusValues.length > 0) { + var lastStatus = statusValues[statusValues.length - 1].trim(); + var intStatus = parseInt(lastStatus, 10); + if (!isNaN(intStatus)) { + event.Put("upstream_status_digital", intStatus); + } + } + } + + // Обработка upstream_response_length + var responseLength = event.Get("upstream_response_length"); + if (responseLength && typeof responseLength === 'string') { + var lengthValues = responseLength.split(","); + if (lengthValues.length > 0) { + var lastLength = lengthValues[lengthValues.length - 1].trim(); + var intLength = parseInt(lastLength, 10); + if (!isNaN(intLength)) { + event.Put("upstream_response_length_digital", intLength); + } + } + } + + // Обработка upstream_bytes_sent (ДОБАВЛЕНО) + var bytesSent = event.Get("upstream_bytes_sent"); + if (bytesSent && typeof bytesSent === 'string') { + var bytesValues = bytesSent.split(","); + if (bytesValues.length > 0) { + var lastBytes = bytesValues[bytesValues.length - 1].trim(); + var intBytes = parseInt(lastBytes, 10); + if (!isNaN(intBytes)) { + event.Put("upstream_bytes_sent_digital", intBytes); + } + } + } + } + - drop_fields: + fields: ["agent","ecs.version","log.offset","input.type","type"] + ignore_missing: true + + + - dissect: + tokenizer: "/var/log/ptaf_nginx/%{TENANT}/%{}" + field: "log.file.path" + target_prefix: "" + + - rename: + fields: + - from: "host.name" + to: "node_name" + ignore_missing: true + fail_on_error: false + +# Процессор для составной переменной agent_name + + - script: + lang: javascript + source: | + function process(event) { + var tenant = event.Get("TENANT"); + var nodeName = event.Get("node_name"); + var logPath = event.Get("log.file.path"); + + if (!tenant || !nodeName || !logPath) return; + + // Извлекаем AZ часть + var azMatch = nodeName.match(/(AZ\d+)/); + var azPart = azMatch ? azMatch[1] : "AZ0"; + + // Извлекаем имя хоста (последняя часть после дефиса) + var parts = nodeName.split('-'); + var nodePart = parts[parts.length - 1]; + + // Извлекаем agent (ищем "ptaf-agent001") + var agentName = "agent000"; + var agentMatch = logPath.match(/ptaf-(agent\d+)/); + if (agentMatch) { + agentName = agentMatch[1]; + } + + // Преобразуем nodePart: test01 → t01 + var shortNodePart = "t00"; + if (nodePart) { + // Ищем первую букву и цифры + var nodeMatch = nodePart.match(/^([a-zA-Z])[a-zA-Z]*(\d+)$/); + if (nodeMatch) { + var letter = nodeMatch[1]; // первая буква + var digits = nodeMatch[2]; // цифры + shortNodePart = letter.toLowerCase() + digits; + } else { + // Если не нашли буквы, берем только цифры + var digitsOnly = nodePart.match(/(\d+)/); + if (digitsOnly) { + shortNodePart = "t" + digitsOnly[1]; + } + } + } + + // Преобразуем agentName: agent001 → a001 + var shortAgentName = "a000"; + if (agentName) { + // Ищем первую букву и цифры + var agentMatch = agentName.match(/^([a-zA-Z])[a-zA-Z]*(\d+)$/); + if (agentMatch) { + var letter = agentMatch[1]; // первая буква + var digits = agentMatch[2]; // цифры + shortAgentName = letter.toLowerCase() + digits; + } else { + // Если не нашли буквы, берем только цифры + var digitsOnly = agentName.match(/(\d+)/); + if (digitsOnly) { + shortAgentName = "a" + digitsOnly[1]; + } + } + } + + // Создаем composite_id в новом формате + event.Put("agent_name", tenant + "_" + azPart + "_" + shortNodePart + "_" + shortAgentName); + } + ignore_failure: true + +# Процессор для nginx-error: парсинг timestamp из сообщения + - dissect: + tokenizer: "%{error_timestamp} [%{log_level}] %{rest}" + field: "message" + target_prefix: "" + ignore_failure: true + when: + equals: + log_type: "error" + + # Преобразование timestamp для nginx-error + - timestamp: + field: "error_timestamp" + layouts: + - "2006-01-02 15:04:05.000" + timezone: "Europe/Moscow" + target_field: "@timestamp" + ignore_failure: true + when: + equals: + log_type: "error" + # Удаление временных полей для nginx-error + - drop_fields: + fields: ["error_timestamp", "log_level", "rest"] + ignore_missing: true + when: + equals: + log_type: "error" + + - drop_fields: + fields: ["agent","ecs.version","log.offset","input.type","type"] + ignore_missing: true + + + - dissect: + field: "log.file.path" + tokenizer: '/var/log/angie/%{extracted_sid}_%{rest}' + target_prefix: "" + overwrite_keys: false # Не перезаписывать существующие поля + ignore_failure: true + + # 2. Копируем extracted_sid в SID, если SID не существует + - script: + lang: javascript + source: | + function process(event) { + var extractedSid = event.Get("extracted_sid"); + var existingSid = event.Get("SID"); + + // Если SID уже существует, оставляем его + if (existingSid !== null && existingSid !== undefined && existingSid !== "") { + // Удаляем временное поле extracted_sid + event.Delete("extracted_sid"); + return; + } + + // Если извлекли SID из пути и SID еще не существует + if (extractedSid && !existingSid) { + event.Put("SID", extractedSid); + // Удаляем временное поле + event.Delete("extracted_sid"); + } + } + ignore_failure: true + + # 3. Удаляем временное поле rest + - drop_fields: + fields: ["rest"] + ignore_missing: true +# Процессор для angie-error: парсинг timestamp из сообщения + + # 1. Первичный разбор error-лога с помощью dissect + - dissect: + when: + and: + - equals: + log_type: "angie-error" + - contains: + message: "client:" + field: "message" + tokenizer: '%{error_date} %{error_time} [%{error_level}] %{pid_worker}: *%{connection_id} %{rest}' + target_prefix: "error" + overwrite_keys: true + ignore_failure: true + # 2. Расширенная обработка оставшейся части в script + - script: + when: + and: + - equals: + log_type: "angie-error" + - has_fields: ['error.rest'] + lang: javascript + source: | + function process(event) { + var rest = event.Get("error.rest"); + if (!rest) return; + + // Разделяем текст ошибки и дополнительные поля + // Ищем первое вхождение ", client:" чтобы отделить текст ошибки + var clientIndex = rest.indexOf(", client:"); + if (clientIndex === -1) { + // Если нет client:, значит это простое сообщение + event.Put("error.message_text", rest); + return; + } + + // Извлекаем текст ошибки (все до ", client:") + var errorMessage = rest.substring(0, clientIndex); + event.Put("error.message_text", errorMessage.trim()); + + // Извлекаем ключ-значение пары + var kvString = rest.substring(clientIndex + 2); // +2 чтобы пропустить ", " + + // Разбираем пары ключ:значение + parseKeyValuePairs(kvString, event); + + // Дополнительно разбираем PID#worker + var pidWorker = event.Get("error.pid_worker"); + if (pidWorker && pidWorker.includes("#")) { + var parts = pidWorker.split("#"); + event.Put("error.pid", parts[0]); + event.Put("error.worker", parts[1]); + } + } + + // Функция для разбора строки с key:value парами + function parseKeyValuePairs(kvString, event) { + var regex = /(\w+):\s*(?:"([^"]*)"|([^,]*))/g; + var match; + var fields = {}; + + while ((match = regex.exec(kvString)) !== null) { + var key = match[1]; + var value = match[2] || match[3]; + + // Очищаем значение от лишних пробелов + if (value) { + value = value.trim(); + } + + // Сохраняем поле с соответствующим префиксом + var fieldName = "error." + key; + event.Put(fieldName, value); + } + } + ignore_failure: true + + # 3. Для notice логов (без полей client, server и т.д.) + - dissect: + when: + and: + - equals: + log_type: "angie-error" + - not: + contains: + message: "client:" + field: "message" + tokenizer: '%{error_date} %{error_time} [%{error_level}] %{pid_worker}: %{error_message}' + target_prefix: "error" + overwrite_keys: true + ignore_failure: true + + # 4. Создание единого поля datetime + - script: + when: + equals: + log_type: "angie-error" + lang: javascript + source: | + function process(event) { + var date = event.Get("error.error_date"); + var time = event.Get("error.error_time"); + + if (date && time) { + // Преобразуем дату из 2026/01/29 в 2026-01-29 + var isoDate = date.replace(/\//g, "-"); + // Создаем строку в формате ISO 8601 + var dateTime = isoDate + "T" + time; + event.Put("error.datetime", dateTime); + } + } + ignore_failure: true + + # 5. Установка timestamp из лога + - timestamp: + when: + equals: + log_type: "angie-error" + field: "error.datetime" + layouts: + - "2006-01-02T15:04:05" + timezone: "Europe/Moscow" + ignore_failure: true + + # 6. Дополнительная обработка специальных полей + - script: + when: + and: + - equals: + log_type: "angie-error" + - has_fields: ['error.request'] + lang: javascript + source: | + function process(event) { + // Разбираем поле request на метод, путь и версию + var request = event.Get("error.request"); + if (request) { + var parts = request.split(" "); + if (parts.length >= 3) { + event.Put("error.http_method", parts[0]); + event.Put("error.http_path", parts[1]); + event.Put("error.http_version", parts[2].replace("HTTP/", "")); + } + } + + // Разбираем upstream URL + var upstream = event.Get("error.upstream"); + if (upstream && upstream.startsWith("http")) { + try { + var url = upstream.match(/^(\w+):\/\/([^:/]+)(?::(\d+))?(\/.*)?$/); + if (url) { + event.Put("error.upstream_protocol", url[1]); + event.Put("error.upstream_host", url[2]); + event.Put("error.upstream_port", url[3] || "80"); + event.Put("error.upstream_path", url[4] || "/"); + } + } catch(e) { + // Игнорируем ошибки парсинга + } + } + } + ignore_failure: true + + # 7. Удаление промежуточных полей + - drop_fields: + when: + equals: + log_type: "angie-error" + fields: [ + "error_date", "error_time", "error.error_date", "error.error_time", + "error.datetime", "error.rest", "error.pid_worker", + "error.request", "error.message", "tags" + ] + ignore_missing: true + # Общий drop_fields для всех логов + - drop_fields: + fields: ["agent","ecs.version","log.offset","input.type","type","log.flags"] + ignore_missing: true +... diff --git a/roles/fluent_bit_install/README.md b/roles/fluent_bit_install/README.md new file mode 100644 index 0000000..8d4ea3e --- /dev/null +++ b/roles/fluent_bit_install/README.md @@ -0,0 +1 @@ +# Роль для установки и настройке Fluent-bit для отгрузки логов PT AF заказчикам diff --git a/roles/fluent_bit_install/files/fluent-bit.conf b/roles/fluent_bit_install/files/fluent-bit.conf new file mode 100755 index 0000000..fd377ed --- /dev/null +++ b/roles/fluent_bit_install/files/fluent-bit.conf @@ -0,0 +1,6 @@ +[SERVICE] + flush 1 + storage.path /var/log/flb-storage/ + parsers_file parsers.conf + plugins_file plugins.conf +@INCLUDE ptaf-*.conf diff --git a/roles/fluent_bit_install/files/test.conf b/roles/fluent_bit_install/files/test.conf new file mode 100644 index 0000000..bca2a91 --- /dev/null +++ b/roles/fluent_bit_install/files/test.conf @@ -0,0 +1,31 @@ +[INPUT] + Name syslog + Tag test + Parser syslog-rfc5424 + Mode tcp + Listen 172.17.0.1 + Port 5141 + Buffer_Max_Size 128KB + Buffer_Chunk_Size 15MB + storage.type filesystem + +[OUTPUT] + Name syslog + syslog_format rfc5424 + Match test + host 10.8.0.24 + port 5684 + mode tcp + tls on + tls.verify off + tls.debug 1 + syslog_severity_preset 6 + syslog_facility_preset 16 + syslog_hostname_key host + syslog_appname_key ident + syslog_procid_key pid + syslog_msgid_key msgid + syslog_message_key message + storage.total_limit_size 3000MB + Retry_Limit False + syslog_maxsize 51200 \ No newline at end of file diff --git a/roles/fluent_bit_install/tasks/main.yml b/roles/fluent_bit_install/tasks/main.yml new file mode 100755 index 0000000..bece773 --- /dev/null +++ b/roles/fluent_bit_install/tasks/main.yml @@ -0,0 +1,34 @@ +--- +- name: Check if fluent-bit is installed + ansible.builtin.command: dpkg -l fluent-bit + register: fluent_bit_check + ignore_errors: true + changed_when: false + +- name: Fluent-bit install + ansible.builtin.shell: "curl https://raw.githubusercontent.com/fluent/fluent-bit/master/install.sh | sh" + when: fluent_bit_check.rc != 0 + +- name: Copy fluent-bit conf + ansible.builtin.copy: + src: files/fluent-bit.conf + dest: /etc/fluent-bit/fluent-bit.conf + owner: root + group: root + mode: '0644' + +- name: Copy input output conf + ansible.builtin.template: + src: "{{ item }}" + dest: /etc/fluent-bit/ + owner: root + group: root + mode: '0644' + loop: "{{ lookup('fileglob', 'files/ptaf-*', wantlist=True) }}" + +- name: Ensure fluent-bit service is running and enabled + ansible.builtin.service: + name: fluent-bit + state: restarted + enabled: true +... diff --git a/roles/grafana_gen/defaults/main.yml b/roles/grafana_gen/defaults/main.yml new file mode 100644 index 0000000..8be7918 --- /dev/null +++ b/roles/grafana_gen/defaults/main.yml @@ -0,0 +1,3 @@ +--- +grafana_gen_bin: "/usr/local/bin/grafana_gen" +... diff --git a/roles/grafana_gen/files/grafana_gen_off.sh b/roles/grafana_gen/files/grafana_gen_off.sh new file mode 100644 index 0000000..3263b57 --- /dev/null +++ b/roles/grafana_gen/files/grafana_gen_off.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для комментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/10 * * * * /usr/local/bin/grafana_gen" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в незакомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка найдена и не закомментирована - комментируем её + echo "$CURRENT_CRON" | sed "s|^\(${ESCAPED_LINE}\)|#\1|" | crontab - + echo "Строка закомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка уже закомментирована + echo "Строка уже закомментирована, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/grafana_gen/files/grafana_gen_on.sh b/roles/grafana_gen/files/grafana_gen_on.sh new file mode 100644 index 0000000..462aca3 --- /dev/null +++ b/roles/grafana_gen/files/grafana_gen_on.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для раскомментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/10 * * * * /usr/local/bin/grafana_gen" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в закомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка найдена и закомментирована - раскомментируем её + echo "$CURRENT_CRON" | sed "s|^#\(${ESCAPED_LINE}\)|\1|" | crontab - + echo "Строка раскомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка уже раскомментирована + echo "Строка уже активна, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/grafana_gen/tasks/main.yml b/roles/grafana_gen/tasks/main.yml new file mode 100644 index 0000000..b98e59c --- /dev/null +++ b/roles/grafana_gen/tasks/main.yml @@ -0,0 +1,51 @@ +--- +- name: Copy grafana gen from cloud + ansible.builtin.get_url: + url: "" + dest: "{{ grafana_gen_bin }}" + owner: root + group: root + mode: '0744' + timeout: 60 + force: true + retries: 3 + delay: 10 + register: download_result + +- name: Copy grafana gen on and off scripts + ansible.builtin.copy: + src: "{{ item }}" + dest: /usr/local/bin/ + owner: root + group: root + mode: '0744' + loop: "{{ lookup('fileglob', 'files/*.sh', wantlist=True) }}" + +- name: Create cron task for update + ansible.builtin.cron: + name: "Run grafana_gen every 10 minutes" + minute: "*/10" + hour: "*" + day: "*" + month: "*" + weekday: "*" + job: "{{ grafana_gen_bin }}" + user: root + when: download_result.changed + +- name: Create directory /etc/grafana_gen + ansible.builtin.file: + path: /etc/grafana_gen + state: directory + owner: root + group: root + mode: '0755' + +- name: Create .env + ansible.builtin.template: + src: grafana_gen.env.j2 + dest: /etc/grafana_gen/grafana_gen.env + owner: root + group: root + mode: '0600' +... diff --git a/roles/grafana_gen/templates/grafana_gen.env.j2 b/roles/grafana_gen/templates/grafana_gen.env.j2 new file mode 100644 index 0000000..ed1160f --- /dev/null +++ b/roles/grafana_gen/templates/grafana_gen.env.j2 @@ -0,0 +1,7 @@ +DB_USER={{ db_user }} +DB_PASSWORD={{ db_password }} +GIT_TOKEN={{ git_token }} +GRAFANA_API_KEY={{ grafana_api_token }} +GRAFANA_URL=https://metrics.cloudstack.ru +GRAFANA_FOLDER=WAF - PTAF +DASHBOARD_TITLE=PT AF Requests \ No newline at end of file diff --git a/roles/logrotate_run_now/tasks/main.yml b/roles/logrotate_run_now/tasks/main.yml new file mode 100644 index 0000000..f53d197 --- /dev/null +++ b/roles/logrotate_run_now/tasks/main.yml @@ -0,0 +1,4 @@ +--- +- name: Logrotate run + ansible.builtin.command: "logrotate -f /etc/logrotate.conf" +... diff --git a/roles/logrotate_settings/files/logrotate.timer b/roles/logrotate_settings/files/logrotate.timer new file mode 100755 index 0000000..31d4599 --- /dev/null +++ b/roles/logrotate_settings/files/logrotate.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Daily rotation of log files +Documentation=man:logrotate(8) man:logrotate.conf(5) + +[Timer] +OnCalendar=*:0/10 +AccuracySec=1m +Persistent=true + +[Install] +WantedBy=timers.target \ No newline at end of file diff --git a/roles/logrotate_settings/files/logrotate_angie b/roles/logrotate_settings/files/logrotate_angie new file mode 100755 index 0000000..292d40f --- /dev/null +++ b/roles/logrotate_settings/files/logrotate_angie @@ -0,0 +1,15 @@ +/var/log/angie/*.log { + hourly + missingok + rotate 2 + compress + maxage 15 + notifempty + create 644 angie angie + sharedscripts + postrotate + if [ -f /run/angie.pid ]; then + kill -HUP $(cat /run/angie.pid) + fi + endscript +} \ No newline at end of file diff --git a/roles/logrotate_settings/files/logrotate_ptaf b/roles/logrotate_settings/files/logrotate_ptaf new file mode 100644 index 0000000..aba0465 --- /dev/null +++ b/roles/logrotate_settings/files/logrotate_ptaf @@ -0,0 +1,20 @@ +/var/log/ptaf_nginx/*/*/*.log { + daily + maxsize 200M + missingok + rotate 3 + maxage 15 + compress + notifempty + create 777 root root + su root root + sharedscripts + postrotate + CONTAINER_IDS=$(docker ps --filter "status=running" --filter "name=ptaf*" --format='{{.ID}}') + for CONTAINER_ID in $CONTAINER_IDS; do + docker exec "$CONTAINER_ID" /opt/ptaf/bin/ptaf-nginx -s reopen + done + + find /var/log/ptaf_nginx -type f -name "*.log" -size 0 -mmin +60 -delete 2>/dev/null || true + endscript +} \ No newline at end of file diff --git a/roles/logrotate_settings/files/logrotate_solidwall b/roles/logrotate_settings/files/logrotate_solidwall new file mode 100644 index 0000000..532f930 --- /dev/null +++ b/roles/logrotate_settings/files/logrotate_solidwall @@ -0,0 +1,15 @@ +/var/log/solidwall/*.log { + daily + maxsize 200M + missingok + rotate 3 + maxage 15 + compress + notifempty + create 777 root adm + su root adm + sharedscripts + postrotate + systemctl reload solidwall-nginx > /dev/null 2>&1 || true + endscript +} \ No newline at end of file diff --git a/roles/logrotate_settings/files/logrotate_syslog b/roles/logrotate_settings/files/logrotate_syslog new file mode 100755 index 0000000..eabca70 --- /dev/null +++ b/roles/logrotate_settings/files/logrotate_syslog @@ -0,0 +1,26 @@ +/var/log/syslog +/var/log/mail.info +/var/log/mail.warn +/var/log/mail.err +/var/log/mail.log +/var/log/daemon.log +/var/log/kern.log +/var/log/auth.log +/var/log/user.log +/var/log/lpr.log +/var/log/cron.log +/var/log/debug +/var/log/messages +{ + rotate 2 + daily + maxsize 1G + missingok + notifempty + compress + su root root + sharedscripts + postrotate + /usr/lib/rsyslog/rsyslog-rotate + endscript +} \ No newline at end of file diff --git a/roles/logrotate_settings/tasks/main.yml b/roles/logrotate_settings/tasks/main.yml new file mode 100755 index 0000000..299f1e0 --- /dev/null +++ b/roles/logrotate_settings/tasks/main.yml @@ -0,0 +1,64 @@ +--- +- name: Check logrotate dir + ansible.builtin.file: + path: /etc/logrotate.d/ + mode: '0644' + owner: root + group: root + +- name: Logrotate angie settings + ansible.builtin.copy: + src: logrotate_angie + dest: /etc/logrotate.d/angie + mode: '0644' + owner: root + group: root + when: inventory_hostname is match("^PTAF") + ignore_errors: "{{ ansible_check_mode }}" + +- name: Logrotate syslog settings + ansible.builtin.copy: + src: files/logrotate_syslog + dest: /etc/logrotate.d/rsyslog + mode: '0644' + owner: root + group: root + ignore_errors: "{{ ansible_check_mode }}" + +- name: Logrotate PT AF settings + ansible.builtin.copy: + src: files/logrotate_ptaf + dest: /etc/logrotate.d/ptaf + mode: '0644' + owner: root + group: root + when: inventory_hostname is match("^PTAF") + ignore_errors: "{{ ansible_check_mode }}" + +- name: Logrotate SolidWall settings + ansible.builtin.copy: + src: files/logrotate_solidwall + dest: /etc/logrotate.d/solidwall + mode: '0644' + owner: root + group: root + when: inventory_hostname is match("^ce-swall") + ignore_errors: "{{ ansible_check_mode }}" + +- name: Logrotate timer + ansible.builtin.copy: + src: files/logrotate.timer + dest: /lib/systemd/system/logrotate.timer + mode: '0644' + owner: root + group: root + ignore_errors: "{{ ansible_check_mode }}" + +- name: Start and enable logrotate timer + ansible.builtin.systemd: + name: logrotate.timer + enabled: true + state: started + daemon_reload: true + ignore_errors: "{{ ansible_check_mode }}" +... diff --git a/roles/magos/README.md b/roles/magos/README.md new file mode 100644 index 0000000..73dcb7b --- /dev/null +++ b/roles/magos/README.md @@ -0,0 +1,4 @@ +# Роль magos + +Роль раскатывает на хосты с docker PT AF утилиту magos, которая запускается каждые пять минут по крону и ходит в БД и API ServicePipe и актуализирует данные по upstream, weight и server_name. +Логи выполненных операций пишутся в файл и каждые день отправляются в git. Конфиги Angie и PT AF Nginx также отправляются в git. diff --git a/roles/magos/defaults/main.yml b/roles/magos/defaults/main.yml new file mode 100644 index 0000000..819c854 --- /dev/null +++ b/roles/magos/defaults/main.yml @@ -0,0 +1,7 @@ +--- +magos_upload_logs_script_path: "/usr/local/bin/upload_logs.sh" +magos_upload_configs_script_path: "/usr/local/bin/upload_configs.sh" +magos_metrics_script_path: "/usr/local/bin/magos_metrics.sh" +magos_log_dir: "/var/log/update_apps_configs_logs" +magos_log_file: "/var/log/update_apps_configs_logs/update_apps_configs.log" +... diff --git a/roles/magos/files/magos_off.sh b/roles/magos/files/magos_off.sh new file mode 100644 index 0000000..88f251b --- /dev/null +++ b/roles/magos/files/magos_off.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для комментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/5 * * * * /usr/local/bin/magos_metrics.sh" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в незакомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка найдена и не закомментирована - комментируем её + echo "$CURRENT_CRON" | sed "s|^\(${ESCAPED_LINE}\)|#\1|" | crontab - + echo "Строка закомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка уже закомментирована + echo "Строка уже закомментирована, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/magos/files/magos_on.sh b/roles/magos/files/magos_on.sh new file mode 100644 index 0000000..32f46da --- /dev/null +++ b/roles/magos/files/magos_on.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Скрипт для раскомментирования строки в root crontab + +# Строка, которую нужно найти (без комментария) +TARGET_LINE="*/5 * * * * /usr/local/bin/magos_metrics.sh" + +# Проверяем, запущен ли скрипт от root +if [ "$EUID" -ne 0 ]; then + echo "Ошибка: скрипт должен быть запущен от имени root" + exit 1 +fi + +# Получаем текущий crontab +CURRENT_CRON=$(crontab -l 2>/dev/null) + +# Экранируем специальные символы для использования в regex +ESCAPED_LINE=$(echo "$TARGET_LINE" | sed 's/[.*[\^$]/\\&/g') + +# Проверяем, существует ли строка в закомментированном виде +if echo "$CURRENT_CRON" | grep -qE "^#${ESCAPED_LINE}"; then + # Строка найдена и закомментирована - раскомментируем её + echo "$CURRENT_CRON" | sed "s|^#\(${ESCAPED_LINE}\)|\1|" | crontab - + echo "Строка раскомментирована успешно" + exit 0 +elif echo "$CURRENT_CRON" | grep -qE "^${ESCAPED_LINE}"; then + # Строка уже раскомментирована + echo "Строка уже активна, ничего не делаем" + exit 0 +else + # Строка не найдена вообще + echo "Предупреждение: строка не найдена в crontab" + exit 2 +fi \ No newline at end of file diff --git a/roles/magos/tasks/main.yml b/roles/magos/tasks/main.yml new file mode 100644 index 0000000..bd5966a --- /dev/null +++ b/roles/magos/tasks/main.yml @@ -0,0 +1,90 @@ +--- +- name: Tuning core + ansible.builtin.include_tasks: tuning_core.yml + +- name: Create directoies + ansible.builtin.file: + path: /var/log/{{ item }} + state: directory + owner: root + group: root + mode: '0755' + loop: + - update_apps_configs_logs + - ptaf_configs + +- name: DNS conf + ansible.builtin.include_role: + name: dns_settings + +- name: Copy certs + ansible.builtin.include_role: + name: certs_settings + +- name: Logrotate settings + ansible.builtin.include_role: + name: logrotate_settings + +- name: Node_exporter install + ansible.builtin.include_role: + name: node_exporter_install + +- name: Copy magos from cloud + ansible.builtin.include_role: + name: update_magos + register: magos_download_result + +- name: Copy upload log script to host + ansible.builtin.template: + src: templates/upload_logs.sh.j2 + dest: "{{ magos_upload_logs_script_path }}" + owner: root + group: root + mode: '0744' + +- name: Copy upload configs script to host + ansible.builtin.template: + src: templates/upload_configs.sh.j2 + dest: "{{ magos_upload_configs_script_path }}" + owner: root + group: root + mode: '0744' + +- name: Copy magos metrics script to host + ansible.builtin.template: + src: templates/magos_metrics.sh.j2 + dest: "{{ magos_metrics_script_path }}" + owner: root + group: root + mode: '0744' + +- name: Start soft + ansible.builtin.shell: "{{ magos_metrics_script_path }}" + when: magos_download_result.changed + ignore_errors: true + +- name: Create cron task for update + ansible.builtin.cron: + name: "Run update_apps_configs every 5 minutes" + minute: "*/5" + hour: "*" + day: "*" + month: "*" + weekday: "*" + job: "{{ magos_metrics_script_path }}" + user: root + +- name: Copy magos on and off scripts + ansible.builtin.copy: + src: "{{ item }}" + dest: /usr/local/bin/ + owner: root + group: root + mode: '0744' + loop: "{{ lookup('fileglob', 'files/*.sh', wantlist=True) }}" + +- name: Auspex install + ansible.builtin.include_role: + name: auspex + ignore_errors: true +... diff --git a/roles/magos/tasks/tuning_core.yml b/roles/magos/tasks/tuning_core.yml new file mode 100755 index 0000000..719303a --- /dev/null +++ b/roles/magos/tasks/tuning_core.yml @@ -0,0 +1,19 @@ +--- +- name: Backup sysctl + ansible.builtin.copy: + src: /etc/sysctl.conf + dest: /etc/sysctl.conf.backup + remote_src: true + +- name: Load conntrack module + ansible.builtin.modprobe: + name: nf_conntrack + state: present + +- name: Tuning core + ansible.builtin.sysctl: + name: "{{ item.key }}" + value: "{{ item.value }}" + loop: "{{ sysctl_params | dict2items }}" + notify: Reload sysctl +... diff --git a/roles/magos/templates/magos_metrics.sh.j2 b/roles/magos/templates/magos_metrics.sh.j2 new file mode 100644 index 0000000..abcc93c --- /dev/null +++ b/roles/magos/templates/magos_metrics.sh.j2 @@ -0,0 +1,60 @@ +#!/bin/bash + +# Конфигурация +METRIC_FILE="/var/lib/node_exporter/textfile_collector/cron_magos.prom" +TIMEOUT_SECONDS=120 # 2 минуты максимум на выполнение +mkdir -p "$(dirname ${METRIC_FILE})" + +# Закрываем stdin чтобы скрипты не ждали ввода +exec > /var/log/cron_monitor_errors.log + return 1 + elif [ ${exit_code} -ne 0 ]; then + echo "[$(date)] ERROR: ${description} failed with exit code ${exit_code}" >> /var/log/cron_monitor_errors.log + return 1 + fi + + return 0 +} + +# Выполняем команды последовательно +if safe_run "{{ magos_bin }} > {{ magos_log_file }} 2>&1" "magos"; then + if safe_run "{{ magos_upload_logs_script_path }}" "upload_logs.sh"; then + if safe_run "{{ magos_upload_configs_script_path }}" "upload_configs.sh"; then + STATUS=1 + fi + fi +fi + +DURATION=$(($(date +%s) - START)) + +# Записываем метрики +cat > "${METRIC_FILE}" << EOF +# HELP cron_magos_status Cron job execution status (1=success, 0=failure) +# TYPE cron_magos_status gauge +cron_magos_status ${STATUS} + +# HELP cron_magos_last_run Last execution timestamp +# TYPE cron_magos_last_run gauge +cron_magos_last_run $(date +%s) + +# HELP cron_magos_duration_seconds Execution duration +# TYPE cron_magos_duration_seconds gauge +cron_magos_duration_seconds ${DURATION} +EOF + +exit $((1 - STATUS)) \ No newline at end of file diff --git a/roles/magos/templates/upload_configs.sh.j2 b/roles/magos/templates/upload_configs.sh.j2 new file mode 100644 index 0000000..6d97e3a --- /dev/null +++ b/roles/magos/templates/upload_configs.sh.j2 @@ -0,0 +1,163 @@ +#!/bin/bash +set -euo pipefail + +BRANCH=$(hostname) +ANGIE_CONF_DIR="/etc/angie/http.d/" +PTAF_CONF_DIR="/home/install/conf/ptaf-nginx/" +REPO_URL="https://{{ git_token }}@svc-git.cirex.ru/cloudstack/ptaf_config_logs.git" + +# Функция для обработки одной директории +process_directory() { + local dir="$1" + local branch_suffix="$2" + local full_branch="${BRANCH}-${branch_suffix}" + + echo "$(date '+%Y-%m-%d %H:%M:%S') ======================================" + echo "$(date '+%Y-%m-%d %H:%M:%S') Processing directory: $dir" + echo "$(date '+%Y-%m-%d %H:%M:%S') Branch: $full_branch" + + cd "$dir" + + # Если это не git-репозиторий — инициализируем новый + if [ ! -d ".git" ]; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Инициализируем новый локальный git-репозиторий" + git init + git config user.name "ptaf-sync-script" + git config user.email "ptaf-sync-script@$(hostname)" + fi + + # Настраиваем пользователя + git config user.name "ptaf-sync-script" 2>/dev/null || true + git config user.email "ptaf-sync-script@$(hostname)" 2>/dev/null || true + + # Настраиваем стратегию разрешения конфликтов: всегда предпочитать локальную версию + git config pull.rebase true + git config rebase.autoStash true + + # Добавляем/проверяем remote origin + if ! git remote | grep -q '^origin$'; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Добавляем remote origin" + git remote add origin "$REPO_URL" + else + git remote set-url origin "$REPO_URL" + fi + + # Очищаем возможные битые ссылки + echo "$(date '+%Y-%m-%d %H:%M:%S') Очищаем старые ссылки" + git remote prune origin 2>/dev/null || true + + # КЛЮЧЕВОЕ ИЗМЕНЕНИЕ: Получаем только нашу ветку + echo "$(date '+%Y-%m-%d %H:%M:%S') Проверяем существование ветки '$full_branch' на сервере" + if git ls-remote --heads origin "$full_branch" | grep -q "$full_branch"; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Ветка существует на сервере, получаем её" + git fetch origin "$full_branch:refs/remotes/origin/$full_branch" --force 2>/dev/null || { + echo "$(date '+%Y-%m-%d %H:%M:%S') Ошибка при fetch, очищаем и повторяем" + rm -f .git/refs/remotes/origin/"$full_branch" + git fetch origin "$full_branch:refs/remotes/origin/$full_branch" --force 2>/dev/null || true + } + BRANCH_EXISTS_REMOTE=true + else + echo "$(date '+%Y-%m-%d %H:%M:%S') Ветка '$full_branch' ещё не существует на сервере" + BRANCH_EXISTS_REMOTE=false + fi + + # Проверяем, существует ли ветка локально + if ! git show-ref --verify --quiet refs/heads/"$full_branch"; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Создаём локальную ветку '$full_branch'" + + if [ "$BRANCH_EXISTS_REMOTE" = true ]; then + # Создаём ветку на основе удалённой + git checkout -b "$full_branch" "origin/$full_branch" + else + # Создаём новую orphan ветку + git checkout --orphan "$full_branch" 2>/dev/null || git checkout -b "$full_branch" + git rm -rf . 2>/dev/null || true + fi + else + git checkout "$full_branch" 2>/dev/null || { + echo "$(date '+%Y-%m-%d %H:%M:%S') Ошибка переключения, принудительно переключаемся" + git checkout -f "$full_branch" + } + fi + + # Добавляем все файлы + echo "$(date '+%Y-%m-%d %H:%M:%S') Добавляем все файлы" + git add -A . + + # Проверяем наличие изменений и коммитим ИХ СНАЧАЛА + if ! git diff-index --quiet HEAD -- 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then + COMMIT_MSG="Config update $(date '+%Y-%m-%d %H:%M:%S') [host: $(hostname -s)]" + echo "$(date '+%Y-%m-%d %H:%M:%S') Обнаружены локальные изменения — коммитим их ПЕРЕД pull" + git commit -m "$COMMIT_MSG" + fi + + # Теперь делаем pull/rebase если ветка существует на сервере + if [ "$BRANCH_EXISTS_REMOTE" = true ]; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Синхронизация с удалённой веткой origin/$full_branch" + + # Вариант 1: Пробуем обычный rebase + if git pull --rebase origin "$full_branch" 2>/dev/null; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Rebase успешен" + else + echo "$(date '+%Y-%m-%d %H:%M:%S') Конфликт при rebase, разрешаем автоматически" + + # Прерываем rebase + git rebase --abort 2>/dev/null || true + + # Вариант 2: Используем стратегию merge с предпочтением локальных изменений + echo "$(date '+%Y-%m-%d %H:%M:%S') Используем merge стратегию с предпочтением локальных изменений" + if git pull --no-rebase --strategy=recursive --strategy-option=ours origin "$full_branch" 2>/dev/null; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Merge успешен с предпочтением локальных изменений" + else + echo "$(date '+%Y-%m-%d %H:%M:%S') Merge также не удался, используем force push" + # Вариант 3: Если и merge не сработал - будем пушить с force + # (это безопасно, так как мы уже закоммитили все локальные изменения) + fi + fi + fi + + # Создаём keepalive коммит, если изменений больше нет + if git diff-index --quiet HEAD -- 2>/dev/null && git diff --cached --quiet 2>/dev/null; then + COMMIT_MSG="No changes – keepalive commit $(date '+%Y-%m-%d %H:%M:%S') [host: $(hostname -s)]" + echo "$(date '+%Y-%m-%d %H:%M:%S') Нет новых изменений — создаём пустой коммит" + git commit --allow-empty -m "$COMMIT_MSG" + fi + + # Пушим с fallback вариантами + echo "$(date '+%Y-%m-%d %H:%M:%S') Пушим ветку $full_branch" + if git push origin "$full_branch" --set-upstream 2>/dev/null; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Push успешен" + elif git push origin "$full_branch" --force-with-lease 2>/dev/null; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Push успешен с --force-with-lease" + else + echo "$(date '+%Y-%m-%d %H:%M:%S') Используем force push (локальные изменения приоритетнее)" + git push origin "$full_branch" --force || { + echo "$(date '+%Y-%m-%d %H:%M:%S') ОШИБКА: Не удалось запушить ветку $full_branch" + return 1 + } + fi + + echo "$(date '+%Y-%m-%d %H:%M:%S') Успешно завершено: $dir" + return 0 +} + +# Обрабатываем первую директорию +if [ -d "$ANGIE_CONF_DIR" ]; then + process_directory "$ANGIE_CONF_DIR" "angie-conf" || { + echo "$(date '+%Y-%m-%d %H:%M:%S') ОШИБКА при обработке $ANGIE_CONF_DIR" + } +else + echo "$(date '+%Y-%m-%d %H:%M:%S') ПРЕДУПРЕЖДЕНИЕ: Директория $ANGIE_CONF_DIR не найдена" +fi + +# Обрабатываем вторую директорию +if [ -d "$PTAF_CONF_DIR" ]; then + process_directory "$PTAF_CONF_DIR" "ptaf-conf" || { + echo "$(date '+%Y-%m-%d %H:%M:%S') ОШИБКА при обработке $PTAF_CONF_DIR" + } +else + echo "$(date '+%Y-%m-%d %H:%M:%S') ПРЕДУПРЕЖДЕНИЕ: Директория $PTAF_CONF_DIR не найдена" +fi + +echo "$(date '+%Y-%m-%d %H:%M:%S') ======================================" +echo "$(date '+%Y-%m-%d %H:%M:%S') All backups completed." diff --git a/roles/magos/templates/upload_logs.sh.j2 b/roles/magos/templates/upload_logs.sh.j2 new file mode 100644 index 0000000..20e2b1a --- /dev/null +++ b/roles/magos/templates/upload_logs.sh.j2 @@ -0,0 +1,132 @@ +#!/bin/bash +set -euo pipefail + +BRANCH=$(hostname)-logs +LOGS_DIR="{{ magos_log_dir }}" +REPO_URL="https://{{ git_token }}@svc-git.cirex.ru/cloudstack/ptaf_config_logs.git" + +echo "$(date '+%Y-%m-%d %H:%M:%S') Начинаем синхронизацию логов в ветку '$BRANCH'" +cd "$LOGS_DIR" + +# Если это не git-репозиторий — инициализируем новый +if [ ! -d ".git" ]; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Инициализируем новый локальный git-репозиторий" + git init + git config user.name "ptaf-sync-script" + git config user.email "ptaf-sync-script@$(hostname)" +fi + +# Настраиваем пользователя +git config user.name "ptaf-sync-script" 2>/dev/null || true +git config user.email "ptaf-sync-script@$(hostname)" 2>/dev/null || true + +# Настраиваем стратегию разрешения конфликтов +git config pull.rebase true +git config rebase.autoStash true + +# Добавляем/проверяем remote origin +if ! git remote | grep -q '^origin$'; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Добавляем remote origin: $REPO_URL" + git remote add origin "$REPO_URL" +else + # Обновляем URL на случай изменения токена + git remote set-url origin "$REPO_URL" +fi + +# Очищаем возможные битые ссылки перед fetch +echo "$(date '+%Y-%m-%d %H:%M:%S') Очищаем старые ссылки" +git remote prune origin 2>/dev/null || true + +# КЛЮЧЕВОЕ ИЗМЕНЕНИЕ: Получаем только нашу ветку, а не все ветки +echo "$(date '+%Y-%m-%d %H:%M:%S') Получаем информацию только о ветке '$BRANCH'" +if git ls-remote --heads origin "$BRANCH" | grep -q "$BRANCH"; then + # Ветка существует на сервере - получаем только её + git fetch origin "$BRANCH:refs/remotes/origin/$BRANCH" --force 2>/dev/null || { + echo "$(date '+%Y-%m-%d %H:%M:%S') Ошибка при fetch, пытаемся очистить и повторить" + rm -f .git/refs/remotes/origin/"$BRANCH" + git fetch origin "$BRANCH:refs/remotes/origin/$BRANCH" --force 2>/dev/null || true + } + BRANCH_EXISTS_REMOTE=true +else + echo "$(date '+%Y-%m-%d %H:%M:%S') Ветка '$BRANCH' ещё не существует на сервере" + BRANCH_EXISTS_REMOTE=false +fi + +# Проверяем, существует ли ветка локально +if ! git show-ref --verify --quiet refs/heads/"$BRANCH"; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Создаём локальную ветку '$BRANCH'" + + if [ "$BRANCH_EXISTS_REMOTE" = true ]; then + # Создаём ветку на основе удалённой + git checkout -b "$BRANCH" "origin/$BRANCH" + else + # Создаём новую ветку (может быть пустой или на основе текущего HEAD) + git checkout --orphan "$BRANCH" 2>/dev/null || git checkout -b "$BRANCH" + # Очищаем индекс для orphan ветки + git rm -rf . 2>/dev/null || true + fi +else + git checkout "$BRANCH" 2>/dev/null || { + echo "$(date '+%Y-%m-%d %H:%M:%S') Ошибка переключения на ветку, принудительно переключаемся" + git checkout -f "$BRANCH" + } +fi + +# Добавляем все изменения +echo "$(date '+%Y-%m-%d %H:%M:%S') Добавляем все изменения" +git add -A + +# Проверяем, есть ли что коммитить и коммитим СНАЧАЛА +if ! git diff-index --quiet HEAD -- 2>/dev/null; then + COMMIT_MSG="Auto commit $(date '+%Y-%m-%d %H:%M:%S') [host: $(hostname)]" + echo "$(date '+%Y-%m-%d %H:%M:%S') Коммитим локальные изменения ПЕРЕД pull: $COMMIT_MSG" + git commit -m "$COMMIT_MSG" +fi + +# Теперь делаем pull/rebase если ветка существует на сервере +if [ "$BRANCH_EXISTS_REMOTE" = true ]; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Синхронизация с удалённой веткой origin/$BRANCH" + + # Вариант 1: Пробуем обычный rebase + if git pull --rebase origin "$BRANCH" 2>/dev/null; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Rebase успешен" + else + echo "$(date '+%Y-%m-%d %H:%M:%S') Конфликт при rebase, разрешаем автоматически" + + # Прерываем rebase + git rebase --abort 2>/dev/null || true + + # Вариант 2: Используем стратегию merge с предпочтением локальных изменений + echo "$(date '+%Y-%m-%d %H:%M:%S') Используем merge стратегию с предпочтением локальных изменений" + if git pull --no-rebase --strategy=recursive --strategy-option=ours origin "$BRANCH" 2>/dev/null; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Merge успешен с предпочтением локальных изменений" + else + echo "$(date '+%Y-%m-%d %H:%M:%S') Merge также не удался, используем force push" + # Вариант 3: Если и merge не сработал - будем пушить с force + fi + fi +fi + +# Проверяем снова, есть ли что коммитить после синхронизации +if ! git diff-index --quiet HEAD -- 2>/dev/null; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Есть изменения после синхронизации, коммитим" + git commit -m "Post-sync changes $(date '+%Y-%m-%d %H:%M:%S')" +fi + +echo "$(date '+%Y-%m-%d %H:%M:%S') Пушим в origin/$BRANCH" +# Пушим с fallback вариантами +if git push origin "$BRANCH" --set-upstream 2>/dev/null; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Push успешен" +elif git push origin "$BRANCH" --force-with-lease 2>/dev/null; then + echo "$(date '+%Y-%m-%d %H:%M:%S') Push успешен с --force-with-lease" +else + echo "$(date '+%Y-%m-%d %H:%M:%S') Используем force push (локальные изменения приоритетнее)" + git push origin "$BRANCH" --force +fi + +echo "$(date '+%Y-%m-%d %H:%M:%S') Успешно закоммичено и запушено" + +# Запускаем следующий скрипт +{{ magos_upload_configs_script_path }} & + +exit 0 diff --git a/roles/magos_off/README.md b/roles/magos_off/README.md new file mode 100644 index 0000000..356ab55 --- /dev/null +++ b/roles/magos_off/README.md @@ -0,0 +1,3 @@ +# Magos off + +Отключение автоматизации настройки WAF diff --git a/roles/magos_off/tasks/main.yml b/roles/magos_off/tasks/main.yml new file mode 100644 index 0000000..5da293d --- /dev/null +++ b/roles/magos_off/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: Check script + ansible.builtin.stat: + path: /usr/local/bin/magos_off.sh + register: script_stat + +- name: Waf automata off + ansible.builtin.command: /usr/local/bin/magos_off.sh + register: result + when: script_stat.stat.exists and script_stat.stat.executable + +- name: Show result + ansible.builtin.debug: + var: result.stdout + when: script_stat.stat.exists +... diff --git a/roles/magos_on/README.md b/roles/magos_on/README.md new file mode 100644 index 0000000..cf37894 --- /dev/null +++ b/roles/magos_on/README.md @@ -0,0 +1,3 @@ +# Magos on + +Включение автоматизации настройки WAF diff --git a/roles/magos_on/tasks/main.yml b/roles/magos_on/tasks/main.yml new file mode 100644 index 0000000..ff025fd --- /dev/null +++ b/roles/magos_on/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: Check script + ansible.builtin.stat: + path: /usr/local/bin/magos_on.sh + register: script_stat + +- name: Waf automata on + ansible.builtin.command: /usr/local/bin/magos_on.sh + register: result + when: script_stat.stat.exists and script_stat.stat.executable + +- name: Show result + ansible.builtin.debug: + var: result.stdout + when: script_stat.stat.exists +... diff --git a/roles/netplan_update/README.md b/roles/netplan_update/README.md new file mode 100755 index 0000000..5ce5aa6 --- /dev/null +++ b/roles/netplan_update/README.md @@ -0,0 +1,3 @@ +# Роль для обновления Netplan + +Автоматически смотрит какие адреса назначены на интерфейсы и согласно этому заполняет конфиг Netplan. Сети до которых нужен доступ прописываются в `defaults/main.yml`. diff --git a/roles/netplan_update/defaults/main.yml b/roles/netplan_update/defaults/main.yml new file mode 100644 index 0000000..9f20c0f --- /dev/null +++ b/roles/netplan_update/defaults/main.yml @@ -0,0 +1,5 @@ +--- +netplan_update_gray_additional_routes: + - 10.11.2.5/32 # Zabbix + - 10.10.3.0/24 # Серверы AD DNS NTP +... diff --git a/roles/netplan_update/tasks/main.yml b/roles/netplan_update/tasks/main.yml new file mode 100755 index 0000000..c77a13f --- /dev/null +++ b/roles/netplan_update/tasks/main.yml @@ -0,0 +1,36 @@ +--- +- name: Set gray interface (10.100.x.x) + ansible.builtin.set_fact: + interface_1: "{{ item.key }}" + interface_ip_1_with_mask: "{{ item.value.ipv4.address }}/{{ item.value.ipv4.prefix }}" + loop: "{{ ansible_facts | dict2items }}" + when: + - item.value.ipv4 is defined + - item.value.ipv4.address is defined + - item.value.ipv4.address.startswith('10.100') + +- name: Set white interface + ansible.builtin.set_fact: + interface_2: "{{ item.key }}" + interface_ip_2_with_mask: "{{ item.value.ipv4.address }}/{{ item.value.ipv4.prefix }}" + loop: "{{ ansible_facts | dict2items }}" + when: + - item.value.ipv4 is defined + - item.value.ipv4.address is defined + - not item.value.ipv4.address.startswith('10.100') + - not item.value.ipv4.address.startswith('127.') + +- name: Create backup + ansible.builtin.command: cp /etc/netplan/99-netcfg-vmware.yaml /etc/netplan/99-netcfg-vmware.yaml.bak + +- name: Copy new netplan config + ansible.builtin.template: + src: templates/99-netcfg-vmware.yaml.j2 + dest: /etc/netplan/99-netcfg-vmware.yaml + owner: root + group: root + mode: '0600' + +- name: Apply new netplan + ansible.builtin.command: sudo netplan apply +... diff --git a/roles/netplan_update/templates/99-netcfg-vmware.yaml.j2 b/roles/netplan_update/templates/99-netcfg-vmware.yaml.j2 new file mode 100755 index 0000000..0358f7f --- /dev/null +++ b/roles/netplan_update/templates/99-netcfg-vmware.yaml.j2 @@ -0,0 +1,24 @@ +# Changed from Ansible. +network: + version: 2 + renderer: networkd + ethernets: + {{ interface_1 }}: + dhcp4: no + dhcp6: no + addresses: + - {{ interface_ip_1_with_mask }} + routes: +{% for route in netplan_update_gray_additional_routes %} + - to: {{ route }} + via: {{ gray_gateway }} +{% endfor %} + {{ interface_2 }}: + dhcp4: no + dhcp6: no + addresses: + - {{ interface_ip_2_with_mask }} + routes: + - to: default + via: {{ white_gateway }} + \ No newline at end of file diff --git a/roles/new_node_settings/README.md b/roles/new_node_settings/README.md new file mode 100755 index 0000000..6bae603 --- /dev/null +++ b/roles/new_node_settings/README.md @@ -0,0 +1,9 @@ +# Роль для первичной настройки хоста после разворачивания + +Данная роль выпоняет следующие действия: +1. Устанавливает `Angie` и логротейт для него; +2. Устанавливает `Zabbix-agent` через `Docker`; +3. Ставит различный дополнительный софт из репозиториев, который может понадобиться; +4. Конфигурирует `Chrony` и `DNS`; +5. Настривает `SSH` и подкидывает ключи; +6. Меняет пароль для пользователя `install`. diff --git a/roles/new_node_settings/files/authorized_keys b/roles/new_node_settings/files/authorized_keys new file mode 100755 index 0000000..e69de29 diff --git a/roles/new_node_settings/tasks/change_password_for_user.yml b/roles/new_node_settings/tasks/change_password_for_user.yml new file mode 100755 index 0000000..d45294d --- /dev/null +++ b/roles/new_node_settings/tasks/change_password_for_user.yml @@ -0,0 +1,8 @@ +--- +- name: Change password for install user + ansible.builtin.user: + name: "{{ username_on_new_hosts }}" + password: "{{ install_ssh_pass | password_hash('sha512') }}" + update_password: always + state: present +... diff --git a/roles/new_node_settings/tasks/main.yml b/roles/new_node_settings/tasks/main.yml new file mode 100755 index 0000000..18441b6 --- /dev/null +++ b/roles/new_node_settings/tasks/main.yml @@ -0,0 +1,49 @@ +--- +- name: DNS conf + ansible.builtin.include_role: + name: dns_settings + +- name: Netplan update + ansible.builtin.include_role: + name: netplan_update + +- name: Restart connection + ansible.builtin.meta: reset_connection + +- name: APT cache update + ansible.builtin.apt: + update_cache: true + ignore_errors: true + +- name: Different need soft install + ansible.builtin.include_role: + name: different_need_soft_install + +- name: SolidWall repo install + ansible.builtin.include_role: + name: solidwall_repo_add + when: inventory_hostname is match("^ce-swall") + +- name: Node exporter install + ansible.builtin.include_role: + name: node_exporter_install + +- name: SSH conf + ansible.builtin.include_role: + name: ssh_settings + +- name: Logrotate settings + ansible.builtin.include_role: + name: logrotate_settings + +- name: Chrony conf + ansible.builtin.include_role: + name: chrony_install + +- name: Update firewall + ansible.builtin.include_role: + name: update_firewall + +- name: Change password for user + ansible.builtin.include_tasks: change_password_for_user.yml +... diff --git a/roles/node_exporter_install/README.md b/roles/node_exporter_install/README.md new file mode 100644 index 0000000..091f91b --- /dev/null +++ b/roles/node_exporter_install/README.md @@ -0,0 +1 @@ +# Роль для установки и настройки Node Exporter diff --git a/roles/node_exporter_install/defaults/main.yml b/roles/node_exporter_install/defaults/main.yml new file mode 100755 index 0000000..68df32d --- /dev/null +++ b/roles/node_exporter_install/defaults/main.yml @@ -0,0 +1,10 @@ +--- +node_exporter_install_node_exporter_version: '1.9.1' +node_exporter_install_node_exporter_bin_path: /usr/local/bin/ +node_exporter_install_node_exporter_download_url: +node_exporter_install_node_exporter_bin: /usr/local/bin/node_exporter +node_exporter_install_node_exporter_host: '' +node_exporter_install_node_exporter_port: 9100 +node_exporter_install_node_exporter_options: '' +node_exporter_install_node_exporter_restart: on-failure +... diff --git a/roles/node_exporter_install/files/docker-cpu-metrics.sh b/roles/node_exporter_install/files/docker-cpu-metrics.sh new file mode 100644 index 0000000..4737c39 --- /dev/null +++ b/roles/node_exporter_install/files/docker-cpu-metrics.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# Настройки +METRICS_FILE="/var/lib/node_exporter/textfile_collector/docker_cpu.prom" +TEMP_FILE="/tmp/docker_stats.tmp" + + +# Очищаем выходной файл +> "$METRICS_FILE" + +# Получаем актуальные stats от Docker (без потоковой передачи) +if ! docker stats --no-stream --format "{{.Name}},{{.CPUPerc}},{{.MemUsage}}" > "$TEMP_FILE"; then + echo "Ошибка: не удалось получить данные от Docker" >&2 + exit 1 +fi + +# Пропускаем первую строку (заголовок) и обрабатываем каждую строку +tail -n +1 "$TEMP_FILE" | while IFS=, read -r container_name cpu_percent mem_usage; do + # Проверяем наличие данных + if [[ -z "$container_name" ]] || [[ -z "$cpu_percent" ]]; then + continue + fi + + # Удаляем % и заменяем запятую на точку + cpu_clean=$(echo "$cpu_percent" | sed 's/%//g' | sed 's/,/./g' | xargs) + + # Валидируем числовое значение + if ! [[ "$cpu_clean" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then + echo "Предупреждение: некорректное значение CPU '$cpu_percent' для контейнера '$container_name'" >&2 + continue + fi + + # Формируем метрику (строго: имя{лейбл} значение) + echo "docker_container_cpu_usage_percent{container=\"$container_name\"} $cpu_clean" >> "$METRICS_FILE" +done + +# Удаляем временный файл +rm -f "$TEMP_FILE" + +# Если файл пустой — добавляем заглушку +if ! grep -q "." "$METRICS_FILE"; then + echo "# NO_DOCKER_CONTAINERS" >> "$METRICS_FILE" +fi + +echo "Метрики обновлены в $METRICS_FILE" \ No newline at end of file diff --git a/roles/node_exporter_install/files/docker-ps-metrics.sh b/roles/node_exporter_install/files/docker-ps-metrics.sh new file mode 100755 index 0000000..47e1c8b --- /dev/null +++ b/roles/node_exporter_install/files/docker-ps-metrics.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Путь к директории textfile collector +OUTPUT_DIR="/var/lib/node_exporter/textfile_collector" +OUTPUT_FILE="$OUTPUT_DIR/docker_ps.prom" + +# Выполняем docker ps и преобразуем в метрики +docker ps -a --format "table {{.Names}}\t{{.Status}}" | \ +awk 'NR>1 { + # Очищаем статус от лишних деталей (например, "Up 2 hours" → "running") + status = $2 + if (status ~ /^Up/) status = "running" + else if (status ~ /^Exited/) status = "exited" + else if (status ~ /^Restarting/) status = "restarting" + else status = "unknown" + + # Формируем метрику: 1 для running, 0 для остальных + value = (status == "running") ? 1 : 0 + + # Выводим в формате Prometheus + print "docker_container_status{container=\"" $1 "\",status=\"" status "\"} " value +}' > "$OUTPUT_FILE" + +# Добавляем метаданные (HELP и TYPE) +{ + echo "# HELP docker_container_status Статус контейнера (1=running, 0=не running)" + echo "# TYPE docker_container_status gauge" + cat "$OUTPUT_FILE" +} > "$OUTPUT_FILE.tmp" && mv "$OUTPUT_FILE.tmp" "$OUTPUT_FILE" diff --git a/roles/node_exporter_install/tasks/main.yml b/roles/node_exporter_install/tasks/main.yml new file mode 100755 index 0000000..2239c9d --- /dev/null +++ b/roles/node_exporter_install/tasks/main.yml @@ -0,0 +1,116 @@ +--- +- name: Check current node exporter version. + ansible.builtin.command: "{{ node_exporter_install_node_exporter_bin_path }} --version" + failed_when: false + changed_when: false + register: node_exporter_version_check + +- name: Download and unarchive node exporter into temporary location. + ansible.builtin.unarchive: + src: "{{ node_exporter_install_node_exporter_download_url }}" + dest: /tmp + remote_src: true + mode: '0755' + when: node_exporter_version_check.stdout is not defined or node_exporter_version_check.stdout | length == 0 + register: node_exporter_download_check + +- name: Move node exporter binary into place. + ansible.builtin.copy: + src: "/tmp/node_exporter-{{ node_exporter_install_node_exporter_version }}.linux-amd64/node_exporter" + dest: "{{ node_exporter_install_node_exporter_bin_path }}" + mode: '0755' + remote_src: true + when: + - node_exporter_download_check is changed or node_exporter_version_check.stdout | length == 0 + ignore_errors: "{{ ansible_check_mode }}" + +- name: Create node_exporter group (optional fixed GID) + ansible.builtin.group: + name: node_exporter + gid: "{{ node_exporter_install_node_exporter_gid | default(omit) }}" + state: present + when: "node_exporter_install_node_exporter_gid is defined" + +- name: Create node_exporter user (optional fixed UID) + ansible.builtin.user: + name: node_exporter + shell: /sbin/nologin + create_home: false + uid: "{{ node_exporter_install_node_exporter_uid | default(omit) }}" + group: "{{ (node_exporter_install_node_exporter_gid is defined) | ternary('node_exporter', omit) }}" + state: present + +- name: Copy the node exporter systemd unit file. + ansible.builtin.template: + src: node_exporter.service.j2 + dest: /etc/systemd/system/node_exporter.service + mode: '0644' + register: node_exporter_service + +- name: Create direcory for textfile collector + ansible.builtin.file: + path: /var/lib/node_exporter/textfile_collector + state: directory + mode: '0755' + owner: node_exporter + group: node_exporter + recurse: true + +- name: Copy script for docker state check + ansible.builtin.copy: + src: files/docker-ps-metrics.sh + dest: /usr/local/bin/docker-ps-metrics.sh + owner: root + group: root + mode: '0744' + when: inventory_hostname is match("^PTAF") + +- name: Create cron job for docker state check + ansible.builtin.cron: + name: "Collect Docker state check" + minute: "*/1" + job: "/usr/local/bin/docker-ps-metrics.sh" + user: root + when: inventory_hostname is match("^PTAF") + +- name: Copy script for docker CPU check + ansible.builtin.copy: + src: files/docker-cpu-metrics.sh + dest: /usr/local/bin/docker-cpu-metrics.sh + owner: root + group: root + mode: '0744' + when: inventory_hostname is match("^PTAF") + +- name: Add first cron job + ansible.builtin.cron: + name: "Docker CPU Metrics (every minute)" + minute: "*" + hour: "*" + day: "*" + month: "*" + weekday: "*" + job: "/usr/local/bin/docker-cpu-metrics.sh" + user: "root" + when: inventory_hostname is match("^PTAF") + +- name: Add second cron jobcron + ansible.builtin.cron: + name: "Docker CPU Metrics (with 30s delay)" + minute: "*" + hour: "*" + day: "*" + month: "*" + weekday: "*" + job: "( sleep 30 && /usr/local/bin/docker-cpu-metrics.sh )" + user: "root" + when: inventory_hostname is match("^PTAF") + +- name: Systemd restarted, enable node_exporter and restart node_exporter + ansible.builtin.systemd: + name: node_exporter + state: restarted + enabled: true + daemon_reload: true + when: node_exporter_service is changed +... diff --git a/roles/node_exporter_install/templates/node_exporter.service.j2 b/roles/node_exporter_install/templates/node_exporter.service.j2 new file mode 100755 index 0000000..062f954 --- /dev/null +++ b/roles/node_exporter_install/templates/node_exporter.service.j2 @@ -0,0 +1,11 @@ +[Unit] +Description=NodeExporter + +[Service] +TimeoutStartSec=0 +User=node_exporter +ExecStart={{ node_exporter_install_node_exporter_bin }} --web.listen-address={{ node_exporter_install_node_exporter_host }}:{{ node_exporter_install_node_exporter_port }} {{ node_exporter_install_node_exporter_options }} --collector.textfile.directory=/var/lib/node_exporter/textfile_collector --collector.systemd --collector.systemd.unit-include="angie.service" +Restart={{ node_exporter_install_node_exporter_restart }} + +[Install] +WantedBy=multi-user.target diff --git a/roles/postgres_install/README.md b/roles/postgres_install/README.md new file mode 100644 index 0000000..252a8d3 --- /dev/null +++ b/roles/postgres_install/README.md @@ -0,0 +1,5 @@ +# Роль для установки PostgreSQL и pgAdmin + +После установки заходим на хост и смотрим что запущен Apache2 и выполняем следующий скрипт. + +`sudo /usr/pgadmin4/bin/setup-web.sh` diff --git a/roles/postgres_install/defaults/main.yml b/roles/postgres_install/defaults/main.yml new file mode 100644 index 0000000..b799443 --- /dev/null +++ b/roles/postgres_install/defaults/main.yml @@ -0,0 +1,10 @@ +--- +postgres_install_postgresql_version: "16" +postgres_install_postgresql_listen_addresses: "localhost" +postgres_install_postgresql_port: 5432 +postgres_install_postgresql_locale: "en_US.UTF-8" +postgres_install_postgresql_conf_path: "/etc/postgresql/{{ postgres_install_postgresql_version }}/main/postgresql.conf" +postgres_install_pg_hba_conf_path: "/etc/postgresql/{{ postgres_install_postgresql_version }}/main/pg_hba.conf" +postgres_install_allowed_hosts: + - "127.0.0.1/32" +... diff --git a/roles/postgres_install/handlers/main.yml b/roles/postgres_install/handlers/main.yml new file mode 100644 index 0000000..7275f3b --- /dev/null +++ b/roles/postgres_install/handlers/main.yml @@ -0,0 +1,7 @@ +--- +- name: Restart postgresql + systemd: + name: postgresql + state: restarted + enabled: true +... diff --git a/roles/postgres_install/tasks/main.yml b/roles/postgres_install/tasks/main.yml new file mode 100644 index 0000000..fec6c78 --- /dev/null +++ b/roles/postgres_install/tasks/main.yml @@ -0,0 +1,120 @@ +--- +- name: Update apt cache + ansible.builtin.apt: + update_cache: true + changed_when: false + +- name: Install postgresql-common + ansible.builtin.apt: + name: postgresql-common + state: present + +- name: Install PostgreSQL {{ postgres_install_postgresql_version }} and contrib + ansible.builtin.apt: + name: + - "postgresql-{{ postgres_install_postgresql_version }}" + - "postgresql-contrib-{{ postgres_install_postgresql_version }}" + - apache2 + - python3-pip + - python3-psycopg2 + state: present + +- name: Ensure PostgreSQL service is running and enabled + ansible.builtin.systemd: + name: postgresql + state: started + enabled: true + ignore_errors: "{{ ansible_check_mode }}" + +- name: Configure postgresql.conf (listen_addresses and port) + ansible.builtin.lineinfile: + path: "{{ postgres_install_postgresql_conf_path }}" + regexp: "^#?listen_addresses\\s*=" + line: "listen_addresses = '{{ postgres_install_postgresql_listen_addresses }}'" + notify: Restart postgresql + ignore_errors: "{{ ansible_check_mode }}" + +- name: Configure postgresql.conf (port) + ansible.builtin.lineinfile: + path: "{{ postgres_install_postgresql_conf_path }}" + regexp: "^#?port\\s*=" + line: "port = {{ postgresql__install_postgresql_port }}" + notify: Restart postgresql + ignore_errors: "{{ ansible_check_mode }}" + +- name: Deploy pg_hba.conf from template + ansible.builtin.template: + src: pg_hba.conf.j2 + dest: "{{ postgres_install_pg_hba_conf_path }}" + owner: postgres + group: postgres + mode: '0640' + notify: Restart postgresql + ignore_errors: "{{ ansible_check_mode }}" + +- name: Create database user + community.postgresql.postgresql_user: + name: "{{ db_user }}" + password: "{{ db_password }}" + role_attr_flags: CREATEDB,LOGIN + become_user: postgres + ignore_errors: "{{ ansible_check_mode }}" + +- name: Create database + community.postgresql.postgresql_db: + name: "{{ db_name }}" + encoding: UTF8 + lc_ctype: "{{ postgres_install_postgresql_locale }}" + lc_collate: "{{ postgres_install_postgresql_locale }}" + become_user: postgres + ignore_errors: "{{ ansible_check_mode }}" + +- name: Disable angie + ansible.builtin.systemd: + name: angie + state: stopped + enabled: false + +- name: Download and install PGAdmin GPG key + ansible.builtin.get_url: + url: https://www.pgadmin.org/static/packages_pgadmin_org.pub + dest: /tmp/packages_pgadmin_org.pub + mode: '0644' + register: gpg_key_download + ignore_errors: "{{ ansible_check_mode }}" + +- name: Import PGAdmin GPG key into APT keyring + ansible.builtin.copy: + src: /tmp/packages_pgadmin_org.pub + dest: /tmp/pgadmin_key_for_import.pub + remote_src: true + changed_when: false + check_mode: false + +- name: Add key from copied file + ansible.builtin.apt_key: + file: /tmp/pgadmin_key_for_import.pub + keyring: /usr/share/keyrings/packages-pgadmin-org.gpg + ignore_errors: "{{ ansible_check_mode }}" + +- name: Add PGAdmin APT repository + ansible.builtin.apt_repository: + repo: > + deb [signed-by=/usr/share/keyrings/packages-pgadmin-org.gpg] + https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/{{ ansible_lsb.codename }} + pgadmin4 main + state: present + filename: pgadmin4 + ignore_errors: "{{ ansible_check_mode }}" + +- name: Update APT cache after adding repository + ansible.builtin.apt: + update_cache: true + +- name: Install pgadmin packages + ansible.builtin.apt: + name: + - pgadmin4 + - pgadmin4-web + ignore_errors: "{{ ansible_check_mode }}" +... diff --git a/roles/postgres_install/templates/pg_hba.conf.j2 b/roles/postgres_install/templates/pg_hba.conf.j2 new file mode 100644 index 0000000..9068d7c --- /dev/null +++ b/roles/postgres_install/templates/pg_hba.conf.j2 @@ -0,0 +1,19 @@ +# PostgreSQL Client Authentication Configuration File +# Generated by Ansible + +# TYPE DATABASE USER ADDRESS METHOD + +# Local connections +local all all scram-sha-256 +host all all 127.0.0.1/32 scram-sha-256 +host all all ::1/128 scram-sha-256 + +{% for host in postgres_install_allowed_hosts %} +host all all {{ host }} scram-sha-256 +{% endfor %} + +# IPv4 local connections: +host replication all 127.0.0.1/32 scram-sha-256 +host replication all ::1/128 scram-sha-256 +host waf_info install 10.100.10.0/24 md5 +host waf_info install 10.100.13.0/24 md5 diff --git a/roles/settings_for_support/tasks/main.yml b/roles/settings_for_support/tasks/main.yml new file mode 100644 index 0000000..2e7cb3f --- /dev/null +++ b/roles/settings_for_support/tasks/main.yml @@ -0,0 +1,102 @@ +--- +- name: Create restricted bin directory for support user + ansible.builtin.file: + path: /home/support/bin + state: directory + owner: root + group: root + mode: '0755' + +- name: Create symlinks to allowed commands + ansible.builtin.file: + src: "{{ item.src }}" + dest: "/home/support/bin/{{ item.name }}" + state: link + loop: + - {src: '/bin/ping', name: 'ping'} + - {src: '/usr/bin/telnet', name: 'telnet'} + - {src: '/usr/bin/mtr', name: 'mtr'} + - {src: '/usr/local/bin/auspex', name: 'auspex'} + - {src: '/usr/local/bin/lazydocker', name: 'lazydocker'} + - {src: '/usr/bin/traceroute', name: 'traceroute'} + - {src: '/usr/bin/sudo', name: 'sudo'} + - {src: '/usr/bin/curl', name: 'curl'} + - {src: '/usr/bin/grep', name: 'grep'} + - {src: '/usr/bin/tee', name: 'tee'} + - {src: '/usr/bin/ls', name: 'ls'} + +- name: Set rbash as shell for support user + ansible.builtin.user: + name: support + shell: /bin/rbash + home: /home/support + +- name: Allow support user to run mtr with sudo without password + ansible.builtin.copy: + content: | + support ALL=(root) NOPASSWD: /usr/bin/mtr + dest: /etc/sudoers.d/support-mtr + owner: root + group: root + mode: '0440' + validate: 'visudo -cf %s' + +- name: Allow support user to run lazydocker with sudo without password + ansible.builtin.copy: + content: | + support ALL=(root) NOPASSWD: /usr/local/bin/lazydocker + dest: /etc/sudoers.d/support-lazydocker + owner: root + group: root + mode: '0440' + validate: 'visudo -cf %s' + +- name: Allow support user to run auspecs with sudo without password + ansible.builtin.copy: + content: | + support ALL=(root) NOPASSWD: /usr/local/bin/auspex + dest: /etc/sudoers.d/support-auspex + owner: root + group: root + mode: '0440' + validate: 'visudo -cf %s' + +- name: Allow support user to run curl with sudo without password + ansible.builtin.copy: + content: | + support ALL=(root) NOPASSWD: /usr/bin/curl + dest: /etc/sudoers.d/support-curl + owner: root + group: root + mode: '0440' + validate: 'visudo -cf %s' + +- name: Allow support user to run curl with sudo without password + ansible.builtin.copy: + content: | + support ALL=(root) NOPASSWD: /usr/bin/ls + dest: /etc/sudoers.d/support-ls + owner: root + group: root + mode: '0440' + validate: 'visudo -cf %s' + + +- name: Configure .bash_profile with restricted PATH + ansible.builtin.copy: + content: | + PATH=/home/support/bin + export PATH + readonly PATH + dest: /home/support/.bash_profile + owner: root + group: root + mode: '0444' + +- name: Remove write permissions from home directory + ansible.builtin.file: + path: /home/support + owner: root + group: support + mode: '0755' +... diff --git a/roles/solidwall_repo_add/defaults/main.yml b/roles/solidwall_repo_add/defaults/main.yml new file mode 100644 index 0000000..c04bbb2 --- /dev/null +++ b/roles/solidwall_repo_add/defaults/main.yml @@ -0,0 +1,3 @@ +--- +solidwall_token: +... diff --git a/roles/solidwall_repo_add/tasks/main.yml b/roles/solidwall_repo_add/tasks/main.yml new file mode 100644 index 0000000..4bd09d9 --- /dev/null +++ b/roles/solidwall_repo_add/tasks/main.yml @@ -0,0 +1,19 @@ +--- +- name: Remove old configs SolidWall + ansible.builtin.file: + path: /etc/apt/sources.list.d/solidwall.list + state: absent + +- name: Add SolidWall repo + ansible.builtin.shell: | + curl -fsSL https://repo.solidwall.io | TOKEN={{ solidwall_token }} sh - + args: + creates: /etc/apt/sources.list.d/solidwall.list + register: repo_result + changed_when: repo_result.rc == 0 + +- name: Update cache + ansible.builtin.apt: + update_cache: true + when: repo_result.changed +... diff --git a/roles/ssh_settings/README.md b/roles/ssh_settings/README.md new file mode 100755 index 0000000..364d321 --- /dev/null +++ b/roles/ssh_settings/README.md @@ -0,0 +1,7 @@ +# Роль для настройки SSH + +Данная роль создаёт пользователей без паролей и с записью в `sudoers`, которые указаны в переменной `user_list` в `group_vars/prod.yml`. + +Для данных пользователей также создаются директории и прокидываются ssh-ключи, которые хранятся в `files/keys`. + +Далее меняются настройки доступа на хост `только` по `ssh-ключам`. \ No newline at end of file diff --git a/roles/ssh_settings/files/90-auth.conf b/roles/ssh_settings/files/90-auth.conf new file mode 100755 index 0000000..55a1241 --- /dev/null +++ b/roles/ssh_settings/files/90-auth.conf @@ -0,0 +1,15 @@ +# Отключение аутентификации по паролю +PasswordAuthentication no +ChallengeResponseAuthentication no + +# Включение аутентификации по ключу +PubkeyAuthentication yes +AuthorizedKeysFile .ssh/authorized_keys + +# Дополнительные настройки безопасности +PermitRootLogin no +X11Forwarding no +UsePAM yes +PrintMotd no +ClientAliveInterval 180 +ClientAliveCountMax 3 \ No newline at end of file diff --git a/roles/ssh_settings/handlers/main.yml b/roles/ssh_settings/handlers/main.yml new file mode 100755 index 0000000..e49f91c --- /dev/null +++ b/roles/ssh_settings/handlers/main.yml @@ -0,0 +1,7 @@ +--- +- name: Restart SSH + service: + name: "ssh" + state: restarted + ignore_errors: true +... diff --git a/roles/ssh_settings/tasks/copy_ssh_keys.yml b/roles/ssh_settings/tasks/copy_ssh_keys.yml new file mode 100755 index 0000000..3881611 --- /dev/null +++ b/roles/ssh_settings/tasks/copy_ssh_keys.yml @@ -0,0 +1,31 @@ +--- +- name: Create users dirs + ansible.builtin.file: + path: "{{ item.home_dir }}/.ssh" + owner: "{{ item.username }}" + group: "{{ item.username }}" + mode: 0700 + state: directory + loop: "{{ user_list }}" + +- name: Install rights on .ssh + ansible.builtin.file: + path: "{{ item.home_dir }}/.ssh" + owner: "{{ item.username }}" + group: "{{ item.username }}" + mode: 0700 + loop: "{{ user_list }}" + ignore_errors: "{{ ansible_check_mode }}" + notify: Restart SSH + +- name: Overwrite authorized_keys + ansible.builtin.copy: + content: "{{ lookup('file', item.key_file) }}" + dest: "{{ item.home_dir }}/.ssh/authorized_keys" + owner: "{{ item.username }}" + group: "{{ item.username }}" + mode: '0600' + loop: "{{ user_list }}" + ignore_errors: "{{ ansible_check_mode }}" + notify: Restart SSH +... diff --git a/roles/ssh_settings/tasks/copy_ssh_settings.yml b/roles/ssh_settings/tasks/copy_ssh_settings.yml new file mode 100755 index 0000000..6246816 --- /dev/null +++ b/roles/ssh_settings/tasks/copy_ssh_settings.yml @@ -0,0 +1,10 @@ +--- +- name: SSH conf settings copy + ansible.builtin.copy: + src: files/90-auth.conf + dest: /etc/ssh/sshd_config.d/90-auth.conf + mode: '0644' + owner: root + group: root + notify: Restart SSH +... diff --git a/roles/ssh_settings/tasks/create_users.yml b/roles/ssh_settings/tasks/create_users.yml new file mode 100755 index 0000000..cd52d45 --- /dev/null +++ b/roles/ssh_settings/tasks/create_users.yml @@ -0,0 +1,17 @@ +--- +- name: Create users + ansible.builtin.user: + name: "{{ item.username }}" + createhome: true + shell: /bin/bash + state: present + loop: "{{ user_list }}" + +- name: Add useres to sudoers + ansible.builtin.lineinfile: + path: /etc/sudoers + line: "{{ item.username }} ALL=(ALL) NOPASSWD: ALL" + validate: 'visudo -cf %s' + loop: "{{ user_list | rejectattr('username', 'equalto', 'support') }}" + when: sudo_enabled | default(true) +... diff --git a/roles/ssh_settings/tasks/main.yml b/roles/ssh_settings/tasks/main.yml new file mode 100755 index 0000000..54cbbd0 --- /dev/null +++ b/roles/ssh_settings/tasks/main.yml @@ -0,0 +1,13 @@ +--- +- name: Create TB users + ansible.builtin.include_tasks: + file: create_tb_users.yml + +- name: Copy SSH keys + ansible.builtin.include_tasks: + file: copy_ssh_keys.yml + +- name: Copy SSH settings + ansible.builtin.include_tasks: + file: copy_ssh_settings.yml +... diff --git a/roles/support_node_install/README.md b/roles/support_node_install/README.md new file mode 100644 index 0000000..df2b7a6 --- /dev/null +++ b/roles/support_node_install/README.md @@ -0,0 +1 @@ +# Роль для настройки Support ноды diff --git a/roles/support_node_install/files/.xsession b/roles/support_node_install/files/.xsession new file mode 100755 index 0000000..0f703ea --- /dev/null +++ b/roles/support_node_install/files/.xsession @@ -0,0 +1 @@ +startxfce4 \ No newline at end of file diff --git a/roles/support_node_install/files/startwm.sh b/roles/support_node_install/files/startwm.sh new file mode 100755 index 0000000..969c3e1 --- /dev/null +++ b/roles/support_node_install/files/startwm.sh @@ -0,0 +1,10 @@ +#!/bin/sh +unset DBUS_SESSION_BUS_ADDRESS +unset XDG_RUNTIME_DIR + +if [ -r /etc/default/locale ]; then + . /etc/default/locale + export LANG LANGUAGE +fi + +exec /etc/X11/Xsession diff --git a/roles/support_node_install/tasks/install_terraform.yml b/roles/support_node_install/tasks/install_terraform.yml new file mode 100755 index 0000000..3e62251 --- /dev/null +++ b/roles/support_node_install/tasks/install_terraform.yml @@ -0,0 +1,26 @@ +--- +- name: Download archive + ansible.builtin.get_url: + url: + dest: /tmp/terraform.zip + +- name: Create temp dir + ansible.builtin.file: + name: /tmp/extracted_files + owner: root + group: root + mode: '0644' + state: directory + +- name: Unpacking + ansible.builtin.unarchive: + src: /tmp/terraform.zip + dest: /tmp/extracted_files + remote_src: true + +- name: Move files to /usr/bin + ansible.builtin.shell: | + mv /tmp/extracted_files/* /usr/bin/ + rm -rf /tmp/extracted_files + rm /tmp/terraform.zip +... diff --git a/roles/support_node_install/tasks/main.yml b/roles/support_node_install/tasks/main.yml new file mode 100755 index 0000000..e67d62a --- /dev/null +++ b/roles/support_node_install/tasks/main.yml @@ -0,0 +1,58 @@ +--- +- name: APT cache update + ansible.builtin.apt: + update_cache: true + +- name: Install support soft + ansible.builtin.apt: + name: "{{ item }}" + state: present + with_items: "{{ need_support_soft }}" + +- name: Install XFCE + ansible.builtin.apt: + name: "{{ item }}" + state: present + with_items: + - xfce4 + - xfce4-goodies + - dbus-launch + +- name: XFCE start file copy + ansible.builtin.copy: + src: files/.xsession + dest: /home/install/.xsession + owner: install + group: install + mode: '0775' + +- name: Startwm file copy + ansible.builtin.copy: + src: files/startwm.sh + dest: /etc/xrdp/startwm.sh + owner: root + group: root + mode: '0755' + +- name: Install VS Code + ansible.builtin.apt: + deb: "" + +- name: Install Terraform + ansible.builtin.include_tasks: install_terraform.yml + +- name: Control settings + ansible.builtin.include_role: + name: ssh_settings + +- name: Add system users to video group + ansible.builtin.user: + name: "{{ item }}" + groups: video + append: true + with_items: + - install + +- name: XRDP settings + ansible.builtin.include_tasks: xrdp_settings.yml +... diff --git a/roles/support_node_install/tasks/xrdp_settings.yml b/roles/support_node_install/tasks/xrdp_settings.yml new file mode 100755 index 0000000..50bf7c3 --- /dev/null +++ b/roles/support_node_install/tasks/xrdp_settings.yml @@ -0,0 +1,23 @@ +--- +- name: Set xrdp user password + ansible.builtin.user: + name: xrdp + password: "{{ xrdp_pass | password_hash('sha512') }}" + update_password: always + state: present + +- name: Add xrdp user to ssl group + ansible.builtin.user: + name: xrdp + groups: ssl-cert + append: true + +- name: Reload systemd daemon + ansible.builtin.systemd: + daemon_reload: true + +- name: Restart xrdp service + ansible.builtin.systemd: + name: xrdp + state: restarted +... diff --git a/roles/sw_analyzer_restart/tasks/main.yml b/roles/sw_analyzer_restart/tasks/main.yml new file mode 100644 index 0000000..4d6edd6 --- /dev/null +++ b/roles/sw_analyzer_restart/tasks/main.yml @@ -0,0 +1,19 @@ +--- +- name: Update /etc/solidwall/ngwaf/config.yml + shell: sudo sed -i -e "s/localhost/$(hostname -I | awk '{print $1}')/" /etc/solidwall/ngwaf/config.yml + when: inventory_hostname is match('^ce-swall-ngwaf-\\d+$') + +- name: Update /etc/solidwall/ngwaf/config.yml + shell: sudo sed -i -e "s/localhost/$(hostname -I | awk '{print $2}')/" /etc/solidwall/ngwaf/config.yml + when: inventory_hostname is match('^ce-swall-ngwaf-nl-\\d+$') + +- name: Reload service solidwall-ngwaf, in all cases + ansible.builtin.service: + name: solidwall-ngwaf + state: reloaded + +- name: Reload service solidwall-nginx, in all cases + ansible.builtin.service: + name: solidwall-nginx + state: reloaded +... diff --git a/roles/sw_push_configs/files/sites-available/default.conf b/roles/sw_push_configs/files/sites-available/default.conf new file mode 100644 index 0000000..11d7e47 --- /dev/null +++ b/roles/sw_push_configs/files/sites-available/default.conf @@ -0,0 +1,23 @@ +server { + listen 80 default_server; +# access_log /var/log/solidwall-nginx/404.log waf; +# error_log /var/log/solidwall-nginx/404.log error; + server_name _; + server_tokens off; + return 404; +} + +server { + listen 443 default_server ssl; +# access_log /var/log/solidwall-nginx/404.log waf; +# error_log /var/log/solidwall-nginx/404.log error; + server_name _; + server_tokens off; + + ssl_certificate ssl/cert.pem; + ssl_certificate_key ssl/key.pem; + ssl_protocols TLSv1.3 TLSv1.2; + ssl_prefer_server_ciphers on; + + return 404; +} \ No newline at end of file diff --git a/roles/sw_push_configs/tasks/main.yml b/roles/sw_push_configs/tasks/main.yml new file mode 100644 index 0000000..bfd6ea9 --- /dev/null +++ b/roles/sw_push_configs/tasks/main.yml @@ -0,0 +1,48 @@ +--- +- name: Remove Old Configs + shell: /bin/rm -rf /etc/solidwall-nginx/sites-available/* && /bin/rm -rf /etc/solidwall-nginx/sites-enabled/* + +- name: Copy ssl certs from repository + copy: + src: '{{ item }}' + dest: '/etc/solidwall-nginx/ssl/' + owner: root + group: root + mode: 0644 + with_fileglob: + - files/ssl/* + +- name: Copy solidwall-nginx config from repository (available) + copy: + src: '{{ item }}' + dest: '/etc/solidwall-nginx/sites-available/' + owner: root + group: root + mode: 0644 + with_fileglob: + - files/sites-available/* + +- name: Create symlinks in sites-enabled + ansible.builtin.file: + src: '/etc/solidwall-nginx/sites-available/{{ item | basename }}' + dest: '/etc/solidwall-nginx/sites-enabled/{{ item | basename }}' + state: link + force: true + with_fileglob: + - files/sites-available/* + +- name: Copy solidwall-nginx templates from repository + copy: + src: '{{ item }}' + dest: '/etc/solidwall-nginx/templates/' + owner: root + group: root + mode: 0644 + with_fileglob: + - files/templates/* + +- name: Reload service solidwall-nginx, in all cases + ansible.builtin.service: + name: solidwall-nginx + state: reloaded +... diff --git a/roles/update_firewall/README.md b/roles/update_firewall/README.md new file mode 100755 index 0000000..521e753 --- /dev/null +++ b/roles/update_firewall/README.md @@ -0,0 +1,3 @@ +# Роль для настройки nftables + +В данный момент часть настроек в роли есть, но блокировка всего трафика не подподающего в правила пока выключена. \ No newline at end of file diff --git a/roles/update_firewall/tasks/add_fw_rules.yml b/roles/update_firewall/tasks/add_fw_rules.yml new file mode 100755 index 0000000..190e58d --- /dev/null +++ b/roles/update_firewall/tasks/add_fw_rules.yml @@ -0,0 +1,56 @@ +--- +- name: Set gray interface (10.100.x.x) + ansible.builtin.set_fact: + interface_1: "{{ item.key }}" + update_firewall_interface_ip_1: "{{ item.value.ipv4.address }}" + loop: "{{ ansible_facts | dict2items }}" + when: + - item.value.ipv4 is defined + - item.value.ipv4.address is defined + - item.value.ipv4.address.startswith('10.100') + +- name: Set white interface + ansible.builtin.set_fact: + interface_2: "{{ item.key }}" + update_firewall_interface_ip_2: "{{ item.value.ipv4.address }}" + loop: "{{ ansible_facts | dict2items }}" + when: + - item.value.ipv4 is defined + - item.value.ipv4.address is defined + - not item.value.ipv4.address.startswith('10.100') + - not item.value.ipv4.address.startswith('127.') + +- name: Add firewall rules + ansible.builtin.template: + src: templates/nftables.conf.j2 + dest: /etc/nftables.conf + mode: '0644' + owner: root + group: root + register: update_firewall_nftables_config + +- name: Validate nftables configuration + ansible.builtin.command: nft -cnf /etc/nftables.conf + register: update_firewall_nftables_validation + failed_when: update_firewall_nftables_validation.rc != 0 + when: update_firewall_nftables_config.changed + +- name: Restart nftables + ansible.builtin.service: + name: nftables + state: restarted + when: + - update_firewall_nftables_config.changed + - update_firewall_nftables_validation.rc == 0 + ignore_errors: "{{ ansible_check_mode }}" + +- name: Restart Docker service + ansible.builtin.systemd: + name: docker + state: restarted + when: + - update_firewall_nftables_config.changed + - update_firewall_nftables_validation.rc == 0 + - inventory_hostname is match("^PTAF") + ignore_errors: "{{ ansible_check_mode }}" +... diff --git a/roles/update_firewall/tasks/main.yml b/roles/update_firewall/tasks/main.yml new file mode 100755 index 0000000..dcf6eb6 --- /dev/null +++ b/roles/update_firewall/tasks/main.yml @@ -0,0 +1,5 @@ +--- +- name: Add firewall rules + ansible.builtin.include_tasks: add_fw_rules.yml + when: need_install_firewall == true +... diff --git a/roles/update_firewall/templates/nftables.conf.j2 b/roles/update_firewall/templates/nftables.conf.j2 new file mode 100755 index 0000000..244ea2d --- /dev/null +++ b/roles/update_firewall/templates/nftables.conf.j2 @@ -0,0 +1,19 @@ +#!/usr/sbin/nft -f + +flush ruleset + +table ip filter { + chain input { + type filter hook input priority -1; + # включить логгирование заблокированных пакетов + log prefix "[NFT BLOCK]" + } + chain forward { + type filter hook forward priority -1; + # включить логгирование заблокированных пакетов + log prefix "[NFT BLOCK]" + } + chain output { + type filter hook output priority 0; + } +} diff --git a/roles/update_magos/README.md b/roles/update_magos/README.md new file mode 100644 index 0000000..9568871 --- /dev/null +++ b/roles/update_magos/README.md @@ -0,0 +1,3 @@ +# Update magos + +Роль для обновления утилиты magos \ No newline at end of file diff --git a/roles/update_magos/tasks/main.yml b/roles/update_magos/tasks/main.yml new file mode 100644 index 0000000..4cb26c6 --- /dev/null +++ b/roles/update_magos/tasks/main.yml @@ -0,0 +1,29 @@ +--- +- name: Copy magos from cloud + ansible.builtin.get_url: + url: "" + dest: "{{ magos_bin }}" + owner: root + group: root + mode: '0744' + timeout: 60 + force: true + retries: 3 + delay: 10 + +- name: Create directory /etc/magos + ansible.builtin.file: + path: /etc/magos + state: directory + owner: root + group: root + mode: '0755' + +- name: Create .env + ansible.builtin.template: + src: magos.env.j2 + dest: /etc/magos/magos.env + owner: root + group: root + mode: '0600' +... diff --git a/roles/update_magos/templates/magos.env.j2 b/roles/update_magos/templates/magos.env.j2 new file mode 100644 index 0000000..f50782b --- /dev/null +++ b/roles/update_magos/templates/magos.env.j2 @@ -0,0 +1,10 @@ +DB_USER={{ db_user }} +DB_PASSWORD={{ db_password }} +DB_NAME=waf_info +DB_PORT=5432 +PRIMARY_DB_HOST=10.10.1.8 +SECONDARY_DB_HOST=10.10.1.5 +API_TOKEN={{ api_sp_token }} +DOCKER_IMAGE=ptaf-core-nginx-agent:release-4.1.6.409465 +WORKER_PROCESSES=4 +WORKER_CONNECTIONS=64000 \ No newline at end of file diff --git a/roles/waf_manual/README.md b/roles/waf_manual/README.md new file mode 100755 index 0000000..a649de6 --- /dev/null +++ b/roles/waf_manual/README.md @@ -0,0 +1,7 @@ +# Роль для подготовки хоста и установки PT AF в Docker-контейнер + +1. Добавляются настройки для хостового `Angie` для работы Load balancer; +2. Патчится ядро ОС; +3. Добавляются сертификаты; +4. Создаются директории и файлы для `PT AF nginx` и `Docker` в зависимости от нужного количества контейнеров; +5. Через `Docker compose` запускаются контейнеры с `PT AF`. diff --git a/roles/waf_manual/defaults/main.yml b/roles/waf_manual/defaults/main.yml new file mode 100755 index 0000000..a1633bb --- /dev/null +++ b/roles/waf_manual/defaults/main.yml @@ -0,0 +1,3 @@ +--- +waf_manual_start_secure_port_for_containers: 17000 +... diff --git a/roles/waf_manual/files/find_free_ports.sh b/roles/waf_manual/files/find_free_ports.sh new file mode 100644 index 0000000..4bbc1e7 --- /dev/null +++ b/roles/waf_manual/files/find_free_ports.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +start_port=$1 +needed=$2 + +if [[ -z "$start_port" || -z "$needed" || "$needed" -le 0 ]]; then + echo "Usage: $0 " + exit 1 +fi + +free_ports=() +found_base=-1 + +check_port() { + local p=$1 + timeout 1 bash -c "exec 6<>/dev/tcp/127.0.0.1/$p" 2>/dev/null && return 1 || return 0 +} +for ((port = start_port; port <= start_port + 2000; port++)); do + if check_port "$port"; then + # порт свободен + free_ports+=("$port") + + # если это первый порт в потенциальном блоке — запомним его + if [ "${#free_ports[@]}" -eq 1 ]; then + found_base=$port + fi + # если набрали нужное количество подряд свободных + if [ "${#free_ports[@]}" -eq "$needed" ]; then + base_port=${free_ports[0]} + # Считаем, какой порт должен быть в диапазоне 18000–18999 + offset=$((base_port - 19000)) # например, 19015 → offset=15 + mirror_port=$((18000 + offset)) + conflict=false + # Проверяем весь блок в зеркальном диапазоне 18000+ + for ((i=0; i 0 else 0)) * 10 }}" + +- name: Execute external script to find free ports + ansible.builtin.script: files/find_free_ports.sh "{{ waf_manual_start_secure_port_for_containers }}" "{{ required_count }}" + register: port_result + +- name: Finded port + ansible.builtin.set_fact: + finded_port: "{{ port_result.stdout_lines[0] | int }}" +... diff --git a/roles/waf_manual/tasks/main.yml b/roles/waf_manual/tasks/main.yml new file mode 100755 index 0000000..ed41f1b --- /dev/null +++ b/roles/waf_manual/tasks/main.yml @@ -0,0 +1,33 @@ +--- +- name: Tuning core + ansible.builtin.include_tasks: tuning_core.yml + +- name: Install certs for Angie and PT AF Nginx + ansible.builtin.include_role: + name: certs_settings + +- name: Check free ports + ansible.builtin.include_tasks: find_free_ports.yml + +- name: Angie settings + ansible.builtin.include_tasks: angie_settings.yml + +- name: Nginx in Docker settings + ansible.builtin.include_tasks: add_nginx_conf_for_docker.yml + +- name: Sysctl modify + ansible.builtin.include_tasks: sysctl_modify.yml + +- name: Fluent-bit install + ansible.builtin.include_role: + name: fluent_bit_install + when: app_config[app].FLUENT_BIT_NEED + +- name: Auspex install + ansible.builtin.include_role: + name: auspex + ignore_errors: true + +- name: Docker PTAF run + ansible.builtin.include_tasks: docker_ptaf_run.yml +... diff --git a/roles/waf_manual/tasks/make_range_list.yml b/roles/waf_manual/tasks/make_range_list.yml new file mode 100755 index 0000000..7e489ba --- /dev/null +++ b/roles/waf_manual/tasks/make_range_list.yml @@ -0,0 +1,5 @@ +--- +- name: Make range list + ansible.builtin.set_fact: + range_list: "{{ range(1, (app_config[app].CONTAINER_NUMBERS | int) + 1) | list }}" +... diff --git a/roles/waf_manual/tasks/sysctl_modify.yml b/roles/waf_manual/tasks/sysctl_modify.yml new file mode 100755 index 0000000..0449121 --- /dev/null +++ b/roles/waf_manual/tasks/sysctl_modify.yml @@ -0,0 +1,28 @@ +--- +- name: Sysctl modify service copy + ansible.builtin.copy: + src: files/sysctl-modify-parameters.service + dest: /etc/systemd/system/sysctl-modify-parameters.service + mode: '0755' + owner: root + group: root + register: service_copy_result + +- name: Sysctl modify script copy + ansible.builtin.copy: + src: files/sysctl-modify-parameters.sh + dest: /usr/local/bin/sysctl-modify-parameters.sh + mode: '0755' + owner: root + group: root + register: script_copy_result + +- name: Enable and start service + ansible.builtin.systemd: + name: sysctl-modify-parameters.service + enabled: true + state: started + daemon_reload: true + ignore_errors: "{{ ansible_check_mode }}" + when: service_copy_result.changed or script_copy_result.changed +... diff --git a/roles/waf_manual/tasks/tuning_core.yml b/roles/waf_manual/tasks/tuning_core.yml new file mode 100755 index 0000000..719303a --- /dev/null +++ b/roles/waf_manual/tasks/tuning_core.yml @@ -0,0 +1,19 @@ +--- +- name: Backup sysctl + ansible.builtin.copy: + src: /etc/sysctl.conf + dest: /etc/sysctl.conf.backup + remote_src: true + +- name: Load conntrack module + ansible.builtin.modprobe: + name: nf_conntrack + state: present + +- name: Tuning core + ansible.builtin.sysctl: + name: "{{ item.key }}" + value: "{{ item.value }}" + loop: "{{ sysctl_params | dict2items }}" + notify: Reload sysctl +... diff --git a/roles/waf_manual/templates/docker_compose_template.yml.j2 b/roles/waf_manual/templates/docker_compose_template.yml.j2 new file mode 100755 index 0000000..b642816 --- /dev/null +++ b/roles/waf_manual/templates/docker_compose_template.yml.j2 @@ -0,0 +1,59 @@ +services: + ptaf-{{ app_config[app].TENANT_NAME }}-agent{{ '%03d' | format(item) }}: + image: '{{ docker_image }}' + restart: unless-stopped + shm_size: '1gb' + container_name: ptaf_{{ app_config[app].TENANT_NAME }}_{{ '%03d' | format(item) }} + hostname: ptaf_{{ app_config[app].TENANT_NAME }}_{{ '%03d' | format(item) }} + environment: + - CONNECTION_STRING={{ app_config[app].CONNECTION_STRING }} + - WORKER_PROCESSES={{ number_of_worker_processes }} + - WORKER_CONNECTIONS={{ number_of_worker_connections }} + - INCLUDE_CUSTOM_CONFIG=True + - PTAF_CONFIGURATOR_DISABLED=1 +{% if app_config[app].FLUENT_BIT_NEED == true %} + - EVENT_SENDER_ENABLED=1 + - EVENT_SENDER_HOST=172.17.0.1 + - EVENT_SENDER_PORT={{ app_config[app].FLUENT_BIT_INPUT_PORT }} + - EVENT_SENDER_TIMEOUT=3 + - EVENT_WEB_UI_URL=https://af.ptcloud.ru/events/attacks/%s/general/ +{% endif %} + sysctls: + kernel.sem: "32000 1024000000 500 32000" + ports: +{% for i in range(app_config[app].SID_NUMBERS | length) %} + - 127.0.0.1:{{ finded_port | int + item - 1000 + i * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }}:80/tcp + - 127.0.0.1:{{ finded_port | int + item + i * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }}:443/tcp +{% endfor %} +{% if app_config[app].CUSTOM_CONFIG_ANGIE_NEED == true %} +{% for i in range(app_config[app].SID_NUMBERS_WITH_CUSTOM | length) %} + - 127.0.0.1:{{ finded_port | int + (((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + (app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) + item - 1000 + (i - 1) * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }}:80/tcp + - 127.0.0.1:{{ finded_port | int + (((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + (app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) + item + (i - 1) * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }}:443/tcp +{% endfor %} +{% endif %} +{% if app_config[app].CUSTOM_PORTS_NEED == true %} +{% if app_config[app].CUSTOM_CONFIG_ANGIE_NEED == false %} +{% for i in range(app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS | length) %} + - 127.0.0.1:{{ finded_port | int + (((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + (app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) + item + (i - 1) * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }}:{{ app_config[app].CUSTOM_PORTS[i] }}/tcp +{% endfor %} +{% else %} +{% for i in range(app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS | length) %} + - 127.0.0.1:{{ finded_port | int + (finded_port | int + (((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + (app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) + item + (i - 1) * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10)) }}:app_config[app].CUSTOM_PORTS[item]/tcp +{% endfor %} +{% endif %} +{% endif %} + volumes: + - /var/log/ptaf_nginx/{{ app_config[app].TENANT_NAME }}/ptaf-agent{{ '%03d' | format(item) }}:/var/log/nginx + - /home/install/conf/ptaf-nginx/{{ app_config[app].TENANT_NAME }}/ptaf-agent{{ '%03d' | format(item) }}/conf.d:/opt/ptaf/conf/conf.d + - /home/install/conf/ptaf-nginx/{{ app_config[app].TENANT_NAME }}/ptaf-agent{{ '%03d' | format(item) }}/nginx.conf:/opt/ptaf/conf/nginx.conf + - /home/install/conf/ptaf-nginx/{{ app_config[app].TENANT_NAME }}/ptaf-agent{{ '%03d' | format(item) }}/mime.types:/opt/ptaf/conf/mime.types + networks: + - ptaf-{{ app_config[app].TENANT_NAME }}-net + logging: + driver: "json-file" + options: + max-size: "100m" + max-file: "5" +networks: + ptaf-{{ app_config[app].TENANT_NAME }}-net: + driver: bridge diff --git a/roles/waf_manual/templates/ptaf_nginx_for_docker.conf.j2 b/roles/waf_manual/templates/ptaf_nginx_for_docker.conf.j2 new file mode 100755 index 0000000..9227cf2 --- /dev/null +++ b/roles/waf_manual/templates/ptaf_nginx_for_docker.conf.j2 @@ -0,0 +1,91 @@ +#user ptaf; +master_process on; +worker_processes {{ number_of_worker_processes }}; +worker_rlimit_nofile 1048576; + +daemon off; + +load_module /opt/ptaf/lib/ngx_wrapper.so; +{% set random_ip = '135.' + (range(1,255) | random) | string + '.' + (range(1,255) | random) | string + '.' + (range(1,255) | random) | string %} +env POD_IP={{ random_ip }}; +env PTAF_LOG_LEVEL=INFO; +env DEBUG=false; +env HOSTNAME=ptaf-{{ app_config[app].TENANT_NAME }}-agent{{ '%03d' | format(item) }}; +error_log stderr notice; +pid /opt/ptaf/logs/nginx.pid; + +events { + worker_connections {{ number_of_worker_connections }}; + accept_mutex off; +} + +http { + include /opt/ptaf/conf/mime.types; + default_type application/octet-stream; + + log_format waf escape=json + '{' + '"SID":$http_x_sid,' + '"server_name":"$server_name",' + '"app_name":"$host",' + '"proxyed_to":"$upstream_addr",' + '"upstream_status":"$upstream_status",' + '"upstream_response_length":"$upstream_response_length",' + '"upstream_response_time":"$upstream_response_time",' + '"upstream_bytes_sent":"$upstream_bytes_sent",' + '"server_port":$server_port,' + '"server_addr":"$server_addr",' + '"server_protocol":"$server_protocol",' + '"remote_addr":"$remote_addr",' + '"response_status_code":$status,' + '"response_body_bytes_sent":$body_bytes_sent,' + '"http_x_forwarded_for":"$http_x_forwarded_for",' + '"uri":"$uri",' + '"http_user_agent":"$http_user_agent",' + '"query_string":"$query_string",' + '"request_method":"$request_method",' + '"request_time":$request_time,' + '"@timestamp":"$time_iso8601"' + '}'; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + log_format main_upstream '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for" $upstream_response_time'; + + access_log /var/log/nginx/{{ app_config[app].TENANT_NAME }}_access.log waf; + + client_max_body_size 0; + sendfile on; + gzip on; + server_names_hash_bucket_size 512; + server_tokens off; + ptaf_fallback 503; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + proxy_buffer_size 8k; + proxy_buffers 8 8k; + proxy_busy_buffers_size 16k; + proxy_connect_timeout 60s; + resolver_timeout 30s; + + geo $dollar { + default "$"; + } + map $http_upgrade $proxy_http_connection { + default upgrade; + '' ''; + } + + ptaf_config {{ app_config[app].CONNECTION_STRING }}; + + include /opt/ptaf/conf/conf.d/*.conf; + + +} \ No newline at end of file diff --git a/roles/waf_manual/templates/template_angie.conf.j2 b/roles/waf_manual/templates/template_angie.conf.j2 new file mode 100755 index 0000000..2fc6f23 --- /dev/null +++ b/roles/waf_manual/templates/template_angie.conf.j2 @@ -0,0 +1,383 @@ +# angie configuration file +# inserts into http location + +{% if app_config[app].USUAL_SETTINGS %} +{% for item in range(app_config[app].SID_NUMBERS | length) %} +upstream secure{{ app_config[app].SID_NUMBERS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES[item] }} { +{% for i in range(1, (app_config[app].CONTAINER_NUMBERS | int) + 1) %} + server 127.0.0.1:{{ finded_port | int + i + item * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }} weight=50; +{% endfor %} + keepalive 60; + keepalive_timeout 70s; +} + +upstream unsecure{{ app_config[app].SID_NUMBERS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES[item] }} { +{% for i in range(1, (app_config[app].CONTAINER_NUMBERS | int) + 1) %} + server 127.0.0.1:{{ finded_port | int + i - 1000 + item * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }} weight=50; +{% endfor %} + keepalive 60; + keepalive_timeout 70s; +} + +server { + listen 80; + server_name {{ app_config[app].SERVER_NAMES_FOR_APPS[item] }}; + + access_log /var/log/angie/{{ app_config[app].SID_NUMBERS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES[item] }}_access.log waf; + error_log /var/log/angie/{{ app_config[app].SID_NUMBERS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES[item] }}_error.log error; + + # waf networks + {% for nets in waf_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} +# antibot networks + {% for nets in antibot_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} + + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass http://unsecure{{ app_config[app].SID_NUMBERS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES[item] }} ; + } +} + + +server { + listen 443 ssl; + server_name {{ app_config[app].SERVER_NAMES_FOR_APPS[item] }}; + + + access_log /var/log/angie/{{ app_config[app].SID_NUMBERS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES[item] }}_access.log waf; + error_log /var/log/angie/{{ app_config[app].SID_NUMBERS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES[item] }}_error.log error; + + + ssl_certificate /etc/ssl/certs/sp.crt; + ssl_certificate_key /etc/ssl/private/sp.key; + + ssl_protocols TLSv1.3 TLSv1.2; + ssl_prefer_server_ciphers on; + + # waf networks + {% for nets in waf_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} +# antibot networks + {% for nets in antibot_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} + + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass http://secure{{ app_config[app].SID_NUMBERS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES[item] }} ; + + } + +} +{% endfor %} +{% endif %} + +{% if app_config[app].CUSTOM_CONFIG_ANGIE_NEED %} +{% for item in range(app_config[app].SID_NUMBERS_WITH_CUSTOM | length) %} +upstream secure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM[item] }} { +{% for i in range(1, (app_config[app].CONTAINER_NUMBERS | int) + 1) %} + server 127.0.0.1:{{ finded_port | int + ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + i + item * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }} weight=50; +{% endfor %} +{% if app_config[app].CUSTOM_CONFIG_ANGIE_UPSTREAM_NEED %} + {{ app_config[app].CUSTOM_CONFIG_ANGIE_UPSTREAM[item] }} +{% else %} + keepalive 60; + keepalive_timeout 70s; +{% endif %} +} + +upstream unsecure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM[item] }} { +{% for i in range(1, (app_config[app].CONTAINER_NUMBERS | int) + 1) %} + server 127.0.0.1:{{ finded_port | int + ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + i - 1000 + item * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }} weight=50; +{% endfor %} +{% if app_config[app].CUSTOM_CONFIG_ANGIE_UPSTREAM_NEED %} + {{ app_config[app].CUSTOM_CONFIG_ANGIE_UPSTREAM[item] }} +{% else %} + keepalive 60; + keepalive_timeout 70s; +{% endif %} +} + +server { + listen 80; + server_name {{ app_config[app].SERVER_NAMES_FOR_CUSTOM_APPS[item] }}; + + access_log /var/log/angie/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM[item] }}_access.log waf; + error_log /var/log/angie/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM[item] }}_error.log error; + + # waf networks + {% for nets in waf_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} +# antibot networks + {% for nets in antibot_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} + + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass http://unsecure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM[item] }} ; + {{ app_config[app].CUSTOM_CONFIG_ANGIE[item] }} + } +} + + +server { + listen 443 ssl; + server_name {{ app_config[app].SERVER_NAMES_FOR_CUSTOM_APPS[item] }}; + + + access_log /var/log/angie/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM[item] }}_access.log waf; + error_log /var/log/angie/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM[item] }}_error.log error; + + + ssl_certificate /etc/ssl/certs/sp.crt; + ssl_certificate_key /etc/ssl/private/sp.key; + + ssl_protocols TLSv1.3 TLSv1.2; + ssl_prefer_server_ciphers on; + + # waf networks + {% for nets in waf_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} +# antibot networks + {% for nets in antibot_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} + + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass http://secure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM[item] }} ; + {{ app_config[app].CUSTOM_CONFIG_ANGIE[item] }} + } +{% if app_config[app].CUSTOM_LOCATIONS_NEED %} + {{ app_config[app].CUSTOM_LOCATIONS_ANGIE[item] }} +{% endif %} + +} +{% endfor %} +{% endif %} + +{% if app_config[app].CUSTOM_PORTS_NEED %} +{% for item in range(app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS | length) %} +upstream secure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM_PORTS[item] }}_{{ app_config[app].CUSTOM_PORTS[item] }} { +{% for i in range(1, (app_config[app].CONTAINER_NUMBERS | int) + 1) %} +{% if app_config[app].CUSTOM_CONFIG_ANGIE_NEED == false %} + server 127.0.0.1:{{ finded_port | int + ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + i + item * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }} weight=50; +{% else %} + server 127.0.0.1:{{ finded_port | int + (finded_port | int + ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + i + item * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10)) }} weight=50; +{% endif %} +{% endfor %} +{% if app_config[app].CUSTOM_CONFIG_ANGIE_UPSTREAM_NEED_WITH_CUSTOM_PORTS %} + {{ app_config[app].CUSTOM_CONFIG_ANGIE_UPSTREAM_WITH_CUSTOM_PORTS[item] }} +{% else %} + keepalive 60; + keepalive_timeout 70s; +{% endif %} +} + +server { + listen {{ app_config[app].CUSTOM_PORTS[item] }} ssl; + server_name {{ app_config[app].SERVER_NAMES_FOR_CUSTOM_APPS_PORTS[item] }}; + + + access_log /var/log/angie/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM_PORTS[item] }}_access.log waf; + error_log /var/log/angie/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM_PORTS[item] }}_error.log error; + + + ssl_certificate /etc/ssl/certs/sp.crt; + ssl_certificate_key /etc/ssl/private/sp.key; + + ssl_protocols TLSv1.3 TLSv1.2; + ssl_prefer_server_ciphers on; + + # waf networks + {% for nets in waf_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} +# antibot networks + {% for nets in antibot_networks %} +set_real_ip_from {{ nets }}; + {% endfor %} + + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass http://secure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS[item] }}_{{ app_config[app].APP_IN_TENANT_NAMES_WITH_CUSTOM_PORTS[item] }}_{{ app_config[app].CUSTOM_PORTS[item] }} ; +{% if app_config[app].CUSTOM_CONFIG_ANGIE_NEED_WITH_CUSTOM_PORTS %} + {{ app_config[app].CUSTOM_CONFIG_ANGIE_WITH_CUSTOM_PORTS[item] }} +{% endif %} + } + +} +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/roles/waf_manual/templates/template_nginx.conf.j2 b/roles/waf_manual/templates/template_nginx.conf.j2 new file mode 100755 index 0000000..b139da8 --- /dev/null +++ b/roles/waf_manual/templates/template_nginx.conf.j2 @@ -0,0 +1,351 @@ +# nginx configuration file +# inserts into http location + +{% if app_config[app].USUAL_SETTINGS %} +{% for group in app_config[app].UPSTREAM_GROUPS %} +{% if group.ips | length > 0 %} +upstream secure{{ app_config[app].SID_NUMBERS[loop.index0] }}_{{ group.suffix }} { +{% for ip in group.ips %} + server {{ ip }}:443 weight=50; +{% endfor %} + keepalive 60; + keepalive_timeout 70s; +} + +upstream unsecure{{ app_config[app].SID_NUMBERS[loop.index0] }}_{{ group.suffix }} { +{% for ip in group.ips %} + server {{ ip }}:80 weight=50; +{% endfor %} + keepalive 60; + keepalive_timeout 70s; +} + +server { + listen 80; + server_name {{ app_config[app].SERVER_NAMES_FOR_APPS[loop.index0] }}; + + + access_log /var/log/nginx/{{ app_config[app].SID_NUMBERS[loop.index0] }}_{{ group.suffix }}_access.log waf; + error_log /var/log/nginx/{{ app_config[app].SID_NUMBERS[loop.index0] }}_{{ group.suffix }}_error.log error; + + + set_real_ip_from 172.16.0.0/12; + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + #proxy_set_header X-Real-IP $remote_addr; + #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass http://unsecure{{ app_config[app].SID_NUMBERS[loop.index0] }}_{{ group.suffix }}; + } +} + + +server { + listen 443; + server_name {{ app_config[app].SERVER_NAMES_FOR_APPS[loop.index0] }}; + + + access_log /var/log/nginx/{{ app_config[app].SID_NUMBERS[loop.index0] }}_{{ group.suffix }}_access.log waf; + error_log /var/log/nginx/{{ app_config[app].SID_NUMBERS[loop.index0] }}_{{ group.suffix }}_error.log error; + + + proxy_ssl_server_name on; + proxy_ssl_name $host; + + + set_real_ip_from 172.16.0.0/12; + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + #proxy_set_header X-Real-IP $remote_addr; + #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass https://secure{{ app_config[app].SID_NUMBERS[loop.index0] }}_{{ group.suffix }}; + + } + +} +{% endif %} +{% endfor %} +{% endif %} + +{% if app_config[app].CUSTOM_CONFIG_PTAF_NGINX_NEED %} +{% for group in app_config[app].UPSTREAM_GROUPS_CUSTOM %} + +upstream secure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[loop.index0] }}_{{ group.suffix }} { +{% for ip in group.ips %} + server {{ ip }}:443 weight=50; +{% endfor %} +{% if app_config[app].CUSTOM_CONFIG_PTAF_NGINX_UPSTREAM_NEED %} + {{ app_config[app].CUSTOM_CONFIG_PTAF_NGINX_UPSTREAM[loop.index0] }} +{% else %} + keepalive 60; + keepalive_timeout 70s; +{% endif %} +} + + +upstream unsecure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[loop.index0] }}_{{ group.suffix }} { +{% for ip in group.ips %} + server {{ ip }}:80 weight=50; +{% endfor %} +{% if app_config[app].CUSTOM_CONFIG_PTAF_NGINX_UPSTREAM_NEED %} + {{ app_config[app].CUSTOM_CONFIG_PTAF_NGINX_UPSTREAM[loop.index0] }} +{% else %} + keepalive 60; + keepalive_timeout 70s; +{% endif %} +} + + +server { + listen 80; + server_name {{ app_config[app].SERVER_NAMES_FOR_CUSTOM_APPS[loop.index0] }}; + + + access_log /var/log/nginx/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[loop.index0] }}_{{ group.suffix }}_access.log waf; + error_log /var/log/nginx/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[loop.index0] }}_{{ group.suffix }}_error.log error; + + + set_real_ip_from 172.16.0.0/12; + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + #proxy_set_header X-Real-IP $remote_addr; + #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass http://unsecure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[loop.index0] }}_{{ group.suffix }}; + {{ app_config[app].CUSTOM_CONFIG_PTAF_NGINX[loop.index0] }} + } +} + + +server { + listen 443; + server_name {{ app_config[app].SERVER_NAMES_FOR_CUSTOM_APPS[loop.index0] }}; + + + access_log /var/log/nginx/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[loop.index0] }}_{{ group.suffix }}_access.log waf; + error_log /var/log/nginx/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[loop.index0] }}_{{ group.suffix }}_error.log error; + + + proxy_ssl_server_name on; + proxy_ssl_name $host; + + + set_real_ip_from 172.16.0.0/12; + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + #proxy_set_header X-Real-IP $remote_addr; + #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass https://secure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM[loop.index0] }}_{{ group.suffix }}; + {{ app_config[app].CUSTOM_CONFIG_PTAF_NGINX[loop.index0] }} + } +{% if app_config[app].CUSTOM_LOCATIONS_NEED %} + {{ app_config[app].CUSTOM_LOCATIONS_PTAF_NGINX[loop.index0] }} +{% endif %} +} + +{% endfor %} +{% endif %} + +{% if app_config[app].CUSTOM_PORTS_NEED %} +{% for group in app_config[app].UPSTREAM_GROUPS_CUSTOM_PORTS %} +{% set outer_index = loop.index0 %} + +upstream secure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS[loop.index0] }}_{{ group.suffix }}_{{ app_config[app].CUSTOM_PORTS[loop.index0] }} { +{% for ip in group.ips %} + server {{ ip }}:{{ app_config[app].CUSTOM_PORTS[outer_index] }} weight=50; +{% endfor %} +{% if app_config[app].CUSTOM_CONFIG_PTAF_NGINX_UPSTREAM_NEED_WITH_CUSTOM_PORTS %} + {{ app_config[app].CUSTOM_CONFIG_PTAF_NGINX_UPSTREAM_WITH_CUSTOM_PORTS[loop.index0] }} +{% else %} + keepalive 60; + keepalive_timeout 70s; +{% endif %} +} + +server { +{% if app_config[app].CUSTOM_PORTS_NEED == true %} +{% if app_config[app].CUSTOM_CONFIG_ANGIE_NEED == false %} + listen {{ finded_port | int + (((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + (app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) + item + loop.index0 * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) }}; +{% else %} + listen {{ finded_port | int + (finded_port | int + (((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) * (app_config[app].SID_NUMBERS | length) + (app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10) + item + loop.index0 * ((app_config[app].CONTAINER_NUMBERS | int + 9) // 10 * 10)) }}; +{% endif %} +{% endif %} + server_name {{ app_config[app].SERVER_NAMES_FOR_CUSTOM_APPS_PORTS[loop.index0] }}; + + + access_log /var/log/nginx/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS[loop.index0] }}_{{ group.suffix }}_access.log waf; + error_log /var/log/nginx/{{ app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS[loop.index0] }}_{{ group.suffix }}_error.log error; + + + proxy_ssl_server_name on; + proxy_ssl_name $host; + + + set_real_ip_from 172.16.0.0/12; + real_ip_header X-Forwarded-For; + real_ip_recursive on; + + + server_tokens off; + sendfile on; + gzip on; + client_max_body_size 0; + large_client_header_buffers 4 128k; + + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; + proxy_http_version 1.1; + proxy_connect_timeout 3s; + proxy_busy_buffers_size 32k; + proxy_buffers 4 32k; + proxy_buffer_size 16k; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + send_timeout 60s; + keepalive_timeout 75s; + keepalive_requests 1000; + resolver_timeout 30s; + + + #proxy_set_header X-Real-IP $remote_addr; + #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection "upgrade"; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Host $host; + proxy_pass_header Date; + proxy_pass_header Server; + + + location / { + proxy_pass https://secure{{ app_config[app].SID_NUMBERS_WITH_CUSTOM_PORTS[loop.index0] }}_{{ group.suffix }}_{{ app_config[app].CUSTOM_PORTS[loop.index0] }}; +{% if app_config[app].CUSTOM_CONFIG_PTAF_NGINX_NEED_WITH_CUSTOM_PORTS%} + {{ app_config[app].CUSTOM_CONFIG_PTAF_NGINX[loop.index0] }} +{% endif %} + } + +} + +{% endfor %} +{% endif %} diff --git a/site_auspex.yml b/site_auspex.yml new file mode 100755 index 0000000..4cdd16c --- /dev/null +++ b/site_auspex.yml @@ -0,0 +1,6 @@ +--- +- name: Install auspex + hosts: all + roles: + - auspex +... diff --git a/site_auspex_l_off.yml b/site_auspex_l_off.yml new file mode 100644 index 0000000..6e9dfea --- /dev/null +++ b/site_auspex_l_off.yml @@ -0,0 +1,6 @@ +--- +- name: Auspex logs checker off + hosts: all + roles: + - auspex_l_off +... diff --git a/site_auspex_l_on.yml b/site_auspex_l_on.yml new file mode 100644 index 0000000..dca4279 --- /dev/null +++ b/site_auspex_l_on.yml @@ -0,0 +1,6 @@ +--- +- name: Auspex logs checker on + hosts: all + roles: + - auspex_l_on +... diff --git a/site_auspex_m_off.yml b/site_auspex_m_off.yml new file mode 100644 index 0000000..26eb3a2 --- /dev/null +++ b/site_auspex_m_off.yml @@ -0,0 +1,6 @@ +--- +- name: Auspex match checker off + hosts: all + roles: + - auspex_m_off +... diff --git a/site_auspex_m_on.yml b/site_auspex_m_on.yml new file mode 100644 index 0000000..991b368 --- /dev/null +++ b/site_auspex_m_on.yml @@ -0,0 +1,6 @@ +--- +- name: Auspex match checker on + hosts: all + roles: + - auspex_m_on +... diff --git a/site_auspex_p_off.yml b/site_auspex_p_off.yml new file mode 100644 index 0000000..4188b52 --- /dev/null +++ b/site_auspex_p_off.yml @@ -0,0 +1,6 @@ +--- +- name: Auspex port checker off + hosts: all + roles: + - auspex_p_off +... diff --git a/site_auspex_p_on.yml b/site_auspex_p_on.yml new file mode 100644 index 0000000..2f7b173 --- /dev/null +++ b/site_auspex_p_on.yml @@ -0,0 +1,6 @@ +--- +- name: Auspex port checker on + hosts: all + roles: + - auspex_p_on +... diff --git a/site_certs_settings.yml b/site_certs_settings.yml new file mode 100644 index 0000000..d8f7e57 --- /dev/null +++ b/site_certs_settings.yml @@ -0,0 +1,6 @@ +--- +- name: Install certs for Angie and PT AF Nginx + hosts: all + roles: + - certs_settings +... diff --git a/site_chrony_install.yml b/site_chrony_install.yml new file mode 100755 index 0000000..7bd5983 --- /dev/null +++ b/site_chrony_install.yml @@ -0,0 +1,6 @@ +--- +- name: Chrony install + hosts: all + roles: + - chrony_install +... diff --git a/site_different_need_soft_install.yml b/site_different_need_soft_install.yml new file mode 100755 index 0000000..42e5856 --- /dev/null +++ b/site_different_need_soft_install.yml @@ -0,0 +1,6 @@ +--- +- name: Different need soft install + hosts: all + roles: + - different_need_soft_install +... diff --git a/site_dns_settings.yml b/site_dns_settings.yml new file mode 100755 index 0000000..d15ca02 --- /dev/null +++ b/site_dns_settings.yml @@ -0,0 +1,6 @@ +--- +- name: DNS settings + hosts: all + roles: + - dns_settings +... diff --git a/site_expand_disk.yml b/site_expand_disk.yml new file mode 100644 index 0000000..342231f --- /dev/null +++ b/site_expand_disk.yml @@ -0,0 +1,6 @@ +--- +- name: Expand disk + hosts: all + roles: + - expand_disk +... diff --git a/site_filebeat_install.yml b/site_filebeat_install.yml new file mode 100755 index 0000000..ab8a5ec --- /dev/null +++ b/site_filebeat_install.yml @@ -0,0 +1,6 @@ +--- +- name: Logs settings on PT AF + hosts: all + roles: + - filebeat_install +... diff --git a/site_fluent_bit_install.yml b/site_fluent_bit_install.yml new file mode 100755 index 0000000..42e1b28 --- /dev/null +++ b/site_fluent_bit_install.yml @@ -0,0 +1,6 @@ +--- +- name: Fluent-bit install + hosts: all + roles: + - fluent_bit_install +... diff --git a/site_grafana_gen.yml b/site_grafana_gen.yml new file mode 100755 index 0000000..439db1d --- /dev/null +++ b/site_grafana_gen.yml @@ -0,0 +1,6 @@ +--- +- name: Install Grafana gen + hosts: all + roles: + - grafana_gen +... diff --git a/site_logrotate_run_now.yml b/site_logrotate_run_now.yml new file mode 100644 index 0000000..a83b21c --- /dev/null +++ b/site_logrotate_run_now.yml @@ -0,0 +1,6 @@ +--- +- name: Logrotate run now + hosts: all + roles: + - logrotate_run_now +... diff --git a/site_logrotate_settings.yml b/site_logrotate_settings.yml new file mode 100644 index 0000000..d3a672f --- /dev/null +++ b/site_logrotate_settings.yml @@ -0,0 +1,6 @@ +--- +- name: Logrotate settings + hosts: all + roles: + - logrotate_settings +... diff --git a/site_magos.yml b/site_magos.yml new file mode 100755 index 0000000..f9bf61a --- /dev/null +++ b/site_magos.yml @@ -0,0 +1,6 @@ +--- +- name: Install PTAF in docker + hosts: all + roles: + - magos +... diff --git a/site_magos_off.yml b/site_magos_off.yml new file mode 100644 index 0000000..7e6fc64 --- /dev/null +++ b/site_magos_off.yml @@ -0,0 +1,6 @@ +--- +- name: Magos off + hosts: all + roles: + - magos_off +... diff --git a/site_magos_on.yml b/site_magos_on.yml new file mode 100644 index 0000000..fee4acb --- /dev/null +++ b/site_magos_on.yml @@ -0,0 +1,6 @@ +--- +- name: Magos on + hosts: all + roles: + - magos_on +... diff --git a/site_netplan_update.yml b/site_netplan_update.yml new file mode 100755 index 0000000..af3b8e7 --- /dev/null +++ b/site_netplan_update.yml @@ -0,0 +1,6 @@ +--- +- name: Neplan update + hosts: all + roles: + - netplan_update +... diff --git a/site_new_node_settings.yml b/site_new_node_settings.yml new file mode 100755 index 0000000..7e3b6bf --- /dev/null +++ b/site_new_node_settings.yml @@ -0,0 +1,7 @@ +--- +- name: Full settings new nod + hosts: all + remote_user: install + roles: + - new_node_settings +... diff --git a/site_node_exporter_install.yml b/site_node_exporter_install.yml new file mode 100755 index 0000000..197117c --- /dev/null +++ b/site_node_exporter_install.yml @@ -0,0 +1,6 @@ +--- +- name: Node exporter install + hosts: all + roles: + - node_exporter_install +... diff --git a/site_postgres_install.yml b/site_postgres_install.yml new file mode 100755 index 0000000..6ed0a99 --- /dev/null +++ b/site_postgres_install.yml @@ -0,0 +1,6 @@ +--- +- name: Postgres install + hosts: all + roles: + - postgres_install +... diff --git a/site_settings_for_support.yml b/site_settings_for_support.yml new file mode 100644 index 0000000..780d831 --- /dev/null +++ b/site_settings_for_support.yml @@ -0,0 +1,6 @@ +--- +- name: Settings for support + hosts: all + roles: + - settings_for_support +... diff --git a/site_solidwall_repo_add.yml b/site_solidwall_repo_add.yml new file mode 100755 index 0000000..ed7a2be --- /dev/null +++ b/site_solidwall_repo_add.yml @@ -0,0 +1,6 @@ +--- +- name: Solidwall repo add + hosts: all + roles: + - solidwall_repo_add +... diff --git a/site_sp_sync.yml b/site_sp_sync.yml new file mode 100755 index 0000000..643b6f8 --- /dev/null +++ b/site_sp_sync.yml @@ -0,0 +1,6 @@ +--- +- name: Install sp sync + hosts: all + roles: + - sp_sync +... diff --git a/site_sp_sync_off.yml b/site_sp_sync_off.yml new file mode 100644 index 0000000..8396376 --- /dev/null +++ b/site_sp_sync_off.yml @@ -0,0 +1,6 @@ +--- +- name: SP sync off + hosts: all + roles: + - sp_sync_off +... diff --git a/site_sp_sync_on.yml b/site_sp_sync_on.yml new file mode 100644 index 0000000..13874be --- /dev/null +++ b/site_sp_sync_on.yml @@ -0,0 +1,6 @@ +--- +- name: SP sync on + hosts: all + roles: + - sp_sync_on +... diff --git a/site_ssh_settings.yml b/site_ssh_settings.yml new file mode 100755 index 0000000..52c23a3 --- /dev/null +++ b/site_ssh_settings.yml @@ -0,0 +1,6 @@ +--- +- name: SSH setting + hosts: all + roles: + - ssh_settings +... diff --git a/site_support_node_install.yml b/site_support_node_install.yml new file mode 100755 index 0000000..9efe7e7 --- /dev/null +++ b/site_support_node_install.yml @@ -0,0 +1,7 @@ +--- +- name: Support node settings + hosts: all + remote_user: install + roles: + - support_node_install +... diff --git a/site_sw_analyzer_restart.yml b/site_sw_analyzer_restart.yml new file mode 100644 index 0000000..ed06c69 --- /dev/null +++ b/site_sw_analyzer_restart.yml @@ -0,0 +1,7 @@ +--- +- name: SolidWall analyzer restart + hosts: all + remote_user: install + roles: + - sw_analyzer_restart +... diff --git a/site_sw_push_configs.yml b/site_sw_push_configs.yml new file mode 100644 index 0000000..8894351 --- /dev/null +++ b/site_sw_push_configs.yml @@ -0,0 +1,7 @@ +--- +- name: SolidWall push configs + hosts: all + remote_user: install + roles: + - sw_push_configs +... diff --git a/site_update_apps_configs.yml b/site_update_apps_configs.yml new file mode 100644 index 0000000..7615a01 --- /dev/null +++ b/site_update_apps_configs.yml @@ -0,0 +1,6 @@ +--- +- name: Update apps configs + hosts: all + roles: + - update_apps_configs +... diff --git a/site_update_firewall.yml b/site_update_firewall.yml new file mode 100755 index 0000000..0cf4204 --- /dev/null +++ b/site_update_firewall.yml @@ -0,0 +1,6 @@ +--- +- name: Update firewall + hosts: all + roles: + - update_firewall +... diff --git a/site_update_magos.yml b/site_update_magos.yml new file mode 100755 index 0000000..da118a7 --- /dev/null +++ b/site_update_magos.yml @@ -0,0 +1,6 @@ +--- +- name: Update Magos + hosts: all + roles: + - update_magos +... diff --git a/site_update_waf_automata.yml b/site_update_waf_automata.yml new file mode 100755 index 0000000..1b23900 --- /dev/null +++ b/site_update_waf_automata.yml @@ -0,0 +1,6 @@ +--- +- name: Download waf automata + hosts: all + roles: + - update_waf_automata +... diff --git a/site_waf_manual.yml b/site_waf_manual.yml new file mode 100755 index 0000000..ff6db41 --- /dev/null +++ b/site_waf_manual.yml @@ -0,0 +1,6 @@ +--- +- name: Install PTAF in docker + hosts: all + roles: + - waf_manual +...