Русский
Русский
English
Статистика
Реклама

Перевод Как предоставить доступ к кластеру Kubernetes с помощью клиентского сертификата простое руководство

Источник

Предположим, мы создали кластер Kubernetes. И кто-то из команды разработчиков хочет развернуть и протестировать на нем новое приложение. Как нам предоставить ему доступ в кластер?

Команда Kubernetes aaS Mail.ru Cloud Solutions перевела простое руководство по предоставлению доступа к новому кластеру Kubernetes, включая настройку аутентификации и привязку ролей. Автор показывает процесс, используя клиентский сертификат x509.

Управление пользователями в Kubernetes

Для управления кластером Kubernetes и запущенными в нем приложениями обычно используют утилиту kubectl или веб-интерфейс. Под капотом эти инструменты вызывают API Server: HTTP Rest API, открывающий конечные точки управления кластером. Этот HTTP API хорошо документирован посмотрите сами.

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

Аутентификацию выполняют с помощью плагинов, есть плагины с разными механизмами:

  • сертификаты клиентов о них в этой статье;

  • Bearer tokens (персональные токены);

  • аутентифицирующий прокси;

  • базовая аутентификация HTTP.

В зависимости от механизма аутентификации плагин ищет информацию о пользователе в определенных местах. Например, для аутентификации по сертификату клиента идентификацию пользователя (идентификатор, имя, адрес электронной почты и так далее) указывают в поле Common Name (CN) сертификата. Информацию о группе, если она есть, добавляют в поле Organisation (O).

Внутри кластера Kubernetes нет ни ресурсов пользователей, ни ресурсов групп. Их обрабатывают вне кластера и предоставляют с каждым запросом, который направляют на сервер API я проиллюстрирую это ниже.

Некоторые соображения и допущения

  1. Кластер используют несколько команд или клиентов (подход с несколькими пользователями), так что нужно изолировать рабочую нагрузку для каждого клиента. Мы создадим пространство имен для команды разработчиков, в которую входит разработчик, которому надо дать доступ (пусть его зовут Дейв). Это пространство имен мы назовем development.

  2. Дейву предстоит развернуть стандартные ресурсы Kubernetes. Затем он получит право создавать, просматривать, обновлять, получать список и удалять ресурсы Deployment и Service. Дополнительные права можно предоставить при необходимости, но они ограничены пространством имен development.

  3. Скорее всего, членам команды Дейва потребуется такой же уровень доступа. Мы заведем группу dev и предоставим права на уровне группы.

  4. Дейву потребуется kubectl, а также openssl он сгенерирует закрытый ключ и запрос на вход с сертификатом.

Создание закрытого ключа и запроса на подпись сертификата (CSR)

Сначала Дейв генерирует закрытый ключ RSA и CSR. Закрытый ключ можно создать с помощью команды:

$ openssl genrsa -out dave.key 4096

С CSR немного сложнее, поскольку Дейву нужно убедиться, что он:

  1. использует свое имя в поле Common Name (CN) оно требуется для идентификации на сервере API;

  2. использует имя группы в поле Organisation (O) это имя нужно для идентификации группы на сервере API.

Ниже файл конфигурации, который Дейв использует для создания CSR:

[ req ]default_bits = 2048prompt = nodefault_md = sha256distinguished_name = dn[ dn ]CN = daveO = dev[ v3_ext ]authorityKeyIdentifier=keyid,issuer:alwaysbasicConstraints=CA:FALSEkeyUsage=keyEncipherment,dataEnciphermentextendedKeyUsage=serverAuth,clientAuth

Примечание: запись clientAuth в поле extendedKeyUsage нужна, поскольку сертификат будут использовать для идентификации клиента.

С помощью указанного файла конфигурации, сохраненного в csr.cnf, CSR можно создать одной командой:

$ openssl req -config ./csr.cnf -new -key dave.key -nodes -out dave.csr

Создав файл .csr, Дейв отправляет его администраторам, чтобы они подписали его с помощью центра сертификации кластера.

Подписание CSR

После подписания файла .csr выпускается сертификат. Он будет использоваться для аутентификации запросов, который Дейв отправит на сервер API.

Начнем с создания ресурса Kubernetes Certificate Signing Request.

Примечание мы могли создать управляемый кластер (например, в DigitalOcean, Google GKE, Microsoft Azure, Mail.ru Cloud Solutions или другой платформе) или собственный (допустим, kubeadm или kubespray). Процесс подписи везде устроен одинаково.

Мы используем следующую спецификацию и сохраняем ее в csr.yaml:

apiVersion: certificates.k8s.io/v1beta1kind: CertificateSigningRequestmetadata:name: mycsrspec:groups:- system:authenticatedrequest: ${BASE64_CSR}usages:- digital signature- key encipherment- server auth- client auth

Значение ключа request содержимое переменной окружения BASE64_CSR. Первый шаг получить кодированный в base64 файл .csr, созданный Дейвом. Затем использовать envsubst, чтобы заменить значения этой переменной перед созданием ресурса.

# Кодируем файл .csr в base64$ export BASE64_CSR=$(cat ./dave.csr | base64 | tr -d '\n')# Подставляем переменную env BASE64_CSR и создаем ресурс CertificateSigninRequest$ cat csr.yaml | envsubst | kubectl apply -f -

Проверяем статус созданного CSR мы видим, что он находится в состоянии ожидания:

# Проверяем статус созданного CSR$ kubectl get csrNAME        AGE   REQUESTOR            CONDITIONmycsr       9s    28b93...d73801ee46   Pending

Подтверждаем CSR с помощью команды:

$ kubectl certificate approve mycsr

Еще раз проверяем статус CSR теперь он одобрен:

$ kubectl get csrNAME        AGE   REQUESTOR            CONDITIONmycsr       9s    28b93...d73801ee46   Approved,Issued

Сертификат создан, теперь извлечем его из ресурса CSR, сохраним в файле с именем dave.crt и проверим, что внутри:

$ kubectl get csr mycsr -o jsonpath='{.status.certificate}' \| base64 --decode > dave.crt

Следующая команда openssl показывает: сертификат подписан центром сертификации кластера DigitalOcean (часть Issuer). Subject содержит dave в полях CN (CommonName) и O (Organisation), как указал Дейв при создании файла .csr:

$ openssl x509 -in ./dave.crt -noout -textCertificate:Data:    Version: 3 (0x2)    Serial Number:        48:29:cf:ae:d6:...:09:33:ef:14:58Signature Algorithm: sha256WithRSAEncryption    Issuer: O=DigitalOcean, CN=k8saas Cluster CA    Validity        Not Before: Jun  3 07:56:00 2019 GMT        Not After : Jun  2 07:56:00 2020 GMT    Subject: O=dev, CN=dave    Subject Public Key Info:        Public Key Algorithm: rsaEncryption            Public-Key: (4096 bit)            Modulus:...

Примечание в примере используем управляемый кластер Kubernetes, созданный в DigitalOcean мы видим это в Issuer кластера. На другой платформе будет похоже.

Создание пространства имен

Начинаем с создания пространства имен development благодаря этому ресурсы, которые развернут Дейв и его команда, будут изолированы от остальной рабочей нагрузки кластера.

Его можно создать с помощью простой команды:

$ kubectl create ns development

или с помощью файла dev-ns.yaml:

apiVersion: v1kind: Namespacemetadata:name: development

Применяем dev-ns.yaml с помощью команды:

$ kubectl apply -f dev-ns.yaml

Примечание рекомендую создать ресурс ResourceQuota и связать его с пространством имен. Это позволит ограничить объем CPU и ОЗУ, которые можно использовать в пространстве имен.

Настройка правил RBAC

С помощью сертификата Дейв может пройти аутентификацию на сервере API. Но пока у него нет прав, так что он не может делать многие вещи. Давайте дадим ему права создавать, получать список, обновлять, просматривать и удалять ресурсы Deployment и Service в пространстве имен dev.

Ресурсы, задействованные в управлении доступом к базе ролей Kubernetes (RBAC)Ресурсы, задействованные в управлении доступом к базе ролей Kubernetes (RBAC)

Коротко: роль (то же самое справедливо и для ClusterRole) содержит список правил. Каждое правило определяет действия, которые могут быть выполнены (например: list, get, watch) со списком ресурсов (например: Pod, Service, Secret) в apiGroups (например: core, apps/v1). Роль определяет права для конкретного пространства имен, область ClusterRole весь кластер.

Создание роли

Создадим ресурс Role со следующей спецификацией:

kind: RoleapiVersion: rbac.authorization.k8s.io/v1metadata:namespace: developmentname: devrules:- apiGroups: [""]resources: ["pods", "services"]verbs: ["create", "get", "update", "list", "delete"]- apiGroups: ["apps"]resources: ["deployments"]verbs: ["create", "get", "update", "list", "delete"]

Ресурсы подов и служб принадлежат основной группе API (значение ключа apiGroups пустая строка), а ресурсы развертывания группе API приложений. Для этих двух групп apiGroup мы определили список ресурсов и действия, которые нужно авторизовать на этих ресурсах.

Строки сохраняем в файл role.yaml, для создания роли используем команду:

$ kubectl apply -f role.yaml

Создание RoleBinding

Назначение RoleBinding связать роль, то есть список разрешенных действий, с пользователем или группой. Чтобы у Дейва были права, указанные в созданной выше роли, мы привязываем его к этой роли. Для этого используем ресурс RoleBinding:

kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:name: devnamespace: developmentsubjects:- kind: Username: daveapiGroup: rbac.authorization.k8s.ioroleRef:kind: Rolename: devapiGroup: rbac.authorization.k8s.io

Эта RoleBinding связывает:

  • субъект пользователь Дейв;

  • роль: с именем dev, которая позволяет создавать, просматривать, обновлять, получать список, удалять ресурсы Deployment и Service.

Примечание: поскольку Дейв входит в группу разработчиков, то можно использовать следующую привязку RoleBinding для связи роли с группой, а не отдельным пользователем. Помните: информация о группе указывается в поле Organisation (O) сертификата, его отправляют с каждым запросом.

kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:name: devnamespace: developmentsubjects:- kind: Groupname: devapiGroup: rbac.authorization.k8s.ioroleRef:kind: Rolename: devapiGroup: rbac.authorization.k8s.io

Мы сохранили спецификацию ресурса RoleBinding в файле role-binding.yaml и создаем его с помощью команды:

$ kubectl apply -f role-binding.yaml

Создание файла конфигурации KubeConfig

Все настроено. Теперь отправляем Дейву информацию, которая необходима для настройки его локального клиента kubectl для связи с нашим кластером. Сначала создаем файл kubeconfig.tpl со следующим содержанием, его мы будем использовать в качестве шаблона:

apiVersion: v1kind: Configclusters:- cluster:certificate-authority-data: ${CLUSTER_CA}server: ${CLUSTER_ENDPOINT}name: ${CLUSTER_NAME}users:- name: ${USER}user:client-certificate-data: ${CLIENT_CERTIFICATE_DATA}contexts:- context:cluster: ${CLUSTER_NAME}user: davename: ${USER}-${CLUSTER_NAME}current-context: ${USER}-${CLUSTER_NAME}

Чтобы создать kubeconfig из этого шаблона, нужно сначала установить переменные среды:

# Имя пользователя$ export USER="dave"# Имя кластера (полученное из текущего контекста)$ export CLUSTER_NAME=$(kubectl config view --minify -o jsonpath={.current-context})# Сертификат клиента$ export CLIENT_CERTIFICATE_DATA=$(kubectl get csr mycsr -o jsonpath='{.status.certificate}')# Данные центра сертификации кластера$ export CLUSTER_CA=$(kubectl config view --raw -o json | jq -r '.clusters[] | select(.name == "'$(kubectl config current-context)'") | .cluster."certificate-authority-data"')# Точка входа API$ export CLUSTER_ENDPOINT=$(kubectl config view --raw -o json | jq -r '.clusters[] | select(.name == "'$(kubectl config current-context)'") | .cluster."server"')

Подставляем их, используя удобную утилиту envsubst:

$ cat kubeconfig.tpl | envsubst > kubeconfig

Отправляем Дейву файл kubeconfig. Чтобы взаимодействовать с кластером, ему достаточно добавить в файл свой закрытый ключ.

Использование контекста

Чтобы использовать kubeconfig, Дейв устанавливает переменную среды KUBECONFIG, указав путь к файлу.

$ export KUBECONFIG=$PWD/kubeconfig

Примечание: есть разные способы использовать конфигурации Kubernetes. Можно установить переменную среду KUBECONFIG, добавить новую запись в файл $ HOME/.kube/config по умолчанию или использовать флаг --kubeconfig для каждой команды kubectl.

Чтобы добавить закрытый ключ dave.key, Дейв использует команду:

$ kubectl config set-credentials dave \--client-key=$PWD/dave.key \--embed-certs=true

Команда создает ключ client-key-data в записи пользователя файла kubeconfig и устанавливает dave.key в кодировку base64 в качестве значения.

Если все успешно, Дейв может проверить версию сервера (и клиента) с помощью команды:

$ kubectl versionClient Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.2", GitCommit:"66049e3b21efe110454d67df4fa62b08ea79a19b", GitTreeState:"clean", BuildDate:"2019-05-16T16:23:09Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"darwin/amd64"}Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.2", GitCommit:"66049e3b21efe110454d67df4fa62b08ea79a19b", GitTreeState:"clean", BuildDate:"2019-05-16T16:14:56Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}

Теперь проверим, позволяет ли связанная с Дейвом текущая роль отображать узлы кластера:

$ kubectl get nodesError from server (Forbidden): nodes is forbidden: User "dave" cannot list resource "nodes" in API group "" at the cluster scope

Конечно, нет! Но Дейв может что-то развертывать в кластере по крайней мере, в пространстве имен development. Давайте проверим это с помощью YAML-файла, который определяет Deployment на основе образа nginx и Service для его предоставления:

# www.yamlapiVersion: apps/v1kind: Deploymentmetadata:name: wwwnamespace: developmentspec:replicas: 3selector:matchLabels:    app: wwwtemplate:metadata:    labels:    app: wwwspec:    containers:    - name: nginx    image: nginx:1.14-alpine    ports:    - containerPort: 80---apiVersion: v1kind: Servicemetadata:name: wwwnamespace: developmentspec:selector:app: votetype: ClusterIPports:- port: 80targetPort: 80

Из результата следующей команды видно, что Дейв может создавать эти ресурсы в кластере:

$ kubectl apply -f www.yamldeployment.apps/www createdservice/www created

Дейв ограничен пространством имен development. Если он попытается получить список всех подов в пространстве имен по умолчанию, то получит сообщение об ошибке:

$ kubectl get podsError from server (Forbidden): pods is forbidden: User "dave" cannot list resource "pods" in API group "" in the namespace "default"

Еще он не может создавать другие ресурсы, кроме тех, к которым ему предоставили доступ. Например, мы можем попробовать следующую спецификацию ресурса типа Secret:

# credentials.yamlapiVersion: v1kind: Secretmetadata:name: mysecretnamespace: developmentdata:username: YWRtaW4=password: MWYyZDFlMmU2N2Rm

Давайте посмотрим, как Дейв попытается его создать:

$ kubectl apply -f credentials.yamlError from server (Forbidden): error when retrieving current configuration of:Resource: "/v1, Resource=secrets", GroupVersionKind: "/v1, Kind=Secret"Name: "mysecret", Namespace: "development"Object: &{map["apiVersion":"v1" "data":map["password":"MWYyZDFlMmU2N2Rm" "username":"YWRtaW4="] "kind":"Secret" "metadata":map["annotations":map["kubectl.kubernetes.io/last-applied-configuration":""] "name":"mysecret" "namespace":"development"]]}from server for: "credentials.yaml": secrets "mysecret" is forbidden: User "dave" cannot get resource "secrets" in API group "" in the namespace "development"

Заключение

Мы показали, как использовать сертификат клиента для авторизации пользователей в кластере Kubernetes. Можно настраивать аутентификацию другим способом, но этот довольно прост.

После настройки аутентификации мы использовали роль, чтобы определить некоторые права, ограниченные пространством имен, и привязать их к пользователю с помощью RoleBinding. Если нам нужно будет предоставить права для всего кластера, мы сможем использовать ресурсы ClusterRole и ClusterRoleBinding.

Что еще почитать:

  1. 90+ инструментов, без которых не обойтись при использовании Kubernetes.

  2. Основы безопасности внутри Kubernetes: 10 простых советов.

  3. Как устроен Kubernetes as a Service на платформе Mail.ru Cloud Solutions.

Источник: habr.com
К списку статей
Опубликовано: 03.02.2021 18:19:31
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании mail.ru group

Облачные вычисления

Devops

Kubernetes

K8s

Контейнеризация

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru