Добавляю стандартную аннотацию `runbook_url` (поддерживается Grafana, Alertmanager и др.). Базовый URL берём из `git remote`: `https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss`, ветка `master`.

[REDACTED]

Write

---
# Runbook: ссылки на веб-просмотр документов в репозитории (ветка master).
# При переименовании default branch обновите URL в аннотации runbook_url.
groups:
  - name: vault-pki-availability
    rules:
      - alert: VaultEndpointDown
        expr: up{job="vault-pki-app"} == 0
        for: 2m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault metrics endpoint is unreachable"
          description: "Prometheus cannot scrape {{ $labels.instance }}."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultEndpointSealed
        expr: vault_core_unsealed{job="vault-pki-app"} == 0
        for: 1m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault endpoint reports sealed state"
          description: "{{ $labels.instance }} reports vault_core_unsealed=0."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultAutopilotUnhealthy
        expr: vault_autopilot_healthy{job="vault-pki-app"} == 0
        for: 2m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault Autopilot reports unhealthy cluster"
          description: >-
            Vault Autopilot health is 0 for {{ $labels.instance }}.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultAutopilotNodeUnhealthy
        expr: vault_autopilot_node_healthy{job="vault-pki-app"} == 0
        for: 2m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault Autopilot reports unhealthy node"
          description: "Vault node {{ $labels.node_id }} is unhealthy."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultAutopilotFailureToleranceLow
        expr: vault_autopilot_failure_tolerance{job="vault-pki-app"} < 1
        for: 5m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault Autopilot failure tolerance is low"
          description: "Vault failure tolerance is below 1."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

  - name: vault-pki-raft
    rules:
      - alert: VaultRaftLeaderElectionsHigh
        expr: increase(vault_raft_state_candidate{job="vault-pki-app"}[15m]) > 3
        for: 2m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault Raft leader elections are frequent"
          description: "Vault entered candidate state more than 3 times in 15m."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultRaftFollowerStateChangesHigh
        expr: >-
          increase(vault_raft_state_follower{job="vault-pki-app"}[15m])
          > 10
        for: 2m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault Raft follower state changes are frequent"
          description: >-
            Follower state changes increased more than 10 times in 15m.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultLeadershipLost
        expr: >-
          increase(vault_core_leadership_lost_count{job="vault-pki-app"}[15m])
          > 0
        for: 1m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault leadership was lost"
          description: "Vault reported leadership lost in the last 15m."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

  - name: vault-pki-errors
    rules:
      - alert: VaultApi5xxErrors
        expr: >-
          increase(vault_core_response_status_code{
          job="vault-pki-app",type="5xx"}[5m]) > 0
        for: 1m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault API returns 5xx errors"
          description: >-
            {{ $labels.instance }} returned 5xx responses in the last 5m.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultApi4xxSpike
        expr: >-
          increase(vault_core_response_status_code{
          job="vault-pki-app",type="4xx"}[10m]) > 20
        for: 2m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault API 4xx spike"
          description: >-
            {{ $labels.instance }} returned >20 4xx responses in the last 10m.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultAuditLogRequestFailure
        expr: >-
          increase(vault_audit_log_request_failure{job="vault-pki-app"}[5m])
          > 0
        for: 1m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault audit log request failure"
          description: "Vault reports audit log request failures."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultAuditLogResponseFailure
        expr: >-
          increase(vault_audit_log_response_failure{job="vault-pki-app"}[5m])
          > 0
        for: 1m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault audit log response failure"
          description: "Vault reports audit log response failures."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

  - name: vault-pki-capacity
    rules:
      - alert: VaultLeaseCountHigh
        expr: vault_expire_num_leases{job="vault-pki-app"} > 10000
        for: 15m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault lease count is high"
          description: "{{ $labels.instance }} has more than 10000 leases."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultTokenCountHigh
        expr: vault_token_count{job="vault-pki-app"} > 5000
        for: 15m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault token count is high"
          description: "{{ $labels.instance }} has more than 5000 tokens."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultRuntimeGoroutinesHigh
        expr: vault_runtime_num_goroutines{job="vault-pki-app"} > 5000
        for: 15m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault runtime goroutine count is high"
          description: "{{ $labels.instance }} has more than 5000 goroutines."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

  - name: vault-pki-certificates-and-backup
    rules:
      - alert: VaultPkiCaExpiryWarning
        expr: vault_pki_ca_expires_in_seconds < 60 * 24 * 3600
        for: 1h
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault PKI CA expires in less than 60 days"
          description: >-
            Mount {{ $labels.mount }} CA expires in less than 60 days.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiCaExpiryCritical
        expr: vault_pki_ca_expires_in_seconds < 30 * 24 * 3600
        for: 1h
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault PKI CA expires in less than 30 days"
          description: >-
            Mount {{ $labels.mount }} CA expires in less than 30 days.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiCaMetricsMissing
        expr: absent(vault_pki_ca_expires_in_seconds{mount="pki-stage"})
        for: 30m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault PKI CA expiry metric is missing"
          description: >-
            Textfile metric vault_pki_ca_expires_in_seconds for pki-stage
            is missing.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/vault-pki-monitoring-runbook.md

      - alert: VaultObjectStorageBackupStale
        expr: time() - vault_pki_object_storage_latest_mtime_seconds > 2 * 3600
        for: 30m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault Object Storage backup is stale"
          description: "Latest Vault backup object is older than 2 hours."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultObjectStorageBackupMetricsMissing
        expr: absent(vault_pki_object_storage_latest_mtime_seconds)
        for: 30m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault Object Storage backup metric is missing"
          description: >-
            Textfile metric vault_pki_object_storage_latest_mtime_seconds
            is missing.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md


[REDACTED]

Shell

command -v promtool >/dev/null && promtool check rules /home/ruslanpi/Documents/repos/lmru--devops-core--ansible-vault-oss/monitoring/prometheus/vault-pki-alerts.yml || python3 -c "import yaml; yaml.safe_load(open('/home/ruslanpi/Documents/repos/lmru--devops-core--ansible-vault-oss/monitoring/prometheus/vault-pki-alerts.yml')); print('yaml ok')"

Validate rules YAML with promtool or PyYAML


[REDACTED]


[REDACTED]

StrReplace

monitoring/prometheus/vault-pki-alerts.yml
```

В аннотациях правил задано **`runbook_url`** (стандарт Prometheus/Grafana): ссылка на [DR runbook](runbooks/vault-pki-dr-runbook.md), [операционный runbook](runbooks/vault-pki-operations-runbook.md) или этот документ, в зависимости от алерта. При форке репозитория или смене default branch обновите URL в файле правил.

Скопировать на Prometheus-сервер:

monitoring/prometheus/vault-pki-alerts.yml
```

Скопировать на Prometheus-сервер:


Да, это как раз типичная практика: в правилах Prometheus добавляют аннотацию **`runbook_url`** — её подхватывают **Grafana**, **Alertmanager** и многие интеграции, кнопка «Runbook» ведёт сразу в процедуру.

### Что сделано

**`monitoring/prometheus/vault-pki-alerts.yml`**

- У каждого алерта в `annotations` добавлен **`runbook_url`** на веб-просмотр файла в GitHub Enterprise:
  `https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/...`
- **DR runbook** — доступность, sealed, Autopilot, Raft, leadership, **5xx**, сбои audit.
- **Операционный runbook** — **4xx spike** (нагрузка/клиенты), **ёмкость** (leases/tokens/goroutines), срок CA, **stale/missing backup** в Object Storage.
- **`VaultPkiCaMetricsMissing`** — **`docs/vault-pki-monitoring-runbook.md`** (настройка textfile/cron).
- В начале файла комментарий: при смене default branch обновить URL.

**`docs/vault-pki-monitoring-runbook.md` (§8)** — коротко описано, что такое `runbook_url` и что ссылки нужно править при форке/переименовании ветки.

Если правила дублируют в `lmru--promaas--itsec`, те же `runbook_url` стоит перенести туда или держать один источник правды из этого репозитория.

[REDACTED]


<user_query>
в lmru--promaas--itsec и нужно добавить. Пересмотри алерты, проверь ранбук есть ли вся необходимая инфа
</user_query>


Ищем репозиторий `lmru--promaas--itsec` и просматриваем текущие алерты и runbook'и.

[REDACTED]

Shell

ls -la /home/ruslanpi/Documents/repos/ 2>/dev/null | head -40

List sibling repos to find promaas-itsec


[REDACTED]

cd /home/ruslanpi/Documents/repos/lmru--promaas--itsec && git remote -v | head -2

Get itsec repo GitHub URL for runbook links


Добавляем `runbook_url` во все правила в `lmru--promaas--itsec`, расширяем runbook'и под алерты, которые есть только в itsec, и синхронизируем `vault-pki-alerts.yml` в ansible-репозитории.

[REDACTED]

Write

# runbook_url ведут в lmru--devops-core--ansible-vault-oss (документация PKI).
# При смене default branch в том репозитории обновите URL.
groups:
  - name: vault-pki-availability
    rules:
      - alert: VaultEndpointDown
        expr: up{job="vault-pki-app"} == 0
        for: 2m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault metrics endpoint is unreachable"
          description: "Prometheus cannot scrape {{ $labels.instance }}."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultEndpointSealed
        expr: vault_core_unsealed{job="vault-pki-app"} == 0
        for: 1m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault endpoint reports sealed state"
          description: "{{ $labels.instance }} reports vault_core_unsealed=0."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultAutopilotUnhealthy
        expr: vault_autopilot_healthy{job="vault-pki-app"} == 0
        for: 2m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault Autopilot reports unhealthy cluster"
          description: "Vault Autopilot health is 0 for {{ $labels.instance }}."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultAutopilotNodeUnhealthy
        expr: vault_autopilot_node_healthy{job="vault-pki-app"} == 0
        for: 2m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault Autopilot reports unhealthy node"
          description: "Vault node {{ $labels.node_id }} is unhealthy."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultAutopilotFailureToleranceLow
        expr: vault_autopilot_failure_tolerance{job="vault-pki-app"} < 1
        for: 5m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault Autopilot failure tolerance is low"
          description: "Vault failure tolerance is below 1."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

  - name: vault-pki-raft
    rules:
      - alert: VaultRaftLeaderElectionsHigh
        expr: increase(vault_raft_state_candidate{job="vault-pki-app"}[15m]) > 3
        for: 2m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault Raft leader elections are frequent"
          description: "Vault entered candidate state more than 3 times in 15m."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultRaftFollowerStateChangesHigh
        expr: increase(vault_raft_state_follower{job="vault-pki-app"}[15m]) > 10
        for: 2m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault Raft follower state changes are frequent"
          description: >-
            Follower state changes increased more than 10 times in 15m.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultLeadershipLost
        expr: increase(vault_core_leadership_lost_count{job="vault-pki-app"}[15m]) > 0
        for: 1m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault leadership was lost"
          description: "Vault reported leadership lost in the last 15m."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

  - name: vault-pki-errors
    rules:
      - alert: VaultApi5xxErrors
        expr: increase(vault_core_response_status_code{job="vault-pki-app",type="5xx"}[5m]) > 0
        for: 1m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault API returns 5xx errors"
          description: "{{ $labels.instance }} returned 5xx responses in the last 5m."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultApi4xxSpike
        expr: increase(vault_core_response_status_code{job="vault-pki-app",type="4xx"}[10m]) > 20
        for: 2m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault API 4xx spike"
          description: "{{ $labels.instance }} returned >20 4xx responses in the last 10m."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultAuditLogRequestFailure
        expr: increase(vault_audit_log_request_failure{job="vault-pki-app"}[5m]) > 0
        for: 1m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault audit log request failure"
          description: "Vault reports audit log request failures."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultAuditLogResponseFailure
        expr: increase(vault_audit_log_response_failure{job="vault-pki-app"}[5m]) > 0
        for: 1m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault audit log response failure"
          description: "Vault reports audit log response failures."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

  - name: vault-pki-capacity
    rules:
      - alert: VaultLeaseCountHigh
        expr: vault_expire_num_leases{job="vault-pki-app"} > 10000
        for: 15m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault lease count is high"
          description: "{{ $labels.instance }} has more than 10000 leases."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultTokenCountHigh
        expr: vault_token_count{job="vault-pki-app"} > 5000
        for: 15m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault token count is high"
          description: "{{ $labels.instance }} has more than 5000 tokens."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultRuntimeGoroutinesHigh
        expr: vault_runtime_num_goroutines{job="vault-pki-app"} > 5000
        for: 15m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault runtime goroutine count is high"
          description: "{{ $labels.instance }} has more than 5000 goroutines."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

  - name: vault-pki-certificates-and-backup
    rules:
      - alert: VaultPkiCaExpiryWarning
        expr: vault_pki_ca_expires_in_seconds{job="vault-pki"} < 60 * 24 * 3600
        for: 1h
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault PKI CA expires in less than 60 days"
          description: "Mount {{ $labels.mount }} CA expires in less than 60 days."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiCaExpiryCritical
        expr: vault_pki_ca_expires_in_seconds{job="vault-pki"} < 30 * 24 * 3600
        for: 1h
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault PKI CA expires in less than 30 days"
          description: "Mount {{ $labels.mount }} CA expires in less than 30 days."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiCaMetricsMissing
        expr: absent(vault_pki_ca_expires_in_seconds{job="vault-pki",mount="pki-stage"})
        for: 30m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault PKI CA expiry metric is missing"
          description: >-
            Textfile metric vault_pki_ca_expires_in_seconds for pki-stage
            (job vault-pki) is missing.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/vault-pki-monitoring-runbook.md

      - alert: VaultObjectStorageBackupStale
        expr: >-
          time() - vault_pki_object_storage_latest_mtime_seconds{job="vault-pki"}
          > 2 * 3600
        for: 30m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault Object Storage backup is stale"
          description: "Latest Vault backup object is older than 2 hours."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultObjectStorageBackupMetricsMissing
        expr: absent(vault_pki_object_storage_latest_mtime_seconds{job="vault-pki"})
        for: 30m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault Object Storage backup metric is missing"
          description: >-
            Textfile metric vault_pki_object_storage_latest_mtime_seconds
            (job vault-pki) is missing.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiTextfileScrapeError
        expr: >-
          max(
            node_textfile_scrape_error{job="vault-pki"}
            and on(instance) node_textfile_mtime_seconds{
              job="vault-pki",
              file=~".*vault_pki[.]prom"
            }
          ) > 0
        for: 5m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Vault PKI textfile scrape error on {{ $labels.instance }}"
          description: >-
            node_exporter failed to parse vault_pki.prom on this instance.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

  - name: vault-pki-node-host
    rules:
      - alert: VaultPkiDockerServiceNotActive
        expr: >-
          max by (hostname, instance) (
            node_systemd_unit_state{
              job="vault-pki",
              name="docker.service",
              state="active"
            }
          ) < 1
        for: 3m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "docker.service is not active on {{ $labels.hostname }}"
          description: >-
            Vault PKI nodes run in Docker; check systemctl/docker on
            {{ $labels.instance }}.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiFilesystemDeviceError
        expr: node_filesystem_device_error{job="vault-pki",fstype="ext4"} > 0
        for: 5m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Filesystem device error on {{ $labels.hostname }}"
          description: >-
            node_filesystem_device_error on {{ $labels.mountpoint }}
            ({{ $labels.instance }}): check dmesg/disk.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiRootInodeUsageWarning
        expr: >-
          (
            1
            - (
                node_filesystem_files_free{
                  job="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
                / node_filesystem_files{
                  job="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
              )
          ) * 100 > 85
        for: 15m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "High inode usage on root FS ({{ $labels.hostname }})"
          description: >-
            Root ext4 on {{ $labels.instance }} uses more than 85% of inodes.
            Risk for audit logs / Docker overlays.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiRootInodeUsageCritical
        expr: >-
          (
            1
            - (
                node_filesystem_files_free{
                  job="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
                / node_filesystem_files{
                  job="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
              )
          ) * 100 > 95
        for: 10m
        labels:
          severity: critical
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Critical inode usage on root FS ({{ $labels.hostname }})"
          description: >-
            Root ext4 on {{ $labels.instance }} uses more than 95% of inodes.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiClockOffsetHigh
        expr: abs(node_timex_offset_seconds{job="vault-pki"}) > 1
        for: 15m
        labels:
          severity: warning
          owner: devsecops
          service: vault-pki
        annotations:
          summary: "Large clock offset on {{ $labels.hostname }}"
          description: >-
            |node_timex_offset_seconds| > 1s on {{ $labels.instance }}.
            PKI/TLS relies on correct time; check NTP/chrony.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md


Обновляя операционный runbook и синхронизируя `vault-pki-alerts.yml` в ansible-репозитории: переносим audit на operations и добавляем недостающие правила.

[REDACTED]

StrReplace

## 5. Textfile-метрики CA / backup; алерт `VaultPkiTextfileScrapeError`

**Симптомы:** пропали серии `vault_pki_*` в Prometheus, `VaultPkiCaMetricsMissing`, `VaultObjectStorageBackupMetricsMissing`, **`VaultPkiTextfileScrapeError`** (node_exporter не смог разобрать `vault_pki.prom`).

**Действия:**

1. На ноде с textfile-cron:
   ```bash
   sudo cat /var/lib/node_exporter/textfile_collector/vault_pki.prom | head
   sudo tail -30 /var/log/vault-pki-textfile-metrics.log
   ```
2. **Ошибка парсинга (`VaultPkiTextfileScrapeError`):** вручную проверить файл `vault_pki.prom` — допустимый формат Prometheus text exposition (битая строка, незакрытый `# HELP`, неверный тип). Сравнить с рабочей нодой или перезапустить скрипт после исправления; при пустом файле удалить его и дождаться следующего прогона cron.
3. После ребута Vault API может быть кратко недоступен — дождаться следующего cron (**15 мин**) или запустить скрипт вручную с `VAULT_ADDR=https://pki.lmru.tech`.
4. **Универсально:** `curl -s http://127.0.0.1:9100/metrics | rg 'node_textfile_scrape_error|vault_pki_'` на проблемной ноде.

## 6. Алерт: всплеск 4xx по API (`VaultApi4xxSpike`)

Метрика — **агрегат** ответов Vault (не по конкретному клиенту в этих правилах).

1. Уточнить период инцидента в Grafana / Prometheus; нет ли совпадения с релизом потребителей PKI.
2. Типовые причины: массовые **403/401** (истекающие токены, смена policy), **404** (неверный path), ошибки интеграций.
3. При необходимости включить/проверить **аудит** и логи на лидере (объём диска / inodes — §8).
4. Эскалация владельцам сервисов, бьющих в API, при устойчивом шуме.

## 7. Алерт: сбой audit (`VaultAuditLogRequestFailure`, `VaultAuditLogResponseFailure`)

Пока счётчики растут, события могут **не** попадать в приёмник audit.

1. На активном узле Vault: логи контейнера / сервиса на сообщения об **audit** (отказ файла, syslog, сети).
2. **Файловый sink:** место на разделе, права, **inodes** (см. §8.3) — заполненный диск часто ломает audit.
3. **Syslog/socket:** доступность коллектора, сеть, лимиты.
4. Устранить причину **до** перезапуска Vault; перезапуск — по регламенту (кратковременный простой клиентов).
5. Детали политики audit — `docs/adr/architecture.md` (раздел мониторинга / аудит).

## 8. Ноды `job="vault-pki"`: Docker, диск, inodes, время

Prometheus job **`vault-pki`** — node_exporter на хостах кластера (см. `lmru--promaas--itsec/.helm/jobs/vault-pki.yaml`).

### 8.1. `VaultPkiDockerServiceNotActive`

1. SSH на хост из алерта (`instance` / `hostname`).
2. `systemctl status docker`, `journalctl -xeu docker --no-pager`.
3. Поднять `docker`; проверить контейнер Vault (`docker ps`, логи контейнера).
4. Если Docker не поднимается — эскалация; при недоступности кластера см. [vault-pki-dr-runbook.md](vault-pki-dr-runbook.md).

### 8.2. `VaultPkiFilesystemDeviceError`

1. `dmesg`, состояние диска / гипервизора; коррелировать с **`node_filesystem_device_error`** (метка `mountpoint`).
2. Риск для Raft и данных — при деградации кластера действовать по DR runbook после согласования.

### 8.3. `VaultPkiRootInodeUsageWarning` / `VaultPkiRootInodeUsageCritical`

1. `df -i /`, найти потребителей inodes: `journal`, audit, Docker layers, старые логи в `/var/log`, мелкие файлы в каталогах data.
2. Ротация/очистка по политике; не удалять данные Raft вручную без процедуры.
3. Высокие inodes часто **коррелируют** с `VaultAuditLog*` и сбоями записи логов.

### 8.4. `VaultPkiClockOffsetHigh`

1. `timedatectl`, `chronyc tracking` (или аналог NTP в вашем дистрибутиве).
2. Рассинхрон >1 с вредит TLS и PKI; восстановить синхронизацию с NTP.

### 8.5. `VaultEndpointDown` (дополнительно)

Если недоступен scrape **`vault-pki-app`**, а **ноды живы**: проверить VIP/LB `pki.lmru.tech`, сеть до балансировщика. Если падают и нодовые метрики — начинать с §8.1.

## 9. Дубли алертов в OnCall (две карточки на одно событие)

## 5. Textfile-метрики CA / backup пропали в Prometheus

1. На ноде с textfile-cron:
   ```bash
   sudo cat /var/lib/node_exporter/textfile_collector/vault_pki.prom | head
   sudo tail -30 /var/log/vault-pki-textfile-metrics.log
   ```
2. После ребута Vault API может быть кратко недоступен — дождаться следующего cron (**15 мин**) или запустить скрипт вручную с `VAULT_ADDR=https://pki.lmru.tech`.
3. `node_textfile_scrape_error` в Prometheus — проверить синтаксис `.prom` и права каталога.

## 6. Дубли алертов в OnCall (две карточки на одно событие)

## 10. Эскалация

## 7. Эскалация

---

## Алерты и ссылки (`runbook_url`)

Канонические правила: **`lmru--promaas--itsec`** — `.helm/rules/vault_pki_alerts.yaml` (значение **`owner: devsecops`**; дубли с тем же `alertname` и другим `owner` дают двойные тикеты в OnCall).
Дубликат для ручной установки Prometheus: `monitoring/prometheus/vault-pki-alerts.yml` в этом репозитории.

| Алерт (примеры) | Runbook |
|-----------------|---------|
| Доступность API, sealed, Autopilot, Raft, 5xx | [vault-pki-dr-runbook.md](vault-pki-dr-runbook.md) |
| Backup/Object Storage, 4xx, audit, ёмкость, CA/textfile, ноды Docker/FS/inode/time | Этот документ |
| Первичная настройка scrape/textfile | [vault-pki-monitoring-runbook.md](../vault-pki-monitoring-runbook.md) |


[REDACTED]

**DR / полное восстановление кластера** — в отдельном документе: [vault-pki-dr-runbook.md](vault-pki-dr-runbook.md).

## 1. Контекст (что где лежит)

**DR / полное восстановление кластера** — в отдельном документе: [vault-pki-dr-runbook.md](vault-pki-dr-runbook.md).

### Алерты и `runbook_url`

Канонические правила: **`lmru--promaas--itsec`** — `.helm/rules/vault_pki_alerts.yaml`. Референс для «голого» Prometheus: `monitoring/prometheus/vault-pki-alerts.yml` в этом репозитории. Не дублировать один и тот же `alertname` с разным **`owner`** — иначе двойные тикеты в OnCall.

| Тип алертов | Документ |
|-------------|----------|
| Доступность API, sealed, Autopilot, Raft, 5xx | [vault-pki-dr-runbook.md](vault-pki-dr-runbook.md) |
| Backup/S3, 4xx, audit, CA/textfile, ёмкость, Docker/диск/inode/NTP | Этот runbook |
| Первичная настройка scrape и textfile | [vault-pki-monitoring-runbook.md](../vault-pki-monitoring-runbook.md) |

## 1. Контекст (что где лежит)


[REDACTED]

### 8.6. `VaultLeaseCountHigh`, `VaultTokenCountHigh`, `VaultRuntimeGoroutinesHigh`

Предупреждения по росту **leases**, **токенов** или **goroutines** (пороги в правилах itsec).

1. Сравнить тренд в Grafana: внезапный скачок vs медленный рост.
2. **Leases/tokens:** типично утечки автоматизации (не отзываются short-lived токены), всплеск клиентов; при необходимости точечный revoke / работа с владельцами ролей (см. `docs/adr/architecture.md`).
3. **Goroutines:** может сопровождать нагрузку или баг; при корреляции с 5xx/падением — [vault-pki-dr-runbook.md](vault-pki-dr-runbook.md); иначе зафиксировать и наблюдать, собрать профиль по согласованию.

### 8.5. `VaultEndpointDown` (дополнительно)

### 8.5. `VaultEndpointDown` (дополнительно)


[REDACTED]

### 8.4. `VaultPkiClockOffsetHigh`

1. `timedatectl`, `chronyc tracking` (или аналог NTP в вашем дистрибутиве).
2. Рассинхрон >1 с вредит TLS и PKI; восстановить синхронизацию с NTP.

### 8.5. `VaultEndpointDown` (дополнительно)

Если недоступен scrape **`vault-pki-app`**, а **ноды живы**: проверить VIP/LB `pki.lmru.tech`, сеть до балансировщика. Если падают и нодовые метрики — начинать с §8.1.

### 8.6. `VaultLeaseCountHigh`, `VaultTokenCountHigh`, `VaultRuntimeGoroutinesHigh`

Предупреждения по росту **leases**, **токенов** или **goroutines** (пороги в правилах itsec).

1. Сравнить тренд в Grafana: внезапный скачок vs медленный рост.
2. **Leases/tokens:** типично утечки автоматизации (не отзываются short-lived токены), всплеск клиентов; при необходимости точечный revoke / работа с владельцами ролей (см. `docs/adr/architecture.md`).
3. **Goroutines:** может сопровождать нагрузку или баг; при корреляции с 5xx/падением — [vault-pki-dr-runbook.md](vault-pki-dr-runbook.md); иначе зафиксировать и наблюдать, собрать профиль по согласованию.

## 9. Дубли алертов в OnCall (две карточки на одно событие)

### 8.4. `VaultPkiClockOffsetHigh`

1. `timedatectl`, `chronyc tracking` (или аналог NTP в вашем дистрибутиве).
2. Рассинхрон >1 с вредит TLS и PKI; восстановить синхронизацию с NTP.

### 8.6. `VaultLeaseCountHigh`, `VaultTokenCountHigh`, `VaultRuntimeGoroutinesHigh`

Предупреждения по росту **leases**, **токенов** или **goroutines** (пороги в правилах itsec).

1. Сравнить тренд в Grafana: внезапный скачок vs медленный рост.
2. **Leases/tokens:** типично утечки автоматизации (не отзываются short-lived токены), всплеск клиентов; при необходимости точечный revoke / работа с владельцами ролей (см. `docs/adr/architecture.md`).
3. **Goroutines:** может сопровождать нагрузку или баг; при корреляции с 5xx/падением — [vault-pki-dr-runbook.md](vault-pki-dr-runbook.md); иначе зафиксировать и наблюдать, собрать профиль по согласованию.

### 8.5. `VaultEndpointDown` (дополнительно)

Если недоступен scrape **`vault-pki-app`**, а **ноды живы**: проверить VIP/LB `pki.lmru.tech`, сеть до балансировщика. Если падают и нодовые метрики — начинать с §8.1.

## 9. Дубли алертов в OnCall (две карточки на одно событие)


Обновляю `vault-pki-alerts.yml` в ansible-репозитории: синхронизация с itsec и исправление `runbook_url` для audit.

[REDACTED]

          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultAuditLogResponseFailure

          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

      - alert: VaultAuditLogResponseFailure


[REDACTED]

          description: "Vault reports audit log response failures."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

  - name: vault-pki-capacity

          description: "Vault reports audit log response failures."
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-dr-runbook.md

  - name: vault-pki-capacity


[REDACTED]

      - alert: VaultObjectStorageBackupMetricsMissing
        expr: absent(vault_pki_object_storage_latest_mtime_seconds)
        for: 30m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault Object Storage backup metric is missing"
          description: >-
            Textfile metric vault_pki_object_storage_latest_mtime_seconds
            is missing.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiTextfileScrapeError
        expr: >-
          max(
            node_textfile_scrape_error{job="vault-pki"}
            and on(instance) node_textfile_mtime_seconds{
              job="vault-pki",
              file=~".*vault_pki[.]prom"
            }
          ) > 0
        for: 5m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Vault PKI textfile scrape error on {{ $labels.instance }}"
          description: >-
            node_exporter failed to parse vault_pki.prom on this instance.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

  - name: vault-pki-node-host
    rules:
      - alert: VaultPkiDockerServiceNotActive
        expr: >-
          max by (hostname, instance) (
            node_systemd_unit_state{
              job="vault-pki",
              name="docker.service",
              state="active"
            }
          ) < 1
        for: 3m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "docker.service is not active on {{ $labels.hostname }}"
          description: >-
            Vault PKI nodes run in Docker; check systemctl/docker on
            {{ $labels.instance }}.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiFilesystemDeviceError
        expr: node_filesystem_device_error{job="vault-pki",fstype="ext4"} > 0
        for: 5m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Filesystem device error on {{ $labels.hostname }}"
          description: >-
            node_filesystem_device_error on {{ $labels.mountpoint }}
            ({{ $labels.instance }}): check dmesg/disk.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiRootInodeUsageWarning
        expr: >-
          (
            1
            - (
                node_filesystem_files_free{
                  job="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
                / node_filesystem_files{
                  job==="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
              )
          ) * 100 > 85
        for: 15m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "High inode usage on root FS ({{ $labels.hostname }})"
          description: >-
            Root ext4 on {{ $labels.instance }} uses more than 85% of inodes.
            Risk for audit logs / Docker overlays.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiRootInodeUsageCritical
        expr: >-
          (
            1
            - (
                node_filesystem_files_free{
                  job="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
                / node_filesystem_files{
                  job="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
              )
          ) * 100 > 95
        for: 10m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Critical inode usage on root FS ({{ $labels.hostname }})"
          description: >-
            Root ext4 on {{ $labels.instance }} uses more than 95% of inodes.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultPkiClockOffsetHigh
        expr: abs(node_timex_offset_seconds{job="vault-pki"}) > 1
        for: 15m
        labels:
          severity: warning
          service: vault-pki
        annotations:
          summary: "Large clock offset on {{ $labels.hostname }}"
          description: >-
            |node_timex_offset_seconds| > 1s on {{ $labels.instance }}.
            PKI/TLS relies on correct time; check NTP/chrony.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md

      - alert: VaultObjectStorageBackupMetricsMissing
        expr: absent(vault_pki_object_storage_latest_mtime_seconds)
        for: 30m
        labels:
          severity: critical
          service: vault-pki
        annotations:
          summary: "Vault Object Storage backup metric is missing"
          description: >-
            Textfile metric vault_pki_object_storage_latest_mtime_seconds
            is missing.
          runbook_url: >-
            https://github.lmru.tech/adeo/lmru--devops-core--ansible-vault-oss/blob/master/docs/runbooks/vault-pki-operations-runbook.md


[REDACTED]

                / node_filesystem_files{
                  job="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
              )
          ) * 100 > 85

                / node_filesystem_files{
                  job==="vault-pki",
                  fstype="ext4",
                  mountpoint="/"
                }
              )
          ) * 100 > 85


[REDACTED]

Shell

python3 -c "import yaml; yaml.safe_load(open('/home/ruslanpi/Documents/repos/lmru--devops-core--ansible-vault-oss/monitoring/prometheus/vault-pki-alerts.yml'))" && python3 -c "import yaml; yaml.safe_load(open('/home/ruslanpi/Documents/repos/lmru--promaas--itsec/.helm/rules/vault_pki_alerts.yaml'))" && echo OK

Validate YAML for both alert files

StrReplace

## 7. Ссылки

* Алерты (`runbook_url`): **`lmru--promaas--itsec`** — `.helm/rules/vault_pki_alerts.yaml`
* Архитектура PKI: `docs/adr/architecture.md`
* ADR: `docs/adr/ADR-001-pki-architecture.md`
* Операции backup и хост: [vault-pki-operations-runbook.md](vault-pki-operations-runbook.md)
* Мониторинг setup: `docs/vault-pki-monitoring-runbook.md`

## 7. Ссылки

* Архитектура PKI: `docs/adr/architecture.md`
* ADR: `docs/adr/ADR-001-pki-architecture.md`
* Операции backup: [vault-pki-operations-runbook.md](vault-pki-operations-runbook.md)
* Мониторинг setup: `docs/vault-pki-monitoring-runbook.md`

В аннотациях правил задано **`runbook_url`**: ссылка на [DR runbook](runbooks/vault-pki-dr-runbook.md), [операционный runbook](runbooks/vault-pki-operations-runbook.md) или этот документ. Источник правил в кластере: **`lmru--promaas--itsec`** (`.helm/rules/vault_pki_alerts.yaml`). При форке репозитория или смене default branch обновите URL в файле правил.

В аннотациях правил задано **`runbook_url`** (стандарт Prometheus/Grafana): ссылка на [DR runbook](runbooks/vault-pki-dr-runbook.md), [операционный runbook](runbooks/vault-pki-operations-runbook.md) или этот документ, в зависимости от алерта. При форке репозитория или смене default branch обновите URL в файле правил.


[REDACTED]

Shell

command -v promtool >/dev/null && promtool check rules /home/ruslanpi/Documents/repos/lmru--devops-core--ansible-vault-oss/monitoring/prometheus/vault-pki-alerts.yml 2>&1 || true

Run promtool check rules if installed


Кратко, что сделано.

## `lmru--promaas--itsec`

Файл **`.helm/rules/vault_pki_alerts.yaml`**:

- У **каждого** правила в `annotations` добавлен **`runbook_url`** на веб-просмотр документов в **`lmru--devops-core--ansible-vault-oss`** (ветка **`master`**).
- **`VaultAuditLog*`** ведут в **операционный** runbook (диск/inodes/приёмник audit), а не в DR — так же в ansible-файле.
- В шапке файла комментарий, что канон документации — репозиторий ansible-vault-oss.

## `lmru--devops-core--ansible-vault-oss`

**`docs/runbooks/vault-pki-operations-runbook.md`** доведён до покрытия **всех** алертов из itsec:

- Таблица: куда вести **DR / операции / мониторинг**; указание, что канон правил — **itsec**.
- **§5** — явно **`VaultPkiTextfileScrapeError`** и разбор `vault_pki.prom`.
- **§6** — **`VaultApi4xxSpike`**.
- **§7** — **`VaultAuditLogRequestFailure` / `VaultAuditLogResponseFailure`**.
- **§8** — ноды **`job="vault-pki"`**: Docker, FS, inodes, время, **`VaultEndpointDown`** (VIP vs ноды), **§8.6** — leases/tokens/goroutines.
- Нумерация: дубли OnCall — **§9**, эскалация — **§10**.

**`docs/runbooks/vault-pki-dr-runbook.md`** — в §7 добавлена ссылка на **`.helm/rules/vault_pki_alerts.yaml`**.

**`docs/vault-pki-monitoring-runbook.md`** — уточнено, что **`runbook_url`** живут в **itsec**.

**`monitoring/prometheus/vault-pki-alerts.yml`**:

- У **`VaultAuditLogResponseFailure`** исправлен **`runbook_url`** на операционный runbook.
- Добавлены правила как в itsec: **`VaultPkiTextfileScrapeError`**, группа **`vault-pki-node-host`** (Docker, FS, inodes, clock). Исправлена опечатка **`job===`** → **`job=`** в черновике (сейчас везде `job=`).

---

Дальнейшие шаги для вас: закоммитить изменения **в обоих** репозиториях и выкатить Helm/chart с обновлённым `vault_pki_alerts.yaml` в Prometheus Operator. Если default branch в **`lmru--devops-core--ansible-vault-oss`** когда‑нибудь станет не `master`, имеет смысл массово поправить URL в правилах.

[REDACTED]


<user_query>
@docs/adr/ADR-001-pki-architecture.md у нас принят вот такой шаблон для АДР, подойдет ли мой?

6

Аватар пользователя Руслан Петрович
Трекер
Задачи
Проекты и портфели
Цели
Очереди
Доски задач
Дашборды и отчёты
История
Architecture Decision Records
/
ADR-554

Создано только что, обновлено только что
[Draft] Архитектура PKI на HashiCorp Vault OSS
Решение
TBD Выбранный вариант и дата

Контекст
ДЕТАЛЬНОЕ ОПИСАНИЕ КОНТЕКСТА

Сроки
TBD Ограничения по срокам, если есть

Варианты
1. Делаем хорошо и без архитектурного долга

Описываем изменения
И состав работ
Оценки варианта:
✅ Аргумент в пользу этого решения (например: быстро приносим ценность или ликвидируем техдолг)
⛔ Аргумент против этого решения (например, создаём техдолг или нарушаем процесс)
❓ Описание неизвестных последствий (например: это решение может теоретически сломать какой-то бизнес-процесс, но это не точно)
⏳ Описание неизвестных сроков (например: нужны доработки, требующие анализ в командах, которые ещё не привлекались к обсуждению)
2. Делаем быстро и с архитектурным долгом

Описываем изменения
И состав работ
Оценки варианта:
✅ Аргумент в пользу этого решения (например: быстро приносим ценность или ликвидируем техдолг)
⛔ Аргумент против этого решения (например, создаём техдолг или нарушаем процесс)
❓ Описание неизвестных последствий (например: это решение может теоретически сломать какой-то бизнес-процесс, но это не точно)
⏳ Описание неизвестных сроков (например: нужны доработки, требующие анализ в командах, которые ещё не привлекались к обсуждению)
3. Не делаем ничего

Описываем изменения
И состав работ
Оценки варианта:
✅ Аргумент в пользу этого решения (например: быстро приносим ценность или ликвидируем техдолг)
⛔ Аргумент против этого решения (например, создаём техдолг или нарушаем процесс)
❓ Описание неизвестных последствий (например: это решение может теоретически сломать какой-то бизнес-процесс, но это не точно)
⏳ Описание неизвестных сроков (например: нужны доработки, требующие анализ в командах, которые ещё не привлекались к обсуждению)
Последствия
TBD Заполняем после обсуждения и принятия решения
Примеры:

Создаём техдолг, фиксируем его расположение и договорённости о сроках его ликвидации.
Есть влияние на порядок разбора инцидентов, фиксируем договорённости о распределении бюджета ошибок.
Есть изменения в процессах, фиксируем ответственных за описание и дату встречи, на которой будет презентован новый процесс
Решение принимали
TBD Список людей, принимавших решение

No file chosen
Активность
Начните писать текст или введите "/", чтобы открыть список команд

No file chosen
Статус
Тип статуса: Начальный
Новый
Учёт времени
—
Тип
Задача
Приоритет
Средний
Дедлайн
Автор
Руслан Петрович
Исполнитель
Наблюдатели
Проект
Связанные цели
Теги
Компоненты
Доски
Нужен ответ пользователя
Поля со списками
© 2026 ООО «Яндекс»

</user_query>


По содержанию ваш **ADR-001** как технический документ **сильнее** шаблона из трекера: контекст, выбранное решение, альтернативы и последствия уже есть и согласованы между собой.

По **форме шаблона ADR-554** — это не копия один в один, а **близкая по смыслу** версия. Сопоставление:

| Блок шаблона (ADR-554) | Ваш `ADR-001-pki-architecture.md` |
|------------------------|-----------------------------------|
| **Решение** (вариант + дата) | Есть блок «Решение», но **без явной даты принятия** и одной строки «выбран вариант X». |
| **Контекст** | Есть, детально — ок. |
| **Сроки** | **Отдельной секции нет** (можно добавить даже «нет жёсткого дедлайна / привязка к INIT-1793, ввод pki-prod — …»). |
| **Варианты** (3 сценария + ✅⛔❓⏳) | Есть «Рассмотренные альтернативы» **A/B/C** с плюсами/минусами — по сути то же, но **не те же три «аркетипа»**, что в шаблоне («хорошо без долга / быстро с долгом / не делаем»), и **нет** явных блоков про неизвестные последствия и сроки на каждый вариант. |
| **Последствия** | Есть (плюсы, компромиссы, риски) — даже богаче, чем примеры в шаблоне. |
| **Решение принимали** | **Нет** списка людей/ролей. |

**Вывод:** для работы команд и для согласования **подходит**; чтобы **формально лечь в ADR-554**, достаточно **добавить недостающие поля**, не переписывая всё:

1. В начало «Решения» — одну строку: *«Принято: Vault OSS + описанная иерархия PKI; дата: …»*.
2. Секция **«Сроки»** (хотя бы TBD с пояснением).
3. Секция **«Решение принимали»** (ФИО или роли из критериев приёмки п.1).
4. По желанию: для каждого из A/B/C добавить короткие подпункты **❓ неизвестные последствия** и **⏳ неизвестные сроки** — можно вынести из уже написанных «минусов».

Отдельно: **«Критерии приёмки ADR»** в вашем файле — это плюс к шаблону; в трекере ADR-554 такого блока нет, его можно **оставить** как расширение.

Итого: шаблон **не конфликтует** с вашим ADR; нужны в основном **метаданные** (дата, кто решил, сроки) и при желании **подгонка заголовков/вопросов** под три формальных варианта или явная пометка, что альтернативы A/B/C = заполнение блока «Варианты» в терминах предметной области.

[REDACTED]


<user_query>
что это значит?
сам факт хэндовера логируется, проверяется ИБ.
</user_query>


Речь про **передачу чувствительного артефакта** (в вашем контексте — чаще всего PEM-бандла intermediate CA с ключом) от одной стороны к другой (например, от ITOP к команде Vault).

**«Сам факт хэндовера логируется»** значит: не только «файл ушёл», а то, что **действие передачи зафиксировано в учёте** — тикет, журнал выдачи секрета, запись в CMDB, аудит в корпоративном Vault/KMS, подпись в процедуре и т.п. Цель — чтобы потом было видно: **когда, кто кому, по какому тикету** передал материал.

**«Проверяется ИБ»** значит: **информационная безопасность** эту цепочку **контролирует** — по регламенту: периодический разбор, выборочный аудит, проверка что хэндовер по процессу (доступы, канал, уничтожение копий у отправителя), соответствие политикам. Не обязательно «ИБ сидит и смотрит каждый байт в момент передачи», а что процесс **подпадает под их контроль/требования**.

Если эта фраза у вас в тексте про intermediate от ITOP: смысл — **передача ключа не «в тихую»**, а с **следом для аудита** и с **ролью ИБ в контроле процесса**.

[REDACTED]


<timestamp>Tuesday, May 12, 2026, 3:24 PM (UTC+3)</timestamp>
<user_query>

Поэтому мы и просим Вас сформировать crl

Приватный ключ останется у нас, а он нам не нужен

Сервис то ваш

Руслан Петрович
15:02
Возможно, мы говорим о разных вещах.
Мне нужен подписанный intermediate сертификат по нашему CSR
Приватный ключ остаётся у нас в Vault, и мы сами будем выпускать сертификаты
Поэтому просим только подпись CSR, а не выпуск сертов с вашей стороны

26 января

Сергей Коротеев
10:49
Я понимаю, нам чтобы выпустить промежуточный сертификат, который мы отправим вам, нужно получить от вас csr

Руслан Петрович
13:29

2 Файла
prod.csr
CSR2KB
stage.csr
CSR2KB

Сергей Коротеев
14:21
Короче, какой CN= и какой DNS= вам нужен?

Руслан Петрович
14:40
Опятт не так?

Я переделал через openssl

Сергей Коротеев
14:40
Нет, противиться

Проще самому выпустить и передать на флешке

Руслан Петрович
14:43
Позже напишу

Сергей Коротеев
14:46
Окай

27 января

Руслан Петрович
11:04
CN нужен только для промежуточного CA, SAN/DNS не требуется.
Stage: CN = LMRU PKI Stage Intermediate CA
Prod:  CN = LMRU PKI Prod Intermediate CA
Если ваша CA требует SAN, можем добавить DNS=pki.lmru.tech, но для CA это обычно не нужно.

Сергей Коротеев
11:18
Нет, в windows PKI независимо от шаблона требуется указывать subject name  и san

Руслан Петрович
11:25
Еще надо что-то?

Сергей Коротеев
11:42
Пока нет

28 января

Сергей Коротеев
13:35
Отправил Антону сертификаты, не знаю как у вас это будет работать без приватных ключей

Руслан Петрович
13:37
Отправь ключи тоже, пожалуйста

Сергей Коротеев
13:38
они остались в нашем pki

их нельзя вытащить оттуда

Чтобы они были у вас, вы должны дать нам crl

Руслан Петрович
13:40
Я без ключа не заимпорчу

Сергей Коротеев
13:41
тогда нужно выпускать вам через
certreq на windows машине

Руслан Петрович
13:42
А через certreq заимпортить с нужным атрибутом нельзя?

Мой crl

Первый который давал

Сергей Коротеев
13:46
Пока не знаю

Руслан Петрович
13:47
Посмотри, пожалуйста
Если не получится, найду винду

Сергей Коротеев
13:49
Окай, гляну

Сергей Коротеев
16:22
Отправил для stage crt и key

Проверь, будет ли работать

Cегодня

Руслан Петрович
15:19

привет
можешь подсказать, пожалуйста?
Александр Аверченков
4 дня назад
@Руслан Петрович привет! Возвращаюсь по pki, можешь подсказать плиз, то что сейчас настроили, это уже продовый инстанс?
Судя по всему те серты которые выдались, не подписаны нашим основным CA ЛеманаПРО, тк я подгрузил их в кафку и не могу подключиться к кафке через доверенный основной CA

4 ответа
Новые сообщения

Александр Аверченков
4 дня назад
Если что у нас как intermediate используется серт с CA Issuers:
http://crl.leroymerlin.ru/pki/aia/ADEO Vostok Root CA(1).crt

-4 дн.
а за ним еще root используем

Александр Аверченков
3 минуты назад
@Руслан Петрович привет, сможешь подсказать?

Руслан Петрович
2 минуты назад

привет, смотрю

Успешный вход в систему

Сергей Коротеев
15:20
Привет, не совсем понял суть вопроса

Руслан Петрович
15:21
от каккого рутового серта сделан промежуточный который ты мне выдал для pki.lmru.tech

Новые сообщения

Сергей Коротеев
15:22
а в цепочке самого серта не написано разве?

если нужно сходи на тачку посмотри что нужно
@/home/ruslanpi/.cursor/projects/home-ruslanpi-Documents-repos-lmru-devops-core-ansible-vault-oss/terminals/1.txt:7-9
</user_query>


Понял, сейчас проверю цепочку прямо по `pki.lmru.tech` и, если получится, зайду на ноду по SSH, чтобы точно ответить каким Root подписан текущий intermediate.

**Evaluating SSH and Vault checks**

I'm thinking about using an SSH command, but I'm aware that it might hang, so I should first send a commentary update. I'll attempt to run the SSH command remotely and aim for non-interactive access to avoid complications with passwords. It’s crucial to check which root signs the intermediate certificates currently in Vault. The simplest way looks like running a local OpenSSL command to fetch issuer information. However, the user wants to access the machine directly, so I can consider SSHing and inspecting the relevant TLS files.
**Checking issuer information**

I’m planning to examine the issuer's subject and Authority Information Access (AIA). I can use curl along with OpenSSL to fetch the subject and issuer details. It looks like I may also need to compose a response in Russian for Alexander, explaining that currently, it seems like the stage isn't signed by the LemanPRO root due to a wrong initial chain from ITOP. I should verify this, but without access, it could be difficult. I’ll first check network accessibility via curl and send a brief commentary.

openssl s_client -connect pki.lmru.tech:443 -servername pki.lmru.tech -showcerts </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer

Check TLS cert subject and issuer

curl -sk https://pki.lmru.tech/v1/pki-stage/ca/pem | openssl x509 -noout -subject -issuer -serial

Inspect stage CA certificate from Vault API

curl -sk https://pki.lmru.tech/v1/pki-prod/ca/pem | openssl x509 -noout -subject -issuer -serial

Inspect prod CA certificate from Vault API


<timestamp>Tuesday, May 12, 2026, 3:26 PM (UTC+3)</timestamp>
<user_query>
переподключил ВПН
</user_query>


Отлично, повторяю проверки цепочки сейчас после переподключения VPN.

openssl s_client -connect pki.lmru.tech:443 -servername pki.lmru.tech -showcerts </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -serial -dates

Check public TLS certificate chain leaf

curl -sSk https://pki.lmru.tech/v1/pki-stage/ca/pem | openssl x509 -noout -subject -issuer -serial -dates

Inspect pki-stage intermediate CA details

curl -sSk https://pki.lmru.tech/v1/pki-prod/ca/pem | openssl x509 -noout -subject -issuer -serial -dates

Inspect pki-prod intermediate CA details


**Checking background commands**

I need to perform a one-shot status check on background commands, particularly the block_until command. It seems like this is auto-backgrounded rather than manually triggered, but I might still need to poll since the next step is blocked regardless. I should utilize AwaitShell for each task and perhaps use a small block to ensure completion. Doing this in parallel could be beneficial, and maybe I can treat each task independently.


**Reviewing file reading methods**

I need to read some output files using ReadFile instead of using cat. So, I'll go ahead and focus on using ReadFile for these specific paths. I want to make sure I'm using the right method since I don't want to mess this up. It's important to rely on the appropriate function to ensure everything works smoothly. I'll follow through with that and see how it goes!


curl -sSk -w '\nHTTP:%{http_code}\n' https://pki.lmru.tech/v1/pki-prod/ca/pem

Check raw response for pki-prod CA endpoint

curl -sSk -w '\nHTTP:%{http_code}\n' https://pki.lmru.tech/v1/pki-stage/ca/pem | sed -n '1,4p'

Check stage endpoint raw response and status


**Checking sed usage**

I'm wondering if using `sed` is permitted since, according to the guidelines, only tools like `grep`, `find`, `cat`, `head`, and `tail` are prohibited. It seems `sed` might be okay after all. I also realize that I should check the HTTP code for the stage because, when piped to `sed`, I might lose the end result. Running a separate command to retrieve the stage code could be a good idea, but I need to evaluate that further.

curl -sSk -o /dev/null -w 'HTTP:%{http_code}\n' https://pki.lmru.tech/v1/pki-stage/ca/pem

Get HTTP status for pki-stage CA endpoint


Проверил после VPN — сейчас факты такие:

- `https://pki.lmru.tech/v1/pki-stage/ca/pem` отдает intermediate:
  - `subject=CN=LMRU PKI Stage Intermediate CA`
  - `issuer=... CN=TestLMRUTech`
  - срок: `2026-01-28` → `2028-01-28`
- `https://pki.lmru.tech/v1/pki-prod/ca/pem` возвращает `HTTP 204` (сертификат не выдан/не импортирован).
- TLS-сертификат самого хоста `pki.lmru.tech` — `*.lmru.tech` от GlobalSign (это сертификат балансировщика, не цепочка Vault PKI).

Итог: **сейчас у вас stage выдан не от “основного CA ЛеманаПРО”, а от TestLMRUTech**, и **prod intermediate фактически отсутствует**.

Можно ответить Александру так:
> Сейчас это не продовая цепочка. В `pki-stage` intermediate подписан `TestLMRUTech`, а `pki-prod` еще не загружен (пусто). Поэтому сертификаты не сходятся с доверенным основным CA.

Если хочешь, подготовлю короткий текст для Сергея/ITOP с точным запросом на перевыпуск intermediate под нужный root (и отдельно для stage/prod).


<timestamp>Tuesday, May 12, 2026, 3:33 PM (UTC+3)</timestamp>
<user_query>
вот полный чат с сергеем из ITOP

Руслан Петрович
15:02
Возможно, мы говорим о разных вещах.
Мне нужен подписанный intermediate сертификат по нашему CSR
Приватный ключ остаётся у нас в Vault, и мы сами будем выпускать сертификаты
Поэтому просим только подпись CSR, а не выпуск сертов с вашей стороны

26 января

Сергей Коротеев
10:49
Я понимаю, нам чтобы выпустить промежуточный сертификат, который мы отправим вам, нужно получить от вас csr

Руслан Петрович
13:29

2 Файла
prod.csr
CSR2KB
stage.csr
CSR2KB

Сергей Коротеев
14:21
Короче, какой CN= и какой DNS= вам нужен?

Руслан Петрович
14:40
Опятт не так?

Я переделал через openssl

Сергей Коротеев
14:40
Нет, противиться

Проще самому выпустить и передать на флешке

Руслан Петрович
14:43
Позже напишу

Сергей Коротеев
14:46
Окай

27 января

Руслан Петрович
11:04
CN нужен только для промежуточного CA, SAN/DNS не требуется.
Stage: CN = LMRU PKI Stage Intermediate CA
Prod:  CN = LMRU PKI Prod Intermediate CA
Если ваша CA требует SAN, можем добавить DNS=pki.lmru.tech, но для CA это обычно не нужно.

Сергей Коротеев
11:18
Нет, в windows PKI независимо от шаблона требуется указывать subject name  и san

Руслан Петрович
11:25
Еще надо что-то?

Сергей Коротеев
11:42
Пока нет

28 января

Сергей Коротеев
13:35
Отправил Антону сертификаты, не знаю как у вас это будет работать без приватных ключей

Руслан Петрович
13:37
Отправь ключи тоже, пожалуйста

Сергей Коротеев
13:38
они остались в нашем pki

их нельзя вытащить оттуда

Чтобы они были у вас, вы должны дать нам crl

Руслан Петрович
13:40
Я без ключа не заимпорчу

Сергей Коротеев
13:41
тогда нужно выпускать вам через
certreq на windows машине

Руслан Петрович
13:42
А через certreq заимпортить с нужным атрибутом нельзя?

Мой crl

Первый который давал

Сергей Коротеев
13:46
Пока не знаю

Руслан Петрович
13:47
Посмотри, пожалуйста
Если не получится, найду винду

Сергей Коротеев
13:49
Окай, гляну

Сергей Коротеев
16:22
Отправил для stage crt и key

Проверь, будет ли работать

Cегодня

Руслан Петрович
15:19

привет
можешь подсказать, пожалуйста?
Александр Аверченков
4 дня назад
@Руслан Петрович привет! Возвращаюсь по pki, можешь подсказать плиз, то что сейчас настроили, это уже продовый инстанс?
Судя по всему те серты которые выдались, не подписаны нашим основным CA ЛеманаПРО, тк я подгрузил их в кафку и не могу подключиться к кафке через доверенный основной CA

4 ответа
Новые сообщения

Александр Аверченков
4 дня назад
Если что у нас как intermediate используется серт с CA Issuers:
http://crl.leroymerlin.ru/pki/aia/ADEO Vostok Root CA(1).crt

-4 дн.
а за ним еще root используем

Александр Аверченков
3 минуты назад
@Руслан Петрович привет, сможешь подсказать?

Руслан Петрович
2 минуты назад

привет, смотрю

Успешный вход в систему

Сергей Коротеев
15:20
Привет, не совсем понял суть вопроса

Руслан Петрович
15:21
от каккого рутового серта сделан промежуточный который ты мне выдал для pki.lmru.tech

Сергей Коротеев
15:22
а в цепочке самого серта не написано разве?

Руслан Петрович
15:28
subject=CN=LMRU PKI Stage Intermediate CA
issuer=... CN=TestLMRUTech
срок: 2026-01-28 → 2028-01-28
</user_query>


Да, из этого чата видно, где разъехались ожидания:

- вы просили **подписать ваш CSR** (правильный для Vault путь: ключ у вас, ITOP только подписывает intermediate cert),
- ITOP в какой-то момент пошёл по пути «выпустим у себя», из-за этого возникла путаница про ключ/CRL,
- текущий факт: stage intermediate подписан от **`TestLMRUTech`**, а не от боевого root.

И ключевое: фраза «дайте CRL, чтобы вытащить ключ» — технически некорректна.
**CRL не имеет отношения к передаче приватного ключа.**

### Что написать Александру (коротко)
> Сейчас это не продовая цепочка.
> Проверили: текущий intermediate `LMRU PKI Stage Intermediate CA` выдан `TestLMRUTech`, поэтому доверие через основной CA не сходится.
> Делаем перевыпуск intermediate от нужного root (ADEO Vostok Root CA), после этого дадим обновление по срокам.

### Что написать Сергею/ITOP (чёткий запрос)
> Подтверждаю требование: нужен **только подписанный intermediate сертификат по нашему CSR** (SubCA).
> Приватный ключ генерируется и хранится у нас в Vault, передавать/генерировать ключ на вашей стороне не нужно.
> Сейчас в `pki-stage` issuer = `TestLMRUTech`, нам нужен issuer от боевой цепочки (ADEO Vostok Root CA).
> Просьба подписать наши CSR (`stage.csr`, `prod.csr`) от нужного root и вернуть цепочку в PEM (cert + chain, без private key).

Если хочешь, соберу ещё «жёсткую» версию сообщения для тикета в ITOP с acceptance criteria (какой issuer/SKI/AKI должны быть у выданного intermediate).


[Image]
<image_files>
The following images were provdied by the user and saved to the workspace for future use:
1. /home/ruslanpi/.cursor/projects/home-ruslanpi-Documents-repos-lmru-devops-core-ansible-vault-oss/assets/image-ae031036-6c07-45c4-a22f-33e317e40fa7.png

These images can be copied for use in other locations.
</image_files>
<timestamp>Tuesday, May 12, 2026, 3:35 PM (UTC+3)</timestamp>
<user_query>
я ему писал, чтоб он мои CSR подписал
он сказал не получается

Руслан Петрович
16:38
чатгпт так ответил

CSR корректный, он сгенерирован Vault как SubCA.
В CSR нет Microsoft‑template extension, поэтому CA ругается.
Нужно подавать CSR с атрибутом CertificateTemplate.

Ошибка на скрине — типичная для Microsoft AD CS: CA требует указание Certificate Template.
В CSR, который сгенерировал Vault, нет template‑extension, поэтому CA возвращает CERTSRV_E_NO_CERT_TYPE.
Что нужно сделать
Шаблон задаётся на этапе подачи CSR в CA, а не внутри Vault.
То есть CSR из Vault корректный, но при отправке его в CA надо указать template OID.
Как подать CSR в Microsoft CA (варианты)
Вариант 1 — через certreq -attrib (самый частый):
certreq -submit -attrib "CertificateTemplate:<OID>" stage.csr
Для stage:
CertificateTemplate:1.3.6.1.4.1.311.21.8.14237930.1511221.15222719.5956947.11577261.64.1.18
Для prod:
CertificateTemplate:1.3.6.1.4.1.311.21.8.2948531.4767004.15287991.14645216.16501896.108.1.18
Вариант 2 — если у CA есть “Template Name” (предпочтительно, если знают имя):
certreq -submit -attrib "CertificateTemplate:SubCA_Stage" stage.csr

Сергей Коротеев
17:05
https://serverfault.com/questions/977445/generate-csr-including-certificate-template-information-with-openssl

https://kernelmanic.com/2020/06/20/generating-certificates-with-custom-oids-using-openssl/

23 января

Руслан Петрович
12:50
давай созвонимся обсудим?

Сергей Коротеев
13:03
А в чем вопрос?

Руслан Петрович
13:08
ну или так
обсудить возможность, чтоб ты не через веб сделал, а через консоль и сам указал темплейт

Vault PKI (intermediate/generate/internal)
Где ключ:
Генерируется внутри Vault и хранится в хранилище Vault (Raft/Consul/etc).
На файловой системе клиента ключ не появляется.
Кто владеет ключом:
Vault. Пользователь его не видит и не выгружает.
Безопасность:
✅ минимальный риск утечки
✅ проще соответствие требованиям ИБ
✅ логирование и аудит операций в Vault

OpenSSL (openssl req ...)
Где ключ:
Генерируется на локальной машине в виде файла *.key.
Кто владеет ключом:
Оператор/сервер, который выполняет команду.
Безопасность:
⚠ ключ лежит локально (может попасть в бэкап, историю, лишние руки)
⚠ ответственность за защиту ключа — на вас
Плюс:
Можно добавить любой custom OID / template extension в CSR (Microsoft CA).

Сергей Коротеев
13:10
А в чем проблема через опенс ссл сделать crl?

Мы не можем через свой ца сделать выпуск, иначе он будет выпущен не от рут , а от интермидиат

Цепочка будет дркгая

Поэтому мы и просим Вас сформировать crl

Приватный ключ останется у нас, а он нам не нужен

Сервис то ваш

Руслан Петрович
15:02
Возможно, мы говорим о разных вещах.
Мне нужен подписанный intermediate сертификат по нашему CSR
Приватный ключ остаётся у нас в Vault, и мы сами будем выпускать сертификаты
Поэтому просим только подпись CSR, а не выпуск сертов с вашей стороны

26 января

Сергей Коротеев
10:49
Я понимаю, нам чтобы выпустить промежуточный сертификат, который мы отправим вам, нужно получить от вас csr

Руслан Петрович
13:29

2 Файла
prod.csr
CSR2KB
stage.csr
CSR2KB

Сергей Коротеев
14:21
Короче, какой CN= и какой DNS= вам нужен?

Руслан Петрович
14:40
Опятт не так?

Я переделал через openssl

Сергей Коротеев
14:40
Нет, противиться

Проще самому выпустить и передать на флешке

Руслан Петрович
14:43
Позже напишу

Сергей Коротеев
14:46
Окай

27 января

Руслан Петрович
11:04
CN нужен только для промежуточного CA, SAN/DNS не требуется.
Stage: CN = LMRU PKI Stage Intermediate CA
Prod:  CN = LMRU PKI Prod Intermediate CA
Если ваша CA требует SAN, можем добавить DNS=pki.lmru.tech, но для CA это обычно не нужно.

Сергей Коротеев
11:18
Нет, в windows PKI независимо от шаблона требуется указывать subject name  и san

Руслан Петрович
11:25
Еще надо что-то?

Сергей Коротеев
11:42

Пока нет
</user_query>


Да, ты всё правильно писал — проблема у них **на этапе подачи CSR в AD CS**, не в твоём CSR.

Скрин это подтверждает:
`0x80094801 CERTSRV_E_NO_CERT_TYPE` = CA требует **Certificate Template** (в extension или в request attribute), а запрос отправлен без него.

И ещё важно: у Сергея в переписке местами путаница терминов — он пишет **CRL**, но по смыслу нужен **CSR**.

## Что это значит практически

- Твой CSR из Vault как SubCA — валиден.
- ITOP должен подать его через `certreq` с атрибутом шаблона (или выбрать template в оснастке, если так поддерживается).
- Генерировать ключ у себя на стороне им не нужно и не нужно соглашаться на это.

## Что им отправить (готовый текст)

> Коллеги, у нас корректный CSR из Vault для SubCA.
> Просьба подписать именно этот CSR на вашем Root CA с указанием шаблона при submit (ошибка `CERTSRV_E_NO_CERT_TYPE` указывает, что template не передан в запрос).
> Приватный ключ остаётся у нас в Vault и не передаётся.
>
> Пример:
> ```bash
> certreq -submit -attrib "CertificateTemplate:<TemplateNameOrOID>" stage.csr
> certreq -submit -attrib "CertificateTemplate:<TemplateNameOrOID>" prod.csr
> ```
> (если policy CA требует SAN, добавьте атрибут SAN при submit).
>
> Нужен результат: подписанный intermediate cert + цепочка CA (PEM/CRT), **без private key**.

Если хочешь, сделаю вторую, более «жёсткую» версию под тикет с acceptance criteria (issuer должен быть боевой root, CN stage/prod, KU/BasicConstraints для SubCA).

**Considering certificate submission**

I should suggest using the command certreq -submit -config with the appropriate file paths and attributes. I might also need to include SAN options if required, like "san:dns=pki.lmru.tech." For the subordinate CA, it seems unnecessary to include SAN. I need to mention that they had a typo with CRL; they meant CSR. Additionally, I'll draft a message asserting that the key must be non-exportable. It might also be wise to escalate security concerns if they insist on generating the private key themselves. I want to keep my message concise.


<timestamp>Tuesday, May 12, 2026, 3:36 PM (UTC+3)</timestamp>
<user_query>
он еще вышел из мессенджера, мне бы исполнителя сменить :)
</user_query>


Логично 🙂
Пока он оффлайн, лучше сразу перевести задачу на другого исполнителя из ITOP и в комментарии зафиксировать блокер.

Можно так написать в тикете:

> Сменил исполнителя, т.к. текущий исполнитель недоступен.
> Блокер: при подписании нашего CSR в AD CS ошибка `0x80094801 (CERTSRV_E_NO_CERT_TYPE)` — не передан `CertificateTemplate` при submit.
> Требуется: подписать предоставленные `stage.csr` и `prod.csr` на Root CA с указанием template, вернуть `crt + chain` (без private key).

Если хочешь, помогу сформулировать короткое сообщение для нового исполнителя (в 2-3 строки для чата и отдельный вариант для тикета).


<timestamp>Tuesday, May 12, 2026, 3:42 PM (UTC+3)</timestamp>
<user_query>
Он отвечает за это, не получится сменить
Сергей Коротеев
15:22
а в цепочке самого серта не написано разве?

Руслан Петрович
15:28
subject=CN=LMRU PKI Stage Intermediate CA
issuer=... CN=TestLMRUTech
срок: 2026-01-28 → 2028-01-28

Новые сообщения

Сергей Коротеев
15:39

Значит это выпущенный сертификат в тестовом домене
</user_query>


Да, он сам подтвердил корень проблемы:
**текущий intermediate выпущен в тестовом домене** (`issuer ... TestLMRUTech`), значит для продовой цепочки он не подходит.

Сейчас лучше сразу закрыть это сообщением-фиксацией и конкретным запросом на действие:

> Подтверждаю: текущий `LMRU PKI Stage Intermediate CA` выдан `TestLMRUTech`, это тестовый контур.
> Для прода нужен новый intermediate, подписанный от боевого Root (`ADEO Vostok Root CA(1)` / целевой root из доверенной цепочки Kafka).
> Просьба выпустить по нашим CSR (`stage.csr`, `prod.csr`) с указанием нужного template при submit (`CERTSRV_E_NO_CERT_TYPE` уже видели), и передать `crt + chain` (без private key).

Если ответит “дайте SAN/CN/template”, можно коротко:
- `CN Stage`: `LMRU PKI Stage Intermediate CA`
- `CN Prod`: `LMRU PKI Prod Intermediate CA`
- SAN: только если их policy требует (например `DNS=pki.lmru.tech`)
- Template: их корпоративный SubCA template (имя/OID пусть дадут сами, чтобы не гадать).

**Advising on negotiation steps**

I need to figure out how to respond about the next steps in negotiation. Since I don’t need any tools here, I can keep it concise. I want to make sure my response is clear and provides valuable guidance for the user. I'll want to outline key things they should consider or do next in the negotiation process without being too wordy. Keeping it straightforward will help!


<timestamp>Tuesday, May 12, 2026, 3:43 PM (UTC+3)</timestamp>
<user_query>

Сергей Коротеев
16:05

если что вот oid для stage

1.3.6.1.4.1.311.21.8.14237930.1511221.15222719.5956947.11577261.64.1.18
этот для prod

1.3.6.1.4.1.311.21.8.2948531.4767004.15287991.14645216.16501896.108.1.18

</user_query>


Отлично, это именно то, чего не хватало для AD CS submit.

Можешь отправить ему сразу так:

> Спасибо, супер.
> Тогда прошу выпустить по нашим CSR с этими template OID:
>
> - stage: `1.3.6.1.4.1.311.21.8.14237930.1511221.15222719.5956947.11577261.64.1.18`
> - prod: `1.3.6.1.4.1.311.21.8.2948531.4767004.15287991.14645216.16501896.108.1.18`
>
> Нам нужен результат: **подписанный intermediate cert + chain**, без private key.
> Важно, чтобы issuer был из боевой цепочки (не `TestLMRUTech`).

И если нужно, можно добавить команду для него (чтобы точно без ошибки `CERTSRV_E_NO_CERT_TYPE`):

```bash
certreq -submit -attrib "CertificateTemplate:1.3.6.1.4.1.311.21.8.14237930.1511221.15222719.5956947.11577261.64.1.18" stage.csr
certreq -submit -attrib "CertificateTemplate:1.3.6.1.4.1.311.21.8.2948531.4767004.15287991.14645216.16501896.108.1.18" prod.csr
```

Если хочешь, помогу сразу текстом для проверки результата (что смотреть в `subject/issuer` после получения).


[Image]
<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://serverfault.com/questions/977445/generate-csr-including-certificate-template-information-with-openssl
Website Title: Generate CSR including certificate template information with OpenSSL - Server Fault
Website Content:
Skip to main content

#### Stack Exchange Network

 Stack Exchange network consists of 183 Q&A communities including Stack Overflow, the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Visit Stack Exchange

Loading…

1. * Tour Start here for a quick overview of the site
   * Help Center Detailed answers to any questions you might have
   * Meta Discuss the workings and policies of this site
   * About Us Learn more about Stack Overflow the company, and our products
2. ### current community
   * Server Fault
   help chat
   * Meta Server Fault
### your communities
Sign up or log in to customize your list.
### more stack exchange communities
company blog
3. Log in
4. Sign up

Server Fault

1. 1. Home
   2. Questions
   3. Unanswered
   4. AI Assist
   5. Tags
   6. Chat
   7. Users
   8. Companies
2. Stack Internal
 Stack Overflow for Teams is now called **Stack Internal**. Bring the best of human thought and AI automation together at your work.
Try for free Learn more
3. Stack Internal
4. Bring the best of human thought and AI automation together at your work.Learn more

**Stack Internal**

Knowledge at work

Bring the best of human thought and AI automation together at your work.

 Explore Stack Internal

# Generate CSR including certificate template information with OpenSSL

 Ask Question

Asked 6 years, 9 months ago

Modified 6 years, 9 months ago

Viewed 32k times

8

I'm generating a CSR with OpenSSL using the following configuration file:

```
[ req ]
default_bits           = 2048
default_keyfile        = usercert.key
distinguished_name     = req_distinguished_name
attributes             = req_attributes
prompt                 = no

[ req_distinguished_name ]
C            = FR
L            = Paris
OU           = IT
CN           = FirstName LastName

[ req_attributes ]
1.3.6.1.4.1.311.13.2.1 = CertificateTemplate=CustomUserOffline

```

My goal here is to include the template name in the CSR in order for a Windows CA to be able to process it.

I use the following command line to generate the CSR:

```
openssl req -new -key usercert.key -out usercert.csr -config usercert.cnf

```

I get no error when running it and I can verify the CSR with the following command:

```
openssl req -text -noout -verify -in usercert.csr

```

```
verify OK
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = FR, L = Paris, OU = IT, CN = FirstName LastName
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:af:85:28:40:84:d8:8a:58:35:86:b8:f5:25:b2:
                    ...
                    05:8d:57:cc:a0:4c:8f:da:f3:f4:a7:57:76:51:e2:
                    56:25
                Exponent: 65537 (0x10001)
        Attributes:
            1.3.6.1.4.1.311.13.2.1   :CertificateTemplate=CustomUserOffline
    Signature Algorithm: sha256WithRSAEncryption
         1e:4e:9b:6d:24:75:81:5f:be:52:58:ba:79:a1:ac:c8:d6:c9:
         ...
         40:2d:b6:fc

```

But when I try to verify the CSR with `certutil usercert.csr` on Windows I get the following error:

```
PKCS10 Certificate Request:
Version: 1
Subject:
    CN=FirstName LastName
    OU=IT
    L=Paris
    C=FR
  Name Hash(sha1): ab6adbd772e0ca2a0fce4a32abfdd1645686c0b9
  Name Hash(md5): 21d7edb09130201e880133c245617304

Public Key Algorithm:
    Algorithm ObjectId: 1.2.840.113549.1.1.1 RSA (RSA_SIGN)
    Algorithm Parameters:
    05 00
Public Key Length: 2048 bits
Public Key: UnusedBits = 0
    0000  30 82 01 0a 02 82 01 01  00 af 85 28 40 84 d8 8a
    ...
    0100  f3 f4 a7 57 76 51 e2 56  25 02 03 01 00 01
Request Attributes: 1
  1 attributes:

  Attribute[0]: 1.3.6.1.4.1.311.13.2.1 (Enrollment Name Value Pair)
    Value[0][0], Length = 27
Cannot decode object: The data is invalid. 0x8007000d (WIN32: 13 ERROR_INVALID_DATA)
CertUtil: -dump command FAILED: 0x8007000d (WIN32: 13 ERROR_INVALID_DATA)
CertUtil: The data is invalid.

```

It seems that the custom attribute is recognized as `1.3.6.1.4.1.311.13.2.1 (Enrollment Name Value Pair)` is displayed but then I guess the name/value pair `CertificateTemplate=CustomUserOffline` is not in the proper format.
How can I fix it?

A few notes:

* I'm using OpenSSL to generate the CSR because in the end it will be a Linux client generating the CSR
* I'm aware of the `certreq -attrib "CertificateTemplate:CustomUserOffline" -submit usercert.csr` command, but the request will be submitted through C# code using the certenroll API so that's why I would like to include the certificate template information directly in the CSR.

* openssl
* certificate
* csr

Share

Improve this question

 Follow

edited Aug 1, 2019 at 7:54

 asked Jul 31, 2019 at 15:07

Chris's user avatar

Chris

33411 gold badge33 silver badges1212 bronze badges

 Add a comment  |

## 1 Answer 1

 Sorted by:  Reset to default

 Highest score (default)  Date modified (newest first)  Date created (oldest first)

7

At the top of your `openssl.conf` enter:

```
[ OIDs ]

certificateTemplateName = 1.3.6.1.4.1.311.20.2

```

In your `[req_attributes]`:

```
certificateTemplateName = ASN1:PRINTABLESTRING:CustomUserOffline

```

You could, of course, skip the definition of the OID, just like you did in your question, and use the OID directly.

---

Using the following openssl config file:

```
oid_section = OIDs

[ OIDs ]

# This uses the short name of the template:
certificateTemplateName = 1.3.6.1.4.1.311.20.2

# Use this instead if you need to refer to the template by OID:
# certificateTemplateOID = 1.3.6.1.4.1.311.21.7

  [ req ]

prompt             = no
string_mask        = default

# The size of the keys in bits:
default_bits       = 2048
distinguished_name = req_dn
req_extensions     = req_ext

[ req_dn ]

# Note that the following are in 'reverse order' to what you'd expect to see in
# Windows and the numbering is irrelevant as long as each line's number differs.

# Domain Components style:
# Server name:
# 2.DC = com
# 1.DC = example
# commonName = Acme Web Server

# Locality style:
# countryName = GB
# stateOrProvinceName = London
# localityName = Letsby Avenue
# organizationName = Acme
# organizationalUnitName = IT Dept
# organizationalUnitName = Web Services
# commonName = Acme Web Server

# Or traditional org style:
countryName = GB
organizationName = Acme
organizationalUnitName = IT Dept
2.organizationalUnitName = Web Services
commonName = Acme Web Server

[ req_ext ]

#basicConstraints=critical,CA:TRUE

# This requests a certificate using the 'CustomUserOffline' template.  Check with the CA for the correct name to use,
# or alternatively comment it out and let the CA apply it:
certificateTemplateName = ASN1:PRINTABLESTRING:CustomUserOffline

subjectAltName = @alt_names

[alt_names]
# To copy the CN (in the case of a DNS name in the CN) use:
# DNS = ${req_dn::commonName}
DNS.1 = www.example.com
DNS.2 = example.com

```

This results in the following extract when viewed using `openssl req -in usercert.csr -noout -text`:

```
    Attributes:
    Requested Extensions:
        1.3.6.1.4.1.311.20.2:
            ..CustomUserOffline

```

and the following extract when viewed with `certutil usercert.csr`:

```
  Attribute[0]: 1.2.840.113549.1.9.14 (Certificate Extensions)
    Value[0][0], Length = 4d
Certificate Extensions: 2
    1.3.6.1.4.1.311.20.2: Flags = 0, Length = 13
    Certificate Template Name (Certificate Type)
        CustomUserOffline

```

Share

Improve this answer

 Follow

edited Jul 31, 2019 at 20:12

 answered Jul 31, 2019 at 16:34

garethTheRed's user avatar

garethTheRed

5,5851919 silver badges2525 bronze badges

3

* It works as expected, so in fact the key thing is to use the proper OID :) and make sure it's in the certificate extensions not attributes. Also I noticed that it works if I use the ASN1:UTF8String prefix. Any recommendation on which type should be used?
Chris
– Chris
2019-08-01 06:50:12 +00:00
Commented Aug 1, 2019 at 6:50
* It depends on what characters you use in your template names and the characters that Microsoft allow. Here's a link on the differences. I tend to use `A-Za-z0-9` in my tempate names, so either would work.
garethTheRed
– garethTheRed
2019-08-01 10:47:11 +00:00
Commented Aug 1, 2019 at 10:47
* Use the template name (the one without spaces) and not the Display Name (the one with the spaces, most likely)!
bgStack15
– bgStack15
2020-08-26 18:22:44 +00:00
Commented Aug 26, 2020 at 18:22

 Add a comment  |

##  You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

* openssl
* certificate
* csr

See similar questions with these tags.

* The Overflow Blog
* Introducing the Heap, the software engineering blog for everyone
* Connecting the dots for accurate AI
* Featured on Meta
* (Almost) One year of Challenges

#### Related

12 How can I verify/read an IIS7 SSL renewal CSR with OpenSSL

14 OpenSSL: how to generate a CSR with interactively solicited Subject Alternative Names (SANs)?

0 How to convert a SSL certificate and private key to a PFX for import in IIS?

2 How to create ssl certificate for multiple domains which requires the CA root key in Linux

0 Why can I not parse my certificate signing request with openssl on my Windows workstation

9 Can I get anSHA-256 certificate when the CSR is for SHA-1?

6 OpenSSL - Add Subject Alternate Name (SAN) when signing with CA

1 Bash script with openssl req -new -key rootCA.key -out rootCA.csr -config rootCA\_openssl.cnf --passin pass:password

####  Hot Network Questions

* Can I use wedge anchors for mounting a ceiling box on a precast concrete ceiling?
* Hitting flat footed ac with a touch attack
* What is the significance of Paul's use of πνευματικός?
* How to bake large loafs of bread without burning the crust (whole wheat)
* Empirical convergence rate of the Hardy-Littlewood prediction for prime pairs in arithmetic progressions modulo 9
* Is there an argument from first principles for proportional representation rather than first-past-the-post?
* How do I solve quadratic equations using factorization method?
* Minimum cabinet back thickness to prevent cabinet sagging under heavy countertops?
* Linux share mounted from Windows shows R/O even though shared R/W from Linux host
* DRV8245 Motor Driver Faults Constantly
* What would be the most realistic way to design a creature that uses a reflective mane like part and bioluminescence to create flashes like a camera?
* Kenmore Range model 790 small coils intermittently overheat, temperature control issues
* Who first used the word "convolution" in mathematics?
* High performance program with UI (producer consumer architecture)
* Could Bilbo and company actually have seen the Lonely Mountain from where they were deposited by the eagles?
* Double for penalty or for takeout?
* Ladder access to tall, narrow windows
* How can I self-study physics without lab classes for someone with a pure math background?
* I have Sanctuary, I move, OA occurs, fails DC, OA to ally next to me?
* Is the awareness of reality as "Non-dual" important in all traditions of Buddhism?
* How to figure the basis for this redemption?
* Arrows pointing into dots
* Establishing the Structure of Sentences in the Rough Draft
* GN Procedural Plunging Breaker Wave
 more hot questions

 Question feed

#  Subscribe to RSS

 Question feed

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

##### Server Fault

* Tour
* Help
* Chat
* Contact
* Feedback

##### Company

* Stack Overflow
* Stack Internal
* Stack Data Licensing
* Stack Ads
* About
* Press
* Legal
* Privacy Policy
* Terms of Service
* Your Privacy Choices
* Cookie Policy

##### Stack Exchange Network

* Technology
* Culture & recreation
* Life & arts
* Science
* Professional
* Business
* API
* Data

* Blog
* Facebook
* Twitter
* LinkedIn
* Instagram

Site design / logo © 2026 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2026.5.8.42955
____

</external_links>
<image_files>
The following images were provdied by the user and saved to the workspace for future use:
1. /home/ruslanpi/.cursor/projects/home-ruslanpi-Documents-repos-lmru-devops-core-ansible-vault-oss/assets/image-be1078bd-5436-41bd-aeab-dc8f7f5c8df5.png

These images can be copied for use in other locations.
</image_files>
<timestamp>Tuesday, May 12, 2026, 3:46 PM (UTC+3)</timestamp>
<user_query>
он хочет, чтобы я в CSR указывал темплейт
Сергей Коротеев
15:58

Не указали инфу про шаблон
https://serverfault.com/questions/977445/generate-csr-including-certificate-template-information-with-openssl
https://kernelmanic.com/2020/06/20/generating-certificates-with-custom-oids-using-openssl/

</user_query>


Понял. Коротко: **он просит не то место, где это обычно задается**.

Для AD CS шаблон может быть передан:
1) при submit (`certreq -attrib "CertificateTemplate:..."`),
2) или внутри CSR как extension.

Ошибка `CERTSRV_E_NO_CERT_TYPE` означает только то, что CA не увидела template **ни в одном виде**.

В вашем случае правильный рабочий путь (с ключом в Vault) — **не менять CSR**, а чтобы ITOP подал его с `-attrib`:

```bash
certreq -submit -attrib "CertificateTemplate:1.3.6.1.4.1.311.21.8.14237930.1511221.15222719.5956947.11577261.64.1.18" stage.csr
certreq -submit -attrib "CertificateTemplate:1.3.6.1.4.1.311.21.8.2948531.4767004.15287991.14645216.16501896.108.1.18" prod.csr
```

Если он **настаивает именно на template внутри CSR**, это обычно требует OpenSSL-CSR с Microsoft OID (как в обсуждении на ServerFault), но тогда ключ/CSR будут генериться вне Vault, что ломает ваш требуемый flow “ключ остается в Vault”.
Ссылка по механике OID в CSR: [ServerFault](https://serverfault.com/questions/977445/generate-csr-including-certificate-template-information-with-openssl), [Kernelmanic](https://kernelmanic.com/2020/06/20/generating-certificates-with-custom-oids-using-openssl/).

Можешь отправить Сергею так:

> Наш CSR корректный и сгенерирован Vault (ключ внутри Vault).
> Просьба подавать его в AD CS с template через `certreq -attrib "CertificateTemplate:<OID>"`.
> OID для stage/prod уже согласованы выше.
> Нужен результат: signed intermediate cert + chain, без private key.

Если хочешь, напишу еще “жесткую” формулировку на 3 строки, чтобы закрыть спор без долгой переписки.


<timestamp>Tuesday, May 12, 2026, 3:50 PM (UTC+3)</timestamp>
<user_query>
я ему так писал, он сказал, что всегда делает через exe, а не certreq
</user_query>


Тогда всё сходится: его `.exe`/GUI, вероятно, **не подставляет template в запрос** для вашего типа CSR, поэтому и ловит `CERTSRV_E_NO_CERT_TYPE`.

Что можно сделать без спора “GUI vs certreq”:

- Попросить его в GUI выбрать **конкретный Certificate Template** (не Display Name, а именно template), если такой выбор есть.
- Если в его `.exe` это поле отсутствует — это ограничение инструмента, и для вашего кейса нужен `certreq -attrib`.
- Компромисс: пусть он остаётся на своей Windows-машине, но один шаг submit делает через `certreq` (остальное как привык).

Готовая фраза ему:

> Понял, что вы обычно работаете через GUI/exe.
> В нашем случае CA возвращает `CERTSRV_E_NO_CERT_TYPE`, т.е. в запрос не попадает Certificate Template.
> Если в вашем интерфейсе можно явно указать Template — ок, используем его.
> Если нельзя, давайте именно submit сделаем через `certreq -attrib "CertificateTemplate:<OID>"` (для stage/prod OID уже есть).
> CSR остаётся наш (из Vault), private key не передаётся.

Если нужно, дам максимально короткий one-liner для него под stage/prod, чтобы он просто скопировал в консоль.

**Explaining UI options**

I need to think about how to provide clear guidance without using any tools. The user is conversing in Russian, so I'll want to be considerate of that. I should explain that if they are using the exe UI, there are specific template and attribute options they can specify, and if certificate templates aren't showing up, it might be due to configuration issues. I could suggest asking for a screenshot of the fields for clarity. I’ll keep it concise!


<timestamp>Wednesday, May 27, 2026, 2:18 PM (UTC+3)</timestamp>
<user_query>

Александр Порохин
4 минуты назад

Антон Федоров
28 минут назад
@Александр Порохин Саша, привет! помоги, пожалуйста, новый сертификат, нам очень нужно для работы нашего сервиса.

Привет! Мы уже говорили, что для выпуска сертификата ожидаем от вас файл запроса CSR. Главный смысл в том, чтобы на вашей стороне сформировался приватный ключ.

так, дождался нового человека
надо сгенерить для стейджа новый CSR

</user_query>