Kubernetes надає безліч функцій, які спрощують безпечний та надійний запуск робочих навантажень у промислових середовищах. Хоча планування, перевірки стану та ліміти ресурсів, ймовірно, знаходяться на вістрі вашої уваги, ще одна важлива функція Kubernetes — це виробнича ідентичність, як ваше робоче навантаження може автентифікуватися в інших системах для виконання своєї роботи.
До цього моменту основним вбудованим механізмом виробничої ідентичності в Kubernetes були JWT токени службових облікових записів (JSON Web Tokens). Це криптографічно підписані токени, що видаються панеллю управління кластера, які дозволяють всім зрозуміти, хто здійснює виклик, коли ваше робоче навантаження використовує їх.
У Kubernetes 1.37, основи нової вбудованої технології виробничої ідентичності перейшли у стабільний стан (GA). Сертифікати Podʼів (Pod Certificates) та тісно повʼязані з ними пакети довіри кластера (Cluster Trust Bundles) приносять выпуск X.509 сертифікатів для TLS та mTLS безпосередньо до ядра Kubernetes.
Чому?
Токени службових облікових записів мають багато переваг:
Вони вбудовані безпосередньо в Kubelet і працюють просто дивовижно. Вони записуються у файлову систему контейнера вашого робочого навантаження до його запуску і автоматично підтримуються в актуальному стані.
Система випуску дотримується принципів найменших привілеїв; втулок допуску з обмеженнями вузла (node restriction admission plugin) гарантує, що токени можуть запитувати лише той Kubelet, який на даний момент фактично запускає ваш Pod.
Їх можна об’єднати в федерацію, що дозволить використовувати їх для автентифікації в інших системах поза межами Kubernetes. Токени службових облікових записів лежать в основі сховища автентифікації pod-to-cloud для всіх найбільших хмарних провайдерів і мають широку підтримку у багатьох додаткових сервісах та програмних пакетах. Якщо система розуміє JWT, ви можете автентифікуватися в ній за допомогою токена службового облікового запису.
Однак у токенів службових облікових записів є один значний недолік — це токени на предʼявника (bearer tokens). З токенами на предʼявника, якщо ви маєте токен, то ви і є ідентичність, заявлена цим токеном. Оскільки ви обовʼязково повинні передавати копії JWT усім своїм партнерам для автентифікації, вони також можуть виглядати як ви.
Існують часткові заходи помʼякшення цієї проблеми, і токени службових облікових записів їх використовують (обмеження за часом, обʼєктом та аудиторією), але жоден з них не є повним захистом.
Рішенням цієї проблеми є облікові дані з доказом володіння (proof-of-possession credentials), де ви не надсилаєте всі свої облікові дані партнеру, а лише доказ того, що ви ними володієте. На практиці ці схеми завжди базуються на асиметричних криптографічних підписах (RSA, ECDSA та подібні).
Існує кілька різних стандартних підходів, таких як підпис запитів (AWS SigV4, JWT DPoP, RFC 9421), але найширше розгорнутим і зрозумілим рішенням є сертифікати X.509, що використовуються в TLS. У TLS ваші облікові дані розділено на дві частини:
Приватний ключ, який для максимальної безпеки має генеруватися всередині вашого робочого навантаження (або всередині модуля апаратної безпеки) і ніколи не виходити за його межі.
Сертифікат, який є описом вашої ідентичності та публічного ключа, підписаний Центром сертифікації (CA).
Мета сертифікатів Podʼів — зробити використання сертифікатів X.509 з вашого Kubernetes робочого навантаження таким самим простим, як використання JWT токенів службових облікових записів, водночас зберігаючи високу планку безпеки Kubernetes. Отже, ми влучили в ціль.
В розділах про архітектуру та приклади нижче, існує багато схожостей між дизайном випуску JWT токенів службових облікових записів та сертифікатами Podʼів. Однак одне значне місце, де вони розходяться, — це те, що сертифікати Podʼів є набагато більш гнучким механізмом. Kubernetes пропонує лише один вид JWT токенів службових облікових записів зі стандартизованими claims.
Екосистема X.509 значно більш різноманітна за екосистему JWT, і сертифікати X.509, що використовуються для різних цілей, містять різні розширення та інформацію. З цієї причини сертифікати Podʼів мають спільний механізм, вбудований у kubelet, але пропонують підʼєднуваний інтерфейс, щоб у одному кластері одночасно могли видаватися багато різних типів сертифікатів.
Згодом очікується, що Kubernetes запропонує принаймні два вбудовані постачальника сертифікатів:
Один, що видає серверні TLS сертифікати для DNS імен, що використовуються Kubernetes Services.
Один, що пропонує SPIFFE клієнтські сертифікати, заповнюючи ту саму роль, яку виконують JWT токени службових облікових записів сьогодні.
Решта статті присвячена загальній архітектурі Kubernetes робочого навантаження з використанням сертифікатів Podʼів, а також містить приклад встановлення та використання реального (демонстраційного) контролера підписувача сертифікатів Podʼів.
Архітектура
Коли ви використовуєте сертифікати Podʼів та пакети довіри кластера, існують такі основні компоненти:
Ваш застосунок, який запитує сертифікати в своїй специфікації Podʼа і читає ключі, сертифікати та пакети довіри з файлової системи контейнера для використання в (m)TLS.
Kubelet, який створює обʼєкти PodCertificateRequest та читає обʼєкти ClusterTrustBundle від імені вашого робочого навантаження.
Контролер підписувача (signer controller), який відповідає на PodCertificateRequests і публікує ClusterTrustBundles.
Архітектура застосунку, що використовує сертифікати Podʼів
Найкращий спосіб зрозуміти, що робить кожен з цих компонентів — слідувати за процесом випуску хронологічно:
Як тільки ваш Pod застосунку планується на вузлі, kubelet визначає всі джерела проєкційних томів podCertificate та clusterTrustBundle в його специфікації.
Для кожного джерела podCertificate:
Kubelet генерує новий приватний ключ відповідно до поля keyType.
Kubelet створює PodCertificateRequest, адресований підписувачу (signer), імені, вказаному в джерелі.
Контролер підписувача бачить PodCertificateRequest і вирішує, чи видати сертифікат.
Контролер підписувача видає сертифікат, заповнюючи поле status.certificateChain.
Контролер підписувача також заповнює поле status.beginRefreshAt, щоб наказати kubelet, коли він має почати спробу оновити сертифікат.
Для кожного джерела clusterTrustBundle:
Kubelet збирає всі ClusterTrustBundles, що відповідають імені підписувача та селекторам міток у джерелі.
Kubelet обʼєднує всі сертифікати зі всіх відповідних ClusterTrustBundles і (стабільно) переупорядковує їх (щоб запобігти випадковій залежності застосунків від конкретного порядку).
Kubelet записує сертифікати у файловий шлях, заданий у джерелі.
Ваш Pod застосунку запускається, і застосунок читає ключі, сертифікати та точки довіри з файлової системи.
Kubelet періодично оновлює файли з джерел clusterTrustBundle, коли вміст вибраних ClusterTrustBundles змінюється. Застосунок має підхоплювати зміни за допомогою inotify або опитування (polling).
Коли час beginRefreshAt кожного сертифіката настане, kubelet повторює процес з кроку 2 для оновлення сертифікатів і записує оновлені приватні ключі та ланцюжки сертифікатів у файлову систему. Як і в кроці 5, застосунок має підхоплювати зміни за допомогою inotify або опитування.
Декілька ключових висновків:
Автоматична ротація вбудована. Застосунки повинні належно її обробляти. Будь-які підписувачі, що в кінцевому підсумку будуть поставлятися в ядрі Kubernetes, видадуть сертифікати з максимальним терміном дії 24 години. Максимальний дозволений термін дії для інших підписувачів — 91 день.
Щоб зробити підтримку автоматичної ротації максимально простою, kubelet підтримує запис приватного ключа та ланцюжка сертифікатів у єдиний файл (credential bundle — пакет облікових даних). Це дозволяє застосунку просто підписатися на події inotify для (або опитувати) єдиного файлу, прочитати вміст і використовувати його. Kubelet також підтримує запис приватного ключа та ланцюжка сертифікатів у окремі файли, але тоді застосунку потрібно обережно керувати потенційними станами гонитви при читанні файлів посеред ротації.
Де це можливо, перевірки безпеки вбудовані в kube-apiserver, а не перекладаються на розробників підписувачів чи застосунків. Як приклад, вбудований втулок допуску з обмеженнями вузла (node restriction admission plugin) забезпечує ізоляцію вузлів, гарантуючи, що один скомпрометований вузол не може поширити доступ, запитуючи сертифікати для Podʼів, які не заплановані на ньому.
Спробуйте
Оскільки проєкт Kubernetes ще не поставляє жодних підписувачів сертифікатів Podʼів у ядрі, щоб спробувати ці функції, вам потрібно встановити сторонній підписувач у свій кластер. Щоб полегшити це, було створено Tinycert, який ви можете встановити у свій кластер (або кластер Kind).
Tinycert не є повним виробничим рішенням, але це гарна початкова точка для експериментів з сертифікатами Podʼів, а також база для створення власних підписувачів.
Підписувач ahmedtd.github.io/tinycert-spiffe, який видає SPIFFE-сумісні сертифікати, що ідентифікують простір імен та службовий обліковий запис вашого Podʼа. Їх можна використовувати як клієнтські, так і (за певних зусиль) серверні сертифікати.
Перегляньте та надайте відгук щодо проєкту стандарту SPIFFE Filesystem Delivery, який прагне зробити використання SPIFFE сертифікатів безпосередньо на нативному Kubernetes максимально простим.
Приєднуйтесь до Kubernetes SIG Auth, щоб допомогти формувати майбутнє підписувачів, що вбудовані безпосередньо в ядро Kubernetes.
Спробуйте створити власний підписувач на основі Tinycert.