Безопасность
Авторизация и аутентификация
По умолчанию аутентификация на основе сертификата, но поддерживаются внешние источники.
Аутентификация на основе сертификата.
Авторизация RBAC (пользователь - действие - ресурс). По умолчанию запрещено все что не разрешено. Роли определяют правила, RoleBindings определяют принадлежность пользователей к ролям. Пример настройки ролей:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: shield
name: read-deployments
rules:
- verbs: ["get", "watch", "list"] <<==== Allowed actions
apiGroups: ["apps"] <<==== on resources
resources: ["deployments"] <<==== of this type
Пример RoleBinding:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-deployments
namespace: shield
subjects:
- kind: User
name: sky <<==== Name of the authenticated user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: read-deployments <<==== This is the Role to bind to the user
apiGroup: rbac.authorization.k8s.io
Свойства правил роли:
verbs ["get", "watch", "list", "create", "update", "patch", "delete"]
ApiGroups (в пределах namespace):
apiGroup | Ресурс |
"" | pods, secrets |
“storage.k8s.io” | storageclass |
“apps” | deployments |
Полный список API ресурсов:
kubectl api-resources --sort-by name -o wide
Можно использовать звездочку.
Все роли используются только в контексте namespace!
Кластерные роли и привязки
ClusterRoleBindings используется для создания шаблонов ролей и привязки их к конкретным ролям.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole <<==== Cluster-scoped role
metadata:
name: read-deployments
rules:
- verbs: ["get", "watch", "list"]
apiGroups: ["apps"]
resources: ["deployments"]
Пользователи
Интересная статья Еще одна, тоже стоит почитать
Обычных пользователей нельзя добавить через вызовы API. Возможные варианты:
- Базовая аутентификация (basic auth):
- передача конфигурации API-серверу со следующим (или похожим) содержимым: password, username, uid, group;
- Клиентский сертификат X.509:
- создание секретного ключа пользователя и запроса на подпись сертификата;
- заверение его в центре сертификации (Kubernetes CA) для получения сертификата пользователя;
- Bearer-токены (JSON Web Tokens, JWT):
- OpenID Connect;
- слой аутентификации поверх OAuth 2.0;
- веб-хуки (webhooks).
Структура файла ~/.kube/config
- Clusters - список кластеров. Сертификат кластера, адрес и внутреннее имя
- Users - пользователи. Внутреннее имя, сертификат и ключ
- Contexts - объединение пользователя и кластера. Внутреннее имя, внутреннее имя кластера и внутреннее имя пользователя
- Current-context - имя текущего контекста
Важный момент: кубер не управляет членством пользователей в группах. Получить напрямую доступ к спискам пользователей в группе нельзя.
Пример создания пользователя с авторизацией через X.509 сертификат.
Создаем директорию хранения информации о пользователях и генерируем в нее ключ
mkdir -p users/sergey/.certs
openssl genrsa -out ~/users/sergey/.certs/sergey.key 2048
Генерируем запрос на сертификат
openssl req -new -key ~/users/sergey/.certs/sergey.key -out ~/users/sergey/.certs/sergey.csr -subj "/CN=sergey/O=testgroup"
Обработка запроса на сертификат
openssl x509 -req -in ~/users/sergey/.certs/sergey.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out ~/users/sergey/.certs/sergey.crt -days 500
В некоторых ресурсах говорится, что команда kubectl config set-credentials ... создает пользователя в кластере Kubernetes. Но это не так, команда kubectl config ... создает/модифицирует файл .kube/config, поэтому нужно быть осторожным и не побить свой файл. А Kubernetes авторизует всех пользователей, чей сертификат подписан его центром сертификации.
Добавляем пользователя sergey
kubectl config set-credentials sergey \
--client-certificate=/root/users/sergey/.certs/sergey.crt \
--client-key=/root/users/sergey/.certs/sergey.key \
--embed-certs=true
Если нужно - создали бы настройки кластера, но у нас есть, поэтому создаем контекст с существующим кластером. Namespace, если нужно, указывается в настройках контекста.
kubectl config set-context sergey-context --cluster=kubernetes --user=sergey --namespace=sergey-ns
Теперь осталось пользователю определить права.
Например определим роль sergey-ns-full с полным доступом к namespace sergey-ns
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: sergey-ns-full
namespace: sergey-ns
rules:
- apiGroups: [ "*" ]
resources: [ "*" ]
verbs: [ "*" ]
Сейчас вместо привязки пользователя, привяжем группу к роли.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: testgroup-rolebinding # Название RoleBinding
namespace: sergey-ns # Namespace, где применяется
subjects:
- kind: Group # Тип субъекта — группа
name: testgroup # Название группы
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # Тип привязываемой роли (Role или ClusterRole)
name: sergey-ns-full # Название роли
apiGroup: rbac.authorization.k8s.io
Переключаемся на контекст и проверяем
kubectl config use-context sergey-context
Создаем простой под
kind: Pod
apiVersion: v1
metadata:
name: hello-pod
labels:
zone: prod
version: v1
spec:
containers:
- name: hello-ctr
image: nigelpoulton/k8sbook:1.0
ports:
- containerPort: 8080
resources:
limits:
memory: 128Mi
cpu: 0.5
Проверяем факт создания пода
kubectl get pods
Удалось!
Основные команды управления пользователями
Если при создании ... указать флаг --embed-certs=true то тогда вместо путей к файлам сертификатов, в файл настройки будут встроено содержание сертификатов в Base64.
Команда | Доп. параметры |
Описание |
kubectl get clusterroles.rbac.authorization.k8s.io --all-namespaces | Список пользователей | |
kubectl config view | Показать текущую конфигурацию (.kube/config) | |
kubectl config current-context | Показать текущий активный контекст | |
kubectl config get-contexts | Список всех контекстов | |
kubectl config use-context cont_name | Переключиться на контекст cont_name | |
kubectl config set-cluster clast_name | Добавить/изменить кластер
|
|
kubectl config set-credentials | Добавить/изменить учетные данные пользователя
|
|
kubectl config set-context cont_name | --cluster=dev-cluster \ --user=dev-user \ --namespace=dev-ns |
Создать/изменить контекст |
kubectl config delete-context | Удалить контекст | |
kubectl config delete-cluster | Удалить кластер | |
kubectl config delete-user user_name | Удалить пользователя | |
kubectl config rename-context | Переименовать контекст |
Безопасность, общая теория
Запрет передачи ключей SA
Каждому поду по умолчанию передаются ключи сервисный аккаунт. Поэтому при получении доступа к поду можно получить доступ вплоть до всего кластера. Обычно подам не нужно управлять кластером. Поэтому можно запретить передачу ключей.
apiVersion: v1
kind: Pod
metadata:
name: service-account-example-pod
spec:
serviceAccountName: some-service-account
automountServiceAccountToken: false <<==== This line
<Snip>
Также можно передавать временные ключи, но это потом.
Контроль целостности ресурсов
- Ограничьте доступ к серверам, на которых запущены компоненты Kubernetes, особенно к компонентам control plane
- Ограничьте доступ к репозиториям, хранящим конфигурационные файлы Kubernetes
- Передача файлов и управление только через SSH
- Проверка контрольной суммы после скачивания
- Ограничьте доступ к регистру образов и связанным хранилищам
Файловая система пода в read-only режим
apiVersion: v1
kind: Pod
metadata:
name: readonly-test
spec:
securityContext:
readOnlyRootFilesystem: true <<==== R/O root filesystem
allowedHostPaths: <<==== Make anything below
- pathPrefix: "/test" <<==== this mount point
readOnly: true <<==== read-only (R/O)
<Snip>
Лог действий на кластере и связанной инфраструктуре
Защита данных кластера
Cluster store (обычно etcd) хранит все данные. Необходимо ограничить и контролировать доступ к серверам, на которых работает Cluster store.
DoS
Подвергается API сервер. Должно быть минимум 3 Control plane сервера и 3 worker ноды. Изоляция etcd на сетевом уровне. Ограничения ресурсов для подов и количества подов.
apiVersion: v1
kind: ResourceQuota
metadata:
name: pod-quota
namespace: skippy
spec:
hard:
pods: "100"
Доп. опция podPidsLimit ограничивает количество процессов одним подом. Также можно ограничить кол-во подов на одной ноде.
По умолчанию etcd устанавливается на сервер с control plane. На production кластере нужно разделять.
Запретить сетевое взаимодействие между подами и внешние взаимодействия (где это не нужно) при помощи сетевых политик Kubernetes.
Защита подов и контейнеров
Запрет запуска процессов от root
apiVersion: v1
kind: Pod
metadata:
name: demo
spec:
securityContext: <<==== Applies to all containers in this Pod
runAsUser: 1000 <<==== Non-root user
containers:
- name: demo
image: example.io/simple:1.0
Это запускает все контейнеры от одного непривилегированного пользователя, но позволяет контейнерам использовать общие ресурсы. При запуске нескольких подов, будет аналогично. Поэтому лучше дополнительно настраивать пользователей контейнера:
apiVersion: v1
kind: Pod
metadata:
name: demo
spec:
securityContext: <<==== Applies to all containers in this Pod
runAsUser: 1000 <<==== Non-root user
containers:
- name: demo
image: example.io/simple:1.0
securityContext:
runAsUser: 2000 <<==== Overrides the Pod-level setting
Рутовые права складываются примерно из 30 capabilities. Простой способ - в тестовом окружении ограничить все и по логам добавлять нужные. Естественно финальное тестирование должно быть максимально всеобъемлющим. Пример разрешений:
apiVersion: v1
kind: Pod
metadata:
name: capability-test
spec:
containers:
- name: demo
image: example.io/simple:1.0
securityContext:
capabilities:
add: ["NET_ADMIN", "CHOWN"]
Фильтрация системных вызовов.
Похоже на capabilities, но фильтрует системные вызовы. Способы поиска минимальных разрешений: разрешить все + логгирование, запрет + постепенное разрешение.
Также есть Pod Security Standarts (PSS) и Pod Security Admission (PSA). PSA применяют PSS при старте пода.
Основные команды
Параметр | Описание |
kubectl describe clusterrole role_name | Описание роли |
kubectl get clusterrolebindings | grep role_name | Список пользователей с такой ролью |
kubectl describe clusterrolebindings role_name | Информация по сопоставлению |
Аналогично для ролей (clusterrolebindings -> rolebindings) |
No Comments