![Image](https://files.bool.dev/site/blog/c2e30238-ffd0-447b-95f4-4d08d1c8f700/3d8b511d-3bcc-4eb2-b733-1498d7945e04.png) Безопасность 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 на практике ![Image](https://devopscube.com/content/images/2025/05/image-55.png) ![Image](https://miro.medium.com/1%2A1M2aEs-x6C-NyXUJD88c6Q.png) --- ## 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|осторожно| ---