Write

# Архитектура PKI на HashiCorp Vault OSS (DSO-192)

Документ описывает и легализует архитектуру PKI на базе HashiCorp Vault OSS для корпоративного использования.

Разделы и структура соответствуют чеклисту задачи DSO-192:

1. Безопасность и доверие.
2. Соответствие и риски.
3. Эксплуатация и доступность.

---

## 0. Executive summary

Мы используем HashiCorp Vault OSS в качестве внутреннего PKI для автоматизированного выпуска сертификатов между сервисами.

Ключевые факты:

- Vault работает как **issuing CA (intermediate)**, сертификаты которого выпущены от **корпоративного Root CA**.
- Два независимых PKI mount: `pki-stage` и `pki-prod` (разделение по критичности).
- Автоматика работает через `AppRole` с короткоживущими токенами.
- Люди логинятся через `OIDC` (Keycloak).
- Интеграция с `cert-manager` реализована через endpoint `sign` (Vault подписывает CSR, ключ генерируется клиентом).
- Vault Enterprise и внешние CA не используются (ограничение по лицензиям).

---

## 1. Безопасность и доверие

### 1.1. Иерархия CA

- **Root CA** — корпоративный, находится вне нашей зоны ответственности.
- **Intermediate CA (issuing)** — выпускается от корпоративного Root CA и устанавливается в Vault.
- Реализовано два отдельных intermediate'а внутри одного Vault-кластера:
  - `pki-stage` — для нон-прод сред и пилотов;
  - `pki-prod` — для продакшн-нагрузок.

Разделение через **разные mounts** означает:

- изолированные приватные ключи intermediate CA;
- независимые CRL/OCSP контуры;
- независимые политики, роли и ограничения;
- компрометация stage не приводит автоматически к компрометации prod.

### 1.2. Политики выпуска

Стандартизированы как **роль на продукт** внутри каждого mount'а:

- имя роли = код продукта (например `P0239`);
- `allowed_domains` ограничивает зону имен (`kafka.apim.lmru.tech` для Kafka-продукта);
- `allow_subdomains=true` и `allow_wildcard_certificates=true` разрешают структурированные имена внутри зоны;
- выпуск возможен **только** через Vault-путь роли (`issue/<ROLE>` или `sign/<ROLE>`), никаких wildcard-доступов.

Для интеграции с `cert-manager` используется endpoint `sign`:

- `cert-manager` сам генерирует приватный ключ в Kubernetes Secret;
- Vault подписывает входящий CSR в рамках ограничений роли;
- endpoint `issue` для `cert-manager` не подходит и не должен использоваться.

### 1.3. Сроки действия и отзыв

Принципы:

- **Короткий TTL по умолчанию**, renew через автоматизацию (cert-manager / CI).
- TTL задается на уровне роли (`ttl` / `max_ttl`) и/или явно в запросе.

Текущие значения для Kafka (`P0239`, stage):

- `ttl = 24h` по умолчанию;
- `max_ttl = 720h`;
- для тестов выпускаем на `168h` (неделя).

Отзыв:

- revoke выполняется через Vault по `serial_number`;
- CRL обновляется автоматически и доступен по HTTP;
- процедуру revoke владеет централизованная команда (DevSecOps/SOC), а не продуктовые команды.

### 1.4. Защита ключей и ролей

Машинный доступ:

- автоматизация использует `AppRole`:
  - `role_id` хранится в конфигурации потребителя (не секрет по классу);
  - `secret_id` генерируется отдельно и хранится **только** в корпоративном секрет-хранилище;
  - `secret_id` не попадает в Git;
  - `token_ttl = 1h`, `token_max_ttl = 1h` — никаких долгоживущих машинных токенов.

Человеческий доступ:

- только через `OIDC` (Keycloak);
- Vault root token используется только для аварийных сценариев.

Приватные ключи intermediate CA:

- хранятся внутри Vault, не извлекаются наружу;
- доступ к их экспорту не выдается никому в рамках штатной эксплуатации.

### 1.5. Аудит

Реализация:

- Включаются Vault audit devices (file backend в Vault).
- Все операции PKI (login, issue, sign, revoke, policy changes) попадают в аудит лог.

Рекомендации к развитию:

- дублировать audit в syslog/SIEM, чтобы защитить от локальной компрометации узла;
- настроить retention аудита в соответствии с требованиями ИБ после их формализации.

### 1.6. Сценарии компрометации и реагирование

| Сценарий | Последствие | Действия |
|---|---|---|
| Утечка `secret_id` AppRole | Автоматика получает токены 1h | Пересоздать `secret_id`, ротация; при необходимости `bind_secret_id`/CIDR |
| Утечка Vault OIDC-токена пользователя | Доступ в Vault с правами пользователя | Отзыв токена, смена пароля в Keycloak, выход сессий |
| Компрометация intermediate CA (`pki-stage`) | Возможность выпускать stage-сертификаты | Revoke intermediate на Root CA, ротация intermediate, revoke всех затронутых сертификатов |
| Компрометация intermediate CA (`pki-prod`) | Критично для прод | То же + инцидент-процесс, уведомление ИБ |
| Компрометация узла Vault | Доступ к зашифрованному Raft storage | Unseal блокируется без ключей; ротация ключей, восстановление из snapshot |
| Компрометация Root CA | Выходит за зону ответственности | Делегируется владельцам Root CA |

---

## 2. Соответствие и риски

### 2.1. Внутренние требования

На момент написания документа формализованных внутренних ИБ-стандартов (классификация контуров, SLA на PKI, требования аудита), на которые можно прямо сослаться, нет.

После формализации они должны быть явно добавлены в раздел 2.1 и отражены в ADR.

### 2.2. Классификация контуров

Принимаем два класса критичности на уровне PKI:

- **Stage** — нон-прод, пилоты, тестовые инсталляции. Меньшие требования к доступности и аудиту. Mount: `pki-stage`.
- **Prod** — продакшн-нагрузки. Повышенные требования к доступности, отзыву, аудиту. Mount: `pki-prod`.

Продуктовые команды выпускают сертификаты **только** внутри своего mount'а и своей роли продукта.

### 2.3. Матрица ответственности (RACI)

| Активность | DevSecOps (владелец PKI) | Продуктовая команда | SOC/ИБ | Владельцы Root CA |
|---|---|---|---|---|
| Развертывание и обслуживание Vault | R, A | I | C | I |
| Выпуск intermediate CA | R | I | C | A |
| Создание роли продукта | R | C | I | — |
| Выпуск/ротация сертификатов | A | R | I | — |
| Хранение `secret_id` в секрет-хранилище | C | R | I | — |
| Revoke сертификата | A | C | R | — |
| Инцидент с компрометацией | C | I | R, A | C |
| Ротация intermediate CA | R, A | I | C | R |

R — Responsible, A — Accountable, C — Consulted, I — Informed.

### 2.4. Критерии приемки

Архитектура считается принятой, если:

1. Согласована архитекторами ИБ, Архитекторами Компании, Техническими Архитекторами и RedTeam.
2. Есть утвержденный ADR.
3. Zugzwang-кейсы (см. 1.6) имеют зафиксированные процедуры реагирования.
4. Есть утвержденная RACI-матрица.
5. Есть работающий референсный кейс интеграции (Kafka `P0239` — реализован).

### 2.5. Исключения и компенсирующие контроли

- **Нет Vault Enterprise** → недоступны namespace'ы, performance replication, DR replication, HSM auto-unseal.
  - Компенсирующий контроль: mount-based изоляция, строгие ACL policy, регулярные Raft snapshots, процедурная автоматизация unseal.
- **Нет внешних публичных CA** → публичные сертификаты в этой архитектуре не выдаются, контур сугубо внутренний.
  - Компенсирующий контроль: зона имен ограничена внутренними доменами в `allowed_domains`.
- **Нет формализованных ИБ-стандартов** → не на что сослаться в 2.1.
  - Компенсирующий контроль: привязка к корпоративному Root CA + согласование этого документа и ADR с ИБ/архитекторами закрывает «legal» часть.

---

## 3. Эксплуатация и доступность

### 3.1. SLA на выпуск и отзыв

Предлагаемые целевые значения (на согласование):

| Метрика | Stage | Prod |
|---|---|---|
| Время выпуска сертификата (p95) | 1 минута | 30 секунд |
| Время до отображения revoke в CRL | 24 часа | 1 час |
| Доступность Vault API | 99.0% | 99.5% |

Фактические значения должны быть подтверждены после нагрузочного профилирования.

### 3.2. Обслуживание Vault (Vault OSS Community)

Архитектурные ограничения Community edition:

- **HA**: поддерживается через Raft (integrated storage), рекомендованный размер кластера 3/5 узлов.
- **DR / Performance replication**: не поддерживаются. DR реализуется через snapshot + restore.
- **Namespaces**: не поддерживаются. Изоляция строится на mount + policy.
- **HSM auto-unseal (PKCS#11)**: в OSS недоступен. Используется Shamir или cloud-KMS auto-unseal (при наличии).

Режим эксплуатации:

- unseal-ключи хранятся у нескольких доверенных владельцев (n из m);
- Raft snapshots делаются регулярно (рекомендовано — ежечасно), хранятся вне того же контура;
- тест восстановления из snapshot проводится не реже одного раза в квартал.

### 3.3. Отказоустойчивость в рамках OSS

- 3 узла Raft дают отказоустойчивость уровня "одна нода";
- 5 узлов — "две ноды".
- Отсутствие performance replication означает, что все клиенты ходят в один кластер.
- Возможность географического разнесения ограничена: active-active между регионами в OSS не поддерживается.

Решение:

- стартуем с 3 узлов Raft в одной площадке;
- при росте критичности рассматриваем 5 узлов и разнос по availability zone;
- DR — через регулярные snapshots и документированную процедуру восстановления в резервной площадке.

### 3.4. Мониторинг и алерты

Минимальный набор:

- доступность Vault API (health-check);
- статус seal (не должен быть `sealed`);
- срок действия intermediate CA (алерт за 60/30 дней);
- ошибки выпуска и подписи (5xx на `issue`/`sign`, 4xx на `auth/approle/login`);
- размер аудит-лога и ротация;
- рост `vault.expire.num_leases` (индикатор неправильно работающих потребителей).

Развертывание метрик/алертов описывается в операционной документации команды.

### 3.5. Восстановление после сбоев

Сценарии и процедуры:

1. **Перезапуск узла** → штатный, без ручного unseal, если настроен auto-unseal. Иначе — ручной unseal по процедуре.
2. **Потеря одного узла Raft** → заменить узел, добавить в кластер, выполнить Raft sync.
3. **Потеря большинства узлов** → восстановление из последнего Raft snapshot в новой инсталляции.
4. **Полная потеря площадки** → восстановление из snapshot на резервной площадке, обновление DNS/LB, валидация выпусков.
5. **Компрометация intermediate CA** → см. 1.6; включает revoke intermediate на Root CA, перевыпуск intermediate, ротация всех активных сертификатов.

Целевые RTO/RPO (к согласованию): RTO ≤ 4 часа, RPO ≤ 1 час (соответствует частоте snapshot).

### 3.6. Процедуры смены и обновления CA

**Ротация intermediate CA** (плановая, до истечения):

1. Сгенерировать новый CSR intermediate во Vault.
2. Подписать CSR у владельцев Root CA.
3. Загрузить новый issued cert во Vault как issuer.
4. Настроить нового issuer как default для mount'а.
5. Старый issuer оставить активным до истечения всех выпущенных по нему сертификатов.
6. После — удалить или перевести в read-only.

**Внеплановая смена (инцидент)**:

1. Заморозить выпуск новых сертификатов на mount'е.
2. Выполнить revoke скомпрометированного intermediate у владельцев Root CA.
3. Выпустить новый intermediate.
4. Перевыпустить все активные leaf-сертификаты через автоматизацию (cert-manager/CI).
5. Обновить CRL-потребителей, убедиться в доставке.

Rotate intermediate должен быть отрепетирован на stage до применения на prod.

# ADR-001: Архитектура внутреннего PKI на HashiCorp Vault OSS

- **Статус**: Draft (на согласование)
- **Дата**: 2026-04-24
- **Автор**: Руслан Петрович (DevSecOps)
- **Связанные артефакты**: `docs/pki-architecture.md`, задача DSO-192
- **Согласующие**: Архитекторы ИБ, Архитекторы Компании, Технические Архитекторы, RedTeam

---

## Context

Компании требуется внутренний PKI для автоматизированного выпуска TLS-сертификатов между сервисами (mTLS, Kafka brokers, внутренние HTTPS endpoints).

Исходные условия:

- Корпоративный Root CA существует и эксплуатируется отдельной командой; мы не владеем Root CA.
- Vault Enterprise недоступен (ограничение по лицензиям).
- Внешние (публичные) CA в этом контуре не применяются — он полностью внутренний.
- Формализованных внутренних ИБ-стандартов (классификация, SLA, требования аудита) на момент принятия решения нет; документ и ADR являются первичной фиксацией.
- Референсный потребитель (Kafka, продукт `P0239`) уже внедрен и проверен.

Ключевая проблема: без централизованного PKI команды идут в сторону "у каждого своя мини-CA" или ручной выдачи сертификатов, что создает риски безопасности, операционные издержки и невозможность единого контроля.

---

## Decision

В качестве корпоративного внутреннего PKI используем **HashiCorp Vault OSS** со следующей архитектурой:

1. **Иерархия**:
   - Root CA — корпоративный, внешний по отношению к нашей инсталляции;
   - Vault эксплуатирует **два intermediate CA**, выпущенные от корпоративного Root CA:
     - `pki-stage` — нон-прод;
     - `pki-prod` — продакшн.

2. **Изоляция** — через разные PKI mounts:
   - независимые приватные ключи intermediate;
   - независимые CRL;
   - независимые policy, роли и ACL.

3. **Модель ролей** — одна роль на продукт внутри каждого mount'а:
   - имя роли = код продукта (пример: `P0239`);
   - `allowed_domains` ограничивает доменную зону продукта;
   - `allow_subdomains` и `allow_wildcard_certificates` разрешают структуру SAN внутри зоны.

4. **Интеграция с Kubernetes/cert-manager**:
   - строго через endpoint `sign` (Vault подписывает CSR, приватный ключ остается у клиента);
   - endpoint `issue` для cert-manager не применяется.

5. **Доступ**:
   - люди — через OIDC (Keycloak);
   - автоматика — через AppRole с короткими токенами (`token_ttl` ≤ 1h);
   - root token — только для аварий.

6. **Хранение секретов**:
   - `role_id` — в конфигурации потребителя;
   - `secret_id` — только в корпоративном секрет-хранилище, не в Git.

7. **Эксплуатация Vault**:
   - Raft integrated storage, 3 узла (с возможностью расширения до 5);
   - регулярные Raft snapshots и квартальные тесты восстановления;
   - DR — через snapshot + restore (performance/DR replication недоступны в OSS).

8. **Revoke и CRL**:
   - владельцем процедуры revoke являются DevSecOps/SOC, не продуктовые команды;
   - CRL публикуется Vault и доступен потребителям.

Детальное описание — в `docs/pki-architecture.md`.

---

## Alternatives considered

### A. Vault Enterprise

**Плюсы**:

- Namespaces для многотенантности.
- DR и performance replication из коробки.
- HSM auto-unseal (PKCS#11).
- Официальная корпоративная поддержка.

**Минусы**:

- Недоступен по лицензионным ограничениям компании.

**Решение**: отклонено по причине отсутствия лицензии. Компенсируем недостающие возможности mount-based изоляцией, процедурной автоматизацией unseal и регулярными snapshot-ами.

### B. Другой PKI-инструмент (не Vault)

Рассматривается как принципиально другой путь: замена Vault на альтернативную платформу управления сертификатами.

**Плюсы**:

- Может иметь более узкую специализацию под PKI.

**Минусы**:

- Потеря уже реализованной интеграции и работающего рабочего контура для Kafka `P0239`.
- Новая operational cost, новое обучение команд.
- В компании уже используется Vault для других задач; отдельный инструмент только под PKI увеличивает fleet.

**Решение**: отклонено. Vault OSS покрывает требования, есть рабочий референсный кейс.

### C. Децентрализованный подход (каждая команда делает свою CA/выдачу)

**Плюсы**:

- Нулевая зависимость от централизованной команды.

**Минусы**:

- Нет единого контроля, аудита, стандартов.
- Дублирование усилий, несовместимые конфигурации.
- Высокий риск ошибок ИБ.

**Решение**: отклонено как противоречащее целям централизации и ИБ-контроля.

---

## Consequences

### Положительные

- Единая точка выпуска, единый контроль ACL, единый аудит.
- Короткоживущие машинные токены вместо долгоживущих секретов.
- Изоляция stage/prod на уровне разных intermediate CA.
- Готовая интеграция с cert-manager через `sign`.
- Масштабируемость на новые продукты без изменения архитектуры (нужно только новая роль и policy).

### Отрицательные / компромиссы

- Без Vault Enterprise: нет namespace'ов, нет performance replication, ограничены варианты HA.
- Повышенная операционная ответственность команды DevSecOps за snapshot/restore и unseal.
- Публичные сертификаты не выдаются — только внутренние домены.
- Без формализованных ИБ-стандартов ADR сам является первичной фиксацией правил.

### Compliance и ИБ

- Доверие цепочки — через выпуск intermediate от корпоративного Root CA.
- Аудит — Vault audit backend + рекомендация по дублированию в SIEM.
- Ротация и revoke — владельцем процедур является DevSecOps/SOC.
- Компрометационные сценарии зафиксированы в `docs/pki-architecture.md` §1.6.

---

## Review и статус согласования

| Роль | Представитель | Статус |
|---|---|---|
| Архитекторы ИБ | — | Pending |
| Архитекторы Компании | — | Pending |
| Технические Архитекторы | — | Pending |
| RedTeam | — | Pending |

После сбора апрувов статус ADR меняется на **Accepted** и фиксируется дата.


Готово. Сделал два документа под DSO-192, с учетом твоих ответов (никаких внешних регуляторных требований, без разделов «связанные артефакты» и «открытые вопросы», Vault Enterprise и внешние CA исключены, Root CA корпоративный, внутренних ИБ-стандартов для ссылок нет).

### Созданные файлы

- `docs/pki-architecture.md` — основной архитектурный документ под три блока чеклиста.
- `docs/adr/ADR-001-pki-architecture.md` — draft ADR для согласования.

### Что внутри `docs/pki-architecture.md`

- `0. Executive summary`
- `1. Безопасность и доверие`
  - `1.1` Иерархия CA (Root корпоративный → два intermediate в Vault)
  - `1.2` Политики выпуска (роль на продукт, `sign` vs `issue`)
  - `1.3` Сроки и отзыв
  - `1.4` Защита ключей и ролей (AppRole, OIDC, приватные ключи intermediate)
  - `1.5` Аудит
  - `1.6` Сценарии компрометации (таблица)
- `2. Соответствие и риски` (без внешних регуляторов)
  - `2.1` Внутренние требования — с явной ремаркой, что формальных стандартов пока нет
  - `2.2` Классификация контуров (stage / prod)
  - `2.3` RACI-матрица
  - `2.4` Критерии приемки
  - `2.5` Исключения и компенсирующие контроли (Enterprise/public CA/стандарты)
- `3. Эксплуатация и доступность`
  - `3.1` SLA (целевые значения на согласование)
  - `3.2` Обслуживание Vault OSS (с честным списком, чего нет в Community)
  - `3.3` Отказоустойчивость в рамках OSS
  - `3.4` Мониторинг и алерты
  - `3.5` DR-сценарии и целевые RTO/RPO
  - `3.6` Плановая и внеплановая ротация intermediate CA

### Что внутри ADR

- `Status: Draft`, автор, список согласующих (ИБ-архитекторы, Архитекторы Компании, ТехАрхитекторы, RedTeam).
- `Context` с фиксацией вводных: Root CA корпоративный, Vault Enterprise нет, внешних CA нет, стандартов пока нет.
- `Decision` — 8 пунктов: иерархия, mounts, роли, `sign` для cert-manager, OIDC/AppRole, хранение секретов, эксплуатация Vault, revoke.
- `Alternatives considered`:
  - A — Vault Enterprise (отклонено, нет лицензии);
  - B — другой инструмент (отклонено, Vault уже закрывает задачу и есть работающий контур);
  - C — децентрализация (отклонено по ИБ-соображениям).
- `Consequences` — плюсы и честные компромиссы (нет namespaces/replication/HSM), Compliance/ИБ.
- `Review` — таблица согласующих, после апрувов статус меняем на Accepted.

### Следующие шаги

1. Открой `docs/pki-architecture.md` — прочитай разделы 1.3 (TTL), 3.1 (SLA), 3.5 (RTO/RPO). Это единственные места, где стоят «предлагаемые» значения — их стоит поправить под свои ожидания перед показом.
2. Отправь оба документа тимлиду для предварительной проверки, потом выноси на согласование.
3. После согласования я поменяю статус ADR на Accepted и уберу пометки «на согласование».

Если хочешь — следом сделаю короткий email-черновик для рассылки архитекторам, со ссылкой на оба документа и списком вопросов к каждой роли.


<user_query>
про auto-unseal надо изменить, что ожидается переход коммунального Vault на новую версию, после этого появиться возможность добавить auto-unseal
</user_query>


Поправлю упоминания auto-unseal в `pki-architecture.md` и в ADR, чтобы отразить план перехода коммунального Vault на новую версию.

 I need to locate all mentions of auto-unseal in the PKI architecture documentation and update them to reflect that it'll become available after the Vault migration to the new version.


StrReplace

- **Нет Vault Enterprise** → недоступны namespace'ы, performance replication, DR replication, HSM auto-unseal.
  - Компенсирующий контроль: mount-based изоляция, строгие ACL policy, регулярные Raft snapshots, процедурная автоматизация unseal.

- **Нет Vault Enterprise** → недоступны namespace'ы, performance replication, DR replication, HSM auto-unseal.
  - Компенсирующий контроль: mount-based изоляция, строгие ACL policy, регулярные Raft snapshots, процедурная автоматизация unseal.
  - Планируется миграция коммунального Vault на новую версию; после этого появится возможность включить auto-unseal и перейти со Shamir на auto-unseal без изменения архитектуры PKI.

- **HSM auto-unseal (PKCS#11)**: в OSS недоступен. Используется Shamir или cloud-KMS auto-unseal (при наличии).

Режим эксплуатации:

- unseal-ключи хранятся у нескольких доверенных владельцев (n из m);
- Raft snapshots делаются регулярно (рекомендовано — ежечасно), хранятся вне того же контура;
- тест восстановления из snapshot проводится не реже одного раза в квартал.

- **HSM auto-unseal (PKCS#11)**: в OSS недоступен.
- **Текущий unseal**: Shamir (n из m доверенных владельцев).
- **Плановый переход**: ожидается миграция коммунального Vault на новую версию, после которой появится возможность включить auto-unseal; это будет сделано отдельным мероприятием и не меняет архитектуру PKI.

Режим эксплуатации:

- до перехода — unseal-ключи (Shamir) хранятся у нескольких доверенных владельцев (n из m);
- после перехода на auto-unseal — ручные Shamir-ключи выводятся из оборота по регламенту, процедура документируется отдельно;
- Raft snapshots делаются регулярно (рекомендовано — ежечасно), хранятся вне того же контура;
- тест восстановления из snapshot проводится не реже одного раза в квартал.

1. **Перезапуск узла** → штатный, без ручного unseal, если настроен auto-unseal. Иначе — ручной unseal по процедуре.

1. **Перезапуск узла** → сейчас требуется ручной unseal по процедуре (Shamir). После миграции коммунального Vault на новую версию с auto-unseal перезапуск станет штатным без ручного участия.

**Решение**: отклонено по причине отсутствия лицензии. Компенсируем недостающие возможности mount-based изоляцией, процедурной автоматизацией unseal и регулярными snapshot-ами.

**Решение**: отклонено по причине отсутствия лицензии. Компенсируем недостающие возможности mount-based изоляцией, процедурной автоматизацией unseal и регулярными snapshot-ами. Auto-unseal планируется включить после миграции коммунального Vault на новую версию (вне рамок этого ADR).

- Повышенная операционная ответственность команды DevSecOps за snapshot/restore и unseal.

- Повышенная операционная ответственность команды DevSecOps за snapshot/restore и unseal. До перехода коммунального Vault на новую версию unseal выполняется по Shamir-процедуре, после — планируется auto-unseal.


Обновил оба документа. Сейчас формулировки по auto-unseal выглядят так:

- В `docs/pki-architecture.md`:
  - раздел 2.5 (исключения) — отмечено, что после миграции коммунального Vault на новую версию появится возможность включить auto-unseal без изменений архитектуры PKI;
  - раздел 3.2 (обслуживание Vault OSS) — явно описан текущий режим `Shamir` и плановый переход на auto-unseal;
  - раздел 3.5 (восстановление после сбоев) — уточнено, что сейчас перезапуск узла требует ручного unseal, а после миграции станет штатным без ручного участия.

- В `docs/adr/ADR-001-pki-architecture.md`:
  - в alternative A (Vault Enterprise) — фиксирована ссылка, что auto-unseal планируется после миграции коммунального Vault;
  - в Consequences — уточнена операционная нагрузка и планируемый переход на auto-unseal.

Если хочешь, также могу добавить отдельный блок "план миграции на новую версию Vault" в раздел 3.5 как последовательность шагов; но это обычно уже тема отдельного runbook, а не архитектурного документа.


<user_query>
INIT-1793 Замена Vault EE на Vault CE

</user_query>


Понял, это конкретная инициатива INIT-1793 (замена Vault EE на Vault CE у коммунального Vault). Уточню формулировки в обоих документах — чтобы вместо общего "переход на новую версию" была привязка к INIT-1793.

 Ah, so the initiative is actually to replace Vault Enterprise with the Community Edition—the opposite of what I initially thought. Let me reconsider: the user mentioned earlier that acquiring Vault Enterprise wasn't an option, which now makes sense as context for why they're moving toward CE instead.

The key insight is that auto-unseal via cloud KMS (AWS, GCP, Azure) or Transit seal works fine in CE, so the migration doesn't eliminate that capability. The user's comment about auto-unseal becoming possible after migration suggests they're currently running Shamir-based unsealing on the communal Vault EE, and the plan is to switch to CE with a new version and configure cloud KMS auto-unseal at that point.

I need to update the documentation to reference INIT-1793 specifically, clarify that this is about replacing EE with CE (not just upgrading versions), and note that auto-unseal configuration will happen as part of or following this migration.

- **Нет Vault Enterprise** → недоступны namespace'ы, performance replication, DR replication, HSM auto-unseal.
  - Компенсирующий контроль: mount-based изоляция, строгие ACL policy, регулярные Raft snapshots, процедурная автоматизация unseal.
  - Планируется миграция коммунального Vault на новую версию; после этого появится возможность включить auto-unseal и перейти со Shamir на auto-unseal без изменения архитектуры PKI.

- **Нет Vault Enterprise** → недоступны namespace'ы, performance replication, DR replication, HSM auto-unseal.
  - Компенсирующий контроль: mount-based изоляция, строгие ACL policy, регулярные Raft snapshots, процедурная автоматизация unseal.
  - В рамках инициативы **INIT-1793 «Замена Vault EE на Vault CE»** коммунальный Vault переводится с Enterprise на Community Edition; в ходе этого мероприятия будет включён auto-unseal (через Transit или cloud KMS — доступно в CE), что позволит уйти от Shamir без изменения архитектуры PKI.

- **HSM auto-unseal (PKCS#11)**: в OSS недоступен.
- **Текущий unseal**: Shamir (n из m доверенных владельцев).
- **Плановый переход**: ожидается миграция коммунального Vault на новую версию, после которой появится возможность включить auto-unseal; это будет сделано отдельным мероприятием и не меняет архитектуру PKI.

Режим эксплуатации:

- до перехода — unseal-ключи (Shamir) хранятся у нескольких доверенных владельцев (n из m);
- после перехода на auto-unseal — ручные Shamir-ключи выводятся из оборота по регламенту, процедура документируется отдельно;
- Raft snapshots делаются регулярно (рекомендовано — ежечасно), хранятся вне того же контура;
- тест восстановления из snapshot проводится не реже одного раза в квартал.

- **HSM auto-unseal (PKCS#11)**: в CE недоступен.
- **Текущий unseal**: Shamir (n из m доверенных владельцев).
- **Плановый переход** — в рамках инициативы **INIT-1793 «Замена Vault EE на Vault CE»**:
  - коммунальный Vault переводится с Enterprise на Community Edition;
  - в ходе миграции настраивается auto-unseal (Transit или cloud KMS, доступно в CE);
  - работа ведётся отдельным мероприятием, архитектура PKI не меняется.

Режим эксплуатации:

- до завершения INIT-1793 — unseal-ключи (Shamir) хранятся у нескольких доверенных владельцев (n из m);
- после включения auto-unseal — ручные Shamir-ключи выводятся из оборота по регламенту, процедура документируется отдельно;
- Raft snapshots делаются регулярно (рекомендовано — ежечасно), хранятся вне того же контура;
- тест восстановления из snapshot проводится не реже одного раза в квартал.

1. **Перезапуск узла** → сейчас требуется ручной unseal по процедуре (Shamir). После миграции коммунального Vault на новую версию с auto-unseal перезапуск станет штатным без ручного участия.

1. **Перезапуск узла** → сейчас требуется ручной unseal по процедуре (Shamir). После завершения INIT-1793 и включения auto-unseal перезапуск станет штатным без ручного участия.

**Решение**: отклонено по причине отсутствия лицензии. Компенсируем недостающие возможности mount-based изоляцией, процедурной автоматизацией unseal и регулярными snapshot-ами. Auto-unseal планируется включить после миграции коммунального Vault на новую версию (вне рамок этого ADR).

**Решение**: отклонено по причине отсутствия лицензии. Компенсируем недостающие возможности mount-based изоляцией, процедурной автоматизацией unseal и регулярными snapshot-ами. Кроме того, в рамках инициативы **INIT-1793 «Замена Vault EE на Vault CE»** коммунальный Vault переводится с Enterprise на Community Edition, и auto-unseal (Transit или cloud KMS) будет включён в ходе этой миграции — вне рамок данного ADR.

- Повышенная операционная ответственность команды DevSecOps за snapshot/restore и unseal. До перехода коммунального Vault на новую версию unseal выполняется по Shamir-процедуре, после — планируется auto-unseal.

- Повышенная операционная ответственность команды DevSecOps за snapshot/restore и unseal. До завершения INIT-1793 unseal выполняется по Shamir-процедуре; после миграции коммунального Vault с EE на CE планируется включить auto-unseal.


Привязал формулировки про auto-unseal к конкретной инициативе INIT-1793.

Изменения:

- `docs/pki-architecture.md`:
  - раздел 2.5: уточнено, что в рамках **INIT-1793 «Замена Vault EE на Vault CE»** коммунальный Vault переводится с Enterprise на CE, и в ходе этого auto-unseal (Transit/cloud KMS — доступно в CE) будет включён;
  - раздел 3.2: расшифровано — HSM auto-unseal в CE недоступен, сейчас Shamir, после INIT-1793 — auto-unseal;
  - раздел 3.5: перезапуск узла станет штатным без ручного участия после завершения INIT-1793.

- `docs/adr/ADR-001-pki-architecture.md`:
  - в альтернативе A (Vault Enterprise) указана привязка к INIT-1793;
  - в Consequences уточнена операционная нагрузка до/после INIT-1793.

Если у INIT-1793 в трекере есть официальное название или ссылка на тикет — могу подставить её тоже (чтобы рецензенты могли перейти одним кликом).


<external_links>
### Potentially Relevant Websearch Results

You should respond as if these information are known to you. Refrain from saying "I am unable to browse the internet" or "I don't have access to the internet" or "I'm unable to provide real-time news updates". This is your internet search results. Please always cite any links you referenced from the above search results in your response in markdown format.

-------
Website URL: https://tracker.yandex.ru/INIT-1793
Website Title: Вы не робот?
Website Content:
# Подтвердите, что запросы отправляли вы, а не робот

Нам очень жаль, но запросы с вашего устройства похожи на автоматические. Почему это могло произойти?

Я не робот Нажмите, чтобы продолжить

SmartCaptcha by Yandex Cloud

Если у вас возникли проблемы, пожалуйста, воспользуйтесь формой обратной связи

8573695692640250717:1777025463
____

</external_links>
<user_query>
https://tracker.yandex.ru/INIT-1793
</user_query>


Добавлю ссылку на INIT-1793 во все места, где она упоминается — чтобы рецензенты могли перейти в тикет.

 The user shared a Yandex Tracker link to INIT-1793, but I can't access it directly due to a captcha. I'll add the link to both documents so reviewers can view it themselves.


- В рамках инициативы **INIT-1793 «Замена Vault EE на Vault CE»** коммунальный Vault переводится с Enterprise на Community Edition; в ходе этого мероприятия будет включён auto-unseal (через Transit или cloud KMS — доступно в CE), что позволит уйти от Shamir без изменения архитектуры PKI.

- В рамках инициативы [**INIT-1793 «Замена Vault EE на Vault CE»**](https://tracker.yandex.ru/INIT-1793) коммунальный Vault переводится с Enterprise на Community Edition; в ходе этого мероприятия будет включён auto-unseal (через Transit или cloud KMS — доступно в CE), что позволит уйти от Shamir без изменения архитектуры PKI.

- **Плановый переход** — в рамках инициативы **INIT-1793 «Замена Vault EE на Vault CE»**:

- **Плановый переход** — в рамках инициативы [**INIT-1793 «Замена Vault EE на Vault CE»**](https://tracker.yandex.ru/INIT-1793):

- до завершения INIT-1793 — unseal-ключи (Shamir) хранятся у нескольких доверенных владельцев (n из m);

- до завершения [INIT-1793](https://tracker.yandex.ru/INIT-1793) — unseal-ключи (Shamir) хранятся у нескольких доверенных владельцев (n из m);

1. **Перезапуск узла** → сейчас требуется ручной unseal по процедуре (Shamir). После завершения INIT-1793 и включения auto-unseal перезапуск станет штатным без ручного участия.

1. **Перезапуск узла** → сейчас требуется ручной unseal по процедуре (Shamir). После завершения [INIT-1793](https://tracker.yandex.ru/INIT-1793) и включения auto-unseal перезапуск станет штатным без ручного участия.

**Решение**: отклонено по причине отсутствия лицензии. Компенсируем недостающие возможности mount-based изоляцией, процедурной автоматизацией unseal и регулярными snapshot-ами. Кроме того, в рамках инициативы **INIT-1793 «Замена Vault EE на Vault CE»** коммунальный Vault переводится с Enterprise на Community Edition, и auto-unseal (Transit или cloud KMS) будет включён в ходе этой миграции — вне рамок данного ADR.

**Решение**: отклонено по причине отсутствия лицензии. Компенсируем недостающие возможности mount-based изоляцией, процедурной автоматизацией unseal и регулярными snapshot-ами. Кроме того, в рамках инициативы [**INIT-1793 «Замена Vault EE на Vault CE»**](https://tracker.yandex.ru/INIT-1793) коммунальный Vault переводится с Enterprise на Community Edition, и auto-unseal (Transit или cloud KMS) будет включён в ходе этой миграции — вне рамок данного ADR.

- Повышенная операционная ответственность команды DevSecOps за snapshot/restore и unseal. До завершения INIT-1793 unseal выполняется по Shamir-процедуре; после миграции коммунального Vault с EE на CE планируется включить auto-unseal.

- Повышенная операционная ответственность команды DevSecOps за snapshot/restore и unseal. До завершения [INIT-1793](https://tracker.yandex.ru/INIT-1793) unseal выполняется по Shamir-процедуре; после миграции коммунального Vault с EE на CE планируется включить auto-unseal.


Проставил кликабельные ссылки на [INIT-1793](https://tracker.yandex.ru/INIT-1793) во всех местах, где он упоминается:

- `docs/pki-architecture.md` — 4 ссылки (разделы 2.5, 3.2 × 2, 3.5);
- `docs/adr/ADR-001-pki-architecture.md` — 2 ссылки (Alternatives A и Consequences).

Сам тикет я открыть не могу — Яндекс Трекер требует авторизацию и отдаёт капчу. Если нужно, пришли заголовок/описание из тикета, и я вставлю в документы короткий цитатный блок (например, статус и DoD), чтобы рецензентам не приходилось кликать.


<user_query>
- **Текущий unseal**: Shamir (1 из 1 доверенных владельцев для теста). так норм или префразировать?
</user_query>


Переформулировать стоит — "1 из 1 для теста" в архитектурном документе архитекторам/ИБ читается как "сейчас PKI фактически не защищён по unseal". Лучше явно разделить **текущее состояние (временно)** и **целевое состояние (до промышленной эксплуатации)**.

 The user is asking about whether to keep the current phrasing around the Shamir unseal configuration in their PKI architecture document, or if it needs rewording. The current setup has just one person holding the unseal key, which is clearly a testing scenario rather than something production-ready. For a document that'll be reviewed by architects and security people, I need to balance being honest about the current state while also considering how to present it appropriately.

I'm thinking the best approach is to separate what's happening right now from what should happen before this goes into production—maybe something like noting the current temporary setup with Shamir 1-of-1 for development, then clearly stating the target configuration with distributed keys among trusted owners or auto-unseal once the relevant work is complete. Let me look at the actual file context to see what makes the most sense.


Проблема не только в формулировке — ещё и внутреннее противоречие: на строке 182 ты пишешь "1 из 1", а на 190 — "n из m". Правлю так, чтобы было честно и без противоречий.

 I'm seeing a few options for how to phrase this better — either split it into current temporary state versus the target pre-production state, simplify it to just "current test state," or keep it as is. But there's also an inconsistency I need to flag: line 190 mentions Shamir keys distributed among n of m owners, which contradicts what line 182 says about "1 of 1."

- **HSM auto-unseal (PKCS#11)**: в CE недоступен.
- **Текущий unseal**: Shamir (1 из 1 доверенных владельцев для теста).
- **Плановый переход** — в рамках инициативы [**INIT-1793 «Замена Vault EE на Vault CE»**](https://tracker.yandex.ru/INIT-1793):
  - коммунальный Vault переводится с Enterprise на Community Edition;
  - в ходе миграции настраивается auto-unseal (Transit или cloud KMS, доступно в CE);
  - работа ведётся отдельным мероприятием, архитектура PKI не меняется.

Режим эксплуатации:

- до завершения [INIT-1793](https://tracker.yandex.ru/INIT-1793) — unseal-ключи (Shamir) хранятся у нескольких доверенных владельцев (n из m);
- после включения auto-unseal — ручные Shamir-ключи выводятся из оборота по регламенту, процедура документируется отдельно;
- Raft snapshots делаются регулярно (рекомендовано — ежечасно), хранятся вне того же контура;
- тест восстановления из snapshot проводится не реже одного раза в квартал.

- **HSM auto-unseal (PKCS#11)**: в CE недоступен.
- **Текущее состояние unseal (временно, этап настройки)**: Shamir `1-of-1`. Эта конфигурация допустима только до завершения [INIT-1793](https://tracker.yandex.ru/INIT-1793) и не является целевой.
- **Целевое состояние unseal (до промышленной эксплуатации)** — в рамках инициативы [**INIT-1793 «Замена Vault EE на Vault CE»**](https://tracker.yandex.ru/INIT-1793):
  - коммунальный Vault переводится с Enterprise на Community Edition;
  - в ходе миграции настраивается auto-unseal (Transit или cloud KMS, доступно в CE);
  - работа ведётся отдельным мероприятием, архитектура PKI не меняется.

Режим эксплуатации:

- на текущем этапе — Shamir `1-of-1` (временная тестовая конфигурация, признаётся риском и закрывается через INIT-1793);
- если INIT-1793 затягивается — переходим на Shamir `n-of-m` с распределением ключей между доверенными владельцами по регламенту ИБ;
- после включения auto-unseal — ручные Shamir-ключи выводятся из оборота по регламенту, процедура документируется отдельно;
- Raft snapshots делаются регулярно (рекомендовано — ежечасно), хранятся вне того же контура;
- тест восстановления из snapshot проводится не реже одного раза в квартал.


Почему так — коротко, чтобы ты сам решил, оставить/откатить:

**Было хуже по двум причинам**

- "Shamir 1 из 1 для теста" в архитектурном документе выглядит как "текущая рекомендуемая конфигурация". Архитекторы ИБ/RedTeam на этом месте застрянут.
- У тебя уже было противоречие: строка 182 — "1 из 1", строка 190 — "n из m". Одно из них было неправдой.

**Что теперь в документе**

- Явно помечено: текущий `Shamir 1-of-1` — **временное тестовое состояние**, **не целевое**, закрывается через INIT-1793.
- Целевое состояние — auto-unseal через Transit/cloud KMS после миграции EE→CE.
- Есть fallback: если INIT-1793 затянется, переходим на `Shamir n-of-m` по регламенту ИБ (чтобы не жить годами на `1-of-1`).
- Убрано противоречие между строками.

Если хочешь совсем нейтрально и без "признаётся риском" — могу убрать это слово, но именно такая формулировка снимет вопросы от ИБ на ревью.


<user_query>
Shamir `n-of-m` какой рекомендуется выбрать формат?
</user_query>


Стандартная практика — **5 ключей / порог 3** (в нотации: `threshold=3 of shares=5`). Это же дефолт HashiCorp для `vault operator init` ([Vault docs](https://developer.hashicorp.com/vault/docs/commands/operator/init)).

## Что рекомендовать в документе

**Целевой формат (для pre-prod и prod):** `threshold = 3 of shares = 5`.

Почему именно так:

- 3 — порог ≥ 2, чтобы **один скомпрометированный ключ не давал unseal**;
- 5 — есть запас на ротации и отпуска, при этом не слишком много для физического хранения;
- дефолт HashiCorp — его проще согласовать с ИБ, не надо доказывать «почему именно столько».

**Минимально допустимый формат (если людей мало):** `threshold = 2 of shares = 3`.

## Кто держит ключи

Чтобы схема имела смысл, ключи должны лежать **в разных зонах доверия**:

- 1 — DevSecOps (владелец PKI)
- 1 — Платформа/SRE
- 1 — ИБ
- 1 — резервный в сейфе (опечатанный, off-site)
- 1 — ещё один резерв (другая физическая локация)

Если 5 владельцев — перебор, можно 3: DevSecOps / ИБ / резерв в сейфе.

Обязательные практики:

- ключи шифруются PGP-ключами владельцев при `init`/`rekey` (Vault это поддерживает);
- никто не хранит в открытом виде, не в переписке, не в общих чатах;
- `rekey` (`vault operator rekey`) — плановая процедура минимум раз в N месяцев и при смене владельца;
- регламент `unseal` в инциденте (кто звонит, кому, в каком порядке).

## Как формулируем в документе

Предлагаю такую формулировку (если согласен — внесу):

- Целевой fallback: `Shamir threshold=3 of shares=5`, ключи распределены между DevSecOps, ИБ и минимум двумя независимыми резервами; хранение — зашифровано PGP-ключами владельцев; ротация и rekey — по регламенту ИБ.
- Минимально допустимый fallback при нехватке владельцев: `threshold=2 of shares=3`.

Хочешь — сразу пропишу именно это в `docs/pki-architecture.md` вместо текущего обобщённого "n-of-m".

 The user is asking about recommended Shamir secret sharing configurations for Vault. The standard approach is 5 shares with a threshold of 3, which balances security against the risk of losing access. Production systems should never use a 1-of-1 setup, and higher security requirements might call for 7 shares with a 4-share threshold instead. The core idea is distributing the key across multiple holders to eliminate single points of failure while maintaining a reasonable threshold for recovery.

For implementation, I'm thinking through the practical recommendation: 5-of-3 is HashiCorp's default and industry standard for corporate PKI setups, with each key held by different trusted team members and backups stored separately. For smaller teams, 3-of-2 is the minimum acceptable configuration. I should clarify the nomenclature since the user wrote "n-of-m"—that means n shares required out of m total, so 3-of-5 means 3 required from 5 total shares. I'll recommend the standard approach, explain the tradeoffs, suggest who should hold the keys, and offer to document this in their setup guide.


<user_query>
несчет рутового серта.
у нас рутовый серт на виндовс инфре, CSR сгенерированный Вольтом он не принимает. Поэтому команда itop выдает готовый сертификат
</user_query>


Это важная особенность — ломает стандартный vault-флоу "generate CSR → sign by Root". Нужно переписать разделы про иерархию CA и про ротацию intermediate. Посмотрю, что сейчас, и поправлю точечно.

 So the Root CA is Windows-based and won't accept CSRs from Vault, which means the ITOP team generates the intermediate certificate themselves and loads it directly into Vault rather than following the standard workflow where Vault creates the CSR. In Vault, this requires using the `set-signed-certificate` approach instead of the typical CSR signing flow.

Since ITOP provides the complete keypair (certificate plus private key), I need to import the entire bundle into Vault using either the legacy `config/ca` endpoint or the newer `issuers/import/bundle` endpoint with the PEM bundle. The actual process is straightforward: ITOP generates the intermediate cert and key on their Windows CA, hands it over as a PEM bundle, and we import it into Vault as an issuer.

This is a critical architectural difference that needs to be documented properly — I should update the PKI architecture docs to clarify that the intermediate comes from an external team rather than being generated by Vault, and revise the rotation procedure section to reflect this "ITOP issues → we import" flow instead of the standard "Vault CSR → Root signs" approach. I'll also need to update the ADR context to mention this Windows CA constraint.


 I need to update the PKI architecture documentation to clarify that the Root CA runs on Windows infrastructure and doesn't accept Vault CSRs directly — instead, the ITOP team generates the intermediate certificate with its keypair outside of Vault and imports it. I also need to revise the key protection section to reflect that the intermediate's private key is generated externally by ITOP rather than within Vault itself.

For the rotation section, I'll replace the current steps with the actual workflow: ITOP issues a new certificate and key bundle, then we import it into Vault. The ADR needs similar updates to document this constraint and the external issuance process, plus I should explicitly note the security consideration that the private key exists outside Vault during the handover period — this is a risk that needs compensating controls.

Let me start by checking the exact wording around the key protection section to make sure I'm accurately representing what's already there versus what needs to change.


Обновляю три блока: 1.1 (иерархия), 1.4 (защита ключей, добавлю риск хэндовера), 3.6 (ротация через ITOP-бандл). И параллельно поправлю ADR в разделах Context/Decision/Consequences.

### 1.1. Иерархия CA

- **Root CA** — корпоративный, находится вне нашей зоны ответственности.
- **Intermediate CA (issuing)** — выпускается от корпоративного Root CA и устанавливается в Vault.
- Реализовано два отдельных intermediate'а внутри одного Vault-кластера:
  - `pki-stage` — для non-prod сред;
  - `pki-prod` — для prod-нагрузок.

Разделение через **разные mounts** означает:

- изолированные приватные ключи intermediate CA;
- независимые CRL/OCSP контуры;
- независимые политики, роли и ограничения;
- компрометация stage не приводит автоматически к компрометации prod.

### 1.1. Иерархия CA

- **Root CA** — корпоративный, на Windows-инфраструктуре (AD CS), находится вне нашей зоны ответственности. Владелец — команда ITOP.
- **Intermediate CA (issuing)** — выпущен от корпоративного Root CA и установлен в Vault.
- Реализовано два отдельных intermediate'а внутри одного Vault-кластера:
  - `pki-stage` — для non-prod сред;
  - `pki-prod` — для prod-нагрузок.

Разделение через **разные mounts** означает:

- изолированные приватные ключи intermediate CA;
- независимые CRL/OCSP контуры;
- независимые политики, роли и ограничения;
- компрометация stage не приводит автоматически к компрометации prod.

**Особенность процесса выпуска intermediate (фактическая):**

- Корпоративный Root CA на Windows не принимает CSR, сгенерированный Vault (несовместимость форматов/профилей Windows AD CS).
- Поэтому стандартный Vault-флоу «Vault генерирует CSR → Root подписывает» в нашем контуре **не применяется**.
- Вместо этого команда **ITOP** генерирует готовую пару intermediate (сертификат + приватный ключ) на стороне Windows CA и передаёт её нам как PEM-бандл.
- Мы импортируем этот бандл в соответствующий mount Vault как issuer (`config/ca` / `issuers/import/bundle`), после чего intermediate начинает выпускать leaf-сертификаты уже из Vault.
- Передача бандла — чувствительная операция (см. §1.4), отдельный регламент с ITOP и ИБ.

Приватные ключи intermediate CA:

- хранятся внутри Vault, не извлекаются наружу;
- доступ к их экспорту не выдается никому в рамках штатной эксплуатации.

Приватные ключи intermediate CA:

- **генерируются на стороне ITOP (Windows CA)** и передаются нам в PEM-бандле (см. §1.1);
- после импорта в Vault хранятся внутри Vault и не извлекаются наружу;
- доступ к их экспорту не выдаётся никому в рамках штатной эксплуатации.

Риск хэндовера и компенсирующие контроли:

- на время передачи бандла приватный ключ intermediate существует вне Vault;
- бандл передаётся только по защищённому каналу, согласованному с ИБ (не почта, не мессенджеры);
- после импорта в Vault все локальные копии бандла у инженеров и на стороне ITOP уничтожаются по регламенту;
- сам факт хэндовера логируется, проверяется ИБ.

### 3.6. Процедуры смены и обновления CA

**Ротация intermediate CA** (плановая, до истечения):

1. Сгенерировать новый CSR intermediate во Vault.
2. Подписать CSR у владельцев Root CA.
3. Загрузить новый issued cert во Vault как issuer.
4. Настроить нового issuer как default для mount'а.
5. Старый issuer оставить активным до истечения всех выпущенных по нему сертификатов.
6. После — удалить или перевести в read-only.

**Внеплановая смена (инцидент)**:

1. Заморозить выпуск новых сертификатов на mount'е.
2. Выполнить revoke скомпрометированного intermediate у владельцев Root CA.
3. Выпустить новый intermediate.
4. Перевыпустить все активные leaf-сертификаты через автоматизацию (cert-manager/CI).
5. Обновить CRL-потребителей, убедиться в доставке.

Rotate intermediate должен быть отрепетирован на stage до применения на prod.

### 3.6. Процедуры смены и обновления CA

В нашем контуре Root CA на Windows не принимает CSR от Vault (см. §1.1), поэтому ротация intermediate **не идёт через Vault CSR**. Используется «импорт готового бандла от ITOP».

**Ротация intermediate CA** (плановая, до истечения):

1. Запрос к ITOP на выпуск нового intermediate (cert + private key, PEM-бандл) на Windows CA.
2. Приём бандла по защищённому каналу, согласованному с ИБ (см. §1.4).
3. Импорт бандла во Vault как нового issuer:
   `vault write <mount>/issuers/import/bundle pem_bundle=@bundle.pem`
4. Назначение нового issuer как default для mount'а.
5. Уничтожение локальных копий бандла на стороне DevSecOps и ITOP по регламенту.
6. Старый issuer оставить активным до истечения всех ранее выпущенных leaf-сертификатов.
7. После — удалить или перевести в read-only.

**Внеплановая смена (инцидент, компрометация intermediate)**:

1. Заморозить выпуск новых сертификатов на mount'е.
2. Инцидент-коммуникация с ИБ и ITOP; запрос на revoke скомпрометированного intermediate на Root CA (Windows AD CS).
3. ITOP выпускает новый intermediate (cert + key, PEM-бандл) на Windows CA.
4. Импорт бандла во Vault (шаги 2–5 из плановой ротации).
5. Перевыпуск всех активных leaf-сертификатов через автоматизацию (cert-manager/CI).
6. Обновление CRL-потребителей, проверка доставки.

Rotate intermediate должен быть отрепетирован на stage до применения на prod. Регламент передачи бандла — общий с §1.4.


Теперь ADR. Смотрю конкретные участки.


- Корпоративный Root CA существует и эксплуатируется отдельной командой; мы не владеем Root CA.
- Vault Enterprise недоступен (ограничение по лицензиям).
- Внешние (публичные) CA в этом контуре не применяются — он полностью внутренний.
- Формализованных внутренних ИБ-стандартов (классификация, SLA, требования аудита) на момент принятия решения нет; документ и ADR являются первичной фиксацией.
- Референсный потребитель (Kafka, продукт `P0239`) уже внедрен и проверен.

- Корпоративный Root CA существует и эксплуатируется отдельной командой (ITOP); мы не владеем Root CA.
- Root CA развёрнут на Windows-инфраструктуре (AD CS) и **не принимает CSR, сгенерированный Vault**. Следовательно, стандартный Vault-флоу «генерация CSR во Vault → подпись на Root» в нашем контуре неприменим; intermediate выдаётся командой ITOP в виде готового PEM-бандла (cert + private key) и импортируется в Vault.
- Vault Enterprise недоступен (ограничение по лицензиям).
- Внешние (публичные) CA в этом контуре не применяются — он полностью внутренний.
- Формализованных внутренних ИБ-стандартов (классификация, SLA, требования аудита) на момент принятия решения нет; документ и ADR являются первичной фиксацией.
- Референсный потребитель (Kafka, продукт `P0239`) уже внедрен и проверен.

1. **Иерархия**:
   - Root CA — корпоративный, внешний по отношению к нашей инсталляции;
   - Vault эксплуатирует **два intermediate CA**, выпущенные от корпоративного Root CA:
     - `pki-stage` — нон-прод;
     - `pki-prod` — продакшн.

1. **Иерархия**:
   - Root CA — корпоративный Windows CA (AD CS), внешний по отношению к нашей инсталляции, владелец — ITOP;
   - Vault эксплуатирует **два intermediate CA**, выпущенные от корпоративного Root CA:
     - `pki-stage` — нон-прод;
     - `pki-prod` — продакшн.
   - Intermediate CA (сертификат + приватный ключ) **генерируется на стороне ITOP** (Root CA на Windows не принимает CSR от Vault) и передаётся нам PEM-бандлом; мы импортируем его в соответствующий mount как issuer. Ротация и внеплановая замена intermediate идут по тому же флоу (см. `docs/pki-architecture.md` §3.6).

- Без Vault Enterprise: нет namespace'ов, нет performance replication, ограничены варианты HA.
- Повышенная операционная ответственность команды DevSecOps за snapshot/restore и unseal. До завершения [INIT-1793](https://tracker.yandex.ru/INIT-1793) unseal выполняется по Shamir-процедуре; после миграции коммунального Vault с EE на CE планируется включить auto-unseal.
- Публичные сертификаты не выдаются — только внутренние домены.
- Без формализованных ИБ-стандартов ADR сам является первичной фиксацией правил.

- Без Vault Enterprise: нет namespace'ов, нет performance replication, ограничены варианты HA.
- Повышенная операционная ответственность команды DevSecOps за snapshot/restore и unseal. До завершения [INIT-1793](https://tracker.yandex.ru/INIT-1793) unseal выполняется по Shamir-процедуре; после миграции коммунального Vault с EE на CE планируется включить auto-unseal.
- Intermediate CA выпускается командой ITOP вместе с приватным ключом (Windows CA не принимает Vault-CSR), поэтому на время передачи бандла ключ intermediate существует вне Vault. Риск компенсируется защищённым каналом передачи, уничтожением локальных копий после импорта и логированием (см. `docs/pki-architecture.md` §1.4, §3.6).
- Публичные сертификаты не выдаются — только внутренние домены.
- Без формализованных ИБ-стандартов ADR сам является первичной фиксацией правил.


Проверяю, не осталось ли в pki-architecture.md формулировок, подразумевающих CSR-флоу или генерацию ключа intermediate внутри Vault.

 I'm checking the risks table in pki-architecture.md and reviewing the sections around lines 107-110 and 127-136 where intermediate CA compromise is discussed, particularly to verify the revocation process and whether there's any mention of intermediate private keys being generated in Vault.


Остальные упоминания CSR — про `cert-manager sign` (это про leaf-сертификаты, корректно) и про explicit "не идёт через CSR" в §3.6. Все места, где подразумевался CSR-флоу для intermediate, обновлены.

Что теперь зафиксировано в документации:

- `docs/pki-architecture.md` §1.1 — явно указано: Root CA на Windows (AD CS), владелец ITOP; стандартный Vault-флоу CSR не применяется; intermediate (cert + private key) выдаёт ITOP как PEM-бандл, мы импортируем в Vault как issuer.
- `docs/pki-architecture.md` §1.4 — приватный ключ intermediate генерируется на стороне ITOP, после импорта живёт внутри Vault; добавлен блок «Риск хэндовера и компенсирующие контроли» (защищённый канал, уничтожение копий, логирование).
- `docs/pki-architecture.md` §3.6 — процедуры плановой ротации и внеплановой замены переписаны на импорт бандла от ITOP (`vault write <mount>/issuers/import/bundle pem_bundle=@bundle.pem`), без генерации CSR во Vault.
- `docs/adr/ADR-001-pki-architecture.md` Context — добавлено ограничение Windows CA как исходное условие.
- `docs/adr/ADR-001-pki-architecture.md` Decision §1 — уточнено, что intermediate приходит как PEM-бандл от ITOP.
- `docs/adr/ADR-001-pki-architecture.md` Consequences → Отрицательные — добавлен пункт про наличие приватного ключа intermediate вне Vault в момент передачи и компенсирующие контроли.

Если хочешь — следом зафиксирую рекомендованный `Shamir n-of-m` (например 3-of-5) в §1.4 и §3.5 как целевую конфигурацию на период до включения auto-unseal по INIT-1793.


<user_query>
настроен один продукт и сделан рутовый сертификат пока только для стейджа
</user_query>


 So the user is clarifying the setup: only one product (P0239) is currently configured, and the intermediate CA they imported into Vault is from their external root (ITOP), which is only staged right now — there's no production intermediate CA yet.

I need to update the documentation to reflect that `pki-stage` has the CA loaded but `pki-prod` is still waiting for the intermediate from ITOP to be obtained and configured.


I need to add a clear "Current State (Actual)" section at the top to document what's actually configured right now — specifically that only the P0239 product is set up, and only pki-stage has the CA loaded while pki-prod is still waiting for the CA request to go through ITOP. Let me check if there's already a current state section I can build on.

Grep

[Тт]екущ|[Фф]актическ|состояние


 Нужно добавить раздел о текущем состоянии — лучше всего вставить краткие факты в Executive summary, а затем развернуть в подразделе 1.1. В summary отражу, что на момент написания развёрнут и импортирован intermediate только для `pki-stage`, настроен один референс-продукт `P0239`, и начну описывать статус production-контура.

Также нужно уточнить существующие пункты — буллет про два независимых PKI mount описывает целевую модель, поэтому добавлю рядом информацию о текущем состоянии, и строку про два отдельных intermediate'а переформулирую, чтобы различить целевое и фактическое. Не забыть добавить текущее состояние и в ADR раздел Context.

StrReplace

Ключевые факты:

- Vault работает как **issuing CA (intermediate)**, сертификаты которого выпущены от **корпоративного Root CA**.
- Два независимых PKI mount: `pki-stage` и `pki-prod` (разделение по критичности).
- Автоматика работает через `AppRole` с короткоживущими токенами.
- Люди логинятся через `OIDC` (Keycloak).
- Интеграция с `cert-manager` Kubernetes реализована через endpoint `sign` (Vault подписывает CSR, ключ генерируется клиентом).

Ключевые факты:

- Vault работает как **issuing CA (intermediate)**, сертификаты которого выпущены от **корпоративного Root CA**.
- Целевая архитектура — два независимых PKI mount: `pki-stage` и `pki-prod` (разделение по критичности).
- Автоматика работает через `AppRole` с короткоживущими токенами.
- Люди логинятся через `OIDC` (Keycloak).
- Интеграция с `cert-manager` Kubernetes реализована через endpoint `sign` (Vault подписывает CSR, ключ генерируется клиентом).

Фактическое состояние на момент написания документа:

- Настроен и работает только **`pki-stage`**: intermediate CA получен от ITOP и импортирован; выпуск leaf-сертификатов проверен.
- Настроен **один референс-продукт** — `P0239` (Kafka), одна роль и одна policy.
- **`pki-prod`** ещё не введён в эксплуатацию: intermediate CA для prod у ITOP не запрошен; будет введён по мере готовности продуктовых команд и процесса передачи бандла (см. §1.1, §3.6).

- **Root CA** — корпоративный, на Windows-инфраструктуре (AD CS), находится вне нашей зоны ответственности. Владелец — команда ITOP.
- **Intermediate CA (issuing)** — выпущен от корпоративного Root CA и установлен в Vault.
- Реализовано два отдельных intermediate'а внутри одного Vault-кластера:
  - `pki-stage` — для non-prod сред;
  - `pki-prod` — для prod-нагрузок.

- **Root CA** — корпоративный, на Windows-инфраструктуре (AD CS), находится вне нашей зоны ответственности. Владелец — команда ITOP.
- **Intermediate CA (issuing)** — выпускается ITOP от корпоративного Root CA и устанавливается в Vault.
- Целевая модель — два отдельных intermediate'а внутри одного Vault-кластера:
  - `pki-stage` — для non-prod сред (развёрнут, работает);
  - `pki-prod` — для prod-нагрузок (запланирован, intermediate у ITOP ещё не запрошен).


Now I'm checking the rollout plan and the plans section to make sure production is marked as the immediate priority.


I need to add a section about the initial intermediate CA setup for pki-prod as the next step—either as a subsection or dedicated item in §3.6. A small addition to §3.6 with a step-by-step "Ввод в эксплуатацию pki-prod (первичный выпуск)" makes sense, and I should check if there's a plan-of-rollout section where this belongs as well.

### 3.6. Процедуры смены и обновления CA

В нашем контуре Root CA на Windows не принимает CSR от Vault (см. §1.1), поэтому ротация intermediate **не идёт через Vault CSR**. Используется «импорт готового бандла от ITOP».

**Ротация intermediate CA** (плановая, до истечения):

### 3.6. Процедуры смены и обновления CA

В нашем контуре Root CA на Windows не принимает CSR от Vault (см. §1.1), поэтому ротация intermediate **не идёт через Vault CSR**. Используется «импорт готового бандла от ITOP».

**Первичный ввод `pki-prod` в эксплуатацию** (ближайшая задача, intermediate для prod ещё не запрошен):

1. Согласовать с ИБ и ITOP параметры intermediate для prod (CN/organizational fields, срок действия, профиль ключа).
2. Запросить у ITOP выпуск intermediate CA для prod (cert + private key, PEM-бандл) на Windows CA.
3. Принять бандл по защищённому каналу (см. §1.4).
4. Включить PKI mount `pki-prod` и импортировать бандл:
   `vault secrets enable -path=pki-prod pki`
   `vault write pki-prod/issuers/import/bundle pem_bundle=@bundle.pem`
5. Настроить URLs mount'а (`config/urls`) и CRL.
6. Создать prod-роли продуктов (начать с `P0239`) и соответствующие policy.
7. Уничтожить локальные копии бандла на стороне DevSecOps и ITOP.
8. Verify: тестовый выпуск leaf-сертификата в prod по продуктовой AppRole.

**Ротация intermediate CA** (плановая, до истечения):


I need to update the ADR documentation to make it clearer that only the live stage is currently deployed with P0239, even though the existing statement about the reference consumer already being implemented and verified implies this — I'll add a more explicit note about the current deployment state.

- Формализованных внутренних ИБ-стандартов (классификация, SLA, требования аудита) на момент принятия решения нет; документ и ADR являются первичной фиксацией.
- Референсный потребитель (Kafka, продукт `P0239`) уже внедрен и проверен.

- Формализованных внутренних ИБ-стандартов (классификация, SLA, требования аудита) на момент принятия решения нет; документ и ADR являются первичной фиксацией.
- Фактическое состояние на момент принятия решения: развёрнут и работает только `pki-stage` с одним референсным продуктом — Kafka `P0239`. `pki-prod` запланирован, intermediate CA для prod у ITOP ещё не запрошен.


Зафиксировал текущее состояние во всех ключевых местах:

- `docs/pki-architecture.md` §0 Executive summary — добавлен блок «Фактическое состояние на момент написания»: работает только `pki-stage`, настроен один продукт `P0239`, `pki-prod` запланирован (intermediate у ITOP ещё не запрошен).
- `docs/pki-architecture.md` §1.1 — переформулировано: `pki-stage` «развёрнут, работает», `pki-prod` — «запланирован, intermediate у ITOP ещё не запрошен». Слово «реализовано» (звучит как факт) заменено на «целевая модель».
- `docs/pki-architecture.md` §3.6 — добавлена отдельная процедура «Первичный ввод `pki-prod` в эксплуатацию» (8 шагов, включая `vault secrets enable -path=pki-prod pki` и `issuers/import/bundle`), отражающая, что это ближайшая задача, а не уже пройденный этап.
- `docs/adr/ADR-001-pki-architecture.md` Context — добавлена явная фиксация: развёрнут только `pki-stage`, один продукт `P0239`, `pki-prod` пока не запрошен.

Если встретишь ещё формулировки «реализовано/работает оба mount'а» или что у нас несколько продуктов — говори, подчищу.


<user_query>
Zugzwang-кейсы (см. 1.6) имеют зафиксированные процедуры реагирования. это чего такое вообще, давай по-русски
</user_query>


Нужно заменить "Zugzwang-кейсы" на русский эквивалент — это шахматный термин, который здесь использован неправильно. В контексте раздела 1.6 про компрометационные сценарии подойдет что-то вроде "инцидентные сценарии" или "кризисные сценарии". Сейчас найду точное место в тексте.


Это был мой косяк — Zugzwang это шахматный термин (позиция, где любой ход ухудшает ситуацию), к PKI/ИБ он не относится. Раздел 1.6 называется «Сценарии компрометации и реагирование», под это и формулирую.

 I realize I used "zugzwang" incorrectly here — that's a chess term for a position where any move worsens your situation. The section is actually about compromise scenarios, so I should just call it that instead.

3. Zugzwang-кейсы (см. 1.6) имеют зафиксированные процедуры реагирования.

3. Сценарии компрометации (см. §1.6) имеют зафиксированные процедуры реагирования.


Поправил — в §2.3 теперь «Сценарии компрометации (см. §1.6) имеют зафиксированные процедуры реагирования».

Больше «Zugzwang» в доках не встречается. Если найдёшь ещё англицизмы или термины не по теме — маякни, приберу.


<user_query>
нон-прод; продакшн.
много где так и вариации, нужно на русском или уже английском, от контекста
</user_query>


 I'm noticing the inconsistency in how environment names are being handled — mixing transliterated Russian terms like "нон-прод" and "продакшн" with English abbreviations like "stage" and "prod". In Russian DevOps contexts, it's more natural to stick with either the English terms directly or use consistent Russian equivalents like "стейдж" and "прод", rather than this hybrid approach.

Since the document is primarily Russian technical prose with English terms already in backticks, the cleanest solution is to standardize on using `stage` and `prod` as the technical labels (matching the actual mount names like `pki-stage` and `pki-prod`), while replacing awkward transliterations like "нон-прод" with either "stage" or "non-prod" depending on context. I'll scan through the document to apply this consistently.

Grep

нон-прод|продакшн|продакшен|прод-нагруз|прод-контур


Понял. Приведу к единому виду: английские `stage`/`prod` в технических контекстах (они уже часть имён маунтов `pki-stage`/`pki-prod`), транслиты «нон-прод», «продакшн», «продакшен», «прод-нагрузки» выкидываем.

 Я определяю стратегию для документации: использовать технические сокращения `stage` и `prod` как стандартные имена окружений, соответствующие монтам `pki-stage` и `pki-prod`, и заменить транслитерированные варианты вроде "нон-прод" или "продакшн" на эти короткие обозначения или чистые русские эквиваленты.

Теперь прохожу по конкретным файлам и определяю замены: в ADR-001 просто указываю `stage` и `prod` как имена окружений, в основной документации переписываю описания сред, убирая "нон-прод" и заменяя "продакшн" на "продуктивные нагрузки", при этом сохраняя `prod` английским в технических контекстах вроде "prod-контура".

StrReplace

     - `pki-stage` — нон-прод;
     - `pki-prod` — продакшн.

     - `pki-stage` — для `stage`-сред;
     - `pki-prod` — для `prod`-сред.

  - `pki-stage` — для non-prod сред (развёрнут, работает);
  - `pki-prod` — для prod-нагрузок (запланирован, intermediate у ITOP ещё не запрошен).

  - `pki-stage` — для `stage`-сред (развёрнут, работает);
  - `pki-prod` — для `prod`-сред (запланирован, intermediate у ITOP ещё не запрошен).

| Компрометация intermediate CA (`pki-prod`) | Критично для прод | То же + инцидент-процесс, уведомление ИБ |

| Компрометация intermediate CA (`pki-prod`) | Критично для `prod` | То же + инцидент-процесс, уведомление ИБ |

- **Stage** — нон-прод, пилоты, тестовые инсталляции. Меньшие требования к доступности и аудиту. Mount: `pki-stage`.
- **Prod** — продакшн-нагрузки. Повышенные требования к доступности, отзыву, аудиту. Mount: `pki-prod`.

- **`stage`** — тестовые среды, пилоты, dev/qa. Меньшие требования к доступности и аудиту. Mount: `pki-stage`.
- **`prod`** — продуктивные нагрузки. Повышенные требования к доступности, отзыву, аудиту. Mount: `pki-prod`.


Ещё есть остаток в `outline_pki.md` и в procedure-доке:

 Я нашел еще несколько мест в `outline_pki.md`, где смешаны "Stage" и "next" — нужно привести их в порядок. На строке 161 в таблице стоит "Stage реализовано, prod next", что тоже требует исправления на более четкую формулировку вроде "stage реализовано, prod — планируется".

Теперь проверяю файл `kafka-pki-vault-pki-lmru-procedure.md` на предмет русско-английских миксов. Там встречаются "Прод:" и "прода" в русском тексте — это закрепившийся слэнг, но поскольку пользователь против смешивания языков, лучше заменить эти вхождения на `prod` в бэктиках для единообразия.


| Смешение stage/prod | Отдельные mounts (`pki-stage`, `pki-prod`) | Stage реализовано, prod next |

| Смешение `stage`/`prod` | Отдельные mounts (`pki-stage`, `pki-prod`) | `stage` реализовано, `prod` — планируется |

**Прод:** при необходимости создайте зеркально роль **`P0239`** на mount **`pki-prod`** (те же параметры — после согласования с владельцами PKI).

**`prod`:** при необходимости создайте зеркально роль **`P0239`** на mount **`pki-prod`** (те же параметры — после согласования с владельцами PKI).

Для **прода** заведите отдельный HCL с путями `pki-prod/issue/P0239` и `pki-prod/cert/...` и отдельное имя политики по согласованию.

Для **`prod`** заведите отдельный HCL с путями `pki-prod/issue/P0239` и `pki-prod/cert/...` и отдельное имя политики по согласованию.


Финальная проверка, что транслитов не осталось:

Grep

нон-прод|продакшн|продакшен|прод-нагруз|прод-контур|\bПрод\b|\bпрода\b|\bпрод\b|Stage реализ|Prod next


Готово. Правило, которое применил:

- имена окружений пишем только английскими: `stage`, `prod`, в бэктиках — так они совпадают с именами mount'ов (`pki-stage`, `pki-prod`) и терминологией Vault;
- все транслиты (`нон-прод`, `продакшн`, `продакшен`, «прод», «прода», `prod next`, `non-prod`) из документов убраны;
- остальной текст — по-русски, английское попадает только в бэктиках как технические идентификаторы (`sign`, `issue`, `AppRole`, `OIDC`, `cert-manager` и т.п.).

Затронутые файлы:

- `docs/pki-architecture.md` — §0, §1.1, §1.6, §2.1, §3.1.
- `docs/adr/ADR-001-pki-architecture.md` — §Decision, п.1.
- `docs/outline_pki.md` — таблица рисков.
- `docs/kafka-pki-vault-pki-lmru-procedure.md` — два заголовка про prod-контур.

Если попадётся ещё какой-нибудь разговорный транслит — дай знать, прочешу.


<user_query>
@docs/adr/ADR-001-pki-architecture.md:102-104
</user_query>


Looking at lines 102-104 in the ADR document, I see "operational cost" and "fleet" that need Russian translations. Let me check the surrounding context to make sure I'm using the right terminology that matches the rest of the document.


Там два англицизма — `operational cost` и `fleet`. Плюс «рабочего рабочего» — опечатка. Чищу.

StrReplace

- Потеря уже реализованной интеграции и работающего рабочего контура для Kafka `P0239`.
- Новая operational cost, новое обучение команд.
- В компании уже используется Vault для других задач; отдельный инструмент только под PKI увеличивает fleet.

- Потеря уже реализованной интеграции и работающего контура для Kafka `P0239`.
- Дополнительные эксплуатационные расходы и переобучение команд.
- В компании уже используется Vault для других задач; отдельный инструмент только под PKI увеличивает количество систем в эксплуатации.


Заодно прочешу весь ADR и архитектуру на торчащие англицизмы не в бэктиках.

 Я вижу, что пользователь проверяет текст на английские заимствования, которые не в бэктиках. Просматриваю документацию и ADR на предмет слов вроде compliance, rollout, handover и других англицизмов, которые нужно либо заменить, либо оформить правильно.


### Соответствие требованиям и ИБ

## Review и статус согласования

| Роль | Представитель | Статус |
|---|---|---|
| Архитекторы ИБ | — | Pending |
| Архитекторы Компании | — | Pending |
| Технические Архитекторы | — | Pending |
| RedTeam | — | Pending |

## Статус согласования

| Роль | Представитель | Статус |
|---|---|---|
| Архитекторы ИБ | — | Ожидает согласования |
| Архитекторы Компании | — | Ожидает согласования |
| Технические Архитекторы | — | Ожидает согласования |
| RedTeam | — | Ожидает согласования |

## 11. План до production rollout

1. Создать зеркальную роль `P0239` на `pki-prod`.
2. Создать отдельные prod policy и AppRole с изоляцией от stage.
3. Утвердить runbook ротации AppRole (`secretId`) и аварийного отзыва.
4. Финализировать naming standard для broker FQDN.
5. Зафиксировать SLA/SOP для revoke-процесса и операционной поддержки.

## 11. План до ввода в `prod`

1. Создать зеркальную роль `P0239` на `pki-prod`.
2. Создать отдельные policy и AppRole для `prod` с изоляцией от `stage`.
3. Утвердить регламент ротации AppRole (`secretId`) и аварийного отзыва.
4. Финализировать правила именования FQDN брокеров.
5. Зафиксировать SLA и регламент для процесса отзыва сертификатов и операционной поддержки.


I'm scanning through the document for specific patterns — checking for "Verify:" markers in the architecture file, looking at how "production" appears across different sections, and hunting for references to runbooks and naming conventions. I should also watch for any Russian text mixed with transliteration that might have slipped through.


Цель демо: подтвердить, что решение уже production-oriented и масштабируется без изменения базовой архитектуры.

Цель демо: подтвердить, что решение готово к выводу в `prod` и масштабируется без изменения базовой архитектуры.

## Рассмотренные альтернативы

8. Verify: тестовый выпуск leaf-сертификата в prod по продуктовой AppRole.

8. Проверка: тестовый выпуск leaf-сертификата в `prod` по продуктовой AppRole.

4. Назначение нового issuer как default для mount'а.

4. Назначение нового issuer по умолчанию для mount'а.


Проверю заголовки ADR — после смешанной правки часть по-русски, часть по-английски:

 I'm considering whether the ADR template headers like "Context" and "Decision" should be translated to Russian or kept in English, given the user's preference to match the language to the context. Since these are standard ADR conventions, I'm leaning toward asking for clarification, though the user did indicate they want either Russian or English depending on the situation.

Let me check what the current state of the document is to see which language is already being used.


Я вижу, что пользователь не хочет смешивать языки, поэтому переведу всё на русский, но оставлю аббревиатуру ADR в названии файла, так как это стандартный паттерн, который обычно остаётся на английском в сообществе.

## Последствия


I should look for other status indicators in the ADR document, like "Status: Proposed" or similar patterns that might indicate different states.


- **Статус**: Draft (на согласование)

- **Статус**: Черновик (на согласование)


Итог по ADR и связанным докам — убрал все англицизмы вне бэктиков:

- строки 102–104 ADR: «operational cost» → «эксплуатационные расходы»; «fleet» → «количество систем в эксплуатации»; заодно опечатка «работающего рабочего» → «работающего»;
- заголовки ADR по-русски: `Context` → «Контекст», `Decision` → «Решение», `Alternatives considered` → «Рассмотренные альтернативы», `Consequences` → «Последствия», `Compliance и ИБ` → «Соответствие требованиям и ИБ», `Review и статус согласования` → «Статус согласования»; статусы `Pending` → «Ожидает согласования», `Draft` → «Черновик»;
- `docs/pki-architecture.md`: `Verify:` → «Проверка:», `default для mount'а` → «по умолчанию для mount'а»;
- `docs/outline_pki.md`: заголовок «План до production rollout» → «План до ввода в `prod`»; «production-oriented» → «готово к выводу в `prod`»; `runbook`, `naming standard`, `SOP` → русские эквиваленты.

Технические идентификаторы (`AppRole`, `OIDC`, `cert-manager`, `issuer`, `issue`, `sign`, `secretId`, `Raft`, `Shamir`, `Keycloak`, `mount`, `ACL`, `SIEM` и т.п.) оставил английскими — это имена концепций/продуктов, часто прямо совпадают с именами команд Vault.


<user_query>
выступи со стороны RedTeam и сделай неофициальный список потенциальных реалистичных уязвимостей этой архитектуры
</user_query>


Окей, снимаю галстук. Поехали — красная команда, вид со стороны атакующего, без политесов и без учёта статусов.

## 1. Ключевой материал и CA — самое вкусное

**1.1. Хэндовер intermediate-бандла от ITOP — классическая дыра**
Приватный ключ intermediate CA физически существует вне Vault в момент передачи. Где он лежит и сколько — непонятно. Реалистичные сценарии:
- ITOP сохраняет бандл «на будущее» (личный бэкап, шара, почта, тикет в ITSM). Любая одна точка компрометируется — и у меня ваш issuing CA. Я могу подписать что угодно в вашей корпоративной PKI, хоть `*.lmru.tech`.
- Бандл прилетает в мессенджере/почте без enforced E2E. Теневой IT, ошибочно пересланное вложение, SOC даже не узнает.
- Инженер делает `vault write ... pem_bundle=@bundle.pem`, а файл `bundle.pem` остаётся в `~/Downloads` или в истории bash. `zsh history`, `wsl` бэкап, `syslog` c path — выбирайте.
- Нет криптографической привязки, что ITOP не подписали два одинаковых intermediate и один не оставили себе «на всякий».

**1.2. Нет HSM — barrier key защищает, но не спасёт от админа ноды**
В Vault CE приватный ключ intermediate шифруется barrier key. Barrier key расшифровывается на unseal. Любой, кто получил root token **и** unseal-ключи (а сейчас это Shamir 1-of-1), сможет экспортировать/переиздать.
- Задача атакующего: одновременно скомпрометировать узел Vault + получить unseal key. На 1-of-1 это одна головная боль вместо пяти.

**1.3. Shamir 1-of-1 — это не «временно», это уже навсегда**
«Временно до INIT-1793» в нашей реальности означает «на полгода-год». Единственный держатель ключа — одна точка отказа и атаки:
- Увольнение, больничный, командировка, принуждение — Vault не стартует или стартует в чужих руках.
- Нет split knowledge, нет dual control. С точки зрения ИБ-аудита — финиш.

**1.4. Root CA у ITOP — слепое доверие**
Вы не контролируете:
- Кто у ITOP имеет доступ к Windows CA и может выпустить новый intermediate с вашим именем.
- Какая политика у корпоративного Root CA на отзыв (OCSP/CRL, доступность, время реакции).
- Был ли CA уже скомпрометирован исторически. Windows AD CS с дефолтами — огромный чеклист misconfiguration (ESC1–ESC16 от SpecterOps), вы его не аудируете.

## 2. Авторизация и секреты

**2.1. AppRole: где лежит `secret_id` — там и граница доверия**
В доках «в корпоративном секрет-хранилище, не в Git». На практике для `cert-manager` он почти всегда оказывается в **Kubernetes Secret** (как в `ClusterIssuer`, который вы показывали). Это означает:
- Любой, у кого есть `get secrets` в неймспейсе `cert-manager`, получает полный доступ к выпуску сертификатов `*.kafka.apim.lmru.tech`.
- Любой, у кого есть доступ к `etcd` кластера (node compromise, etcd backup), достаёт его в открытом виде, если etcd не зашифрован полноценно с внешним KMS.
- Cluster admin, compromised operator, kubectl-exec в под `cert-manager` — варианты.

**2.2. Нет `bound_cidr_list` у AppRole (по крайней мере, в докóв не зафиксировано)**
Если украденный `secret_id` можно использовать с ноутбука атакующего через corporate VPN — это слабый контроль. AppRole без CIDR-binding + без `secret_id_num_uses` превращается в bearer token на всю жизнь secret_id.

**2.3. Политика `p0239` даёт `issue` И `sign`**
Для `cert-manager` нужен только `sign`. `issue` оставлен «на всякий». Атакующий с AppRole-токеном через `issue` получит готовый сертификат + приватный ключ в одном ответе. Ни один админ никогда не увидит, откуда этот ключ потом всплывёт.

**2.4. OIDC через Keycloak — ещё одна доверенная точка**
- Если Keycloak общий для всей корпорации, phishing/MFA-bypass/Keycloak-CVE → получение Vault-токена с правами ваших групп.
- Какие группы мапятся в админ-политики Vault — не зафиксировано. Если мапится «DevSecOps» целиком — компрометация одного аккаунта = Vault-root equivalent.
- MFA на OIDC-логине в Vault — упоминания нет. Если Keycloak пропускает пароль без второго фактора, phishing solo достаточно.

**2.5. Root token — «только для аварий», но где он?**
Если root token сгенерирован при bootstrap и не revoked, он где-то лежит (password manager, safe, sticker). Любая утечка = конец. Регулярного revoke/rotate не прописано.

## 3. Конфигурация PKI-роли `P0239`

**3.1. Комбинация `allow_subdomains=true` + `allow_wildcard_certificates=true` на широкой зоне**
`allowed_domains=kafka.apim.lmru.tech` + wildcards + subdomains = любой обладатель AppRole может выпустить:
- `*.kafka.apim.lmru.tech` — wildcard на всю зону, не только на «свой» кластер.
- `anything.kafka.apim.lmru.tech`, `evilbroker.kfk4u-foo.ycd-kafka-a-stage.kafka.apim.lmru.tech`.
Если Kafka-клиенты валидируют только по суффиксу домена (а многие SDK так и делают по дефолту), я как атакующий с `*.kafka.apim.lmru.tech` становлюсь любым брокером любого кластера. MitM между продюсером и брокером, interception + impersonation.

**3.2. Параметры роли, которые в доке не зафиксированы — значит, дефолтные**
- `allow_any_name` — должен быть `false` (default).
- `allow_ip_sans` — default `true`. Кто-то может запросить cert с `IP SAN = 10.0.0.1` и получить — и это валидный cert для внутренних IP-сервисов.
- `allow_localhost` — default `true`. `localhost` сертификат — для атак на locally-bound сервисы.
- `enforce_hostnames` — default `true`, ок.
- `require_cn` — default `true`, ок.
- `key_type`/`key_bits` — если не задано, клиент может прислать CSR с RSA-1024 и Vault подпишет.
- `not_before_duration`, `ttl`, `max_ttl` — если `max_ttl` большой, клиент может запросить сертификат на год «на всякий».
- `no_store=false` (default) — все выпущенные leaf хранятся в Vault. Плюс для audit, минус для атакующего с read на `cert/*`: видна вся история.

**3.3. Один продукт = одна роль. А когда будут два продукта с пересекающимися доменами?**
Если завтра появится продукт `P0512` с доменом `kafka.apim.lmru.tech/отдельная зона` — разграничение только на уровне имени роли, но Vault не мешает двум ролям иметь пересекающиеся `allowed_domains`. Маркировка «одна роль — один продукт» — процедурная, не технически навязанная.

## 4. Эксплуатация Vault

**4.1. Raft-снапшоты — это полная копия PKI**
Снапшот Raft включает зашифрованный (barrier) стейт, в т.ч. приватные ключи intermediate, роли, политики, audit (если в хранилище). Атакующий с доступом к снапшот-хранилищу + unseal ключами = полный replay Vault в своём окружении и извлечение всех ключей. Вопросы:
- Где хранятся снапшоты? S3-совместимое хранилище с ACL? Сервер с `/var/backups`? Копируется ли на ноутбуки админов для «проверки»?
- Как долго хранятся? Годовой снапшот с Shamir 1-of-1 — подарок.
- Ротация/шифрование at-rest снапшота отдельным ключом — не зафиксировано.

**4.2. Патч-менеджмент Vault не описан**
Vault CE активно фиксит CVE (в 2024–2026 были HTTP request smuggling, issuer-related, privilege escalation). Если у вас нет SLA на патч в днях — следующий CVE уровня critical будет пойман пост-фактум.

**4.3. Audit device — легко сделать cosmetic**
Если audit device пишет в локальный файл на одной из нод Vault — админ ноды (или рут-процесс) может:
- Отключить audit (`vault audit disable`) перед злонамеренным действием.
- Удалить/подменить файл.
Правильный паттерн — минимум два device (file + syslog в SIEM, по append-only), алертинг на disable audit, ротация + offsite. В доках только «рекомендация по дублированию в SIEM» — значит, скорее всего, сейчас не сделано.

**4.4. Нет алертинга на аномалии выпуска**
- Никакого detection на «100 сертов за минуту», «выпуск wildcard неожиданным AppRole», «выпуск с новым CN», «issuer changed», «policy changed».
- Revoke тоже не алертится — классический хак, если кто-то массово отзывает критичные серты → DoS.

**4.5. DR «квартальные тесты восстановления» — в плане**
Пока не выполнено, не знаем, работает ли. Реалистично: в инциденте обнаружится, что снапшот битый / unseal-ключ не тот / процедура написана только в голове.

## 5. Сеть и транспорт

**5.1. `pki.lmru.tech` — насколько публичен?**
- Если доступен из всей корпоративной сети (как обычно бывает), любой заражённый хост / любой скомпрометированный подрядчик с VPN — легитимный кандидат на AppRole-логин.
- Если LB/Ingress перед Vault терминирует TLS — между LB и нодами Vault часто plaintext (или self-signed без pinning). Man-in-the-middle на этом хопе = чтение API-запросов с токенами.
- Пойман ли доступ к `/v1/sys/*` (management API) от внешних сетей? Часто забывают закрыть.

**5.2. Сертификат на сам Vault API — кто его выпустил?**
Если Vault обслуживает TLS сертификатом, который сам же себе подписал (из `pki-stage`?) — курица и яйцо. Если из корпоративного CA — ок, но кто валидирует его цепочку у клиента cert-manager / kubectl? Если `insecure_tls_verify=true` где-нибудь в конфигах — поздравляю, MitM.

**5.3. ACME включён на `pki-stage`**
`config/acme enabled=true`. Кто может ходить в ACME-директорию? Если нет External Account Binding (EAB), то любой, у кого сетевой доступ к `pki-stage/acme/directory`, пробует challenge. HTTP-01/DNS-01 зависят от внешней проверки — если внутренняя DNS-зона `kafka.apim.lmru.tech` управляется плохо (или атакующий контролирует хотя бы один брокер/хост), он может пройти challenge и получить cert на FQDN, которым не владеет.

## 6. Revocation и жизненный цикл сертификатов

**6.1. CRL — декоративный?**
- CRL отдаётся по HTTP с `pki.lmru.tech`. Если клиент не делает CRL check (а `openssl verify` по умолчанию не делает, многие Java-клиенты — тоже без настройки), revoke не имеет значения вообще.
- Даже если клиент делает check — без CRLite / stapling он запрашивает CRL редко, окно эксплуатации скомпрометированного cert-а = TTL сертификата.
- При `ttl=168h` (неделя) скомпрометированный leaf живёт неделю независимо от revoke.

**6.2. OCSP/OCSP stapling — не упомянуто**
Значит, его нет, или сделано дефолтно и ни один клиент его не использует.

**6.3. Нет списка «какие системы реально валидируют наш CA»**
Если cert-manager выдаёт серт, но broker-клиенты его не проверяют (или доверяют общему CA bundle, куда мы доливаем наш Root) — легко не заметить, что половина потребителей не видит revoke вообще.

## 7. Инсайдер и процессы

**7.1. DevSecOps = полный доступ ко всему**
Owner PKI = owner Vault = owner audit = owner snapshot. Нет разделения обязанностей:
- Тот же человек пишет policy, аппрувит, деплоит, рулит audit.
- Maker/checker модели нет.
- Gitops для policy с обязательным ревью до apply — в доках не указано.

**7.2. Смена людей**
При увольнении DevSecOps:
- Unseal-ключ Shamir — у него. Rotate-процедуры нет в доке.
- Root token — у него.
- Доступ к Keycloak админ-группе — у него.
Без регламента offboarding на эти артефакты компания остаётся с Vault, где бывший сотрудник знает все ключи.

**7.3. ITOP — доверенная, но внешняя команда**
- Можете ли вы технически проверить, что полученный бандл — именно тот, что запрашивали, а не подложенный злоумышленником внутри ITOP?
- Thumbprint verification out-of-band (голосом по телефону, личной встречей) — есть такое в регламенте? Если нет — социальная инженерия заменяет и ITOP, и ИБ.

## 8. Мелочи, которые «не страшно», пока не сложились вместе

- `role_id` в конфиге потребителя — это, по сути, логин. Если он в Git (вместе с CI, values-файлами Helm), любой разработчик с read-доступом к репо знает половину креденшиала. Вторая половина — `secret_id` в K8s Secret.
- Нет ограничения на `ip_sans`/`uri_sans` — SPIFFE-идентификаторы, произвольные SAN для обхода валидаторов.
- Лимитов по числу запросов к AppRole/PKI на уровне Vault нет → bulk-issuance DoS / exhaust CRL signer.
- `cert-manager` в Kubernetes часто работает с `automountServiceAccountToken=true` и cluster-wide permission → компрометация ноды = полный контроль над issuer.
- `pki-stage` работает и «считается тестовым», но серты оттуда могут использоваться в реальных prod-процессах (Kafka, который «тестовый» для вас, = prod для зависящих продуктов). Соотношение критичности ≠ названию mount.

## Что бы я атаковал в первую очередь

Если ограничить бюджет атаки — в таком порядке:

1. **K8s Secret с `secret_id` AppRole** — самый короткий путь к «выпускаю любые wildcard в зоне Kafka».
2. **Держатель единственного Shamir-ключа** (человек) — через endpoint compromise / фишинг → unseal + root token → всё.
3. **Бандл intermediate у ITOP** — social engineering внутри ITOP («дайте копию, мы проверяем») или перехват на канале передачи.
4. **Keycloak-группа с Vault-админ правами** — phishing SSO + отсутствие MFA enforcement.
5. **Raft snapshot** — если лежит на условном S3/NFS с широким доступом.

Остальное — следующие волны.

## TL;DR для доки с архитектурой

Самые жирные дыры, которые стоит закрыть до демо архитекторам (чтобы не огребать вопросами):

- Shamir 1-of-1 → минимум 3-of-5 или явный сценарий, как прожить до INIT-1793.
- Регламент хэндовера бандла + уничтожение копий + thumbprint verification out-of-band.
- Удалить `issue` из политики `p0239`, оставить только `sign`.
- Зафиксировать в роли `P0239`: `allow_ip_sans=false`, `allow_localhost=false`, `key_type=rsa` ≥ 2048 или `ec` P-256+, `max_ttl` в днях, не месяцах.
- `bound_cidr_list` на AppRole (подсети K8s).
- `secret_id_num_uses` + `secret_id_ttl` с автоматической ротацией.
- Audit в SIEM (минимум два device, append-only).
- Алертинг на массовый issuance, изменения policy, disable audit, issuer change.
- Explicit MFA на OIDC-логине в Vault для админ-групп.
- Shielded процедура offboarding (unseal, root token, OIDC группы).

Если хочешь — оформлю как отдельный раздел `docs/pki-architecture.md` §4 «Известные риски и план их снятия» (для того самого согласования с RedTeam, чтобы архитекторы видели, что вы знаете про эти дыры, а не делаете вид, что их нет). Но это уже официальная версия — скажи, нужно ли.

 I'm shifting into red team mode to identify realistic attack vectors in this PKI setup — thinking about how an attacker would exploit the architecture given what I know about the Vault instance, the intermediate CA key transfer process, and the external Windows root CA.

The intermediate CA private key is the biggest exposure: it exists unencrypted outside Vault during the handover from ITOP to the Vault team, traveling through email or shared drives where it could be intercepted, and sitting on team members' laptops until import with no clear enforcement of deletion afterward. Once ITOP has that bundle, they can import it anywhere, anytime, giving them persistent ability to issue certificates under the corporate root.

The Shamir 1-of-1 unseal is another critical weakness — marked as temporary but likely permanent in practice, meaning a single person controls whether the entire Vault can be accessed, creating a single point of failure for coercion, compromise, or departure.

Keycloak is a trust boundary: if it's compromised, all human access to Vault is compromised, and there's no mention of MFA on OIDC logins or clear policy boundaries to prevent overly broad admin-equivalent access through SSO group mappings.

The AppRole secret_id is only as secure as wherever it's stored — if it's in a Kubernetes Secret, then anyone with K8s RBAC or etcd access can steal it, and without rotation or usage limits, a leaked secret_id grants permanent access from anywhere on the network.

The P0239 role configuration is dangerously permissive: wildcard and subdomain issuance on `kafka.apim.lmru.tech` means an attacker with the role can issue `*.kafka.apim.lmru.tech` covering all clusters at once, or certs for any broker FQDN across teams, and there's no documented CN allowlist or safeguards on IP SANs, localhost, or arbitrary names that might be enabled by default.

The policy grants both `issue` and `sign` when `sign` alone would suffice for cert-manager, and `issue` with AppRole stored in K8s means K8s Secret access directly translates to arbitrary wildcard cert generation within the role's constraints.

The entire Vault cluster is a single point of failure: one compromised backend or one bad operator with sudo access can compromise the PKI, and there's no network or physical segregation between prod and stage environments.

I'm also checking whether the Vault endpoint is internal-only or exposed, whether mTLS is enforced on the API, how the Vault server's own TLS cert is issued, and whether there's an unencrypted hop between a load balancer and the Vault nodes, plus whether the Raft storage on disk is encrypted.

Now I'm looking at snapshots—they contain the entire sealed state including the CA key, so if an attacker obtains a snapshot plus unseal shares, they can recover the full CA key, and I need to understand where snapshots are stored and how long they're retained.

I'm also examining the audit setup: whether logs are on a separate SIEM or just local disk that admins could tamper with, whether there's tamper protection, and whether there's alerting on suspicious issuance patterns like bulk cert generation or unusual domains.

For ACME on pki-stage, I'm checking whether it uses EAB or allows anonymous access, and if HTTP-01 challenges are used, a network attacker who can spoof DNS or HTTP could issue certs for any allowed domain.

On revocation, short TTLs are good, but CRL distribution over HTTP only means an attacker can serve a stale CRL and make revoked certs appear valid, and I need to know if clients actually validate CRL or OCSP or just trust the chain.

Finally, I'm considering operational risks: whether operator workstations have any hardening despite having root token access, where recovery and unseal keys are backed up, and whether Vault is kept patched against known CVEs.

Now I'm moving into the next layer—CI/CD pipelines writing to Vault introduce their own credential exposure, the DevSecOps owner is a single point of trust with no maker-checker on policy or role changes, and the ITOP team can issue intermediates without strong binding, making it purely trust-based.

I'm also flagging that snapshot restore is untested, so real DR could fail, and if primary and snapshot storage share a failure domain, both are lost at once.

For AppRole specifically, if role_id is in consumer config in Git it leaks, and combined with secret_id elsewhere that's full login compromise; token_ttl under 1h is good but I need to check if tokens are renewable and what token_max_ttl is set to, and bound_cidr_list should be enforced or AppRole login works from anywhere.

I'm going to structure this as an unofficial red team list in Russian, organized by severity and impact, covering CA material, authorization, PKI config, Vault exploitation, network, and detection gaps.

Drafting this as a markdown list with what I'd attack, how, realism, and fixes—keeping it punchy and technically precise without formality, biased toward what an attacker tries first.


<user_query>
добавь в доки в план
пункт 6.1 добавь в доки
Gitops для policy
сходил руками поправил полиси, теперь так
path "pki-stage/sign/P0239" {
  capabilities = ["update", "create"]
}

path "pki-stage/cert/ca" {
  capabilities = ["read"]
}

path "pki-stage/cert/ca_chain" {
  capabilities = ["read"]
}

</user_query>


Ок, фиксирую три вещи:
1. Обновляю HCL-файл политики и доки — `issue` убирается, остаётся только `sign`.
2. В `docs/pki-architecture.md` в план работ добавляю: GitOps для policy и пункт про revocation (из списка RedTeam §6.1).

Сначала посмотрю текущие состояния.

 The user has manually edited the `p0239` policy in Vault, removing the `issue` path and keeping only `sign`. They want me to update the documentation to reflect this change, and add two items to the plan: CRL/revocation hardening from the red team findings, and GitOps for policy management. I'm parsing through their Russian text to confirm these are the priorities.

Now I need to check the current policy file to see what needs updating across the documentation and architecture files.


 I need to update the HCL policy file by removing the `issue` block, then revise the documentation to reflect that the policy no longer grants `issue` permissions — though the manual test examples should still work since they use admin credentials with broader access.

For the plan items, I'm looking at where to add GitOps for policy and revocation validation. The outline_pki.md file has a dedicated §11 "План до ввода в `prod`" section, which seems like the right place. I could also add a risks and mitigation section to pki-architecture.md, but since the user asked to add to the plan, outline_pki.md §11 is probably the best fit. I'll add both the GitOps for policy item and the CRL revocation validation fix there. I need to add these two items to the plan section in outline_pki.md §11, then check if pki-architecture.md needs any corresponding updates to keep the policy references consistent.


Теперь всё по порядку.

1) Обновляю HCL-файл — убираю `issue`:

path "pki-stage/issue/P0239" {
  capabilities = ["update", "create"]
}

path "pki-stage/sign/P0239" {
  capabilities = ["update", "create"]
}

path "pki-stage/sign/P0239" {
  capabilities = ["update", "create"]
}


2) `docs/outline_pki.md` — список capability в §5.4:

- Policy: `p0239`
  - `pki-stage/issue/P0239` (`create`, `update`)
  - `pki-stage/sign/P0239` (`create`, `update`)
  - `pki-stage/cert/ca` (`read`)
  - `pki-stage/cert/ca_chain` (`read`)

- Policy: `p0239`
  - `pki-stage/sign/P0239` (`create`, `update`) — единственный путь выпуска для AppRole, `issue` умышленно не выдан;
  - `pki-stage/cert/ca` (`read`)
  - `pki-stage/cert/ca_chain` (`read`)


3) `docs/kafka-pki-vault-pki-lmru-procedure.md` — примеры ручного выпуска и таблица эндпоинтов. `issue` для AppRole больше не работает, но админ через OIDC может использовать `issue` для тестов, отмечу это.


Проверка выпуска:

```bash
vault write -format=json pki-stage/issue/P0239 \
  common_name="*.kafka.apim.lmru.tech" ttl=24h | jq -r '.data.certificate' | openssl x509 -noout -subject -ext subjectAltName

vault write -format=json pki-stage/issue/P0239 \
  common_name="*.kfk4u-ha-test.ycd-kafka-a-stage.kafka.apim.lmru.tech" \
  alt_names="broker-ycd-1000.kfk4u-ha-test.ycd-kafka-a-stage.kafka.apim.lmru.tech" \
  ttl=168h | jq -r '.data.certificate' | openssl x509 -noout -subject -ext subjectAltName
```

Проверка выпуска (выполняется только под админским токеном через `OIDC`, у AppRole `p0239` право на `issue` не выдано — см. §2):

```bash
vault write -format=json pki-stage/issue/P0239 \
  common_name="*.kafka.apim.lmru.tech" ttl=24h | jq -r '.data.certificate' | openssl x509 -noout -subject -ext subjectAltName

vault write -format=json pki-stage/issue/P0239 \
  common_name="*.kfk4u-ha-test.ycd-kafka-a-stage.kafka.apim.lmru.tech" \
  alt_names="broker-ycd-1000.kfk4u-ha-test.ycd-kafka-a-stage.kafka.apim.lmru.tech" \
  ttl=168h | jq -r '.data.certificate' | openssl x509 -noout -subject -ext subjectAltName
```

Для **`prod`** заведите отдельный HCL с путями `pki-prod/issue/P0239` и `pki-prod/cert/...` и отдельное имя политики по согласованию.

Для **`prod`** заведите отдельный HCL с путями `pki-prod/sign/P0239` и `pki-prod/cert/...` и отдельное имя политики по согласованию. Путь `issue` AppRole-у на `prod` также не выдаётся.

| Выпуск (Vault issue API) | `POST /v1/pki-stage/issue/P0239` |
| Подпись CSR для cert-manager (Vault sign API) | `POST /v1/pki-stage/sign/P0239` |
| ACME directory (если используете) | `https://pki.lmru.tech/v1/pki-stage/acme/directory` |
| CA (read) | `GET /v1/pki-stage/cert/ca`, `GET /v1/pki-stage/cert/ca_chain` |

**cert-manager Vault issuer** (без ACME): используйте путь `pki-stage/sign/P0239` (не `issue`) и токен после `auth/approle/login`.

| Подпись CSR для cert-manager (Vault sign API) | `POST /v1/pki-stage/sign/P0239` |
| Выпуск от админа (Vault issue API, только OIDC) | `POST /v1/pki-stage/issue/P0239` |
| ACME directory (если используете) | `https://pki.lmru.tech/v1/pki-stage/acme/directory` |
| CA (read) | `GET /v1/pki-stage/cert/ca`, `GET /v1/pki-stage/cert/ca_chain` |

**cert-manager Vault issuer** (без ACME): используйте путь `pki-stage/sign/P0239` (не `issue`) и токен после `auth/approle/login`. Политика `p0239` намеренно не содержит `issue` — AppRole может только подписывать CSR.