Пример назначения прав администратору кластера
Пример использует экспериментальную ролевую модель.
Для назначения прав администратору кластера используйте роль d8:manage:all:manager в ClusterRoleBinding.
Пример назначения прав администратору кластера (User joe):
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
Создание пользователя
В 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 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" - 
    
Примените манифест, чтобы создать запрос на подпись сертификата:
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:
- исправление аргумента 
--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 —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