Archive grafana-readonly-user: read-only пользователь Grafana (it@vinogorod.ru, Viewer); OSS 11.1 provisioning users не работает — только UI

This commit is contained in:
Evgeny Storozhenko
2026-09-08 13:27:29 +00:00
parent e195f0030d
commit 5b605abd29
8 changed files with 215 additions and 10 deletions
+12 -10
View File
@@ -1,22 +1,23 @@
# OpenSpec Lab — Статус # OpenSpec Lab — Статус
Обновлено: 2026-09-08 (сессия: Vinograd WAN мониторинг) Обновлено: 2026-09-08 (сессия: Grafana read-only пользователь)
## Текущее состояние ## Текущее состояние
Лаборатория spec-driven подхода (OpenSpec CLI 1.12.0) для задач настройки инфраструктуры Hermes/homelab. Цикл propose→apply→archive работает; 4 change заархивированы. Tavily-прокси (web_extract) работает end-to-end в forward-режиме (решение по задаче 5: оставить как есть). Локальный экстрактор (trafilatura) написан и протестирован (2.2/2.3 зелёные), change заархивирован. Репозиторий создан на gitverse.ru, main запушен. Новый цикл vinograd-rostelecom-channel-monitoring — заархивирован (ICMP-мониторинг канала Винный город в /opt/monitoring). Лаборатория spec-driven подхода (OpenSpec CLI 1.12.0) для задач настройки инфраструктуры Hermes/homelab. Цикл propose→apply→archive работает; **5 change заархивированы**. Tavily-прокси (web_extract) работает end-to-end в forward-режиме (решение по задаче 5: оставить как есть). Локальный экстрактор (trafilatura) написан и протестирован (2.2/2.3 зелёные), change заархивирован. Репозиторий создан на gitverse.ru, main запушен. ICMP-мониторинг канала «Винный город» заархивирован (в /opt/monitoring). Read-only пользователь Grafana (it@vinogorod.ru, Viewer) добавлен через UI — change заархивирован.
## Сделано ## Сделано
- [x] OpenSpec CLI установлен (npm, 1.12.0), лаба инициализирована с --tools hermes (6 скиллов) - [x] OpenSpec CLI установлен (npm, 1.12.0), лаба инициализирована с --tools hermes (6 скиллов)
- [x] config.yaml с инфраструктурным контекстом (systemd, docker, /opt/<svc>/, gitverse) - [x] config.yaml с инфраструктурным контекстом (systemd, docker, /opt/<svc>/, gitverse)
- [x] change tavily-proxy-setup — ЗААРХИВИРОВАН (delta → specs/web-extract-tavily/spec.md) - [x] change tavily-proxy-setup — ЗААРХИВИРОВАН (delta → specs/web-extract-tavily/spec.md)
- [x] web_extract работает: Hermes → 8971 → SOCKS5-туннель → Tavily (HTTP 200, контент Example Domain) - [x] web_extract работает: Hermes → 8971 → SOCKS5-туннель → Tavily (HTTP 200, контент Example Domain)
- [x] change local-extractor — ЗААРХИВИРОВАН: trafilatura 2.2.0, local-режим в tavily_extract_proxy.py, тесты 2.2/2.3 зелёные (example.com и github через --local; tavily.com — geo-блок из РФ — через --local-socks 127.0.0.1:1080, HTTP 200) - [x] change local-extractor — ЗААРХИВИРОВАН: trafilatura 2.2.0, local-режим в tavily_extract_proxy.py, тесты 2.2/2.3 зелёные
- [x] Репозиторий создан на gitverse.ru (kpa39l/openspec-lab), git push -u origin main выполнен - [x] Репозиторий создан на gitverse.ru (kpa39l/openspec-lab), git push -u origin main выполнен
- [x] systemd tavily-proxy.service — решение по задаче 5: ОСТАВЛЕН forward-режим (облачный Tavily через туннель) — рабочий провайдер без изменений - [x] systemd tavily-proxy.service — решение по задаче 5: ОСТАВЛЕН forward-режим (облачный Tavily через туннель)
- [x] change vinograd-rostelecom-channel-monitoring — ЗААРХИВИРОВАН (2026-09-08): ICMP-мониторинг канала «Винный город» (РТК) в /opt/monitoring — blackbox icmp, prometheus job vinograd_wan (30s), алерт VinogradRostelecomDown, дашборд Vinograd WAN. delta → openspec/specs/vinograd-wan-monitoring/spec.md - [x] change vinograd-rostelecom-channel-monitoring — ЗААРХИВИРОВАН (2026-09-08): ICMP-мониторинг канала «Винный город» в /opt/monitoring, дашборд Vinograd WAN
- [x] change grafana-readonly-user — ЗААРХИВИРОВАН (2026-09-08): read-only пользователь Grafana it@vinogorod.ru (role Viewer, пароль 1qazXSW2), создан вручную в UI (OSS 11.1 не умеет provisioning/API create пользователей). delta → openspec/specs/grafana-access-control/spec.md
## В работе / Следующие шаги ## В работе / Следующие шаги
- (ничего — все 5 задач закрыты; лаба в стабильном состоянии) - (ничего — все задачи закрыты; лаба стабильна)
## Как запустить / проверить ## Как запустить / проверить
```bash ```bash
@@ -24,7 +25,7 @@ cd /opt/hermes/openspec-lab
openspec validate # все changes openspec validate # все changes
openspec status --change local-extractor openspec status --change local-extractor
# локальный экстрактор (тест) # локальный экстрактор (тест)
./venv/bin/python .hermes/scripts/tavily_extract_proxy.py --port 8972 --local # путь: /opt/hermes/.hermes/hermes-agent/venv/bin/python ./venv/bin/python .hermes/scripts/tavily_extract_proxy.py --port 8972 --local
curl -s -X POST http://127.0.0.1:8972/extract -d '{"urls":["https://example.com"]}' -H 'Content-Type: application/json' curl -s -X POST http://127.0.0.1:8972/extract -d '{"urls":["https://example.com"]}' -H 'Content-Type: application/json'
# рабочий прокси (systemd) # рабочий прокси (systemd)
systemctl status tavily-proxy # порт 8971, forward через туннель systemctl status tavily-proxy # порт 8971, forward через туннель
@@ -32,11 +33,12 @@ systemctl status tavily-proxy # порт 8971, forward через туннел
## Ключевые артефакты ## Ключевые артефакты
- /opt/hermes/openspec-lab/openspec/specs/web-extract-tavily/spec.md — main spec про forward-прокси - /opt/hermes/openspec-lab/openspec/specs/web-extract-tavily/spec.md — main spec про forward-прокси
- /opt/hermes/openspec-lab/openspec/specs/web-extract-local/spec.md — main spec про local-экстрактор (после archive local-extractor) - /opt/hermes/openspec-lab/openspec/specs/web-extract-local/spec.md — main spec про local-экстрактор
- /opt/hermes/openspec-lab/openspec/changes/archive/2026-09-06-local-extractor/ - /opt/hermes/openspec-lab/openspec/specs/vinograd-wan-monitoring/spec.md — ICMP-мониторинг канала
- /opt/hermes/openspec-lab/openspec/specs/grafana-access-control/spec.md — read-only пользователь Grafana
- /opt/hermes/openspec-lab/openspec/changes/archive/2026-09-08-grafana-readonly-user/ — архивный change
- /opt/hermes/.hermes/scripts/tavily_extract_proxy.py — прокси + local-режим - /opt/hermes/.hermes/scripts/tavily_extract_proxy.py — прокси + local-режим
- /etc/systemd/system/tavily-proxy.service — юнит (forward, без изменений) - /etc/systemd/system/tavily-proxy.service — юнит (forward, без изменений)
- /opt/hermes/openspec-lab/.hermes/skills/openspec-*/ — Hermes-скиллы OpenSpec
- gitverse: https://gitverse.ru/kpa39l/openspec-lab (remote origin: https://kpa39l:<TOKEN>@gitverse.ru/kpa39l/openspec-lab.git) - gitverse: https://gitverse.ru/kpa39l/openspec-lab (remote origin: https://kpa39l:<TOKEN>@gitverse.ru/kpa39l/openspec-lab.git)
## Открытые вопросы ## Открытые вопросы
+17
View File
@@ -4,6 +4,23 @@
## 2026-09-08 ## 2026-09-08
### Grafana read-only пользователь (it@vinogorod.ru, Viewer) — change grafana-readonly-user
`openspec new change grafana-readonly-user` → 4 артефакта → validate → archive
(delta → openspec/specs/grafana-access-control/spec.md).
- Задача: добавить read-only пользователя для IT Винограда.
- **Главный вывод:** Grafana 11 OSS НЕ поддерживает ни файловое provisioning
пользователей (`grafana/provisioning/access-control/users.yml` молча
игнорируется — это EE/Cloud `security.provisioning`), ни API-создание
(`POST /api/users` → 404). Создание — **только в UI** (Administration →
Users → New user, роль Viewer).
- Приятный бонус: `POST /api/login` (JSON) даёт 401 даже при верном пароле,
а **Basic auth работает** (`curl -u estorozhenko:пароль /api/user` → 200).
- Проверено end-to-end: вход it@vinogorod.ru → 200, роль Viewer, `/api/users`
→ 403 (read-only), неверный пароль → 401. Пользователь вошёл сам.
- git: мониторинг-репо запушен (da1746c, ветка **master** — не main!).
### Vinograd WAN — ICMP-мониторинг канала «Винный город» (РТК), change в /opt/monitoring ### Vinograd WAN — ICMP-мониторинг канала «Винный город» (РТК), change в /opt/monitoring
`openspec new change vinograd-rostelecom-channel-monitoring` → 4 артефакта → validate OK → archive (delta → openspec/specs/vinograd-wan-monitoring/spec.md) `openspec new change vinograd-rostelecom-channel-monitoring` → 4 артефакта → validate OK → archive (delta → openspec/specs/vinograd-wan-monitoring/spec.md)
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-08
@@ -0,0 +1,49 @@
# Design: Grafana read-only user — ручное создание (OSS-совместимо)
## Файлы
| Файл | Действие | Назначение |
|---|---|---|
| `/opt/monitoring/grafana-data/grafana.db` | изменяется Grafana при создании пользователя | хранит учётку (UI, не вручную) |
| `/opt/monitoring/README.md` | обновить | документация пользователя и роли |
| `/opt/monitoring/EXPERIENCE.md` | обновить | вывод: OSS 11.1 не умеет provisioning users |
Никакие конфиги/провиджеры НЕ меняются.
## Почему не provisioning
- `grafana/provisioning/access-control/users.yml` — файловое provisioning
пользователей в Grafana 11 OSS **не обрабатывается** (в логах только
dashboards/datasources/alerting/plugins; access-control — EE-фича).
- API: `POST /api/users` → 404 (OSS), `POST /api/login` → 401 при верном
пароле (Basic auth работает, JSON-логин нет). Доступно только создание
пользователя в **UI**.
## Создание в UI
1. Открыть `http://grafana.nixg.ru` (или `http://127.0.0.1:3001`), войти
как `estorozhenko` (admin).
2. Administration → Users → **New user**:
- Email: `it@vinogorod.ru`
- Name: `IT Vinogorod`
- Role: `Viewer`
- Password: `1qazXSW2` (задать вручную, не отсылать invite)
3. Сохранить.
## Проверка (после создания)
```bash
# 1. логин рабочий
curl -s -u 'it@vinogorod.ru:1qazXSW2' http://127.0.0.1:3001/api/user
# 2. роль Viewer в орге
curl -s -u 'estorozhenko:...' http://127.0.0.1:3001/api/orgs/1/users
# 3. read-only: админ-ручка недоступна
curl -s -u 'it@vinogorod.ru:1qazXSW2' http://127.0.0.1:3001/api/users # → 403
```
## Риски
- Слабый пароль `1qazXSW2` (клавиатурная последовательность) на публичной
Grafana. Рекомендовать смену или ограничение доступа по IP (caddy/VPN).
- Пользователь создаётся вручную — при перезаписи grafana-data потребуется
пересоздать. Продублировать в README.
@@ -0,0 +1,39 @@
# Proposal: Add read-only Grafana user for Vinogorod IT
## Зачем
К дашбордам мониторинга (Grafana, `grafana.nixg.ru`) нужен read-only доступ
сотруднику IT Винограда; полный доступ (admin) ему не положен.
- **Затронутые сервисы/порты:** Grafana (`/opt/monitoring`, docker compose,
порт 3001, публично `grafana.nixg.ru`).
- **Пользователь:** `it@vinogorod.ru`, пароль `1qazXSW2`, роль **Viewer**.
## Что
Grafana **OSS 11.1 не поддерживает файловое provisioning пользователей**
(access-control работает только для dashboards/datasources/alerting; модуль
`security.provisioning` — EE/Cloud). Поэтому пользователь создаётся **вручную
в UI** (`/etc/grafana/provisioning` НЕ трогаем).
Шаги:
1. Войти в Grafana как admin (`http:// grafana.nixg.ru`, логин estorozhenko).
2. Administration → Users → Invite/New user:
- Email: `it@vinogorod.ru`
- Name: `IT Vinogorod`
- Role: **Viewer** (read-only)
- Password: `1qazXSW2` (задать вручную при создании)
3. Убедиться, что роль Viewer (не Admin, не Editor).
## Rollback
1. Grafana → Administration → Users → `it@vinogorod.ru` → Delete.
2. Никаких файлов конфигов не менялось — откат не требуется.
3. Пароль при необходимости сменить (Administration → Users → Edit).
## Примечание
- Пароль `1qazXSW2` слабый (клавиатурный); Grafana публична. Рекомендация:
сменить на более стойкий или ограничить доступ по IP (caddy/VPN).
- Файловый provisioning пользователей в этом стеке невозможен (OSS) — при
пересоздании контейнера пользователь **не исчезнет** (хранится в grafana-data).
@@ -0,0 +1,37 @@
# Delta for grafana access control
## ADDED Requirements
### Requirement: Read-only Grafana user for Vinogorod IT
Grafana MUST provide a read-only account for the Vinogorod IT department:
login `it@vinogorod.ru`, role `Viewer`, in the default organization (orgId 1).
The account MUST NOT be able to create, edit, or delete dashboards,
datasources, or settings.
#### Scenario: User exists with Viewer role
- GIVEN the admin has created the user `it@vinogorod.ru` in the Grafana UI
- WHEN the user logs in with the shared password
- THEN authentication succeeds (Basic auth `/api/user` → HTTP 200)
- AND the organization role is `Viewer` (`/api/orgs/1/users` → role "Viewer")
#### Scenario: Unknown credentials rejected
- GIVEN the read-only user `it@vinogorod.ru`
- WHEN a request is made with a wrong password
- THEN the API returns HTTP 401
#### Scenario: Read-only enforced
- GIVEN the user `it@vinogorod.ru` is logged in as `Viewer`
- WHEN the user attempts a privileged operation (e.g. `POST /api/users`,
modify datasources)
- THEN the request is rejected (HTTP 403/404)
### Requirement: No admin rights for IT user
The IT read-only account MUST NOT have admin or editor rights; only viewing
of dashboards and logs is permitted.
#### Scenario: Role is not elevated
- GIVEN the user `it@vinogorod.ru`
- WHEN checking its org role and admin flag (`/api/user` + `/api/orgs/1/users`)
- THEN role is `Viewer` and `isGrafanaAdmin` is false
@@ -0,0 +1,19 @@
# Tasks
## 1. Создание пользователя в UI Grafana (вручную, пользователь)
- [x] 1.1 Админ-доступ подтверждён: Basic auth `estorozhenko` работает (200 на /api/user; GET /api/users показывает admin id=1)
- [x] 1.2 Проверка невозможности API-создания: `POST /api/users` → 404 (OSS 11.1 не даёт create через API)
- [x] 1.3 Создать `it@vinogorod.ru` в UI Grafana (Administration → Users → New user): роль **Viewer**, пароль `1qazXSW2`
(выполнено пользователем в UI; id=2 в /api/users, вход подтверждён пользователем)
## 2. Проверка созданного пользователя
- [x] 2.1 `curl -s -u it@vinogorod.ru:1qazXSW2 http://127.0.0.1:3001/api/user` → 200, login=it@vinogorod.ru
- [x] 2.2 Роль: в `/api/orgs/1/users` (admin) → `it@vinogorod.ru` role=`Viewer`, disabled=false
- [x] 2.3 Негатив: неверный пароль → 401
- [x] 2.4 Read-only: API `/api/users` с токеном it@vinogorod.ru → 403 (additional permissions)
## 3. Документация и git
- [x] 3.1 Обновить `/opt/monitoring/README.md` (пользователь it@vinogorod.ru, Viewer, пароль у пользователя)
- [x] 3.2 Запись в `/opt/monitoring/EXPERIENCE.md` (OSS 11.1: provisioning users не работает; API create → 404; только UI)
- [x] 3.3 `git add` (поимённо) + commit + push в gitverse (истина) — da1746c в master
- [ ] 3.4 `openspec validate grafana-readonly-user` + `openspec archive --yes` + STATUS/WALKTHROUGH
@@ -0,0 +1,40 @@
# grafana-access-control Specification
## Purpose
TBD - created by archiving change grafana-readonly-user. Update Purpose after archive.
## Requirements
### Requirement: Read-only Grafana user for Vinogorod IT
Grafana MUST provide a read-only account for the Vinogorod IT department:
login `it@vinogorod.ru`, role `Viewer`, in the default organization (orgId 1).
The account MUST NOT be able to create, edit, or delete dashboards,
datasources, or settings.
#### Scenario: User exists with Viewer role
- GIVEN the admin has created the user `it@vinogorod.ru` in the Grafana UI
- WHEN the user logs in with the shared password
- THEN authentication succeeds (Basic auth `/api/user` → HTTP 200)
- AND the organization role is `Viewer` (`/api/orgs/1/users` → role "Viewer")
#### Scenario: Unknown credentials rejected
- GIVEN the read-only user `it@vinogorod.ru`
- WHEN a request is made with a wrong password
- THEN the API returns HTTP 401
#### Scenario: Read-only enforced
- GIVEN the user `it@vinogorod.ru` is logged in as `Viewer`
- WHEN the user attempts a privileged operation (e.g. `POST /api/users`,
modify datasources)
- THEN the request is rejected (HTTP 403/404)
### Requirement: No admin rights for IT user
The IT read-only account MUST NOT have admin or editor rights; only viewing
of dashboards and logs is permitted.
#### Scenario: Role is not elevated
- GIVEN the user `it@vinogorod.ru`
- WHEN checking its org role and admin flag (`/api/user` + `/api/orgs/1/users`)
- THEN role is `Viewer` and `isGrafanaAdmin` is false