Стадия жизненного цикла модуля: General Availability
Пример назначения прав администратору кластера
Пример использует экспериментальную ролевую модель.
Для назначения прав администратору кластера используйте роль d8:manage:all:manager в ClusterRoleBinding.
Пример назначения прав администратору кластера (User jane):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admin-jane
subjects:
- kind: User
name: jane.doe@example.com
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: d8:manage:all:manager
apiGroup: rbac.authorization.k8s.io
Пример назначения прав сетевому администратору
Пример использует экспериментальную ролевую модель.
Для назначения прав сетевому администратору на управление сетевой подсистемой кластера используйте роль d8:manage:networking:manager в ClusterRoleBinding.
Пример назначения прав сетевому администратору (User jane):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: network-admin-jane
subjects:
- kind: User
name: jane.doe@example.com
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: d8:manage:networking:manager
apiGroup: rbac.authorization.k8s.io
Пример назначения административных прав пользователю в рамках пространства имён
Пример использует экспериментальную ролевую модель.
Для назначения прав на управление ресурсами приложений в рамках пространства имён, но без возможности настройки модулей DKP, используйте роль d8:use:role:admin в RoleBinding в соответствующем пространстве имён.
Пример назначения прав разработчику приложений (User app-developer) в пространстве имён myapp:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: myapp-developer
namespace: myapp
subjects:
- kind: User
name: app-developer@example.com
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: d8:use:role:admin
apiGroup: rbac.authorization.k8s.io
Пример ClusterAuthorizationRule
apiVersion: deckhouse.io/v1
kind: ClusterAuthorizationRule
metadata:
name: test-rule
spec:
subjects:
- kind: User
name: some@example.com
- kind: ServiceAccount
name: gitlab-runner-deploy
namespace: d8-service-accounts
- kind: Group
name: some-group-name
accessLevel: PrivilegedUser
portForwarding: true
# Опция доступна только при включенном режиме enableMultiTenancy.
allowAccessToSystemNamespaces: false
# Опция доступна только при включенном режиме enableMultiTenancy.
namespaceSelector:
labelSelector:
matchExpressions:
- key: stage
operator: In
values:
- test
- review
matchLabels:
team: frontend
Субъект типа User или Group сопоставляется по имени с идентичностью пользователя из токена. При этом локально управляемая идентичность не отличается от полученной от внешнего провайдера аутентификации. По этой причине нельзя создать ресурс User со значением spec.email или Group со значением spec.name, совпадающим с субъектом существующего правила ClusterAuthorizationRule. Это предотвращает незаметное предоставление прав идентичности.
Если совпадение сделано намеренно, например, если правило ClusterAuthorizationRule написано заранее, установите на User или Group аннотацию user-authz.deckhouse.io/allow-authorization-rule-collision: "true".
Для субъектов типа User указывайте email в нижнем регистре. Он записывается в токен в нижнем регистре, поэтому, например, субъект Admin@Example.com не совпадёт с admin@example.com. Имена субъектов типа Group сравнивается точно, поскольку имена групп не приводятся к нижнему регистру.
Ограничение действует только при создании ресурсов User и Group и не запрещает добавлять существующих пользователей и группы в ClusterAuthorizationRule. Если соответствующий User или Group уже существует, после добавления его в правило права будут предоставлены сразу.
Пример выдачи прав на все неймспейсы
Пример относится к текущей ролевой модели.
В режиме multi-tenancy (userAuthz.enableMultiTenancy) ограничение доступа по неймспейсам задаётся полями ресурса ClusterAuthorizationRule.
Варианты настройки:
-
Разрешить доступ во все неймспейсы, включая системные (
kube-*,d8-*,loghouse,defaultи т. п.). Чтобы разрешить доступ во все неймспейсы, включая системные, укажитеspec.namespaceSelector.matchAny: true. Если параметрnamespaceSelectorзадан, значенияlimitNamespacesиallowAccessToSystemNamespacesигнорируются.Пример:
apiVersion: deckhouse.io/v1 kind: ClusterAuthorizationRule metadata: name: all-namespaces-including-system spec: subjects: - kind: User name: user@example.com accessLevel: Editor namespaceSelector: matchAny: true -
Разрешить доступ во все неймспейсы, кроме системных. Чтобы разрешить пользователю доступ во все неймспейсы, кроме системных, при создании ClusterAuthorizationRule не указывайте ни
namespaceSelector, ниlimitNamespaces, ниallowAccessToSystemNamespaces. Перечень системных неймспейсов — в описании полей CR.
Уровень доступа
SuperAdminне снимает ограничения по неймспейсам, заданные в параметрахnamespaceSelectorиlimitNamespaces. При необходимости предоставления доступа ко всем неймспейсам задайте область явно, в том числе черезnamespaceSelector.matchAny.
Если одному субъекту соответствует несколько ресурсов ClusterAuthorizationRule, набор разрешённых неймспейсов объединяется; эффективный accessLevel — самый сильный среди всех подходящих правил. Подробнее — в FAQ.
Ограничения по неймспейсам из ClusterAuthorizationRule реализованы в цепочке авторизации с вебхуком. Если вебхук недоступен, эти ограничения не применяются, пока вебхук снова не станет доступен. Подробнее — в описании модуля.
Создание пользователя
В Kubernetes есть две категории пользователей:
- ServiceAccount’ы, учёт которых ведёт сам Kubernetes через API.
- Остальные пользователи и группы, учёт которых ведёт не сам Kubernetes, а некоторый внешний софт, который настраивает администратор кластера, — существует множество механизмов аутентификации и, соответственно, множество способов заводить пользователей. В настоящий момент поддерживаются способы аутентификации:
- Через модуль
user-authn. Модуль поддерживает следующие внешние провайдеры и протоколы аутентификации: GitHub, GitLab, Atlassian Crowd, BitBucket Cloud, Crowd, LDAP, OIDC. Подробнее — в документации модуляuser-authn. - С помощью сертификатов.
- Через модуль
При выпуске сертификата для аутентификации нужно указать в нём имя (CN=<имя>), необходимое количество групп (O=<группа>) и подписать его с помощью корневого CA-кластера. Именно этим механизмом вы аутентифицируетесь в кластере, когда, например, используете kubectl на master-узле.
Создание ServiceAccount для сервера и предоставление ему доступа
Создание ServiceAccount с доступом к Kubernetes API может потребоваться, например, при настройке развёртывания приложений через CI-системы.
-
Создайте ServiceAccount, например в пространстве имён
d8-service-accounts:d8 k create -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: gitlab-runner-deploy namespace: d8-service-accounts --- apiVersion: v1 kind: Secret metadata: name: gitlab-runner-deploy-token namespace: d8-service-accounts annotations: kubernetes.io/service-account.name: gitlab-runner-deploy type: kubernetes.io/service-account-token EOF -
Дайте необходимые ServiceAccount-права (используя custom resource ClusterAuthorizationRule):
d8 k create -f - <<EOF apiVersion: deckhouse.io/v1 kind: ClusterAuthorizationRule metadata: name: gitlab-runner-deploy spec: subjects: - kind: ServiceAccount name: gitlab-runner-deploy namespace: d8-service-accounts accessLevel: SuperAdmin # Опция доступна только при включенном режиме enableMultiTenancy. allowAccessToSystemNamespaces: true EOFЕсли в конфигурации Deckhouse включён режим мультитенантности (в параметре
enableMultiTenancy), настройте доступные для ServiceAccount пространства имён (в параметреnamespaceSelector). -
Определите значения переменных (они будут использоваться далее), выполнив следующие команды (подставьте свои значения):
export CLUSTER_NAME=my-cluster export USER_NAME=gitlab-runner-deploy.my-cluster export CONTEXT_NAME=${CLUSTER_NAME}-${USER_NAME} export FILE_NAME=kube.config -
Сгенерируйте секцию
clusterв файле конфигурации kubectl:Используйте один из следующих вариантов доступа к API-серверу кластера:
- Если есть прямой доступ до API-сервера:
-
Получите сертификат CA-кластера Kubernetes:
d8 k get cm kube-root-ca.crt -o jsonpath='{ .data.ca\.crt }' > /tmp/ca.crt -
Сгенерируйте секцию
cluster(используется IP-адрес API-сервера для доступа):d8 k config set-cluster $CLUSTER_NAME --embed-certs=true \ --server=https://$(d8 k get ep kubernetes -o json | jq -rc '.subsets[0] | "\(.addresses[0].ip):\(.ports[0].port)"') \ --certificate-authority=/tmp/ca.crt \ --kubeconfig=$FILE_NAME
-
- Если прямого доступа до API-сервера нет, используйте один следующих вариантов:
- включите доступ к API-серверу через Ingress-контроллер (параметр publishAPI) и укажите адреса, с которых будут идти запросы (параметр whitelistSourceRanges);
- укажите адреса, с которых будут идти запросы, в отдельном Ingress-контроллере (параметр acceptRequestsFrom).
-
Если используется непубличный CA:
-
Получите сертификат CA из секрета с сертификатом, который используется для домена
api.%s:d8 k -n d8-user-authn get secrets -o json \ $(d8 k -n d8-user-authn get ing kubernetes-api -o jsonpath="{.spec.tls[0].secretName}") \ | jq -rc '.data."ca.crt" // .data."tls.crt"' \ | base64 -d > /tmp/ca.crt -
Сгенерируйте секцию
cluster(используется внешний домен и CA для доступа):d8 k config set-cluster $CLUSTER_NAME --embed-certs=true \ --server=https://$(d8 k -n d8-user-authn get ing kubernetes-api -ojson | jq '.spec.rules[].host' -r) \ --certificate-authority=/tmp/ca.crt \ --kubeconfig=$FILE_NAME
-
-
Если используется публичный CA. Сгенерируйте секцию
cluster(используется внешний домен для доступа):d8 k config set-cluster $CLUSTER_NAME \ --server=https://$(d8 k -n d8-user-authn get ing kubernetes-api -ojson | jq '.spec.rules[].host' -r) \ --kubeconfig=$FILE_NAME
- Если есть прямой доступ до API-сервера:
-
Сгенерируйте секцию
userс токеном из секрета ServiceAccount в файле конфигурации kubectl:d8 k config set-credentials $USER_NAME \ --token=$(d8 k -n d8-service-accounts get secret gitlab-runner-deploy-token -o json |jq -r '.data["token"]' | base64 -d) \ --kubeconfig=$FILE_NAME -
Сгенерируйте контекст в файле конфигурации kubectl:
d8 k config set-context $CONTEXT_NAME \ --cluster=$CLUSTER_NAME --user=$USER_NAME \ --kubeconfig=$FILE_NAME -
Установите сгенерированный контекст как используемый по умолчанию в файле конфигурации kubectl:
d8 k config use-context $CONTEXT_NAME --kubeconfig=$FILE_NAME
Создание пользователя с помощью клиентского сертификата
Этот способ рекомендуется использовать для системных нужд (аутентификация kubelet’ов, компонентов control plane и пр.). Если нужно создать «обычного» пользователя (например, с доступом через консоль, kubectl и т.д.), используйте генерацию kubeconfig.
При создании пользователя с помощью клиентского сертификата можно использовать OpenSSL или Kubernetes API (объект CertificateSigningRequest).
Сертификаты, выпущенные любым из этих способов, отозвать нельзя. В случае компрометации сертификата потребуется убрать все права этого пользователя (это может быть сложно, если пользователь добавлен в какие-нибудь группы: придётся также удалять все соответствующие группы).
Создание пользователя с помощью сертификата, выпущенного через OpenSSL
При использовании этого способа учитывайте риски безопасности.
ca.crt и ca.keyне должны покидать master-узел: подписывайте CSR только на нём.
При подписании CSR вне master-узла есть риск компрометации корневого сертификата кластера.
Особенности этого способа:
- Клиентский сертификат должен подписываться на master-узле, чтобы не допустить компрометации кластерного сертификата.
- Необходим доступ к CA-ключу кластера (
ca.key). Подписывать сертификаты может только администратор кластера.
Чтобы создать пользователя с помощью клиентского сертификата, выпущенного через OpenSSL, выполните следующие шаги:
- Получите корневой сертификат кластера (
ca.crtиca.key). -
Сгенерируйте ключ пользователя:
openssl ecparam -name prime256v1 -genkey -out myuser.key -
Создайте CSR, указав в нём имя пользователя
myuser, который состоит в группахmygroup1иmygroup2:openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser/O=mygroup1/O=mygroup2" -
Загрузите созданный на предыдущем шаге CSR (в этом примере —
myuser.csr) на master-узел и подпишите его корневым сертификатом кластера. Пример команды для подписания CSR на мастер-узле (убедитесь, что в команде указаны верные для вашего случая пути кmyuser.csr,ca.crtиca.key):openssl x509 -req -in myuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out myuser.crt -days 10
Полученный сертификат можно указывать в конфигурационном файле:
cat << EOF
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: $(cat /etc/kubernetes/pki/ca.crt | base64 -w0)
server: https://<хост кластера>:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: myuser
name: myuser@kubernetes
current-context: myuser@kubernetes
kind: Config
preferences: {}
users:
- name: myuser
user:
client-certificate-data: $(cat myuser.crt | base64 -w0)
client-key-data: $(cat myuser.key | base64 -w0)
EOF
Создание пользователя с помощью сертификата, выпущенного через Kubernetes API
Это более безопасный способ, т.к. для подписания сертификата используется специальный API kubernetes.
Особенности этого способа:
- Подписание сертификата через Kubernetes API: CSR отправляется на подпись через API и прямой доступ к
ca.keyне требуется. - Выпускать клиентские сертификаты может не только администратор кластера. Право на создание CSR и их подписание можно назначить определенному пользователю.
Чтобы создать пользователя с помощью клиентского сертификата, выпущенного через Kubernetes API, выполните следующие шаги:
-
Сгенерируйте ключ пользователя:
openssl ecparam -name prime256v1 -genkey -out myuser.key -
Создайте CSR, указав в нём имя пользователя
myuser, который состоит в группахmygroup1иmygroup2:openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser/O=mygroup1/O=mygroup2" -
Создайте манифест объекта CertificateSigningRequest и сохраните его в файл (в этом примере —
csr.yaml):В поле
requestукажите содержимое CSR, созданного на предыдущем этапе, закодированное в Base64.apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: demo-client-cert spec: request: # CSR в Base64 signerName: "kubernetes.io/kube-apiserver-client" expirationSeconds: 7200 usages: - "digital signature" - "client auth" -
Примените манифест, чтобы создать запрос на подпись сертификата:
d8 k apply -f csr.yaml -
Убедитесь, что сертификат подтвержден:
d8 k get csr demo-client-certЕсли сертификат подтвержден, в колонке
CONDITIONу него будет значениеApproved,Issued. Пример вывода:NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION demo-client-cert 8m24s kubernetes.io/kube-apiserver-client kubernetes-admin 120m Approved,IssuedЕсли сертификат не подтвердился автоматически, подтвердите его:
d8 k certificate approve demo-client-certПосле этого убедитесь, что сертификат подтвержден.
-
Извлеките закодированный сертификат из CSR с именем
demo-client-cert, декодируйте его из Base64 и сохраните в файл (в этом примере —myuser.crt), созданный на шаге 2:d8 k get csr demo-client-cert -ojsonpath="{.status.certificate}" | base64 -d > myuser.crt
Полученный сертификат необходимо указать в конфигурационном файле:
cat << EOF
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: $(cat /etc/kubernetes/pki/ca.crt | base64 -w0)
server: https://<хост кластера>:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: myuser
name: myuser@kubernetes
current-context: myuser@kubernetes
kind: Config
preferences: {}
users:
- name: myuser
user:
client-certificate-data: $(cat myuser.crt | base64 -w0)
client-key-data: $(cat myuser.key | base64 -w0)
EOF
Предоставление доступа созданному пользователю
Для предоставления доступа созданному пользователю создайте ClusterAuthorizationRule.
Пример ClusterAuthorizationRule:
apiVersion: deckhouse.io/v1
kind: ClusterAuthorizationRule
metadata:
name: myuser
spec:
subjects:
- kind: User
name: myuser
accessLevel: PrivilegedUser
portForwarding: true
Настройка kube-apiserver для работы в режиме multi-tenancy
Режим multi-tenancy, позволяющий ограничивать доступ к пространству имён, включается параметром enableMultiTenancy модуля.
Работа в режиме multi-tenancy требует включения плагина авторизации Webhook и выполнения настройки kube-apiserver. Все необходимые для работы режима multi-tenancy действия выполняются автоматически модулем control-plane-manager, никаких ручных действий не требуется.
Изменения манифеста kube-apiserver, которые произойдут после включения режима multi-tenancy:
- настройка цепочки авторизации через structured authorization configuration (
--authorization-config=/etc/kubernetes/deckhouse/extra-files/authorization-config.yaml) с авторизаторамиNode,WebhookиRBAC; - создание
kubeconfigдля authorization webhook по пути/etc/kubernetes/deckhouse/extra-files/webhook-config.yaml; -
добавление
volumeMounts:- name: authorization-webhook-config mountPath: /etc/kubernetes/authorization-webhook-config.yaml readOnly: true -
добавление
volumes:- name: authorization-webhook-config hostPath: path: /etc/kubernetes/authorization-webhook-config.yaml type: FileOrCreate
Как проверить, что у пользователя есть доступ?
Необходимо выполнить следующую команду, в которой будут указаны:
resourceAttributes(как в RBAC) — к чему мы проверяем доступ;user— имя пользователя;groups— группы пользователя.
При совместном использовании с модулем
user-authnгруппы и имя пользователя можно посмотреть в логах Dex —d8 k -n d8-user-authn logs -l app=dex(видны только при авторизации).
cat <<EOF | 2>&1 d8 k create --raw /apis/authorization.k8s.io/v1/subjectaccessreviews -f - | jq .status
{
"apiVersion": "authorization.k8s.io/v1",
"kind": "SubjectAccessReview",
"spec": {
"resourceAttributes": {
"namespace": "",
"verb": "watch",
"version": "v1",
"resource": "pods"
},
"user": "system:kube-controller-manager",
"groups": [
"Admins"
]
}
}
EOF
В результате увидим, есть ли доступ и на основании какой роли:
{
"allowed": true,
"reason": "RBAC: allowed by ClusterRoleBinding \"system:kube-controller-manager\" of ClusterRole \"system:kube-controller-manager\" to User \"system:kube-controller-manager\""
}
Если в кластере включён режим multi-tenancy, нужно выполнить ещё одну проверку, чтобы убедиться, что у пользователя есть доступ в пространство имён:
cat <<EOF | 2>&1 d8 k --kubeconfig /etc/kubernetes/deckhouse/extra-files/webhook-config.yaml create --raw / -f - | jq .status
{
"apiVersion": "authorization.k8s.io/v1",
"kind": "SubjectAccessReview",
"spec": {
"resourceAttributes": {
"namespace": "",
"verb": "watch",
"version": "v1",
"resource": "pods"
},
"user": "system:kube-controller-manager",
"groups": [
"Admins"
]
}
}
EOF
{
"allowed": false
}
Сообщение allowed: false значит, что вебхук не блокирует запрос. В случае блокировки запроса вебхуком вы получите, например, следующее сообщение:
{
"allowed": false,
"denied": true,
"reason": "making cluster scoped requests for namespaced resources are not allowed"
}
Настройка прав высокоуровневых ролей
Если требуется добавить прав для определённой высокоуровневой роли, достаточно создать ClusterRole с аннотацией user-authz.deckhouse.io/access-level: <AccessLevel>.
Пример:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
user-authz.deckhouse.io/access-level: Editor
name: user-editor
rules:
- apiGroups:
- kuma.io
resources:
- trafficroutes
- trafficroutes/finalizers
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- flagger.app
resources:
- canaries
- canaries/status
- metrictemplates
- metrictemplates/status
- alertproviders
- alertproviders/status
verbs:
- get
- list
- watch
- create
- update
- patch
- delete