docs(grafana): add dashboard import playbook and presentation assets

This commit is contained in:
igor04091968
2026-05-15 09:20:02 +03:00
parent 9927cdb195
commit 4fb1c9335e
16 changed files with 344 additions and 5 deletions
+38 -1
View File
@@ -14,6 +14,7 @@
- `ansible/provision_proxmox_ct_matrix_and_deploy_aw.yml` — массовый полный playbook (несколько CT).
- `ansible/deploy_aw_windows.yml` — WinRM playbook для развёртывания Windows/RDP collector'ов.
- `ansible/deploy_aw_pfsense_poller.yml` — развёртывание pfSense poller'а.
- `ansible/deploy_grafana_dashboards.yml` — импорт version-controlled Grafana dashboard'ов через HTTP API.
- `ansible/deploy_tsj_guardian_bot_proxmox.yml` — развёртывание TSJ Guardian Telegram Bot на Proxmox host.
- `ansible/install_full_stack.yml` — полный установочный playbook (оркестратор всех этапов).
- `ansible/inventory.example.ini` — шаблон inventory.
@@ -55,7 +56,8 @@ ansible-playbook -i inventory.ini install_full_stack.yml
- `provision_proxmox_ct_and_deploy_aw.yml` (если есть хосты в группе `[proxmox]`);
- `deploy_aw_server.yml` (группа `[aw_server]`);
- `deploy_aw_windows.yml` (группа `[aw_windows]`);
- `deploy_aw_pfsense_poller.yml` (группа `[aw_pfsense_pollers]`).
- `deploy_aw_pfsense_poller.yml` (группа `[aw_pfsense_pollers]`);
- `deploy_grafana_dashboards.yml` (группа `[grafana]`).
Пустые группы в `inventory.ini` безопасны: соответствующий play будет пропущен.
@@ -162,6 +164,41 @@ Playbook:
- пишет `/etc/aw-pfsense/poller.json`;
- поднимает `aw-pfsense-poller.service`.
## Импорт Grafana dashboard'ов
1. Подготовьте inventory и vars:
- `cp ansible/inventory.example.ini ansible/inventory.ini`
- `cp ansible/group_vars/grafana.example.yml ansible/group_vars/grafana.yml`
2. Укажите в inventory группу `[grafana]` и переменную `grafana_url`.
3. Экспортируйте пароль Grafana API:
```bash
export GRAFANA_ADMIN_PASSWORD='...'
```
4. Запустите:
```bash
cd ansible
ansible-playbook -i inventory.ini deploy_grafana_dashboards.yml
```
Playbook:
- проверяет `GET /api/health`;
- создает или актуализирует folder `AWatch-rus` в Grafana;
- импортирует dashboard JSON из каталога `grafana/`;
- верифицирует доступность dashboard'ов по `uid` через Grafana API.
По умолчанию импортируются:
- `DetMir: Работа пользователей в RDP`
- `DetMir: DLP и ИБ обзор`
- `DetMir: ИБ сводка для руководства`
- `AW-rus: DLP обзор`
Подробная документация: `docs/GRAFANA_DASHBOARDS_RU.md`
## Развёртывание TSJ Guardian Bot на Proxmox
1. Подготовьте vars:
+125
View File
@@ -0,0 +1,125 @@
---
- name: Import AW-rus Grafana dashboards through HTTP API
hosts: grafana
gather_facts: false
connection: local
run_once: true
vars:
aw_repo_root: "{{ playbook_dir | dirname }}"
grafana_api_url: "{{ grafana_url | regex_replace('/+$', '') }}"
grafana_validate_tls_eff: "{{ grafana_validate_tls | default(true) }}"
grafana_folder_uid_eff: "{{ grafana_folder_uid | default('awatch-rus') }}"
grafana_folder_title_eff: "{{ grafana_folder_title | default('AWatch-rus') }}"
grafana_dashboards_import_overwrite_eff: "{{ grafana_dashboards_import_overwrite | default(true) }}"
grafana_dashboards:
- file: "grafana/detmir-rdp-user-activity-dashboard.json"
uid: "detmir-rdp-user-activity"
title: "DetMir: Работа пользователей в RDP"
- file: "grafana/detmir-dlp-security-dashboard.json"
uid: "detmir-dlp-security"
title: "DetMir: DLP и ИБ обзор"
- file: "grafana/detmir-dlp-management-dashboard.json"
uid: "detmir-dlp-management"
title: "DetMir: ИБ сводка для руководства"
- file: "grafana/dlp-dashboard.json"
uid: "awatch-dlp-overview"
title: "AW-rus: DLP обзор"
tasks:
- name: Validate required Grafana settings
ansible.builtin.assert:
that:
- grafana_url is defined
- grafana_url | length > 0
- grafana_admin_user is defined
- grafana_admin_user | length > 0
- grafana_admin_password is defined
- grafana_admin_password | length > 0
fail_msg: "Заполните grafana_url, grafana_admin_user и grafana_admin_password."
- name: Check Grafana health endpoint
ansible.builtin.uri:
url: "{{ grafana_api_url }}/api/health"
method: GET
user: "{{ grafana_admin_user }}"
password: "{{ grafana_admin_password }}"
force_basic_auth: true
validate_certs: "{{ grafana_validate_tls_eff | bool }}"
return_content: true
status_code: 200
- name: Lookup Grafana folder by uid
ansible.builtin.uri:
url: "{{ grafana_api_url }}/api/folders/{{ grafana_folder_uid_eff }}"
method: GET
user: "{{ grafana_admin_user }}"
password: "{{ grafana_admin_password }}"
force_basic_auth: true
validate_certs: "{{ grafana_validate_tls_eff | bool }}"
return_content: true
status_code:
- 200
- 404
register: grafana_folder_lookup
- name: Create Grafana folder when absent
ansible.builtin.uri:
url: "{{ grafana_api_url }}/api/folders"
method: POST
user: "{{ grafana_admin_user }}"
password: "{{ grafana_admin_password }}"
force_basic_auth: true
validate_certs: "{{ grafana_validate_tls_eff | bool }}"
body_format: json
status_code: 200
body:
uid: "{{ grafana_folder_uid_eff }}"
title: "{{ grafana_folder_title_eff }}"
when: grafana_folder_lookup.status == 404
- name: Update Grafana folder title when it already exists
ansible.builtin.uri:
url: "{{ grafana_api_url }}/api/folders/{{ grafana_folder_uid_eff }}"
method: PUT
user: "{{ grafana_admin_user }}"
password: "{{ grafana_admin_password }}"
force_basic_auth: true
validate_certs: "{{ grafana_validate_tls_eff | bool }}"
body_format: json
status_code: 200
body:
title: "{{ grafana_folder_title_eff }}"
version: "{{ (grafana_folder_lookup.json.version | default(0) | int) + 1 }}"
when: grafana_folder_lookup.status == 200
- name: Import Grafana dashboards from repository JSON
ansible.builtin.uri:
url: "{{ grafana_api_url }}/api/dashboards/db"
method: POST
user: "{{ grafana_admin_user }}"
password: "{{ grafana_admin_password }}"
force_basic_auth: true
validate_certs: "{{ grafana_validate_tls_eff | bool }}"
body_format: json
status_code: 200
body:
dashboard: "{{ (lookup('file', aw_repo_root ~ '/' ~ item.file) | from_json) | combine({'id': None}, recursive=True) }}"
folderUid: "{{ grafana_folder_uid_eff }}"
overwrite: "{{ grafana_dashboards_import_overwrite_eff | bool }}"
message: "Imported by Ansible from {{ item.file }}"
loop: "{{ grafana_dashboards }}"
loop_control:
label: "{{ item.title }}"
- name: Verify imported dashboards by uid
ansible.builtin.uri:
url: "{{ grafana_api_url }}/api/dashboards/uid/{{ item.uid }}"
method: GET
user: "{{ grafana_admin_user }}"
password: "{{ grafana_admin_password }}"
force_basic_auth: true
validate_certs: "{{ grafana_validate_tls_eff | bool }}"
status_code: 200
loop: "{{ grafana_dashboards }}"
loop_control:
label: "{{ item.uid }}"
+7
View File
@@ -0,0 +1,7 @@
grafana_url: "http://10.20.30.11:3000"
grafana_admin_user: "admin"
grafana_admin_password: "{{ lookup('env', 'GRAFANA_ADMIN_PASSWORD') }}"
grafana_validate_tls: false
grafana_folder_uid: "awatch-rus"
grafana_folder_title: "AWatch-rus"
grafana_dashboards_import_overwrite: true
+2
View File
@@ -5,6 +5,7 @@
# 2) развёртывание AW server на хостах [aw_server]
# 3) развёртывание Windows/RDP collector'ов на [aw_windows]
# 4) развёртывание pfSense poller'а на [aw_pfsense_pollers]
# 5) импорт Grafana dashboard'ов на [grafana]
#
# Примечания:
# - Заполняйте только нужные группы inventory для своего окружения.
@@ -14,3 +15,4 @@
- import_playbook: deploy_aw_server.yml
- import_playbook: deploy_aw_windows.yml
- import_playbook: deploy_aw_pfsense_poller.yml
- import_playbook: deploy_grafana_dashboards.yml
+5
View File
@@ -10,3 +10,8 @@ win-node1 ansible_host=192.168.100.21 ansible_user=Администратор an
[aw_pfsense_pollers]
# pfsense-poller1 ansible_host=192.168.100.30 ansible_user=root ansible_port=22
[grafana]
# Для API-import playbook достаточно указать grafana_url.
# SSH-подключение не требуется: playbook работает через HTTP API с control host.
grafana-main grafana_url=http://10.20.30.11:3000