Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
etersoft-admin-essentials
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
etersoft
etersoft-admin-essentials
Commits
0997f97a
Commit
0997f97a
authored
Jul 04, 2026
by
Vitaly Lipatov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add vaultwarden-lavtomate bridge design doc
Co-Authored-By:
Claude
<
noreply@anthropic.com
>
parent
4fe1973b
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
212 additions
and
0 deletions
+212
-0
vaultwarden-lavtomate-bridge.md
.claude/docs/vaultwarden-lavtomate-bridge.md
+211
-0
CLAUDE.md
CLAUDE.md
+1
-0
No files found.
.claude/docs/vaultwarden-lavtomate-bridge.md
0 → 100644
View file @
0997f97a
# Связка lavtomate `password_request` ↔ Vaultwarden
Инструкция по реализации брокера паролей: когда Claude вызывает
`password_request`
,
пользователь одобряет в web UI, и
**lavtomate сам достаёт секрет из Vaultwarden**
своим
сервисным аккаунтом, ограниченным одной коллекцией. Claude не получает мастер-ключ,
plaintext не хранится, каждый доступ — через одобрение человека и в аудите.
Модель и обоснование: см. memory
`feedback_password_request_only.md`
.
---
## 0. Действующие лица
-
**Vaultwarden**
: https://bitwarden.eterfund.ru
-
**lavtomate**
: CT 653 на enceladus (
`lavtomate.office.etersoft.ru`
), код в
`gitlab.eterfund.ru/etersoft/...lavtomate`
. MCP-сервер, отдаёт инструмент
`password_request`
(service + description → confirmation → пароль).
-
**Claude Code**
: вызывает
`password_request`
, использует пароль разово.
Принцип тиринга: только секреты из коллекции
**`infra-claude`**
достижимы через брокер.
Критичное (AD admin, CA-ключи, root) в эту коллекцию НЕ кладём — оно недостижимо в принципе.
---
## 1. Сторона Vaultwarden (админская работа)
1.
**Организация**
(если нет):
`Etersoft Infra`
.
2.
**Коллекция**
внутри неё:
`infra-claude`
.
3.
**Сервисный аккаунт**
`claude-broker@etersoft.ru`
:
-
создать пользователя, пригласить в организацию;
-
роль
**User**
(не Admin), доступ
**только**
к коллекции
`infra-claude`
, право
**read-only**
(can view, нельзя edit/manage);
-
задать стойкий мастер-пароль (он же bootstrap-секрет, см. §3).
4.
**API-key**
сервисного аккаунта: Account Settings → Security → Keys →
**View API Key**
→
получить
`client_id`
(
`user.<uuid>`
) и
`client_secret`
. Нужны для неинтерактивного
`bw login`
.
5.
**Занести секреты**
в коллекцию
`infra-claude`
как Login-итемы. Имя итема = то, что Claude
передаёт в
`service`
(договоримся об именах, напр.):
-
`kuma`
(https://kuma.office.etersoft.ru/)
-
`grafana-telegraf`
(https://telegraf.office.etersoft.ru/)
-
`ha-divserver`
(http://192.168.1.5:8123)
Значения (login/пароль) — из admin password store:
`ssh rooter@server pass show <name>`
(не вписывать plaintext в этот файл).
> Имена итемов — это контракт. Зафиксировать список «service → item» в этом файле по мере роста.
---
## 2. Сторона хоста lavtomate: Bitwarden CLI
Ставить и настраивать под сервис-пользователем lavtomate (не root, если сервис не от root).
```
bash
# CT 653 enceladus
ssh root@lavtomate.office.etersoft.ru
# или ssh root@<ip CT 653>
# 1. CLI. На ALT — через epm; если пакета нет, официальный bw из npm:
epm
install
bitwarden-cli
||
npm i
-g
@bitwarden/cli
# бинарь `bw`
# (альтернатива — rbw, но bw ближе к официальному API)
# 2. Указать свой сервер Vaultwarden (один раз):
bw config server https://bitwarden.eterfund.ru
# 3. Логин по API-key (неинтерактивно, без мастер-пароля на этом шаге):
export
BW_CLIENTID
=
'user.<uuid>'
export
BW_CLIENTSECRET
=
'<client_secret>'
bw login
--apikey
# → статус "locked": залогинен, но vault зашифрован
```
`bw login --apikey`
устанавливает сессию аккаунта, но vault остаётся
**locked**
—
для чтения нужен
`bw unlock`
мастер-паролем (§3).
---
## 3. Bootstrap-секрет (мастер-пароль) — храним правильно
Это единственный секрет, который нельзя спрятать за
`password_request`
(курица-яйцо).
Минимизируем ущерб: аккаунт видит только
`infra-claude`
.
**Рекомендуемо — systemd credential (на диск в открытую не ложится):**
```
bash
# зашифрованный credential, читается только этим юнитом:
systemd-ask-password
"BW master for claude-broker"
|
\
systemd-creds encrypt
--name
=
bw_master - /etc/lavtomate/bw_master.cred
chmod
600 /etc/lavtomate/bw_master.cred
```
В unit lavtomate:
```
ini
[Service]
LoadCredentialEncrypted
=
bw_master:/etc/lavtomate/bw_master.cred
Environment
=
BW_CLIENTID=user.<uuid>
LoadCredentialEncrypted
=
bw_clientsecret:/etc/lavtomate/bw_clientsecret.cred
# мастер-пароль доступен процессу как файл $CREDENTIALS_DIRECTORY/bw_master
```
**Минимум-вариант**
(если без systemd-creds): env-файл
`0600`
, владелец — сервис-пользователь:
```
/etc/lavtomate/bw.env (chmod 600, chown lavtomate)
BW_CLIENTID=user.<uuid>
BW_CLIENTSECRET=...
BW_MASTER=...
```
Хуже, чем systemd-creds (лежит расшифрованным на диске), но приемлемо как первый шаг.
**Никогда**
не коммитить эти файлы и не класть в коллекцию
`infra-claude`
.
---
## 4. Управление сессией unlock
`bw unlock`
возвращает
`BW_SESSION`
— ключ для расшифровки на время жизни процесса.
Держать его
**только в памяти**
процесса lavtomate, не писать на диск.
```
bash
# при старте сервиса (псевдо):
export
BW_SESSION
=
"
$(
bw unlock
--passwordfile
"
$CREDENTIALS_DIRECTORY
/bw_master"
--raw
)
"
```
-
Перед каждым чтением проверять
`bw status`
(
`unlocked`
/
`locked`
); при
`locked`
— повторить unlock.
-
Раз в N минут
`bw sync`
(подтянуть новые/изменённые итемы).
-
При рестарте сервиса unlock выполняется заново из credential.
---
## 5. Логика обработчика `password_request` (точка интеграции в lavtomate)
На
**approve**
confirmation выполнить чтение из Vaultwarden со
**строгой проверкой области**
.
Псевдокод (адаптировать под реальный язык lavtomate):
```
python
ALLOWED_COLLECTION
=
"infra-claude"
def
on_password_request_approved
(
service
:
str
,
ctx
):
# 1. найти итем по имени == service
items
=
bw_list_items
(
search
=
service
,
session
=
BW_SESSION
)
# `bw list items --search`
item
=
exact_match
(
items
,
name
=
service
)
if
not
item
:
return
deny
(
f
"no item '{service}'"
)
# 2. ЖЁСТКО проверить, что итем в разрешённой коллекции
if
ALLOWED_COLLECTION
not
in
collection_names
(
item
):
audit
(
"DENY"
,
service
,
ctx
,
reason
=
"out of scope"
)
return
deny
(
"out of allowed collection"
)
# 3. вернуть только пароль (не весь итем) на ОДИН запрос
pw
=
item
[
"login"
][
"password"
]
# `bw get password <id>`
audit
(
"ALLOW"
,
service
,
ctx
,
item_id
=
item
[
"id"
])
return
pw
```
Критично:
-
проверка коллекции —
**на стороне lavtomate**
, не полагаться только на права аккаунта
(defense-in-depth);
-
сопоставление имени —
**точное**
(не подстрока), чтобы
`ha`
не выдал
`ha-admin`
;
-
отдавать
**только**
поле password, не username/notes/totp без явной надобности.
---
## 6. Что показывать в confirmation (контекст для решения человека)
`password_request`
уже носит
`service`
+
`description`
. В web UI показать:
-
какой
`service`
(итем) запрашивается;
-
`description`
— зачем;
-
идентификатор сессии/агента, время, короткий timeout (300с).
Чтобы пользователь мог распознать аномальный запрос и нажать
**Deny**
.
---
## 7. Аудит
-
lavtomate: писать в лог каждый запрос —
`service`
, decision (allow/deny), сессия, время, item_id.
-
Vaultwarden: организация ведёт Event Logs (вход сервис-аккаунта, доступ к итемам) — включить.
Двухслойный аудит: даже при ошибке в одном слое второй фиксирует доступ.
---
## 8. Тестирование
1.
Завести тест-итем
`test-secret`
в
`infra-claude`
, значение известное.
2.
Из Claude:
`password_request(service="test-secret", ...)`
→ approve → должен вернуть значение.
3.
**Негатив-тест области:**
создать итем
`test-forbidden`
ВНЕ
`infra-claude`
→
`password_request(service="test-forbidden")`
→ approve → должен быть
**deny**
(out of scope).
4.
**Deny-тест:**
запросить и нажать Deny → Claude получает отказ, ничего не утекает.
5.
Перезапустить lavtomate → убедиться, что unlock восстанавливается из credential.
---
## 9. После запуска связки
-
Перенести текущие пароли (kuma, grafana-telegraf, ha-divserver) в
`infra-claude`
.
-
**Удалить плоский `.claude/secrets/credentials.md`**
(он gitignored).
-
Критичные секреты (AD admin, CA-ключи) в
`infra-claude`
НЕ заводить — для них остаётся
ручной ввод в
`password_request`
или паттерн «lavtomate сам выполняет действие».
---
## 10. Откат
-
Связка изолирована в обработчике
`password_request`
; при сбое — вернуть прежнее поведение
(ручной ввод пароля в confirmation), сервис-аккаунт Vaultwarden отозвать (revoke API-key,
убрать из организации). Секреты в
`infra-claude`
остаются доступны тебе через обычный web UI.
---
## Разделение работ
-
**§1 (Vaultwarden), §9 (перенос/чистка)**
— админ (могу сделать я).
-
**§2–§7 (CLI на хосте + код обработчика)**
— изменение lavtomate → его мейнтейнеры
(
`gitlab.eterfund.ru/etersoft/...lavtomate`
). Claude — администратор, код API не правит.
CLAUDE.md
View file @
0997f97a
...
...
@@ -75,6 +75,7 @@ ansible-playbook -i /root/.ansible/hosts ansible/playbooks/NAME.yml
-
`nfs.md`
— NFS серверы aspetos/spacer, manage-gids, FS-Cache
-
`epm.md`
— epm/serv команды для ALT Linux
-
`host03.md`
— хостинг host03.eterhost.ru (nginx + Apache CT 390), процедура добавления HTTPS
-
`vaultwarden-lavtomate-bridge.md`
— связка password_request ↔ Vaultwarden (брокер паролей): инструкция по реализации
-
Ты помощник системного администратора и выполняешь задачи по моему указанию. Ведёшь себя осмотрительно и спрашиваешь при выполнении команд.
-
Подключение к удалённым серверам либо без пользователя и потом sudo su -, либо сразу root@
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment