Забезпечення безпечного налагодження в Kubernetes
Під час налагодження в робочому середовищі найшвидший шлях часто передбачає широкий доступ, такий як cluster-admin (ClusterRole, що надає доступ рівня адміністратора), спільні bastions/jump boxes або довготривалі SSH-ключі. Це працює в моменті, але має дві поширені проблеми: аудит стає складним, а тимчасові винятки мають тенденцію ставати звичними.
Цей допис пропонує рекомендації, які можна застосувати до поточних середовищ Kubernetes з мінімальними змінами інструментів:
- Мінімальні привілеї з RBAC
- Короткострокові облікові дані, привʼязані до ідентичності
- Модель рукопотискання в стилі SSH для налагодження в хмарі
Хороша архітектура для забезпечення безпечного налагодження в робочих середовищах полягає у використанні шлюзу SSH за принципом "just-in-time" (часто розгортається як под на вимогу в кластері). Він діє як SSH-подібнs "парадні-двері", що робить тимчасовий доступ дійсно тимчасовим. Ви можете автентифікуватися за допомогою короткострокових облікових даних, привʼязаних до ідентичності, встановити сеанс до шлюзу, а шлюз використовує Kubernetes API та RBAC для контролю того, що вони можуть робити, наприклад pods/log, pods/exec та pods/portforward. Сеанси автоматично закінчуються, а журнали шлюзу та журнали аудиту Kubernetes фіксують, хто отримав доступ до чого і коли, без облікових записів bastion для спільного використання або довготривалих ключів.
1) Використання брокера доступу поверх RBAC Kubernetes
RBAC контролює хто і що можен робити в Kubernetes. Багато середовищ Kubernetes покладаються в основному на RBAC для авторизації, хоча Kubernetes також підтримує інші режими авторизації, такі як авторизація через Webhook. Ви можете забезпечити доступ безпосередньо за допомогою Kubernetes RBAC або розмістити брокера доступу перед кластером, який все ще покладається на дозволи Kubernetes під капотом. У будь-якій моделі Kubernetes RBAC залишається джерелом істини щодо того, що дозволяє API Kubernetes і в якому обсязі.
Брокер доступу додає елементи керування, які RBAC покриває погано. Наприклад, він може вирішувати, чи запит автоматично схвалюється або потребує ручного схвалення, чи може користувач виконувати команду, і які команди дозволені в сеансі. Він також може керувати членством у групах, щоб ви надавали дозволи групам замість окремих користувачів. Kubernetes RBAC може дозволяти дії, такі як pods/exec, але не може обмежити, які команди виконуються всередині сеансу exec.
З цією моделлю Kubernetes RBAC визначає дозволені дії для користувача або групи (наприклад, команди на підтримки в одному просторі імен). Рекомендується визначати правила доступу лише для груп або ServiceAccounts — ніколи для окремих користувачів. Брокер або постачальник ідентичності потім додає або видаляє користувачів з цієї групи за потреби.
Брокер також може застосовувати додаткову політику, наприклад, які команди дозволені в інтерактивному сеансі та які запити можуть бути автоматично схвалені або потребують ручного схвалення. Ця політика може зберігатися у файлі JSON або XML і підтримуватися через рецензування коду, тому оновлення проходять через формальний pull request і рецензуються так само, як будь-які інші зміни в робочому середовищі.
Приклад: роль налагодження для чергового в межах простору імен
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: oncall-debug
namespace: <namespace>
rules:
# Дізнатись, що працює
- apiGroups: [""]
resources: ["pods", "events"]
verbs: ["get", "list", "watch"]
# Читання журналів
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
# Інтерактивні дії налагодження
- apiGroups: [""]
resources: ["pods/exec", "pods/portforward"]
verbs: ["create"]
# Розуміння стану розгортання/контролера
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch"]
# Необов'язково: дозволити kubectl відлагоджувати ефемерні контейнери
- apiGroups: [""]
resources: ["pods/ephemeralcontainers"]
verbs: ["update"]
Прикріпіть роль до групи (а не до окремих користувачів), щоб членством можна було управляти через вашого провайдера ідентичності:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: oncall-debug
namespace: <namespace>
subjects:
- kind: Group
name: oncall-<team-name>
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: oncall-debug
apiGroup: rbac.authorization.k8s.io
2) Короткострокові облікові дані, привʼязані до особи
Мета полягає в тому, щоб використовувати короткострокові облікові дані, привʼязані до особи, які чітко повʼязують сеанс з реальною людиною та швидко закінчуються. Ці облікові дані можуть включати ідентичність користувача та обсяг того, що йому дозволено робити. Вони зазвичай підписуються за допомогою приватного ключа, який залишається у інженера, наприклад, апаратно захищеного ключа (наприклад, YubiKey), тому їх не можна підробити без доступу до цього ключа.
Ви можете реалізувати це за допомогою автентифікації, вбудованої в Kubernetes (наприклад, клієнтські сертифікати або потік на основі OIDC), або дозволити брокеру доступу з попереднього розділу видавати короткострокові облікові дані від імені користувача. У багатьох налаштуваннях Kubernetes все ще використовує RBAC для застосування дозволів на основі автентифікованої особи та груп/тверджень. Якщо ви використовуєте брокера доступу, він також може кодувати додаткові обмеження обсягу в облікових даних і застосовувати їх під час сеансу, наприклад, до якого кластера або простору імен застосовується сеанс і які дії (або затверджені команди) дозволені для подів або вузлів. У будь-якому випадку облікові дані повинні бути підписані сертифікаційним центром (CA), і цей CA слід регулярно оновлювати (наприклад, щоквартально), щоб обмежити довгострокові ризики.
Варіант A: короткострокові токени OIDC
Багато керованих кластерів Kubernetes (що надаються хмарними провайдерами) вже надають короткострокові токени. Головне — переконатися, що ваш kubeconfig автоматично оновлює їх замість того, щоб копіювати довгостроковий токен у файл.
Наприклад:
users:
- name: oncall
user:
exec:
apiVersion: client.authentication.k8s.io/v1
command: cred-helper
args: ["--cluster=prod", "--ttl=30m"]
Варіант B: короткострокові клієнтські сертифікати (X.509)
Якщо ваш API-сервер (або брокер доступу з попереднього розділу) налаштований на довіру до клієнтського CA, ви можете використовувати короткострокові клієнтські сертифікати для доступу до відлагодження. Ідея полягає в наступному:
- Приватний ключ створюється і зберігається на машині інженера (бажано з апаратною підтримкою, наприклад, ключ, який неможливо експортувати, у YubiKey/PIV токені)
- Видається короткостроковий сертифікат (часто через API CertificateSigningRequest або вашого брокера доступу з попереднього розділу, з TTL).
- RBAC зіставляє автентифіковану особу з мінімальною роллю
Це просто реалізувати за допомогою API Kubernetes CertificateSigningRequest.
Згенеруйте ключ і CSR локально:
# Згенеруйте приватний ключ.
# Це можна зробити всередині апаратного токена;
# OpenSSL та кілька подібних інструментів підтримують це.
openssl genpkey -algorithm Ed25519 -out oncall.key
openssl req -new -key oncall.key -out oncall.csr \
-subj "/CN=user/O=oncall-payments"
Створіть CertificateSigningRequest з коротким терміном дії:
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: oncall-<user>-20260218
spec:
request: <base64-encoded oncall.csr>
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 1800 # 30 minutes
usages:
- client auth
Після того як CSR буде затверджено та підписано, ви можете витягти виданий сертифікат і використовувати його разом із приватним ключем для автентифікації, наприклад через kubectl.
3) Використання шлюзу доступу "just-in-time" для виконання команд відлагодження
Після отримання короткострокових облікових даних ви можете використовувати їх для відкриття сеансу безпечного доступу до шлюзу доступу "just-in-time", часто доступного через SSH і створюваного за потреби. Якщо шлюз доступу доступний через SSH, поширеним підходом є видача інженеру короткострокового сертифіката користувача OpenSSH для сеансу. Шлюз довіряє вашому SSH CA, автентифікує інженера під час підключення, а потім застосовує затверджену політику сеансу перед виконанням викликів API Kubernetes від імені користувача. Сертифікати OpenSSH відокремлені від клієнтських сертифікатів Kubernetes X.509, тому зазвичай вони розглядаються як окремі рівні.
Отриманий сеанс також повинен бути обмежений, щоб його не можна було повторно використовувати поза затвердженою областю дії. Наприклад, шлюз або брокер можуть обмежити його до конкретного кластера та простору імен, а за бажанням до більш вузької цілі, такої як под або вузол. Таким чином, навіть якщо хтось спробує повторно використати доступ, він не працюватиме поза призначеною областю дії. Після встановлення сеансу шлюз виконує лише дозволені дії та записує, що сталося для аудиту.
Приклад: Привʼязки ролей у межах простору імен
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: jit-debug
namespace: <namespace>
annotations:
kubernetes.io/description: >
Colleagues performing semi-privileged debugging, with access provided
just in time and on demand.
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jit-debug
namespace: <namespace>
subjects:
- kind: Group
name: jit:oncall:<namespace> # зіставлено з короткостроковим обліковим записом (сертифікат/OIDC)
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: jit-debug
apiGroup: rbac.authorization.k8s.io
Ці обʼєкти RBAC та правила, які вони визначають, дозволяють відлагодження лише в межах зазначеного простору імен; спроби доступу до інших просторів імен не дозволяються.
Приклад: Привʼязки ролей у межах кластера
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jit-cluster-read
rules:
- apiGroups: [""]
resources: ["nodes", "namespaces"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jit-cluster-read
subjects:
- kind: Group
name: jit:oncall:cluster
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: jit-cluster-read
apiGroup: rbac.authorization.k8s.io
Ці правила RBAC надають доступ для читання в межах усього кластера (наприклад, до вузлів і просторів імен) і повинні використовуватися лише для робочих процесів, які дійсно потребують ресурсів, обмежених кластером.
Більш детальні обмеження, такі як «тільки цей под/вузол» або «тільки ці команди», зазвичай застосовуються шлюзом/брокером доступу під час сеансу, але Kubernetes також пропонує інші варіанти, такі як ValidatingAdmissionPolicy для обмеження записів і webhook authorization для користувацької авторизації за діями.
У середовищах з більш жорсткими правилами доступу можна додати додатковий, тимчасовий шар посередництва, щоб відокремити встановлення сеансу від виконання привілейованих дій. Обидва шари є тимчасовими, використовують облікові дані, привʼязані до ідентичності, та генерують незалежні журнали аудиту. Шар посередництва обробляє встановлення/передачу сеансу, а шар виконання виконує лише дозволені Kubernetes дії за RBAC. Це розділення може зменшити ризики, звузивши відповідальність, визначаючи область для облікових даних на кожному кроці та забезпечуючи завершення сеансу.
Посилання
- Авторизація
- Використання RBAC авторизації
- Автентифікація
- Сертифікати та запити на підпис сертифікатів
- Випуск сертифіката для клієнта Kubernetes API за допомогою CertificateSigningRequest
- Поради щодо контролю доступу на основі ролей
Відмова від відповідальності: Думки, висловлені в цьому дописі, належать виключно автору і не відображають погляди роботодавця автора або будь-якої іншої організації.