Terraform модуль для создания RBAC правил

Начиная с Kubernetes 1.6, RBAC политики включены по умолчанию. К тому же использование этих политик помогает безопасно управлять вашим кластером. Раньше нам приходилось вручную создавать подобные политики, сервисные аккаунты и пользователей. Для каждого нового проекта мы проделывали ручные операции, которые отнимали много времени. Особенно создание пользователей, так как требует множества мелких манипуляций. Готового решения, удовлетворяющего нашим требованиям, нам найти не удалось, поэтому мы написали terraform модуль, который упрощает этот процесс. Данный модуль позволяет создавать сервисные аккаунты и пользователей, а затем генерировать готовые конфигурационные файлы (kubeconfig) для них. Также при помощи данного модуля можно создавать роли, кластерные роли и привязывать их к определенным сервисным аккаунтам, пользователям или группам. Модуль можно найти в нашем GitHub репозитории. Для использования модуля  потребуется terraform >= 1.0.0 и kubeconfig, с административными правами.

Описание переменных

  • output_files_path: путь до директории где будут сохранены сгенерированные TLS файлы и kubeconfig для пользователей и сервисных аккаунтов. По умолчанию: «./files».

  • k8s_api_endpoint: имя хоста (в URI формате) для Kubernetes API.

  • k8s_insecure: следует ли обращаться к серверу без проверки сертификата TLS. По умолчанию: false.

  • k8s_cluster_name: название Kubernetes кластера.

  • k8s_auth_cluster_ca_certificate: PEM-кодированный корневой сертификат для TLS аутентификации.

    • raw(опционально): сертификат в неизменном виде. Пример: «——BEGIN CERTIFICATE——\nMIIELDCCApSgAwIBAgIQcLahmhzRbVMSRZX2cQXtuTANBgkqhkiG9w0BAQsFADAv\n … \n——END CERTIFICATE——\n».

    • encoded(опционально): закодированный в base64 сертификат.

Должно быть задано одно из полей raw или encoded. Если заданы оба, будет использовано поле raw.
Переменные k8s_api_endpoint, k8s_auth_cluster_ca_certificate и k8s_cluster_name необходимы для генерации конфигурационных файлов (kubeconfig).

  • k8s_config_path: путь до kubeconfig с административными правами.

  • k8s_config_context(опционально): контекст для kubeconfig.

  • roles_list: список создаваемых ролей.

    • name: название роли.

    • namespace: окружение.

    • rules: список правил для роли.

      • api_groups: список субъектов.

      • resources: список ресурсов.

      • verbs: список глаголов (verb).

  • cluster_roles_list: список создаваемых кластерных ролей.

  • sa_list: список создаваемых сервисных аккаунтов.

  • bindings: список RoleBinding и ClusterRoleBinding.

    • type: тип (role_binding или cluster_role_binding).

    • prefix: уникальная строка, которая используется для формирования названия RoleBinding и ClusterRoleBinding.

    • namespaces(опционально): список окружений, в которых создается RoleBinding. Используется только для RoleBinding.

    • sa_list(опционально): список сервисных аккаунтов.

    • users(опционально): список пользователей. Пользователи создаются из данного списка.

    • groups(опционально): список групп.

    • roles(опционально): список ролей.

    • cluster_roles(опционально): список кластерных ролей.

Значение для переменной type может быть следующим: role_binding или cluster_role_binding.
Переменная namespaces используется только для RoleBinding. Если переменная будет пустая для RoleBinding, деплой не пройдет.
Одна из переменных sa_list, users, groups должна быть задана для RoleBinding и ClusterRoleBinding.
Пользователи создаются и списка users.
Переменные roles или cluster_roles должны быть установлены для RoleBinding.
Переменная cluster_roles должна быть установлена для ClusterRoleBinding.

Пример использования модуля

Рассмотрим конкретный пример использования данного модуля:

Код
module "k8s-rbac-controller" { source = "../k8s-rbac-controller" output_files_path = "./files" k8s_api_endpoint = "https://172.20.1.2" k8s_auth_cluster_ca_certificate = { raw = "-----BEGIN CERTIFICATE-----\nMIIELDCCApSgAwIBAgIQcLahmhzRbVMSRZX2cQXtuTANBgkqhkiG9w0BAQsFADAv\n ... 8hZp/GUpn6jahcXxmuKaAQ==\n-----END CERTIFICATE-----\n" encoded = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS..." } k8s_cluster_name = "cluster-name" k8s_config_path = "~/.kube/config" k8s_config_context = "config-context" roles_list = [ { name = "role-1", namespace = "default", rules = [ { api_groups = [""], resources = ["pods"], verbs = ["get", "list"], } ] } ] cluster_roles_list = [ { name = "cluster-role-1", rules = [ { api_groups = [""], resources = ["namespaces"], verbs = ["get", "list", "watch", "create"], } ] }, { name = "cluster-role-2", rules = [ { api_groups = [""], resources = ["namespaces"], verbs = ["get"] }, { api_groups = [""], resources = ["namespaces"], verbs = ["list"] } ] } ] sa_list = [ { name = "sa-1" namespace = "kube-system" }, { name = "sa-2" namespace = "default" }, ] bindings = [ { type = "role_binding" prefix = "prefix-1" namespaces = ["default"] sa = [ { name = "sa-1", namespace = "kube-system", } ], users = [ { name = "user-1", group = "group-1", }, { name = "user-2", group = "group-2", } ] groups = ["group-1"] roles = ["role-1"] cluster_roles = ["cluster-role-2"] }, { type = "cluster_role_binding" prefix = "prefix-2" sa = [ { name = "sa-2", namespace = "default", } ], users = [ { name = "user-2", group = "group-2", } ], cluster_roles = ["cluster-role-1"] }, ] }

Данный пример можно найти в GitHub репозитории. В этом примере создается роль role-1 в default окружении со следующими правами:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: name: role-1 namespace: default
rules:
- apiGroups: - "" resources: - pods verbs: - list - get

Также создается кластерная роль cluster-role-1 со следующими правами:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata: name: cluster-role-1
rules:
- apiGroups: - "" resources: - namespaces verbs: - get - list - watch - create

и cluster-role-2 со следующими правами:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata: name: cluster-role-2
rules:
- apiGroups: - "" resources: - namespaces verbs: - get
- apiGroups: - "" resources: - namespaces verbs: - list

Дополнительно создаются сервисные аккаунты sa-1 в окружении kube-system и sa-2 в окружении default. Список пользователей для создания берется из поля users в переменной bindings. То есть в данном случае будут созданы 2 пользователя user-1 и user-2 в группах group-1 и group-2 соответственно. Также будут созданы 2 RoleBinding (соответствует количеству элементов в списках roles и cluster_roles, если type = role_binding) cluster-role-2-prefix-1-cluster-role:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: name: cluster-role-2-prefix-1-cluster-role namespace: default
roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ns-viewer
subjects:
- kind: ServiceAccount name: sa-1 namespace: kube-system
- apiGroup: rbac.authorization.k8s.io kind: User name: user-1 namespace: default
- apiGroup: rbac.authorization.k8s.io kind: User name: user-2 namespace: default
- apiGroup: rbac.authorization.k8s.io kind: Group name: group-1 namespace: default

и role-1-prefix-1-role следующего вида:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata: name: role-1-prefix-1-role namespace: default
roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: role-1
subjects:
- kind: ServiceAccount name: sa-1 namespace: kube-system
- apiGroup: rbac.authorization.k8s.io kind: User name: user-1 namespace: default
- apiGroup: rbac.authorization.k8s.io kind: User name: user-2 namespace: default
- apiGroup: rbac.authorization.k8s.io kind: Group name: group-1 namespace: default

Обратите внимание, что в RoleBinding можно указывать ClusterRole.

Также будет создан ClusterRoleBinding (соответствует количеству элементов в списке cluster_roles, если type = cluster_role_binding) cluster-role-1-prefix-2:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata: name: cluster-role-1-prefix-2
roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: ns-creator
subjects:
- kind: ServiceAccount name: sa-2 namespace: default
- apiGroup: rbac.authorization.k8s.io kind: User name: user-2 namespace: default

Название для RoleBinding формируется по следующему принципу:
[${Role}|${ClusterRole}]-[${prefix}]-["role"|"cluster-role"]

Приписка [«role»|»cluster-role»] нужна, так как в RoleBinding можно использовать Role и ClusterRole, которые могут совпадать по названию.

Название для ClusterRoleBinding формируется по следующему принципу:
[${ClusterRole}]-[${prefix}]

Что планируется дальше

В будущем планируется добавить следующий функционал:

  • Возможность выбирать output для сгенерированных kubeconfig — как минимум добавить vault помимо локальных файлов.

  • Возможность задавать для пользователя не одну группу, а передавать список. Для этого необходимо законтребьютить в репозиторий hashicorp/terraform-provider-tls, добавив возможность передавать список в поле organization для ресурса tls_cert_request.

  • Возможность генерировать kubeconfig для существующих сервисных аккаунтов.

  • Добавить модуль в terraform registry, чтобы было удобнее его использовать.

Выводы

Данный модуль помог повысить нашу эффективность. Раньше мы могли тратить от 20 до 60 минут на создание RBAC политик. Сейчас же на это уходит от 5 до 10 минут. То есть наша эффективность возрасла в ~4~6 раз. Как правило для проектов мы используем одни и те же роли и кластерные роли. Поэтому модуль позволяет унифицировать данный процесс, так как описание RBAC политик осуществляется на стороне кода. То есть можно повторно использовать зараннее созданные файлы с заполненными переменными.

P.S.: На текущий момент данный модуль прошел обкатку на небольшом количестве проектов, поэтому возможно будут обнаруживаться какие-то баги. Если вы заметите какой-то баг, пожалуйста, создайте issue на GitHub, мы будем оперативно обрабатывать их.

Кстати, мы также делимся полезной информацией по теме DevOps и не только в telegram-канале DevOps FM, присоединяйтесь.

Читайте так же:

  • Китай рекомендует государственным компаниям перейти на государственные облачные сервисыКитай рекомендует государственным компаниям перейти на государственные облачные сервисы Уведомление об этом пришло в компании за несколько дней до вступления в силу национального законодательства, предусматривающего штрафы до 10 миллионов юаней (1,5 млн долларов США) за выявленные нарушения.До вступления в силу национального закона о безопасности данных осталось всего […]
  • Экран AMOLED, 120/480 Гц, 5000 мА•ч, 64 Мп, стереодинамики и MIUI 12.5. Poco F3 GT ориентирован на геймеровЭкран AMOLED, 120/480 Гц, 5000 мА•ч, 64 Мп, стереодинамики и MIUI 12.5. Poco F3 GT ориентирован на геймеров Компания Poco опубликовала новое изображение своего будущего смартфона Poco F3 GT, заявив. Что компания нацелена на поклонников мобильных игр. Поскольку его экран поддерживает высокую частоту дискретизации сенсорного слоя 480 Гц. Производитель добавил. Что такой экран предлагает […]
  • Контент вордпрессКонтент вордпресс Эта статья посвящена системе управления веб-контентом (WordPress.org). О ведущем блоге см. WordPress.com. WordPress (WP, WordPress.org)-это бесплатная и открытая система управления контентом (CMS). Написанная на PHP[4] и работающая в паре с базой данных MySQL или MariaDB. Функции […]
  • Услуга по наполнению сайта wordpress с вариациямиУслуга по наполнению сайта wordpress с вариациями Пресс-релиз дистрибутив маркетинговый инструмент для вашего WordPress сайта или блога. Вы можете использовать этот плагин для отправки бесплатных пресс-релизов непосредственно редакторам Wire Access. И они проверят и подтвердят это вместе с вами. Прежде чем бесплатно распространить […]