Пример назначения прав администратору кластера
Пример использует экспериментальную ролевую модель.
Для назначения прав администратору кластера используйте роль d8:manage:all:manager
в ClusterRoleBinding
.
Пример назначения прав администратору кластера (User joe
):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admin-joe
subjects:
- kind: User
name: joe
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: d8:manage:all:manager
apiGroup: rbac.authorization.k8s.io
Пример назначения прав сетевому администратору
Пример использует экспериментальную ролевую модель.
Для назначения прав сетевому администратору на управление сетевой подсистемой кластера используйте роль d8:manage:networking:manager
в ClusterRoleBinding
.
Пример назначения прав сетевому администратору (User joe
):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: network-admin-joe
subjects:
- kind: User
name: joe
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
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
Создание пользователя
В 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
:kubectl 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):
kubectl 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:
kubectl get cm kube-root-ca.crt -o jsonpath='{ .data.ca\.crt }' > /tmp/ca.crt
-
Сгенерируйте секцию
cluster
(используется IP-адрес API-сервера для доступа):kubectl config set-cluster $CLUSTER_NAME --embed-certs=true \ --server=https://$(kubectl 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
:kubectl -n d8-user-authn get secrets -o json \ $(kubectl -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 для доступа):kubectl config set-cluster $CLUSTER_NAME --embed-certs=true \ --server=https://$(kubectl -n d8-user-authn get ing kubernetes-api -ojson | jq '.spec.rules[].host' -r) \ --certificate-authority=/tmp/ca.crt \ --kubeconfig=$FILE_NAME
-
-
Если используется публичный CA. Сгенерируйте секцию
cluster
(используется внешний домен для доступа):kubectl config set-cluster $CLUSTER_NAME \ --server=https://$(kubectl -n d8-user-authn get ing kubernetes-api -ojson | jq '.spec.rules[].host' -r) \ --kubeconfig=$FILE_NAME
- Если есть прямой доступ до API-сервера:
-
Сгенерируйте секцию
user
с токеном из секрета ServiceAccount в файле конфигурации kubectl:kubectl config set-credentials $USER_NAME \ --token=$(kubectl -n d8-service-accounts get secret gitlab-runner-deploy-token -o json |jq -r '.data["token"]' | base64 -d) \ --kubeconfig=$FILE_NAME
-
Сгенерируйте контекст в файле конфигурации kubectl:
kubectl config set-context $CONTEXT_NAME \ --cluster=$CLUSTER_NAME --user=$USER_NAME \ --kubeconfig=$FILE_NAME
-
Установите сгенерированный контекст как используемый по умолчанию в файле конфигурации kubectl:
kubectl 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 genrsa -out myuser.key 2048
-
Создайте 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 genrsa -out myuser.key 2048
-
Создайте 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"
-
Примените манифест, чтобы создать запрос на подпись сертификата:
kubectl apply -f csr.yaml
-
Убедитесь, что сертификат подтвержден:
kubectl 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
Если сертификат не подтвердился автоматически, подтвердите его:
kubectl certificate approve demo-client-cert
После этого убедитесь, что сертификат подтвержден.
-
Извлеките закодированный сертификат из CSR с именем
demo-client-cert
, декодируйте его из Base64 и сохраните в файл (в этом примере —myuser.crt
), созданный на шаге 2:kubectl 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:
- исправление аргумента
--authorization-mode
. Перед методом RBAC добавится метод Webhook (например,--authorization-mode=Node,Webhook,RBAC
); - добавление аргумента
--authorization-webhook-config-file=/etc/kubernetes/authorization-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 —kubectl -n d8-user-authn logs -l app=dex
(видны только при авторизации).
cat <<EOF | 2>&1 kubectl 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 kubectl --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