Харденинг контейнеров: readOnlyRootFilesystem + drop ALL во всех приложениях #71

Open
opened 2026-09-20 18:59:02 +00:00 by hermes · 0 comments
hermes commented 2026-09-20 18:59:02 +00:00 (Migrated from git.grachevko.ru)

Зачем

Правило владельца (2026-09-20): все контейнеры — с readOnlyRootFilesystem: true и сопутствующим харденингом. Новые манифесты этому уже следуют (kubernetes/apps/grachevko/hermes), существующие — нет.

Правило и грабли (запись в /run у образов с s6-overlay, обязательный emptyDir и возврат владельца initContainer'ом): см. скилл home-ops-cluster, references/container-hardening.md.

Что сделать в каждом приложении

  1. Добавить в контейнеры (через defaultPodOptions.securityContext в app-template):
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false
    capabilities:
      drop: [ALL]
    
  2. Найти все места, куда контейнер пишет вне тома, и отдать их явными монтированиями: состояние — PVC, временное — emptyDir (/tmp, /run, иные кэши). Определять не на глаз, а по логу старта и падениям записи.
  3. Проверять старт сервиса в логе (процесс может подняться и упасть на первой же записи), а не только Ready пода.

Область: наши приложения (первый заход)

  • ai/hindsight (chart hindsight)
  • ai/searxng (app-template)
  • firecrawl/firecrawl (app-template)
  • grachevko/hindsight (chart hindsight)
  • security/zitadel (chart zitadel)
  • default/echo (app-template)
  • MCP-серверы ToolHive (ai/github-mcp, ai/kubesearch-mcp, ai/proxmox-mcp, gitea/gitea-mcp, security/vault-mcp, kube-system/mcp-k8s, grachevko/virtual-mcp) — через podTemplateSpec в CR
  • toolhive-system/toolhive

Область: апстрим-чарты (второй заход, с оговорками)

kube-system/{cilium,coredns,metrics-server,reloader,spegel}, cert-manager/cert-manager, security/{vault,external-secrets}, network/{envoy-gateway,k8s-gateway}, database/{cloudnative-pg,dragonfly-operator}, storage/proxmox-csi, flux-system/{flux-instance,flux-operator}.

Здесь RO rootfs может быть недостижим: часть контроллеров пишет в корень образа (вебхуки, генерация сертификатов, сокеты). Для каждого — либо включаем, либо фиксируем комментарием в манифесте, почему нельзя. Без комментария «нельзя» — не считается решённым.

Проверка

  • После правки: grep -rL readOnlyRootFilesystem kubernetes/apps не должен находить наши приложения.
  • По каждому пункту — лог старта пода после выката.
## Зачем Правило владельца (2026-09-20): **все контейнеры — с `readOnlyRootFilesystem: true`** и сопутствующим харденингом. Новые манифесты этому уже следуют (`kubernetes/apps/grachevko/hermes`), существующие — нет. Правило и грабли (запись в `/run` у образов с s6-overlay, обязательный `emptyDir` и возврат владельца initContainer'ом): см. скилл `home-ops-cluster`, `references/container-hardening.md`. ## Что сделать в каждом приложении 1. Добавить в контейнеры (через `defaultPodOptions.securityContext` в app-template): ```yaml readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: [ALL] ``` 2. Найти все места, куда контейнер пишет вне тома, и отдать их явными монтированиями: состояние — PVC, временное — `emptyDir` (`/tmp`, `/run`, иные кэши). Определять не на глаз, а по логу старта и падениям записи. 3. Проверять **старт** сервиса в логе (процесс может подняться и упасть на первой же записи), а не только `Ready` пода. ## Область: наши приложения (первый заход) - [ ] `ai/hindsight` (chart hindsight) - [ ] `ai/searxng` (app-template) - [ ] `firecrawl/firecrawl` (app-template) - [ ] `grachevko/hindsight` (chart hindsight) - [ ] `security/zitadel` (chart zitadel) - [ ] `default/echo` (app-template) - [ ] MCP-серверы ToolHive (`ai/github-mcp`, `ai/kubesearch-mcp`, `ai/proxmox-mcp`, `gitea/gitea-mcp`, `security/vault-mcp`, `kube-system/mcp-k8s`, `grachevko/virtual-mcp`) — через `podTemplateSpec` в CR - [ ] `toolhive-system/toolhive` ## Область: апстрим-чарты (второй заход, с оговорками) `kube-system/{cilium,coredns,metrics-server,reloader,spegel}`, `cert-manager/cert-manager`, `security/{vault,external-secrets}`, `network/{envoy-gateway,k8s-gateway}`, `database/{cloudnative-pg,dragonfly-operator}`, `storage/proxmox-csi`, `flux-system/{flux-instance,flux-operator}`. Здесь RO rootfs может быть недостижим: часть контроллеров пишет в корень образа (вебхуки, генерация сертификатов, сокеты). Для каждого — либо включаем, либо фиксируем комментарием в манифесте, почему нельзя. Без комментария «нельзя» — не считается решённым. ## Проверка - После правки: `grep -rL readOnlyRootFilesystem kubernetes/apps` не должен находить наши приложения. - По каждому пункту — лог старта пода после выката.
Sign in to join this conversation.
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
grachevko/home-ops#71
No description provided.