unip-controller/controller/src/basic_resources/rbac.py
2025-04-15 20:56:15 +03:00

148 lines
6.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ============================================================
# Система: Единая библиотека, Центр ИИ НИУ ВШЭ
# Модуль: Управления базовыми объектами Kubernetes
# Авторы: Полежаев В.А., Хританков А.С.
# Дата создания: 2024 г.
# ============================================================
"""
RBAC basic resources module. Implements reusable RBAC-related functions.
"""
import kopf
from kubernetes.client import RbacAuthorizationV1Api, ApiException, CoreV1Api, ApiClient
_DEFAULT_SA_NAME = 'default'
def update_default_sa(api_client, namespace, manifest, logger):
"""
Обновляет сервисный аккаунт (ServiceAccount) 'default'.
Функция является идемпотентной.
Если сервисный аккаунт отсутствует, то обработчик выбрасывает
исключение kopf.TemporaryError, что приводит к повторному
вызову метода спустия заданную задержку.
Если сервисный аккаунт существует, то его спецификация
замещается переданной в параметре `manifest`.
:api_client: Kubernetes API клиент
:param namespace: Пространство имен
:param manifest: Спецификация сервисного аккаунта
:param logger: kopf logger
:return: None.
"""
core_v1_api = CoreV1Api(api_client)
try:
core_v1_api.read_namespaced_service_account(_DEFAULT_SA_NAME, namespace)
except ApiException as exc:
if exc.status == 404:
# SA с именем 'default' всегда существует и создается Kubernetes,
# если отсутствует - нужно подождать
logger.info(f'SA {_DEFAULT_SA_NAME} does not exists.')
raise kopf.TemporaryError(f"Waiting for SA {_DEFAULT_SA_NAME} "
f"to be created by Kubernetes system...",
delay=10)
raise exc
logger.info(f"SA {_DEFAULT_SA_NAME} exists, trying to replace...")
core_v1_api.replace_namespaced_service_account(name=_DEFAULT_SA_NAME, namespace=namespace, body=manifest)
def delete_sa_if_exists(api_client: ApiClient, name, namespace, logger):
core_v1_api = CoreV1Api(api_client)
try:
# не имеет смысла для default SA - будет пересоздан Kubernetes
# оставлено для общего соответствия и на случай изменения имени SA
core_v1_api.delete_namespaced_service_account(name=name, namespace=namespace)
except ApiException as exc:
if exc.status == 404:
logger.warn(f"SA {name} doesnt exist, do nothing")
return
raise exc
logger.info(f"SA {name} is deleted")
def create_role(api_client, name, namespace, manifest):
"""
Создает роль (Role).
Функция является идемпотентной. Если роль существует,
то она будет обновлена.
:param api_client: Kubernetes API клиент
:param name: Имя роли
:param namespace: Пространство имен
:param manifest: Спецификация роли
:return: None.
"""
rbac_v1_api = RbacAuthorizationV1Api(api_client)
rbac_v1_api.replace_namespaced_role(name=name, namespace=namespace, body=manifest)
def delete_role_if_exists(api_client, name, namespace, logger):
"""
Удаляет роль (Role), если она существует.
Функция является идемпотентной.
Если роль существует, то она будет удалена.
Если роль не существует, то ничего не произойдет.
:param api_client: Kuberentes API клиент
:param name: Имя роли
:param namespace: Пространство имен
:param logger: kopf logger
:return: None
"""
rbac_v1_api = RbacAuthorizationV1Api(api_client)
try:
rbac_v1_api.delete_namespaced_role(name=name, namespace=namespace)
except ApiException as exc:
if exc.status == 404:
logger.warn(f"Role {name} doesnt exist, do nothing")
return
raise exc
logger.info(f"Role {name} is deleted")
def create_rb(api_client, name, namespace, manifest):
"""
Создает привязку роли (RoleBinding).
Функция является идемпотентной. Если привязка роли существует,
то она будет обновлена.
:param api_client: Kubernetes API клиент
:param name: Имя привязки роли
:param namespace: Пространство имен
:param manifest: Спецификация привязки роли
:return: None.
"""
rbac_v1_api = RbacAuthorizationV1Api(api_client)
rbac_v1_api.replace_namespaced_role_binding(name=name, namespace=namespace, body=manifest)
def delete_rb_if_exists(api_client, name, namespace, logger):
"""
Удаляет привязку роли (RoleBinding), если она существует.
Функция является идемпотентной.
Если привязка роли существует, то она будет удалена.
Если привязка роли не существует, то ничего не произойдет.
:param api_client: Kuberentes API клиент
:param name: Имя привязки роли
:param namespace: Пространство имен
:param logger: kopf logger
:return: None
"""
rbac_v1_api = RbacAuthorizationV1Api(api_client)
try:
rbac_v1_api.delete_namespaced_role_binding(name=name,
namespace=namespace)
except ApiException as exc:
if exc.status == 404:
logger.warn(f"RoleBinding {name} doesnt exist, do nothing")
return
raise exc
logger.info(f"RoleBinding {name} is deleted")