Пример ClusterAuthorizationRule
| An example of ClusterAuthorizationRule
|
yaml
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 (версия Enterprise Edition).
allowAccessToSystemNamespaces: false
Опция доступна только при включенном режиме enableMultiTenancy (версия Enterprise Edition).
namespaceSelector:
labelSelector:
matchExpressions:
- key: stage
operator: In
values:
- test
- review
matchLabels:
team: frontend
| yaml
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
This option is only available if the enableMultiTenancy parameter is set (Enterprise Edition version)
allowAccessToSystemNamespaces: false
This option is only available if the enableMultiTenancy parameter is set (Enterprise Edition version)
namespaceSelector:
labelSelector:
matchExpressions:
- key: stage
operator: In
values:
- test
- review
matchLabels:
team: frontend
|
Создание пользователя
| Creating a user
|
В Kubernetes есть две категории пользователей:
| There are two types of users in Kubernetes:
|
- ServiceAccount’ы, учет которых ведет сам Kubernetes через API.
- Остальные пользователи, учет которых ведет не сам Kubernetes, а некоторый внешний софт, который настраивает администратор кластера, — существует множество механизмов аутентификации и, соответственно, множество способов заводить пользователей. В настоящий момент поддерживаются два способа аутентификации:
- через модуль user-authn;
- с помощью сертификатов.
|
- Service accounts managed by Kubernetes via the API;
- Regular users managed by some external tool that the cluster administrator configures. There are many authentication mechanisms and, accordingly, many ways to create users. Currently, two authentication methods are supported:
- Via the user-authn module.
- Via the certificates.
|
При выпуске сертификата для аутентификации нужно указать в нем имя (CN=<имя> ), необходимое количество групп (O=<группа> ) и подписать его с помощью корневого CA-кластера. Именно этим механизмом вы аутентифицируетесь в кластере, когда, например, используете kubectl на bastion-узле.
| When issuing the authentication certificate, you need to specify the name (CN=<name> ), the required number of groups (O=<group> ), and sign it using the root CA of the cluster. It is this mechanism that authenticates you in the cluster when, for example, you use kubectl on a bastion node.
|
Создание ServiceAccount для сервера и предоставление ему доступа
| Creating a ServiceAccount for a machine and granting it access
|
Создание ServiceAccount с доступом к Kubernetes API может потребоваться, например, при настройке развертывания приложений через CI-системы.
| You may need to create a ServiceAccount with access to the Kubernetes API when, for example, an application is deployed using a CI system.
|
- Создайте ServiceAccount, например в namespace
d8-service-accounts :
|
- Create a ServiceAccount, e.g., in the
d8-service-accounts namespace:
|
shell
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
| shell
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):
|
- Grant it the necessary privileges (using the ClusterAuthorizationRule custom resource):
|
shell
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 (версия Enterprise Edition).
allowAccessToSystemNamespaces: true
EOF
| shell
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
This option is only available if the enableMultiTenancy parameter is set (Enterprise Edition version)
allowAccessToSystemNamespaces: true
EOF
|
Если в конфигурации Deckhouse включен режим мультитенантности (параметр enableMultiTenancy, доступен только в Enterprise Edition), настройте доступные для ServiceAccount пространства имен (параметр namespaceSelector).
| If multitenancy is enabled in the Deckhouse configuration (the enableMultiTenancy paameter; it is only available in Enterprise Edition), configure the namespaces the ServiceAccount has access to (the namespaceSelector parameter).
|
- Определите значения переменных (они будут использоваться далее), выполнив следующие команды (подставьте свои значения):
|
- Set the variable values (they will be used later) by running the following commands (insert your own values):
|
shell
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
| shell
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:
|
- Generate the
cluster section in the kubectl configuration file:
|
Используйте один из следующих вариантов доступа к API-серверу кластера:
| Use one of the following options to access the cluster API server:
|
- Если есть прямой доступ до API-сервера:
- Получите сертификат CA кластера Kubernetes:
|
- If there is direct access to the API server:
- Get a Kubernetes cluster CA certificate:
|
shell
kubectl get cm kube-root-ca.crt -o jsonpath=’{ .data.ca.crt }’ > /tmp/ca.crt
| shell
kubectl get cm kube-root-ca.crt -o jsonpath=’{ .data.ca.crt }’ > /tmp/ca.crt
|
- Сгенерируйте секцию
cluster (используется IP-адрес API-сервера для доступа):
|
- Generate the
cluster section (the API server’s IP address is used for access):
|
shell
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
| shell
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).
|
- If there is no direct access to the API server, use one of the following options:
- enable access to the API-server over the Ingress controller (the publishAPI parameter) and specify the addresses from which requests originate (the whitelistSourceRanges parameter);
- specify addresses from which requests will originate in a separate Ingress controller (the acceptRequestsFrom parameter).
|
- Если используется непубличный CA:
|
- If a non-public CA is used:
|
- Получите сертификат CA из Secret’а с сертификатом, который используется для домена
api.%s :
|
- Get the CA certificate from the Secret with the certificate that is used for the
api.%s domain:
|
shell
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
| shell
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 для доступа):
|
- Generate the
cluster section (an external domain and a CA for access are used):
|
shell
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
| shell
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 (используется внешний домен для доступа):
|
- If a public CA is used. Generate the
cluster section (an external domain is used for access):
|
shell
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
| shell
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
|
- Сгенерируйте секцию
user с токеном из Secret’а ServiceAccount в файле конфигурации kubectl:
|
- Generate the
user section using the token from the Secret’s ServiceAccount in the kubectl configuration file:
|
shell
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
| shell
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:
|
- Generate the context in the kubectl configuration file:
|
shell
kubectl config set-context $CONTEXT_NAME
–cluster=$CLUSTER_NAME –user=$USER_NAME
–kubeconfig=$FILE_NAME
| shell
kubectl config set-context $CONTEXT_NAME
–cluster=$CLUSTER_NAME –user=$USER_NAME
–kubeconfig=$FILE_NAME
|
- Установите сгенерированный контекст как используемый по умолчанию в файле конфигурации kubectl:
|
- Set the generated context as the default one in the kubectl configuration file:
|
shell
kubectl config use-context $CONTEXT_NAME –kubeconfig=$FILE_NAME
| shell
kubectl config use-context $CONTEXT_NAME –kubeconfig=$FILE_NAME
|
Создание пользователя с помощью клиентского сертификата
| How to create a user using a client certificate
|
Создание пользователя
| Creating a user
|
- Получите корневой сертификат кластера (ca.crt и ca.key).
- Сгенерируйте ключ пользователя:
|
- Get the cluster’s root certificate (ca.crt and ca.key).
- Generate the user key:
|
shell
openssl genrsa -out myuser.key 2048
| shell
openssl genrsa -out myuser.key 2048
|
- Создайте CSR, где укажите, что требуется пользователь
myuser , который состоит в группах mygroup1 и mygroup2 :
|
- Create a CSR file and specify in it the username (
myuser ) and groups to which this user belongs (mygroup1 & mygroup2 ):
|
shell
openssl req -new -key myuser.key -out myuser.csr -subj “/CN=myuser/O=mygroup1/O=mygroup2”
| shell
openssl req -new -key myuser.key -out myuser.csr -subj “/CN=myuser/O=mygroup1/O=mygroup2”
|
- Подпишите CSR корневым сертификатом кластера:
|
- Sign the CSR using the cluster root certificate:
|
shell
openssl x509 -req -in myuser.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out myuser.crt -days 10
| shell
openssl x509 -req -in myuser.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out myuser.crt -days 10
|
- Теперь полученный сертификат можно указывать в конфиг-файле:
|
- Now you can use the certificate issued in the config file:
|
shell
cat « EOF
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: $(cat 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
| shell
cat « EOF
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: $(cat 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
|
Предоставление доступа созданному пользователю
| Granting access to the created user
|
Для предоставления доступа созданному пользователю создайте ClusterAuthorizationRule .
| To grant access to the created user, create a `ClusterAuthorizationRule’.
|
Пример ClusterAuthorizationRule :
| Example of a ClusterAuthorizationRule :
|
yaml
apiVersion: deckhouse.io/v1
kind: ClusterAuthorizationRule
metadata:
name: myuser
spec:
subjects:
- kind: User
name: myuser
accessLevel: PrivilegedUser
portForwarding: true
| yaml
apiVersion: deckhouse.io/v1
kind: ClusterAuthorizationRule
metadata:
name: myuser
spec:
subjects:
- kind: User
name: myuser
accessLevel: PrivilegedUser
portForwarding: true
|
Настройка kube-apiserver для работы в режиме multi-tenancy
| Configuring kube-apiserver for multi-tenancy mode
|
Режим multi-tenancy, позволяющий ограничивать доступ к namespace, включается параметром enableMultiTenancy модуля.
| The multi-tenancy mode, which allows you to restrict access to namespaces, is enabled by the enableMultiTenancy module’s parameter.
|
Работа в режиме multi-tenancy требует включения плагина авторизации Webhook и выполнения настройки kube-apiserver . Все необходимые для работы режима multi-tenancy действия выполняются автоматически модулем control-plane-manager, никаких ручных действий не требуется.
| Working in multi-tenancy mode requires enabling the Webhook authorization plugin and configuring a kube-apiserver. All actions necessary for the multi-tenancy mode are performed automatically by the control-plane-manager module; no additional steps are required.
|
Изменения манифеста kube-apiserver , которые произойдут после включения режима multi-tenancy:
| Changes to the kube-apiserver manifest that will occur after enabling multi-tenancy mode:
|
- исправление аргумента
--authorization-mode . Перед методом RBAC добавится метод Webhook (например — --authorization-mode=Node,Webhook,RBAC );
- добавление аргумента
--authorization-webhook-config-file=/etc/kubernetes/authorization-webhook-config.yaml ;
- добавление
volumeMounts :
|
- The
--authorization-mode argument will be modified: the Webhook method will be added in front of the RBAC method (e.g., --authorization-mode=Node,Webhook,RBAC );
- The
--authorization-webhook-config-file=/etc/kubernetes/authorization-webhook-config.yaml will be added;
- The
volumeMounts parameter will be added:
|
yaml
- name: authorization-webhook-config
mountPath: /etc/kubernetes/authorization-webhook-config.yaml
readOnly: true
| yaml
- name: authorization-webhook-config
mountPath: /etc/kubernetes/authorization-webhook-config.yaml
readOnly: true
|
|
- The
volumes parameter will be added:
|
yaml
- name: authorization-webhook-config
hostPath:
path: /etc/kubernetes/authorization-webhook-config.yaml
type: FileOrCreate
| yaml
- name: authorization-webhook-config
hostPath:
path: /etc/kubernetes/authorization-webhook-config.yaml
type: FileOrCreate
|
Как проверить, что у пользователя есть доступ?
| How do I check that a user has access?
|
Необходимо выполнить следующую команду, в которой будут указаны:
| Execute the command below with the following parameters:
|
resourceAttributes (как в RBAC) — к чему мы проверяем доступ;
user — имя пользователя;
groups — группы пользователя.
|
resourceAttributes (the same as in RBAC) - target resources;
user - the name of the user;
groups - user groups;
|
При совместном использовании с модулем user-authn группы и имя пользователя можно посмотреть в логах Dex — kubectl -n d8-user-authn logs -l app=dex (видны только при авторизации).
|
You can use Dex logs to find out groups and a username if this module is used together with the user-authn module (kubectl -n d8-user-authn logs -l app=dex ); logs available only if the user is authorized).
|
shell
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
| shell
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
|
В результате увидим, есть ли доступ и на основании какой роли:
| You will see if access is allowed and what role is used:
|
json
{
“allowed”: true,
“reason”: “RBAC: allowed by ClusterRoleBinding "system:kube-controller-manager" of ClusterRole "system:kube-controller-manager" to User "system:kube-controller-manager"”
}
| json
{
“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, нужно выполнить еще одну проверку, чтобы убедиться, что у пользователя есть доступ в namespace:
| If the multitenancy mode is enabled in your cluster, you need to perform another check to be sure that the user has access to the namespace:
|
shell
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
| shell
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
|
json
{
“allowed”: false
}
| json
{
“allowed”: false
}
|
Сообщение allowed: false значит, что webhook не блокирует запрос. В случае блокировки запроса webhook’ом вы получите, например, следующее сообщение:
| The allowed: false message means that the webhook doesn’t block access. In case of webhook denying the request, you will see, e.g., the following message:
|
json
{
“allowed”: false,
“denied”: true,
“reason”: “making cluster scoped requests for namespaced resources are not allowed”
}
| json
{
“allowed”: false,
“denied”: true,
“reason”: “making cluster scoped requests for namespaced resources are not allowed”
}
|
Настройка прав высокоуровневых ролей
| Customizing rights of high-level roles
|
Если требуется добавить прав для определенной высокоуровневой роли, достаточно создать ClusterRole с аннотацией user-authz.deckhouse.io/access-level: <AccessLevel> .
| If you want to grant more privileges to a specific high-level role, you only need to create a ClusterRole with the user-authz.deckhouse.io/access-level: <AccessLevel> annotation.
|
Пример:
| An example:
|
yaml
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
| yaml
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
|