
Безопасность Kubernetes изначально проектировалась не как дополнительная функция, а как фундаментальная часть архитектуры системы. Kubernetes рассматривается как распределённая управляющая плоскость, которая запускает потенциально недоверенные рабочие нагрузки на доверенной инфраструктуре. Это означает, что система обязана чётко понимать, кто с ней взаимодействует и какие действия этому субъекту разрешены, независимо от того, является ли этим субъектом человек, сервис или автоматизированный агент.
Каждый запрос к Kubernetes API-серверу проходит два строго разделённых этапа. Сначала выполняется аутентификация, в ходе которой система определяет, кем является отправитель запроса. После этого выполняется авторизация, где Kubernetes решает, какие действия допустимы для уже аутентифицированной сущности. Эти этапы намеренно разделены. Аутентификация никогда не выдаёт прав, а авторизация никогда не устанавливает личность. Такое разделение позволяет Kubernetes поддерживать различные способы идентификации, не меняя логику управления доступом.
Одним из ключевых архитектурных решений Kubernetes является отсутствие встроенного управления пользователями. В системе нет базы пользователей, нет хранения паролей и нет команды для создания или удаления пользователей. Kubernetes не пытается быть системой управления идентификацией. Вместо этого он полностью полагается на внешние доказательства личности, такие как X.509-сертификаты, OIDC-токены или токены ServiceAccount. Это делает Kubernetes гибким, независимым от конкретного облака и легко интегрируемым с корпоративными системами аутентификации.
Сертификаты играют центральную роль в этой модели, поскольку они обеспечивают криптографически надёжную аутентификацию без передачи секретов. В отличие от паролей, закрытый ключ никогда не покидает сторону клиента и не передаётся по сети. Сервер проверяет подлинность клиента, используя открытый сертификат, подписанный доверенным центром сертификации. Такой подход идеально подходит для автоматизации, межсервисного взаимодействия и масштабируемых распределённых систем.
Когда Kubernetes принимает запрос с клиентским сертификатом, он извлекает информацию о личности прямо из сертификата. Поле Common Name интерпретируется как имя пользователя, а поля Organization — как группы, к которым этот пользователь принадлежит. Kubernetes не проверяет, существуют ли такие пользователи или группы в каком-либо внутреннем реестре. Он просто доверяет данным, содержащимся в сертификате, если этот сертификат подписан доверенным центром сертификации. Именно поэтому центр сертификации является абсолютным источником власти в кластере. Тот, кто контролирует закрытый ключ CA, способен создать сертификат с любыми именами и группами и тем самым получить любые полномочия.
Модель доверия Kubernetes полностью строится вокруг центра сертификации. Все удостоверения личности в системе существуют только потому, что они подписаны доверенным CA. После проверки цепочки доверия Kubernetes безоговорочно принимает информацию, содержащуюся в сертификате, и использует её для принятия решений об авторизации. Такая модель проста, быстра и детерминирована, но она требует строгого контроля над ключами CA и процессом выпуска сертификатов.
Авторизация в Kubernetes реализована с помощью RBAC и имеет полностью декларативный характер. Права доступа описываются в виде данных, а не логики. Роли определяют допустимые действия, а привязки связывают эти роли с конкретными личностями или группами. В RBAC отсутствуют условные конструкции, такие как проверка времени, IP-адресов или внешних атрибутов. Это сделано сознательно, чтобы решения об авторизации были предсказуемыми, воспроизводимыми и легко поддавались аудиту. Такой подход отлично сочетается с GitOps-моделью управления инфраструктурой.
Разграничение между Role и ClusterRole отражает ещё один фундаментальный принцип — важность области действия. В подавляющем большинстве случаев доступ должен ограничиваться пространством имён, так как namespace является естественной границей безопасности между командами и приложениями. Полномочия на уровне всего кластера предназначены в первую очередь для платформенных инженеров и системных компонентов. Эта модель стимулирует применение принципа наименьших привилегий и снижает риск случайных или злонамеренных действий.
Использование привязок вместо прямого назначения прав пользователям создаёт дополнительный уровень абстракции, который делает систему более устойчивой. Роли могут переиспользоваться, пользователи и группы могут меняться, а сами правила доступа остаются стабильными и понятными. Это значительно упрощает сопровождение, ревизию и аудит конфигураций безопасности.
Поскольку решения RBAC могут зависеть от множества факторов, Kubernetes предоставляет инструменты для предварительной проверки прав доступа. Команда kubectl auth can-i позволяет симулировать авторизационное решение без выполнения реального запроса. Это отражает философию Kubernetes, согласно которой контроль доступа должен быть проверяемым и прозрачным, а не скрытым или неявным.
Важно понимать, что RBAC решает только задачу контроля доступа к API Kubernetes. Он не защищает от уязвимостей внутри контейнеров, не предотвращает выход за пределы узла и не контролирует сетевой трафик между подами. RBAC является лишь одним слоем в многоуровневой модели безопасности, которая должна дополняться сетевыми политиками, admission-контроллерами, pod security-механизмами и инструментами runtime-защиты.
В целом модель безопасности Kubernetes можно сформулировать следующим образом. Сертификаты устанавливают личность через криптографическое доказательство. Центр сертификации определяет доверие. RBAC определяет полномочия в декларативной и проверяемой форме. Привязки соединяют доверенные личности с разрешёнными действиями. Kubernetes не пытается определить, кто вы как человек; он лишь проверяет, доверяет ли он представленной вами личности и что этой личности разрешено делать.
Именно такая архитектура позволяет Kubernetes масштабироваться от небольших лабораторных кластеров до крупных корпоративных и государственно-критичных систем. Делегирование идентификации внешним системам, строгая декларативная авторизация и опора на криптографическое доверие создают прочную основу для автоматизации, многоарендности и построения архитектур нулевого доверия.
## Аутентификация, сертификаты, kubeconfig и RBAC на практике


---
## 1. Большая архитектурная картина
В Kubernetes **доступ к API** проходит **два этапа**:
```
kubectl → Authentication → Authorization (RBAC) → API
```
|Этап|Что происходит|
|---|---|
|Authentication|Kubernetes понимает **КТО ты**|
|Authorization|Kubernetes решает **ЧТО тебе можно**|
> ❗ RBAC **НИКОГДА не работает**, если аутентификация не прошла.
---
## 2. kubeconfig — точка входа в Kubernetes
Начнём с просмотра текущего kubeconfig.
```bash
kubectl config view
```
### Пример вывода (упрощённо)
```yaml
clusters:
- name: default
cluster:
server: https://127.0.0.1:6443
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
users:
- name: default
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQo=
```
### Что скрыто?
По умолчанию `kubectl` **маскирует** чувствительные данные.
Чтобы увидеть ВСЁ:
```bash
kubectl config view --raw
```
---
## 3. certificate-authority-data — корень доверия
Извлекаем CA-сертификат:
```bash
CERTIFICATE_AUTHORITY_DATA=$(kubectl config view --raw \
| grep certificate-authority-data \
| awk -F': ' '{print $2}')
echo $CERTIFICATE_AUTHORITY_DATA
```
### Что это такое
- `certificate-authority-data` = **ca.crt**
- публичный сертификат
- **кому kubectl доверяет**
Декодируем base64:
```bash
echo $CERTIFICATE_AUTHORITY_DATA | base64 -d
```
Посмотрим содержимое сертификата:
```bash
echo $CERTIFICATE_AUTHORITY_DATA | base64 -d | openssl x509 -text --noout
```
### Пример вывода
```text
Issuer: CN = kubernetes
Subject: CN = kubernetes
Validity:
Not Before: Jan 1 00:00:00 2025 GMT
Not After : Jan 1 00:00:00 2035 GMT
```
### Комментарий
|Поле|Значение|
|---|---|
|Issuer|кто подписал (сам себя — CA)|
|Subject|имя CA|
|Validity|срок доверия|
> 🔐 Это **корень доверия всего кластера**
---
## 4. client-key-data — private key пользователя
Извлекаем закрытый ключ:
```bash
CLIENT_KEY_DATA=$(kubectl config view --raw \
| grep client-key-data \
| awk -F': ' '{print $2}')
echo $CLIENT_KEY_DATA | base64 -d
```
### Комментарий
- это **private key**
- **никогда** не передаётся по сети
- используется для **доказательства владения сертификатом**
> ❗ Потеря ключа = потеря личности
---
## 5. client-certificate-data — основа RBAC
Извлекаем клиентский сертификат:
```bash
CLIENT_CERTIFICATE_DATA=$(kubectl config view --raw \
| grep client-certificate-data \
| awk -F': ' '{print $2}')
echo $CLIENT_CERTIFICATE_DATA | base64 -d
```
Декодируем через OpenSSL:
```bash
echo $CLIENT_CERTIFICATE_DATA | base64 -d | openssl x509 -text --noout
```
### Пример вывода (КЛЮЧЕВОЕ)
```text
Subject:
CN = admin
O = system:masters
```
### Что это значит
|Поле|Интерпретация Kubernetes|
|---|---|
|CN|username|
|O|group|
> ❗ Kubernetes **НЕ хранит пользователей**
> Он **верит тому, что написано в сертификате**
---
## 6. system:masters — root-группа Kubernetes
Проверим ClusterRoleBindings:
```bash
kubectl get clusterrolebindings -o wide
```
### Пример вывода
```text
NAME ROLE GROUPS
cluster-admin ClusterRole/cluster-admin system:masters
```
Посмотрим, что такое `cluster-admin`:
```bash
kubectl describe clusterrole cluster-admin
```
### Вывод (фрагмент)
```text
Resources: *
Verbs: *
```
> 🔥 Любой пользователь в группе `system:masters` = **root в кластере**
---
## 7. kubectl auth can-i — рентген RBAC
```bash
kubectl auth can-i '*' '*'
```
### Ответ
```text
yes
```
Проверка «как если бы»:
```bash
kubectl auth can-i '*' '*' \
--as=batman \
--as-group=cluster-superheroes
```
> Kubernetes **не создаёт пользователя**, а **симулирует запрос**
---
## 8. Создание своей супер-группы
### 8.1 ClusterRole
```bash
kubectl create clusterrole cluster-superhero \
--verb='*' \
--resource='*'
```
|Атрибут|Значение|
|---|---|
|verb='*'|любые действия|
|resource='*'|любые ресурсы|
---
### 8.2 ClusterRoleBinding
```bash
kubectl create clusterrolebinding cluster-superhero \
--clusterrole=cluster-superhero \
--group=cluster-superheroes
```
|Атрибут|Значение|
|---|---|
|clusterrole|что разрешено|
|group|кому разрешено|
---
## 9. Создание пользователя через сертификаты
### 9.1 Генерация ключа
```bash
openssl genrsa -out batman.key 4096
```
- создаёт RSA private key
- **личность пользователя**
---
### 9.2 CSR — запрос на подпись
```bash
openssl req -new \
-key batman.key \
-out batman.csr \
-subj "/CN=batman/O=cluster-superheroes" \
-sha256
```
|Поле|Значение|
|---|---|
|CN|username|
|O|group|
---
## 10. Kubernetes CSR API
Создаём объект CSR:
```yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: batman
spec:
request: <base64 CSR>
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
```
Применяем:
```bash
kubectl apply -f batman-csr-request.yaml
```
Проверяем:
```bash
kubectl get csr
```
```text
NAME AGE SIGNERNAME REQUESTOR CONDITION
batman 5s kubernetes.io/kube-apiserver-client admin Pending
```
---
### 10.1 Одобрение
```bash
kubectl certificate approve batman
```
```bash
kubectl get csr
```
```text
batman Approved,Issued
```
---
### 10.2 Получение сертификата
```bash
kubectl get csr batman \
-o jsonpath='{.status.certificate}' \
| base64 -d > batman.crt
```
Проверка:
```bash
openssl x509 -in batman.crt -text -noout
```
---
## 11. Создание kubeconfig для пользователя
```bash
kubectl config set-credentials batman \
--client-certificate=batman.crt \
--client-key=batman.key \
--embed-certs=true
```
```bash
kubectl config set-context default \
--cluster=default \
--user=batman
```
```bash
kubectl config use-context default
```
---
## 12. Проверка доступа
```bash
KUBECONFIG=batman.config kubectl get nodes
```
```bash
KUBECONFIG=batman.config kubectl run nginx --image=nginx
```
```bash
KUBECONFIG=batman.config kubectl delete pod nginx --now
```
✔ Работает → RBAC корректен
---
## 13. Roles vs ClusterRoles
|Role|ClusterRole|
|---|---|
|namespace scoped|cluster scoped|
|безопаснее|опаснее|
|default choice|осторожно|
---