Безпечні патерни передачі secret values у Kubernetes

security · 2026-03-24

Якщо коротко: секрет, який процес може прочитати, теоретично можна витягнути. Тому правильна ціль — не магічне “неможливо витягти”, а мінімізувати наявність static secrets, скоротити TTL, тримати дані в RAM якомога менше часу, і закрити шляхи attach/exec/debug.

1. Що не варто робити

Secret values в environment variables

Це дуже поширений патерн, але він слабший, ніж здається:

  • env values можуть випадково потрапити в логи, stack traces, crash dumps;
  • їх часто легко засвітити через діагностичні механізми застосунку;
  • вони живуть увесь lifecycle процесу;
  • багато команд сприймають env як “достатньо безпечно”, хоча це просто зручний transport, а не сильна runtime boundary.

Висновок: env vars — acceptable convenience pattern, але не best security pattern.

2. Кращий baseline: workload identity + external secret retrieval

Найздоровіший production-підхід сьогодні:

  • pod отримує workload identity;
  • застосунок або sidecar звертається до Vault / Secret Manager / Key Vault / IAM STS;
  • отримує короткоживучі credentials;
  • тримає їх у memory only;
  • періодично refresh / rotate;
  • не пише static values в pod spec, image або ConfigMap.

Це значно сильніше, ніж зберігати довгоживучі токени у Kubernetes Secrets і передавати їх через env.

3. Ще краще: dynamic secrets

Де можливо, секрети мають бути динамічними:

  • тимчасовий DB user/password;
  • тимчасові cloud credentials;
  • short-lived certificates;
  • lease / revoke / rotate механіка.

Переваги:

  • навіть якщо credential витягнули, його вікно життя маленьке;
  • менший blast radius;
  • простіше робити revoke;
  • не потрібно роками жити з одним shared password.

4. Якщо секрет усе ж треба покласти в pod

Порядок переваги такий:

  1. dynamic retrieval at runtime
  2. in-memory file / tmpfs volume
  3. Kubernetes Secret volume
  4. environment variables

Чому tmpfs / in-memory файл кращий за env:

  • менше випадкового leakage в logs / stack traces;
  • краще контрольований lifecycle;
  • простіше обмежити доступ правами до файлу;
  • легше організувати rotation.

Але чесно: якщо attacker уже має виконання всередині контейнера — він, найімовірніше, зможе це прочитати. Тому секрет delivery не можна розглядати окремо від runtime hardening.

5. Runtime hardening: без цього всі розмови про secret hygiene неповні

Щоб зменшити ризик витягання секретів, потрібно не лише правильно їх доставляти, а й закривати шляхи доступу до процесу:

  • заборонити kubectl exec зайвим ролям;
  • заборонити pods/attach, pods/portforward, pods/ephemeralcontainers без дуже вузького доступу;
  • allowPrivilegeEscalation: false;
  • privileged: false;
  • readOnlyRootFilesystem: true;
  • запуск під non-root;
  • drop capabilities;
  • seccomp / AppArmor / SELinux де доступно;
  • hostPID, hostIPC, hostNetwork = false;
  • мінімізувати service account token exposure;
  • обмежити egress через NetworkPolicy.

Це вже не “секрети”, а platform engineering guardrails — але без них історія про “невитягувані env” просто несерйозна.

Для більшості production систем я б рекомендував такий стек:

  • workload identity
  • Vault / cloud secret manager
  • dynamic or short-lived credentials
  • memory-only usage
  • no exec / no debug by default
  • strict RBAC + admission policies
  • runtime hardening
  • auditability around secret access

Це дає не магічну “невитягуваність”, а операційно сильну, реалістичну модель захисту.

7. Що варто запам’ятати

Правильне запитання не:

“Як зробити так, щоб секрет неможливо було витягнути?”

А ось таке:

“Як зробити так, щоб ми майже не мали static secrets, щоб вони жили коротко, були прив’язані до identity, не лежали в env без потреби, і щоб до workload не можна було просто так приаттачитись?”

Оце вже хороший DevSecOps framing.

References

Нижче — сильні референси, які варто читати не як маркетинг, а як дизайн-матеріал: