Перейти до вмісту

Модуль 3.3: Керування секретами

Складність: [СЕРЕДНЯ] - Базові знання. Час на проходження: 25-30 хвилин. Передумови: Модуль 3.2: Основи RBAC. Цей модуль передбачає Kubernetes 1.35 або новіший і використовує k як псевдонім для kubectl після того, як ви визначите його командою alias k=kubectl у вашій оболонці.

Результати навчання

Розділ «Результати навчання»

Після завершення цього модуля ви зможете:

  1. Оцінити обмеження безпеки об’єктів Secret у Kubernetes, зокрема кодування base64, зберігання в etcd, видимість через API та шляхи доступу на рівні ноди.
  2. Проаналізувати стратегії керування секретами, такі як шифрування у стані спокою, конвертне шифрування з KMS, зовнішні сховища секретів та робочі процеси із запечатаними секретами.
  3. Діагностувати поширені ризики розкриття секретів, пов’язані зі змінними середовища, аргументами команд, надмірним доступом через RBAC, логами, історією Git та незашифрованими резервними копіями.
  4. Впровадити безпечніший план доставки секретів, що використовує RBAC за принципом найменших привілеїв, монтування томів лише для читання, практики ротації та відповідне зовнішнє джерело істини.

Чому цей модуль важливий

Розділ «Чому цей модуль важливий»

Гіпотетичний сценарій: Операційна команда у платіжній компанії середнього розміру витрачає довгі вихідні на з’ясування, чому рутинна ротація пароля бази даних постійно зазнає невдачі. Першою підказкою стає не подія Kubernetes і не сповіщення застосунку; це інженер з безпеки, який знаходить старий пароль у звіті про збій, завантаженому до внутрішнього тікета. Команда відстежує це значення через маніфест Deployment, змінну середовища, аргумент процесу, лог налагодження і нарешті застарілий Secret, що зберігається в резервній копії кластера. Секрет не використали зловмисники, але реагування на аудит усе одно поглинає кілька інженерних днів, затримує запуск продукту і змушує до екстреної ротації облікових даних у кількох середовищах.

Ця історія викликає дискомфорт, бо кожне окреме рішення на момент ухвалення виглядало звичайним. Замість ConfigMap використали об’єкти Secret, RBAC існував, і лише невелика група могла адмініструвати простір імен. Проблема полягала в тому, що команда розглядала об’єкт Secret як сейф, а не як об’єкт API з особливими правилами обробки. Щойно конфіденційне значення потрапляє до API Kubernetes, його можна скопіювати до etcd, доставити до kubelet, змонтувати в Поди, розкрити авторизованим клієнтам, включити до резервних копій і випадково вивести в лог застосунками, які ніколи не проєктувалися для захисту облікових даних.

Цей модуль навчає вас обмірковувати ці шляхи, перш ніж обирати інструмент. Нативні об’єкти Secret у Kubernetes корисні, але самі по собі вони не є повноцінною програмою керування секретами. Ви оціните, куди мандрують дані, вирішите, коли достатньо шифрування у стані спокою, розпізнаєте, коли зовнішній менеджер секретів є кращим джерелом істини, і потренуєтеся переглядати робоче навантаження, яке витікає конфіденційні дані кількома поширеними каналами. Робіть паузу під час читання і ставте практичне запитання: якби вам довелося ротувати ці облікові дані під час інциденту, скільки місць вам довелося б перевірити, перш ніж довіритися ротації?

Огляд об’єктів Secret у Kubernetes: base64, об’єкти API та межі довіри

Розділ «Огляд об’єктів Secret у Kubernetes: base64, об’єкти API та межі довіри»

Об’єкти Secret у Kubernetes існують тому, що застосункам потрібні конфіденційні вхідні дані без вбудовування цих значень у образи контейнерів чи звичайні файли конфігурації. Вони надають API-серверу стандартний об’єкт для невеликих фрагментів конфіденційних даних, зазвичай облікових даних, приватних ключів, сертифікатів або токенів. Ця стандартизація має значення, бо контролери, kubelet, політики допуску, RBAC, інструменти резервного копіювання та робочі процеси розгортання можуть розпізнавати один і той самий тип ресурсу замість винайдення окремого формату облікових даних для кожного робочого навантаження. Secret не є магією; це об’єкт Kubernetes із вужчим призначенням і вищим операційним навантаженням.

Перша хибна думка, яку треба усунути, — це що base64 є шифруванням. Kubernetes зберігає дані Secret у base64, бо об’єкт API є JSON або YAML, а секретні значення можуть містити довільні байти. Кодування робить дані придатними до перенесення через API, але будь-хто, хто може прочитати закодоване значення, може негайно його розкодувати. Сприймайте base64 як вкладення документа в прозорий пластиковий конверт: це захищає форму паперу, а не його вміст від того, хто його тримає. Якщо користувач має доступ get до Secret, API-сервер повертає дані, які він може розкодувати.

┌─────────────────────────────────────────────────────────────┐
│ KUBERNETES SECRETS │
├─────────────────────────────────────────────────────────────┤
│ │
│ WHAT SECRETS ARE: │
│ • Key-value store for sensitive data │
│ • Mounted into pods as files or env vars │
│ • Separate from application config (ConfigMaps) │
│ │
│ WHAT SECRETS ARE NOT: │
│ • Encrypted by default (just base64 encoded) │
│ • Protected from users with get secrets permission │
│ • A complete secrets management solution │
│ │
│ IMPORTANT MISCONCEPTION: │
│ Base64 ≠ Encryption │
│ Base64 is encoding, not security! │
│ │
└─────────────────────────────────────────────────────────────┘

Діаграма навмисно прямолінійна, бо найдорожчі помилки часто починаються з мови, яка звучить нешкідливо. Команди кажуть, що значення “у Secret”, і подумки відносять його до категорії “безпечне”. Точніше сформульоване речення звучить так: “значення зберігається в об’єкті Kubernetes, який отримує особливу поведінку доставки і має бути захищений за допомогою RBAC, шифрування у стані спокою, аудиторського логування, дизайну просторів імен та дисципліни застосунку”. Це довше речення менш зручне, але воно описує справжню межу безпеки.

Об’єкти Secret належать до простору імен. Це означає, що типовою одиницею ізоляції зазвичай є простір імен, а не окремий ключ усередині Secret. RBAC може обмежувати доступ за ресурсом і подеколи за resourceNames, але Kubernetes не надає прав на рівні полів, які дозволили б одному користувачеві читати лише username, тоді як інший читає лише password з того самого об’єкта. Цей дизайн підштовхує команди до менших просторів імен, вужчих сервісних акаунтів і зовнішніх систем, коли їм потрібні рішення щодо політики, точніші за ті, що API Kubernetes може чітко висловити.

# Generic/Opaque secret (most common)
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
password: cGFzc3dvcmQxMjM= # base64 encoded
stringData: # Plain text (encoded at creation)
api-key: my-api-key

Поле data містить значення, закодовані в base64, тоді як stringData дозволяє вам подавати звичайний текст, а API-сервер кодує його під час створення або оновлення об’єкта. Ця зручність корисна для прикладів, написаних вручну, але вона не робить значення безпечнішим. Маніфест усе одно містить секретне значення перед поданням, і будь-який інструмент GitOps, лог CI, історія оболонки чи pull request, що обробляє маніфест, може випадково його зберегти. У продакшені згенерований або синхронізований робочий процес зазвичай має створювати об’єкт, а не просити людей вводити конфіденційні значення у файли YAML.

Вбудовані типи Secret

Розділ «Вбудовані типи Secret»
ТипОписЗастосування
OpaqueЗагальний секретОблікові дані застосунку
kubernetes.io/tlsTLS-сертифікат + ключIngress, TLS сервісу
kubernetes.io/dockerconfigjsonАвтентифікація реєстру DockerСекрети для завантаження образів
kubernetes.io/basic-authІм’я користувача + парольБазова автентифікація
kubernetes.io/ssh-authПриватний ключ SSHАвтентифікація SSH
kubernetes.io/service-account-tokenТокен SAАвтентифікація сервісного акаунту

Застарілий тип; автоматичне створення вилучено в 1.24 — надавайте перевагу проєктованим токенам ServiceAccount (див. Модуль 3.4).

Тип Secret (type) частково є документацією, а частково — валідацією. Secret типу kubernetes.io/tls повинен містити очікувані поля сертифіката та ключа, тоді як Secret типу Opaque може містити довільні імена. Тип не обирає сильніший режим шифрування і не ротує значення автоматично. Цінність типізації полягає в тому, що люди й контролери можуть міркувати про намір: секрет для завантаження образів реєстру має бути вказаний у конфігурації завантаження образів, TLS-секрет має живити TLS інгресу чи сервісу, а довільні облікові дані застосунку мають бути названі та обмежені так, щоб їхнє призначення було очевидним під час огляду.

Практичний огляд починається з окреслення межі довіри навколо Secret. Хто може його створити, оновити, прочитати через API, змонтувати через Под, зробити резервну копію або перевірити ноду, де його використовують? Ці запитання важливіші за те, чи об’єкт виглядає чистим у YAML. Secret, який ніколи не комітиться до Git, але доступний для читання кожному сервісному акаунту у спільному просторі імен, усе одно є слабким дизайном. Secret, який жорстко обмежений, але виводиться застосунком під час запуску, також є слабким.

Уявіть Secret як посилку, що рухається будівлею з багатьма дверима. Посилка може бути позначена як конфіденційна, але напис не замикає поштову кімнату, ліфт, стіл одержувача чи кошик для переробки. Kubernetes дає вам формат посилки та систему доставки; ваш дизайн безпеки вирішує, які двері замкнено і хто може нести посилку. Ця ментальна модель допомагає початківцям уникати хибного відчуття комфорту від єдиного засобу контролю. Вона також допомагає досвідченим операторам пояснити, чому знахідка може бути реальною, навіть коли інший рівень виглядає правильно налаштованим.

Зробіть паузу і передбачте: якщо розробник виконує k get secret app-secrets -o yaml і може побачити cGFzc3dvcmQxMjM=, у чому полягає збій безпеки: у base64, RBAC, шифруванні у стані спокою чи в усьому одразу залежно від шляху? Запишіть свою відповідь, перш ніж продовжувати, бо ця відмінність керуватиме тим, як ви налагоджуватимете реальні інциденти.

Найкраща відповідь полягає в тому, що видимий base64 є очікуваною поведінкою для авторизованого читання через API. Якщо розробник не повинен мати цього Secret, безпосереднім збоєм є RBAC або дизайн простору імен. Якщо занепокоєння стосується викраденого сховища etcd чи резервних копій, відповідним засобом контролю є шифрування у стані спокою. Якщо те саме значення також з’являється в логах, аргументах процесів чи історії Git, контролю над зберіганням об’єкта недостатньо. Зрілий огляд секретів простежує облікові дані впродовж усього їхнього життєвого циклу, а не зупиняється на межі ресурсу Kubernetes.

Використання Secret у Подах: вибір доставки та розкриття під час виконання

Розділ «Використання Secret у Подах: вибір доставки та розкриття під час виконання»

Щойно Secret існує, Kubernetes потрібно доставити його до робочих навантажень. Два поширені нативні варіанти доставки — це змінні середовища та монтування томів. Обидва є легітимними можливостями API, обидва широко використовуються, але вони мають різні режими відмов. Змінні середовища зручні, бо багато застосунків уже читають конфігурацію із середовища. Монтування томів вимагає, щоб застосунок читав файли, але вони зменшують кілька шляхів випадкового розкриття і підтримують подальші оновлення, коли змонтований Secret змінюється.

apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: myapp:1.0
env:
# Single key
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
# Or all keys
envFrom:
- secretRef:
name: app-secrets

Змінні середовища привабливі тим, що вони спрощують запуск застосунку. Проблема в тому, що змінна середовища є частиною стану процесу, а не лише вхідними даними конфігурації. Її можуть успадкувати дочірні процеси, вона може спливти в діагностичних інструментах, потрапити до дампів збоїв, бути захопленою надмірно широким логуванням налагодження або розкритою будь-кому, хто може перевірити середовище процесу всередині контейнера. Деякі команди виявляють це лише під час реагування на інцидент, коли шукають у логах рядок помилки і знаходять облікові дані, виведені поряд із помилкою.

apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: app-secrets
# Optional: specific keys only
items:
- key: password
path: db-password

Монтування томів переміщує секретне значення до файлів, що належать до представлення файлової системи Пода. Цей дизайн не є автоматично безпечним, бо застосунок усе ще може прочитати й витекти файл, але він дає вам кращий контроль над тим, як значення споживається. Ви можете монтувати лише потрібні ключі, обрати шлях, специфічний для застосунку, зробити монтування лише для читання та уникнути розміщення облікових даних у загальносистемному стані середовища. Змонтовані томи Secret також можуть оновлюватися після зміни Secret, хоча застосункам часто потрібна власна поведінка перезавантаження, щоб помітити новий вміст файлу.

Зупиніться і подумайте: Колега каже: “наші секрети в безпеці, бо ми ввімкнули RBAC, і лише адміністратори мають до них доступ”. Які ще шляхи зловмисник може використати для читання секретів навіть без прямих прав RBAC? Сильна відповідь включає права на виконання Подів, доступ до ноди, логи застосунків, ендпоінти налагодження, системи резервного копіювання, помилки контролерів допуску і будь-який контролер, що може створити Под, який монтує цей Secret.

Шлях створення Пода — це тонка деталь. Користувач, який не може напряму виконати get secrets, усе ще може мати змогу створити Под, що посилається на Secret, а потім запустити код усередині цього Пода для читання змонтованого значення. Саме тому документація Kubernetes попереджає, що надання прав на створення Подів може опосередковано дозволити доступ до секретів, доступних сервісному акаунту чи простору імен. Тому огляди RBAC мають вивчати дієслова на кшталт create pods, exec, attach та права контролерів робочих навантажень, а не лише прямі правила get secrets.

┌─────────────────────────────────────────────────────────────┐
│ ENV VARS vs VOLUME MOUNTS │
├─────────────────────────────────────────────────────────────┤
│ │
│ ENVIRONMENT VARIABLES │
│ ├── Pros: │
│ │ └── Simple to use in application │
│ └── Cons: │
│ ├── Visible in /proc/<pid>/environ │
│ ├── Often logged accidentally │
│ ├── Inherited by child processes │
│ └── Not updated when secret changes │
│ │
│ VOLUME MOUNTS │
│ ├── Pros: │
│ │ ├── Can be mounted read-only │
│ │ ├── Updated when secret changes (eventually) │
│ │ └── Less likely to be accidentally logged │
│ └── Cons: │
│ └── Requires file reading in application │
│ │
│ RECOMMENDATION: Prefer volume mounts for sensitive data │
│ │
└─────────────────────────────────────────────────────────────┘

Рекомендація надавати перевагу монтуванню томів є типовим вибором для зниження ризику, а не законом. Деякі застосунки за моделлю дванадцяти факторів побудовані навколо змінних середовища, і їхнє переписування може забрати час. Під час такого переходу ви все одно можете зменшити ризик, уникаючи envFrom для великих об’єктів Secret, вимикаючи докладні дампи конфігурації, не дозволяючи обгорткам оболонки виводити рядки команд та забезпечуючи, щоб інструменти звітування про збої редагували конфіденційні імена. Довгостроковий дизайн має перемістити найбільш конфіденційні облікові дані до монтування файлів або прямого монтування із зовнішнього сховища, особливо коли мають значення поведінка ротації та перезавантаження.

Перш ніж запускати це в лабораторному кластері, який вивід ви очікуєте від k describe pod app, якщо Secret використовується через secretKeyRef? Ви маєте очікувати, що побачите, що змінна середовища береться з посилання на Secret, а не саме розкодоване значення. Це корисно, але це не повна історія захисту, бо значення все одно існує в середовищі запущеного процесу після старту контейнера.

Гіпотетичний сценарій: Одна платформова команда дозволяє розробникам використовувати envFrom для цілих об’єктів Secret, бо це робить онбординг швидким. Через місяці один спільний Secret містить і пароль бази даних, і неспоріднений сторонній API-токен. Сервіс, якому потрібен лише пароль бази даних, успадковує й API-токен, а ендпоінт налагодження виводить усе середовище процесу під час продакшен-інциденту. Виправлення полягає не лише в тому, щоб “використовувати монтування”; воно також полягає в тому, щоб розділити Secret за споживачами, монтувати лише конкретні ключі та зробити так, щоб імена секретів відображали власника облікових даних і план ротації.

Таке очищення легше, коли застосунки мають вузький контракт конфігурації. Якщо сервіс очікує кожне можливе облікове значення у своєму середовищі, платформові команди не можуть міркувати про те, яке значення насправді потрібне. Якщо сервіс читає один шлях до файлу для однієї мети, рецензенти можуть пов’язати Secret, монтування, код застосунку та план ротації. Саме тому робота над секретами часто перетворюється на роботу над архітектурою застосунку. Платформа може надати безпечніший патерн доставки, але кожне робоче навантаження все одно потребує чіткої домовленості про те, що воно споживає і чого ніколи не повинно виводити.

Питання безпеки секретів: etcd, RBAC, ноди та резервні копії

Розділ «Питання безпеки секретів: etcd, RBAC, ноди та резервні копії»

Про ризик секретів найлегше міркувати, коли ви відокремлюєте зберігання, авторизацію, доставку та життєвий цикл. Зберігання запитує, що станеться, якщо хтось отримає дані etcd чи резервну копію. Авторизація запитує, хто може використовувати API Kubernetes для читання, оновлення чи опосередкованого монтування Secret. Доставка запитує, як значення досягає робочого навантаження і які шляхи виконання можуть його розкрити. Життєвий цикл запитує, чи можна значення ротувати, відкликати, проаудитувати та видалити зі старих місць після інциденту.

Типове зберігання (без шифрування)

Розділ «Типове зберігання (без шифрування)»
┌─────────────────────────────────────────────────────────────┐
│ SECRET STORAGE IN ETCD │
├─────────────────────────────────────────────────────────────┤
│ │
│ WITHOUT ENCRYPTION AT REST: │
│ │
│ Secret "password: admin123" │
│ │ │
│ ▼ (base64 encode) │
│ Secret "password: YWRtaW4xMjM=" │
│ │ │
│ ▼ (store in etcd) │
│ etcd: key="/registry/secrets/default/my-secret" │
│ value="YWRtaW4xMjM=" ← Still readable! │
│ │
│ Anyone with etcd access can decode all secrets │
│ │
└─────────────────────────────────────────────────────────────┘

У типовому шляху зберігання без шифрування API-сервер зберігає об’єкт Secret до etcd з конфіденційними значеннями, закодованими, але не захищеними криптографічно засобами Kubernetes. Зловмисник, який скомпрометує сховище etcd, знімки або носії резервних копій, може розкодувати значення, не потребуючи RBAC Kubernetes. Це має значення, бо системи резервного копіювання часто мають інші засоби контролю доступу, ніж сам кластер. Адміністратор сховища, оператор хмарного резервного копіювання або помилково розміщений артефакт в об’єктному сегменті може стати читачем секретів, навіть якщо він ніколи не мав акаунта Kubernetes.

Шифрування у стані спокою усуває цей специфічний для сховища ризик, але воно не приховує дані від авторизованих клієнтів API. Коли користувач із дозволом запитує Secret в API-сервера, API-сервер розшифровує збережений об’єкт і повертає звичайне представлення Secret. Ця відмінність запобігає поширеній хибній тривозі: побачити base64 у k get secret -o yaml після ввімкнення шифрування у стані спокою не доводить, що шифрування дало збій. Це доводить, що API-сервер виконав своє завдання для авторизованого запиту. Щоб перевірити шифрування сховища, ви інспектуєте дані etcd або використовуєте задокументовані процедури валідації площини управління, а не звичайний вивід API.

┌─────────────────────────────────────────────────────────────┐
│ SECRETS ACCESS CONTROL │
├─────────────────────────────────────────────────────────────┤
│ │
│ WHO CAN READ SECRETS: │
│ ├── Users with "get secrets" permission │
│ ├── Service accounts with "get secrets" permission │
│ ├── Anyone with etcd access │
│ └── Node (kubelet) for pods scheduled there │
│ │
│ RISKS: │
│ • `get secrets` in RBAC = read ALL secrets in scope │
│ • No field-level access control │
│ • Listing secrets shows all names (potential info leak) │
│ │
│ BEST PRACTICES: │
│ • Minimize who has `get secrets` permission │
│ • Use namespace isolation for secret scope │
│ • Audit secret access │
│ │
└─────────────────────────────────────────────────────────────┘

RBAC є основним засобом контролю на рівні API, і він заслуговує на більшу повагу, ніж загальна політика “лише адміністратори”. Вбудована ClusterRole view навмисно виключає читання Secret, бо доступ до Secret може ескалувати до ширшого доступу до застосунку. Користувачеві, який може читати облікові дані бази даних, може не знадобитися доступ до оболонки, щоб завдати шкоди системі. Сервісний акаунт, який може переглянути список кожного Secret у просторі імен, може виявити імена, що розкривають постачальників, внутрішні системи чи проєкти міграції, навіть якщо значення захищені деінде.

Використовуйте дизайн просторів імен, щоб радіус ураження був зрозумілим. Спільний простір імен з десятками застосунків змушує до широких компромісів: або сервісний акаунт може читати забагато, або оператори керують крихкими правилами resourceNames, які треба оновлювати для кожного нового Secret. Менші простори імен, один сервісний акаунт на робоче навантаження та окремі Secret для кожного споживача роблять огляд простішим. Зовнішні сховища можуть додати точнішу політику, коли RBAC Kubernetes стає надто грубим для моделі ризиків організації.

Ноди — це ще одна межа довіри. Kubelet на ноді отримує Secret, потрібні Подам, запланованим там, і адміністратори ноди часто можуть перевірити достатньо стану виконання, щоб стати читачами секретів. Це не помилка; нода повинна доставляти дані робочим навантаженням. Це означає, що керування секретами залежить від загартовування ноди, ізоляції робочих навантажень, політики допуску та виборів планування. Високочутливі робочі навантаження можуть вимагати виділених пулів нод, суворішого доступу до налагодження та ретельного контролю над тим, хто може запускати привілейовані Поди.

Резервні копії та системи спостережуваності доповнюють картину. Інструмент резервного копіювання, що зберігає знімки etcd без шифрування, може звести нанівець ваш дизайн RBAC. Конвеєр логування, що індексує конфігурацію запуску, може розкрити змінні середовища у великому масштабі. Генератор пакетів підтримки може включати змонтовані файли, якщо його не налаштовано на редагування відомих шляхів. Діагностуйте розкриття секретів, простежуючи дані до кожної операційної системи, що копіює стан кластера, а не лише перевіряючи живий API.

Огляд також має включати поведінку видалення та збереження. Видалення Secret із живого простору імен не обов’язково видаляє його зі старих резервних копій, подій аудиту, пакетів підтримки, прокрутки термінала чи історії Git. Саме тому запобігання дешевше за очищення. Якщо необроблене значення потрапляє до постійного логу чи репозиторію, ротація стає єдиним надійним кроком стримування, і команда має вважати, що старе значення розкрите. Хороші дизайни зменшують кількість стійких систем, які взагалі бачать облікові дані, що зменшує як масштаб інциденту, так і роботу з аудиту.

Шифрування у стані спокою та KMS: захист збережених секретів без плутанини з API

Розділ «Шифрування у стані спокою та KMS: захист збережених секретів без плутанини з API»

Шифрування у стані спокою захищає дані Secret, що зберігаються в etcd, завдяки тому, що API-сервер шифрує вибрані ресурси перед збереженням. У самокерованих кластерах це зазвичай означає налаштування EncryptionConfiguration для API-сервера. У керованих кластерах хмарний провайдер може надавати налаштування, що інтегрується з його власною службою керування ключами. У будь-якому разі цей засіб контролю стосується збережених даних і резервних копій. Він не замінює RBAC, загартовування під час виконання, ротацію секретів чи редагування на боці застосунку.

Увімкніть шифрування для захисту секретів в etcd:

# EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {} # Fallback for reading unencrypted

Порядок провайдерів має значення, бо перший провайдер записує нові дані, а пізніші провайдери можуть читати старіші дані. Провайдер identity означає відсутність шифрування, але його часто включають як тимчасовий резервний варіант, щоб API-сервер міг читати об’єкти, збережені до ввімкнення шифрування. Після ввімкнення шифрування наявні Secret не переписуються магічним чином, доки їх не оновлять. Оператори зазвичай виконують контрольований перезапис наявних Secret, перевіряють зашифроване сховище, а потім вирішують, чи залишається резервний варіант потрібним під час міграції.

Провайдери шифрування

Розділ «Провайдери шифрування»
ПровайдерОписСценарій використання
identityБез шифруванняНіколи для секретів
aescbcЗастарілий локальний AES-CBC; ключі живуть на площині управління (апстрім не рекомендує)Лише міграція/резерв
aesgcmЗастарілий локальний AES-GCM; ключі живуть на площині управління (апстрім не рекомендує)Лише міграція/резерв
kms v2Стабільний з 1.29; конвертне шифрування з ключами у зовнішньому KMS (рекомендований шлях для продакшену/відповідності)Продакшен, відповідність
kms v1Застарілий з 1.28Мігруйте на kms v2
secretboxXSalsa20 + Poly1305Альтернатива AES

Локальні провайдери AES шифрують дані за допомогою ключів, до яких має доступ API-сервер. Це може задовольнити вимогу зберігання у стані спокою, але це все одно залишає опіку над ключами близько до площини управління. Провайдери KMS переміщують операції з ключами до зовнішньої служби чи плагіна, часто використовуючи конвертне шифрування. API-сервер шифрує кожен об’єкт ключем шифрування даних, тоді як ключ шифрування ключів залишається в KMS. Це дає командам безпеки централізовану політику ключів, логи аудиту та засоби контролю ротації, які краще підходять для корпоративних програм відповідності.

┌─────────────────────────────────────────────────────────────┐
│ KMS ENCRYPTION │
├─────────────────────────────────────────────────────────────┤
│ │
│ ENVELOPE ENCRYPTION: │
│ │
│ Secret ──→ Encrypt with DEK ──→ Encrypted Secret │
│ │ │
│ ▼ │
│ DEK (Data Encryption Key) Store in etcd │
│ │ │
│ ▼ Encrypt with KEK (in KMS) │
│ Encrypted DEK ──→ Store alongside secret │
│ │
│ BENEFITS: │
│ • Key rotation without re-encrypting all secrets │
│ • Key never leaves KMS │
│ • Audit logging in KMS │
│ • Compliance requirements met │
│ │
│ KMS ENCRYPTION PLUGINS (EncryptionConfiguration): │
│ AWS KMS, GCP KMS, Azure Key Vault │
│ │
│ EXTERNAL SECRET STORES (separate integration path): │
│ HashiCorp Vault, cloud secret managers │
│ │
└─────────────────────────────────────────────────────────────┘

Конвертне шифрування подібне до розміщення кожного документа у власному замкненому конверті, а потім замикання всіх ключів від конвертів у сейфі з камерою аудиту. Якщо один документ змінюється, вам не потрібно перебудовувати весь сейф. Якщо змінюється політика, ви можете ротувати чи вимкнути рівень шифрування ключів централізовано. Компромісом є операційна складність: API-сервер тепер залежить від доступності та затримки KMS, а команда кластера має моніторити провайдера, ротувати ключі обдумано і тестувати аварійне відновлення до збою.

Зробіть паузу і передбачте: Ви вмикаєте шифрування у стані спокою для секретів etcd за допомогою aescbc. Розробник використовує kubectl get secret db-creds -o yaml і бачить секретне значення в base64. Чи означає це, що шифрування у стані спокою не працює? Очікувана відповідь — ні; API-сервер розшифровує дані для авторизованих клієнтів, тож шифрування сховища треба перевіряти на шляху зберігання, а не звичайним читанням через API.

Ротація ключів має два рівні. Ротація ключа конфігурації шифрування змінює, який ключ захищає щойно записані дані, але наявні об’єкти можуть усе ще бути захищені старішими провайдерами, доки їх не перезапишуть. Ротація облікових даних застосунку всередині Secret — це окрема операція, яка має оновити справжню базу даних, API, сертифікат чи видавця токенів. Під час реагування на інцидент плутанина між цими рівнями марнує час. Шифрування сховища захищає старі знімки; ротація облікових даних застосунку знецінює значення, яке може використати зловмисник.

Дисциплінований план впровадження включає контроль змін для конфігурації API-сервера, резервне копіювання ключів шифрування, перевірку на непродакшен-кластері та план відкату, який не залишає наявні Secret недоступними. Він також включає документацію для команд застосунків, що пояснює, що вивід k get secret усе одно показуватиме base64 авторизованим користувачам. Без цього пояснення команди часто подають хибні інциденти після розгортання або, що гірше, припускають, що шифрування дало збій, і вимикають засіб контролю, бо неправильно зрозуміли його межу.

Керовані кластери Kubernetes змінюють операційні деталі, але не логіку міркувань. Прапорець у хмарній консолі може приховати конфігурацію API-сервера, розгортання плагіна ключів та послідовність перезапуску площини управління, але команда все одно має знати, які ресурси зашифровано, який ключ їх захищає, як працює ротація ключів і чи потребують наявні об’єкти перезапису. Деякі провайдери шифрують сховище etcd за замовчуванням ключами, керованими провайдером, тоді як інтеграція з ключами, керованими клієнтом, може вимагати окремого налаштування. Сприймайте типові налаштування провайдера як вхідні дані для огляду дизайну, а не як заміну читанню поточної документації кластера.

Зовнішнє керування секретами: джерело істини, синхронізація та прямі монтування

Розділ «Зовнішнє керування секретами: джерело істини, синхронізація та прямі монтування»

Нативні Secret корисні для доставки значень до Подів, але багато організацій хочуть, щоб джерело істини було десь поза кластером. Зовнішні системи, такі як HashiCorp Vault, AWS Secrets Manager, Google Secret Manager, Azure Key Vault та подібні платформи, надають політику, аудит, ротацію, реплікацію та робочі процеси людського доступу, якими Kubernetes не намагається володіти. Питання дизайну полягає в тому, чи має Kubernetes зберігати синхронізовану копію як нативний Secret, монтувати значення безпосередньо в Поди, чи отримувати лише короткочасні облікові дані, згенеровані на вимогу.

Для продакшену розгляньте зовнішні менеджери секретів:

┌─────────────────────────────────────────────────────────────┐
│ EXTERNAL SECRETS MANAGERS │
├─────────────────────────────────────────────────────────────┤
│ │
│ HASHICORP VAULT │
│ ├── Full-featured secrets management │
│ ├── Dynamic secrets (short-lived) │
│ ├── Encryption as a service │
│ └── Kubernetes auth method │
│ │
│ CLOUD PROVIDER SECRETS │
│ ├── AWS Secrets Manager │
│ ├── GCP Secret Manager │
│ ├── Azure Key Vault │
│ └── CSI driver integration │
│ │
│ KUBERNETES INTEGRATIONS │
│ ├── External Secrets Operator — sync external → K8s Secret│
│ └── Secrets Store CSI Driver — direct mount; sync optional│
│ │
│ BENEFITS OVER NATIVE SECRETS: │
│ • Centralized management │
│ • Audit logging │
│ • Dynamic/rotating secrets │
│ • Access policies │
│ • Works across clusters │
│ │
└─────────────────────────────────────────────────────────────┘

Є два поширені стилі інтеграції. Оператор синхронізації читає із зовнішнього сховища та створює або оновлює об’єкти Secret у Kubernetes. Це добре працює із застосунками, які вже споживають нативні Secret, і дозволяє наявним патернам розгортання продовжувати роботу з меншою кількістю змін коду. Компромісом є те, що копія значення тепер існує всередині Kubernetes, тож RBAC, шифрування у стані спокою та резервні копії все одно мають значення. External Secrets Operator є поширеним прикладом цієї моделі.

Інтеграція в стилі CSI монтує секрети із зовнішнього сховища до файлової системи Пода без потреби в довгоживучій нативній копії Secret для кожного значення. Це може зменшити кількість конфіденційних об’єктів, що зберігаються в etcd, і добре узгоджується із застосунками, які вже читають облікові дані з файлів. Компромісом є залежність від провайдера під час виконання, поведінка плагіна ноди та семантика перезавантаження застосунку. Якщо зовнішнє сховище недоступне під час запуску Подів, робочі навантаження можуть зазнати невдачі, навіть якщо сам кластер справний.

# Mount secrets directly from external store
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: secrets-store
mountPath: /mnt/secrets
readOnly: true
volumes:
- name: secrets-store
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: my-provider

Робочі процеси із запечатаними секретами вирішують іншу проблему: безпечне зберігання зашифрованих маніфестів секретів у Git. Контролер тримає приватний ключ усередині кластера, тоді як розробники комітять зашифровані об’єкти, які безпечно переглядати й застосовувати. Це корисно для команд GitOps, але це не те саме, що динамічне керування секретами. Якщо базовий пароль бази даних ніколи не ротується, його запечатування лише робить зберігання в Git безпечнішим. Вам усе одно потрібні право власності, ротація, відкликання та процедури реагування на інцидент для самих облікових даних.

Який підхід ви б обрали тут і чому: невеликий внутрішній інструмент з одними статичними обліковими даними вебхука, платіжний сервіс, що використовує облікові дані бази даних, які ротуються щомісяця, чи мультикластерна платформа, що обслуговує регульовані робочі навантаження? Внутрішній інструмент може бути прийнятним з нативним Secret плюс шифрування у стані спокою та жорстким RBAC. Платіжний сервіс виграє від зовнішнього джерела істини та протестованого шляху перезавантаження. Регульована платформа, ймовірно, потребує централізованого аудиту, інтеграції з KMS, політики допуску та задокументованого процесу винятків.

Найкращі впровадження зовнішніх секретів нудні в щоденному використанні. Розробники запитують облікові дані через схвалену систему, платформа синхронізує чи монтує їх з передбачуваними іменами, RBAC не дає неспорідненим робочим навантаженням їх читати, а ротація відпрацьовується до інциденту. Найслабші впровадження додають оператора, але зберігають ручні нативні Secret як неофіційний запасний хід. Щойно команди мають два способи створення секретів, сліди аудиту фрагментуються, а застарілі облікові дані множаться.

Зовнішні системи також змушують вас визначити ідентичність. Под, який запитує значення у Vault, хмарного менеджера секретів чи CSI-провайдера, має довести, яким робочим навантаженням він є. У Kubernetes це підтвердження часто починається з токена сервісного акаунту і продовжується через специфічну для провайдера конфігурацію довіри. Якщо кожне робоче навантаження ділить один сервісний акаунт, зовнішнє сховище не може ухвалити осмислене рішення щодо авторизації. Та сама звичка найменших привілеїв застосовується на обох рівнях: одна ідентичність робочого навантаження, одна вузька політика, один спостережуваний шлях від запиту до доставленого значення.

Найкращі практики для секретів: проєктування під ротацію та огляд

Розділ «Найкращі практики для секретів: проєктування під ротацію та огляд»

Програма керування секретами — це життєвий цикл, а не шаблон ресурсу. Почніть з права власності: кожне облікове значення має мати власника-застосунок, систему-видавця, перелік споживачів, інтервал ротації та екстрений шлях відкликання. Потім вирішіть, як у цьому бере участь Kubernetes. Подеколи Kubernetes зберігає значення як нативний Secret. Подеколи він лише монтує значення від провайдера. Подеколи він узагалі не повинен бачити довгоживучий секрет, бо доступні ідентичність робочого навантаження чи динамічні облікові дані.

┌─────────────────────────────────────────────────────────────┐
│ SECRETS MANAGEMENT CHECKLIST │
├─────────────────────────────────────────────────────────────┤
│ │
│ STORAGE │
│ ☐ Enable encryption at rest for etcd │
│ ☐ Consider external secrets manager for production │
│ ☐ Use KMS integration if available │
│ │
│ ACCESS CONTROL │
│ ☐ Minimize RBAC "get secrets" permissions │
│ ☐ Use namespace isolation │
│ ☐ Audit secret access │
│ │
│ USAGE │
│ ☐ Prefer volume mounts over env vars │
│ ☐ Mount as read-only │
│ ☐ Don't log secrets │
│ │
│ LIFECYCLE │
│ ☐ Rotate secrets regularly │
│ ☐ Have a revocation plan │
│ ☐ Don't commit secrets to git │
│ │
│ APPLICATION │
│ ☐ Don't hardcode secrets in images │
│ ☐ Don't include secrets in container args │
│ ☐ Use short-lived credentials when possible │
│ │
└─────────────────────────────────────────────────────────────┘

Контрольний список найкорисніший, коли ви застосовуєте його під час огляду дизайну, а не після того, як застосунок уже працює. Запитайте, як буде створено першу версію секрету, як буде розгорнуто другу версію, як старі Поди припинять використовувати стару версію і які докази підтверджують, що старе значення зникло. Якщо відповідь залежить від того, чи людина пам’ятатиме п’ять ручних команд під час злому, дизайн не готовий. Надійна ротація — це інженерна функція, і вона заслуговує на таке саме тестування, як і відкат розгортання.

Аудиторське логування має відповідати на питання, хто отримував доступ до об’єктів Secret чи змінював їх, але логи не повинні стати ще одним витоком. Політика аудиту Kubernetes може записувати метадані запиту без запису повних тіл запитів для конфіденційних ресурсів. Зовнішні сховища секретів зазвичай додають власні записи аудиту, які цінні, бо показують доступ ще до того, як значення досягне Kubernetes. Під час розслідування порівняйте аудит зовнішнього сховища, аудит API Kubernetes, історію розгортань робочого навантаження та логи застосунку. Розбіжність між цими системами часто виявляє неофіційні шляхи.

Контроль допуску може забезпечити дотримання рішень, які люди постійно забувають. Політики можуть відхиляти звичайні маніфести Secret у просторах імен GitOps, блокувати envFrom проти об’єктів Secret, вимагати незмінних посилань на образи, вимагати схвалених міток на Secret або дозволяти лише сервісному акаунту контролера створювати певні типи Secret. Використовуйте політику як запобіжник, а не як єдиний засіб контролю. Політика, що блокує кожен виняток без задокументованого шляху ескалації, буде обійдена; політика, що записує попередження, але ніколи не блокує ризиковані патерни, буде проігнорована.

Найменування — це маленька звичка з великою цінністю для налагодження. Secret з ім’ям db каже вам майже нічого під час інциденту. Secret, названий за застосунком, системою, метою та власником, дає тим, хто реагує, відправну точку без розкодування значень. Мітки можуть записувати право власності та очікування щодо ротації, тоді як анотації можуть вказувати на шлях зовнішнього провайдера, не розкриваючи сам секрет. Уникайте розміщення секретних значень чи конфіденційних ідентифікаторів акаунтів в іменах, мітках чи анотаціях, бо метадані часто видимі ширше, ніж дані.

Планування ротації заслуговує на пробний прогін, перш ніж продакшен почне від нього залежати. Корисна репетиція створює другі облікові дані, оновлює шлях доставки Kubernetes, підтверджує, що нові Поди автентифікуються з новим значенням, спостерігає, як старі Поди відходять, а потім відкликає старі облікові дані у видавця. Інструкція має вказувати, яка телеметрія доводить успіх кожного кроку. Без цього доказу команди часто зупиняються після оновлення об’єкта Secret і пізніше виявляють, що довготривалий Под, кешований пул з’єднань чи забутий пакетний процес усе ще використовує старе значення.

Патерни та антипатерни

Розділ «Патерни та антипатерни»

Використовуйте патерни, коли вони роблять безпечний шлях простішим за небезпечний. Мета не в тому, щоб заборонити кожен нативний Secret чи змусити кожну команду до найскладнішого провайдера від першого дня. Мета — обрати модель доставки, чиї режими відмов зрозумілі, моніторяться і є прийнятними для цінності облікових даних. Наступні патерни масштабуються, бо вони поєднують захист сховища, контроль доступу, дисципліну доставки та право власності на ротацію.

ПатернКоли використовуватиЧому працюєМіркування щодо масштабування
Нативний Secret із шифруванням у стані спокою та жорстким RBACОблікові дані низької-середньої чутливості в одному кластеріТримає доставку простою, водночас захищаючи сховище etcd та звужуючи коло читачів APIПотребує дисципліни просторів імен, політики аудиту та права власності на ротацію
Зовнішнє джерело істини, синхронізоване контролеромКоманди, які вже використовують GitOps чи сховища секретів провайдераЦентралізує право власності, зберігаючи нативну доставку KubernetesУсе одно створює копії Secret у Kubernetes, тож резервні копії та RBAC залишаються важливими
Пряме монтування CSI із зовнішнього сховищаЦінні облікові дані, де копії в etcd слід мінімізуватиЗменшує кількість збережених об’єктів Secret та підтримує політику, нативну для провайдераДодає залежність від плагінів провайдера під час виконання та поведінку перезавантаження файлів застосунком
Динамічні короткочасні облікові даніБази даних, хмарні API чи системи, що можуть видавати тимчасовий доступЗменшує цінність витеклих облікових даних і покращує відкликанняПотребує сумісності застосунку, обробки оновлень та доброї спостережуваності

Найсильніший патерн — той, який ваша команда може експлуатувати під тиском. Ідеальний дизайн зовнішнього сховища, який ніхто не може налагодити о 02:00, є менш безпечним за простіший дизайн із чітким правом власності, протестованою ротацією та надійним моніторингом. Почніть із впливу облікових даних. Токен лише для читання для пісочничного інструмента не потребує такої самої церемонії, як облікові дані продакшен-бази даних платежів. Однак шлях низького ризику все одно має уникати витоків у Git, жорстко закодованих образів, широкого RBAC та незашифрованих резервних копій.

Антипатерни зазвичай виникають через тиск зручності. Розробнику швидко потрібне значення, шаблон розгортання приймає змінні середовища, команда копіює робочий маніфест, і скорочення стає стандартом. Огляди безпеки мають шукати ці звички рано, бо їх стає важче усунути після того, як застосунки починають від них залежати. Таблиця нижче називає режим відмови, чому команди в нього потрапляють, і кращу альтернативу, до якої варто вдатися під час дизайну.

АнтипатернЩо йде не такКраща альтернатива
Сприйняття base64 як захистуБудь-хто з об’єктом може розкодувати значенняВикористовуйте шифрування у стані спокою для сховища та RBAC для доступу через API
Один спільний Secret на простір іменРобочі навантаження отримують облікові дані, яких вони не потребуютьРозділіть за споживачами та монтуйте лише конкретні ключі
Секретні значення в аргументах командЗначення з’являються в переліках процесів та діагностиціЧитайте з файлів чи SDK провайдера під час виконання
Ручні нативні Secret поряд із зовнішніми сховищамиСліди аудиту фрагментуються, а застарілі облікові дані зберігаютьсяДозволяйте лише схваленим контролерам створювати керовані Secret
Ротація як незадокументоване ручне завданняІнциденти залежать від пам’яті та таймінгуРепетируйте ротацію з чіткими критеріями успіху та відкатом

Зверніть увагу, що кращою альтернативою рідко є просто “використовуйте інструмент X”. Інструменти допомагають, коли вони підкріплюють життєвий цикл. Платформова команда все одно має визначити, хто може створювати шляхи провайдера, як команди застосунків запитують доступ, які мітки чи анотації потрібні, як тестується ротація і як спливають винятки. Програма секретів без процесу винятків перетворюється на купу термінових обходів. Програма секретів із чіткими типовими налаштуваннями та вузькими винятками стає простішою для впровадження.

Рамка ухвалення рішень

Розділ «Рамка ухвалення рішень»

Обирайте найпростіший дизайн, який захищає облікові дані на всіх реалістичних шляхах розкриття. Почніть із впливу: якщо це значення витече, що може зробити зловмисник, як швидко ви можете його відкликати і які докази доведуть, що відкликання спрацювало? Потім окресліть операційні обмеження: чи читає застосунок файли, змінні середовища чи SDK провайдера; чи може він перезавантажувати облікові дані; і чи вже експлуатує платформа надійне зовнішнє сховище? Нарешті вирішіть, де Kubernetes має зберігати, посилатися чи уникати конфіденційного значення.

Точка рішенняОберіть нативний SecretОберіть зовнішню синхронізаціюОберіть пряме монтування CSIОберіть динамічні облікові дані
Чутливість облікових данихПомірна та обмеженаПомірна-висока з централізованим правом власностіВисока, уникайте копій в etcdВисока, видавець підтримує короткі терміни життя
Потрібні зміни застосункуНизькіНизькі-середніСередніСередні-високі
Очікування щодо ротаціїРучна чи періодичнаКерована провайдером із синхронізацієюКерована провайдером з оновленням монтуванняАвтоматичне оновлення чи часта видача
Потреба в аудитіАудиту Kubernetes може бути достатньоЗовнішній аудит плюс події KubernetesЗовнішній аудит плюс події плагіна нодиАудит зовнішнього видавця є центральним
Операційний ризикПроста залежність від кластераЗалежність від контролераЗалежність від провайдера та CSIЗалежність від видавця, оновлення та застосунку

Якщо ви не впевнені, проведіть облікові дані через чотири запитання. По-перше, кому дозволено знати це значення поза застосунком? По-друге, де значення зберігається після створення? По-третє, як робоче навантаження отримує його під час виконання? По-четверте, які саме кроки ротують і відкликають його під час інциденту? Дизайн, який не може відповісти на ці запитання, не готовий до продакшену, навіть якщо він використовує шанований інструмент для секретів.

Для міркувань рівня KCSA пам’ятайте про межу між засобами контролю. Шифрування у стані спокою захищає etcd та резервні копії. RBAC захищає читання й запис через API. Монтування томів зменшує розкриття на рівні процесу порівняно зі змінними середовища. Зовнішні сховища централізують політику, аудит та ротацію. Контроль допуску тримає команди на схваленому шляху. Жоден із цих засобів контролю окремо не запобігає кожному витоку, і жоден із них не виправдовує погане логування застосунку чи широкі права на створення Подів.

Ухвалюючи рішення під тиском часу, використовуйте драбину ризиків. Для облікових даних розробки з низьким впливом нативного Secret в ізольованому просторі імен із шифруванням у стані спокою може бути достатньо. Для продакшен-облікових даних, що надають доступ на запис до даних клієнтів, підніміть планку до зовнішнього права власності, ідентичності, специфічної для робочого навантаження, задокументованої ротації та огляду аудиту. Для облікових даних, які можна замінити ідентичністю робочого навантаження чи динамічною видачею, поставте під сумнів, чи взагалі потрібен довгоживучий статичний секрет. Найбезпечніший секрет — це часто той, який вам не довелося зберігати.

  • Base64 не є шифруванням - воно тривіально оборотне. echo "cGFzc3dvcmQ=" | base64 -d миттєво дає вам вихідне значення.

  • Секрети зберігаються в etcd поряд з усіма іншими об’єктами Kubernetes. Якщо etcd скомпрометовано, то скомпрометовано й усі ваші секрети, якщо тільки шифрування у стані спокою не захищає збережене представлення.

  • ClusterRole view не включає секрети за задумом. Це навмисно, щоб дозволити широкий доступ на читання без розкриття конфіденційних даних.

  • Оновлення секретів поширюються на змонтовані томи з часом, зазвичай приблизно за хвилину у звичайних кластерах, але змінні середовища потребують перезапуску Пода, бо середовища процесів фіксуються після старту.

ПомилкаЧому це стаєтьсяЯк це виправити
Припущення, що base64 означає зашифрованоВивід YAML виглядає перетвореним, тож команди плутають кодування із захистомУвімкніть шифрування у стані спокою та поясніть рецензентам, що вивід API залишається в base64 для авторизованих читань
Розміщення секретів у змінних середовища за замовчуваннямФреймворки спрощують конфігурацію через середовище, а приклади швидко копіюютьсяНадавайте перевагу монтуванню томів лише для читання для конфіденційних значень і редагуйте дампи середовища
Коміт необроблених маніфестів Secret до GitКоманди хочуть GitOps без безпечного робочого процесу шифруванняВикористовуйте запечатані секрети, оператор зовнішніх секретів чи синхронізацію провайдером із захищеного джерела
Надання широких прав get secretsОператори перевикористовують ролі в стилі адміністратора для зручностіСтворюйте сервісні акаунти, специфічні для робочого навантаження, розділяйте простори імен та аудитуйте прямі читання Secret
Ігнорування створення Подів як опосередкованого шляху читанняОгляди зосереджуються лише на прямому RBAC get secretsСприймайте створення Подів, exec, attach та права контролерів як частину моделі доступу до Secret
Забування про наявні об’єкти після ввімкнення шифруванняНові записи шифруються, але старі дані залишаються, доки їх не перезапишутьПерезапишіть наявні Secret під час міграції та перевірте сховище через задокументований шлях etcd
Ротація Secret у Kubernetes, але не справжніх облікових данихКоманди оновлюють об’єкт доставки і забувають про систему-видавцяРотуйте у видавця спочатку, розгорніть нове значення, перевірте споживачів і відкличте старі облікові дані
1. Аудит відповідності виявляє паролі бази даних, що зберігаються як об'єкти Secret у Kubernetes без шифрування у стані спокою. Керівник команди каже, що кодування base64 їх захищає. У чому хибність такого міркування і який ризик залишається, якщо резервні копії etcd витечуть?

Base64 — це лише формат кодування, тож будь-хто, хто може прочитати об’єкт Secret, може його обернути без ключа. Ризик сховища полягає в тому, що знімки чи резервні копії etcd можуть містити закодовані значення у формі, яку можна розкодувати поза RBAC Kubernetes. Шифрування у стані спокою захищає цей шлях зберігання, шифруючи вибрані ресурси перед збереженням. Воно все одно не запобігає читанню Secret авторизованими користувачами API, тож RBAC та засоби контролю аудиту залишаються необхідними.

2. Ваш застосунок отримує пароль бази даних через змінну середовища. Під час реагування на інцидент значення з'являється у звіті про збій та діагностичному пакеті. Що ймовірно сталося і який метод доставки вам слід оцінити першим?

Змінні середовища стають частиною стану процесу, тож інструменти налагодження, репортери збоїв, дочірні процеси та пакети підтримки можуть їх захопити. Безпечнішим нативним методом доставки зазвичай є монтування тому Secret лише для читання з розкриттям лише потрібних ключів. Це не робить застосунок нездатним витекти значення, але усуває кілька автоматичних шляхів розкриття на основі середовища. Вам також слід перевірити конфігурацію логування та редагування пакетів підтримки.

3. Платформова команда вмикає шифрування `aescbc` з `identity` як резервом. Розробник потім виконує `k get secret db-creds -o yaml` і все одно бачить дані base64. Чи бачать вони доказ того, що шифрування дало збій?

Ні. Шифрування у стані спокою захищає збережене представлення в etcd, тоді як API-сервер розшифровує дані для авторизованих клієнтів і повертає звичайний формат Secret. Бачити base64 через k get secret очікувано, бо відповідь API кодує дані, безпечні для двійкового формату. Щоб перевірити шифрування, інспектуйте шлях зберігання через задокументовані процедури, а не звичайні читання API. Команда також має перезаписати наявні Secret, щоб старі незашифровані об’єкти зберігалися з новим провайдером.

4. Ваша організація використовує Vault, але один простір імен усе ще дозволяє розробникам створювати нативні Secret типу Opaque вручну. Який ризик створює цей подвійний шлях і як ви взяли б його під контроль?

Подвійний шлях фрагментує аудит, право власності та ротацію, бо одні значення слідують політиці Vault, тоді як інші існують лише в Kubernetes. Застарілі облікові дані стає важче знайти, а ті, хто реагує на інциденти, не можуть довіряти єдиному джерелу істини. Практичним виправленням є дозволити схваленим контролерам чи інтеграціям CSI створювати керовані Secret, тоді як політика допуску блокує некеровані Secret типу Opaque у продакшен-просторах імен. Винятки мають бути задокументованими, обмеженими в часі та видимими для процесу огляду безпеки.

5. Простір імен містить багато Secret, і трьом сервісним акаунтам потрібні різні підмножини. RBAC Kubernetes здається надто грубим для бажаної політики. Як вам слід перепроєктувати межу?

Почніть із розділення споживачів та облікових даних, щоб кожне робоче навантаження отримувало лише те, що йому потрібно. Менші простори імен та сервісні акаунти, специфічні для робочого навантаження, роблять RBAC простішим для огляду. Для названих винятків resourceNames може обмежити прямі читання Secret, але це може стати крихким, коли імена змінюються. Якщо організація потребує стійкої політики на рівні шляху чи облікових даних, зовнішній менеджер секретів із правилами доступу, нативними для провайдера, зазвичай є кращим джерелом істини.

6. Команда ротує значення в Secret Kubernetes, але забуває оновити сам пароль бази даних. Поди успішно перезапускаються, проте автентифікація все одно зазнає невдачі. Що вони неправильно зрозуміли?

Вони сплутали ротацію об’єкта доставки з ротацією облікових даних на боці видавця. Оновлення Secret Kubernetes змінює те, що отримують Поди, але не змінює автоматично пароль, токен чи сертифікат у системі, яка його перевіряє. Правильна ротація починається у видавця або використовує скоординований період подвійної дійсності, потім оновлює споживачів, перевіряє нове значення і відкликає старе. Інструкція має називати і об’єкт Kubernetes, і зовнішню систему.

7. Інженер, у якого немає права `get secrets`, може створювати Поди у просторі імен. Він створює Под, що монтує наявний Secret, а потім читає файл. Який урок має зафіксувати огляд RBAC?

Створення Подів може бути опосередкованим шляхом до доступу до Secret, бо kubelet доставляє посилані Secret запланованим Подам. Огляди RBAC мають враховувати create pods, створення контролерів, exec, attach та використання сервісних акаунтів, а не лише прямі дієслова для Secret. Виправлення може включати жорсткіші права на створення робочих навантажень, окремі простори імен, засоби контролю допуску, що обмежують посилання на Secret, та сервісні акаунти, обмежені одним застосунком. Прямі правила читання Secret — лише одна частина моделі доступу.

Практична вправа: огляд безпеки секретів

Розділ «Практична вправа: огляд безпеки секретів»

Сценарій: Перегляньте цей Deployment і визначте проблеми безпеки, пов’язані із секретами:

apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
env:
- name: DB_PASSWORD
value: "supersecret123"
- name: API_KEY
valueFrom:
secretKeyRef:
name: api-secret
key: key
command:
- /app
- --db-password=$(DB_PASSWORD)
- --debug

Пройдіть огляд так, ніби ви платформовий інженер, який схвалює продакшен-зміну. Не зупиняйтеся після виявлення жорстко закодованого пароля. Простежте значення через Git, API Kubernetes, середовище Пода, аргументи процесу, поведінку налагодження застосунку та відтворюваність образу. Сильний огляд називає шлях розкриття, пояснює, чому він має значення під час інциденту, і пропонує зміну, яку команда застосунку справді може впровадити.

  • Визначте кожне місце, де Deployment може розкрити конфіденційне значення ще до того, як контейнер запуститься.
  • Замініть жорстко закодовані значення схваленим джерелом Secret і поясніть, хто володіє обліковими даними.
  • Перепроєктуйте доставку так, щоб застосунок читав конфіденційні значення з файлів лише для читання, а не з аргументів процесу.
  • Вирішіть, чи має це робоче навантаження використовувати нативний Secret, зовнішню синхронізацію, пряме монтування CSI чи динамічні облікові дані.
  • Визначте критерії успіху для ротації, зокрема як довести, що старе значення більше не використовується.
Проблеми безпеки
  1. Жорстко закодований пароль у env

    • DB_PASSWORD стоїть безпосередньо в маніфесті
    • Буде закомічено до Git, видно через API
    • Виправлення: Перемістіть до ресурсу Secret
  2. Секрет в аргументах команди

    • --db-password=$(DB_PASSWORD) розкриває секрет у переліку процесів
    • Видно через ps aux, /proc та переліки процесів на ноді
    • Виправлення: Читайте з монтування тому Secret лише для читання (або шляху до файлу CSI/провайдера); не передавайте через аргументи команд чи env
  3. Секрет як змінна середовища

    • API_KEY через env видно в /proc
    • Виправлення: Монтуйте як том натомість
  4. Увімкнено режим налагодження

    • --debug може логувати конфіденційні дані
    • Виправлення: Вимкніть у продакшені
  5. image: myapp:latest

    • Змінний тег, непередбачувана версія
    • Виправлення: Використовуйте незмінний тег із дайджестом

Безпечна версія:

apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
template:
spec:
containers:
- name: app
image: myapp@sha256:abc123...
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: app-secrets

Безпечна версія навмисно мінімальна, тож завершіть вправу описом того, чого все ще бракує. Маніфест зрештою має містити справжній незмінний дайджест образу, робочий процес створення Secret, що уникає необроблених значень у Git, план перезавантаження чи розгортання для ротації та політику, що запобігає прапорцям налагодження у продакшені. Якщо в організації вже є зовнішнє сховище, кращою відповіддю може бути заміна нативного тому Secret монтуванням, підкріпленим провайдером, чи синхронізованим Secret, керованим контролером.

Використовуйте вправу як шаблон для реальних оглядів. Почніть із маніфесту, бо він видимий, але не закінчуйте на цьому. Запитайте, звідки взявся пароль, чи може система-видавець ротувати його без простою, який сервісний акаунт може його монтувати, чи захищають його резервні копії і чи можуть логи чи інструменти підтримки його розкрити. Ті самі запитання застосовуються до ключів TLS, облікових даних реєстру, ключів SSH, токенів вебхуків та токенів сервісних акаунтів. Керування секретами повторюване за задумом; повторюваність — це те, що робить інциденти переживними.

Модуль 3.4: Безпека ServiceAccount - Захист ідентичностей Подів та доступу до API.