База данных

Этот документ описывает базовые требования к PostgreSQL для работы SmartCPD, поддерживаемые модели доступа и принципы организации схем и ролей.

Базовые требования#

  • Поддерживаемая СУБД: PostgreSQL.
  • Поддерживаемая версия: 14+.

Это не означает, что SmartCPD гарантированно не будет работать на более старых версиях PostgreSQL, но разработка и тестирование выполняются только на поддерживаемых LTS и не End-of-Life версиях.

  • Мультиплексоры и connection pooler-решения типа pgbouncer в текущей версии SmartCPD не поддерживаются.
  • PostgreSQL не входит в состав поставки SmartCPD. Подготовка, установка, отказоустойчивость, эксплуатация, мониторинг, backup и restore базы данных находятся в зоне ответственности Заказчика.

Отказоустойчивость БД#

Требования к отказоустойчивой схеме PostgreSQL и поведение SmartCPD при недоступности БД описаны в разделе База данных.

При недоступности БД SmartCPD продолжает обслуживать вызовы, но деградирует по ряду функций, завязанных на доступ к данным. В первую очередь это влияет на:

  • административные интерфейсы;
  • возможность управления и настройки;
  • авторизацию при использовании API;
  • потерю статистических данных (cdr).

Со стороны SmartCPD поддерживается только единый внешний DB endpoint. Если инфраструктура Заказчика использует primary/replica или иную HA-схему PostgreSQL, переключение между экземплярами должно быть скрыто за этим endpoint.

Поддерживаемые модели доступа#

SmartCPD поддерживает две модели организации доступов к PostgreSQL:

  • per-schema
    • простая настройка и администрирование;
    • простое сопровождение миграций;
    • меньшее разграничение доступа между внутренними сервисами SmartCPD.
  • per-service
    • более сложная настройка
    • необходимость контроля изменений схемы при миграциях;
    • более удобный аудит;
    • более точный контроль владения и доступа к объектам БД.

Обе модели поддерживаются. Выбор конкретной модели зависит от требований к разграничению прав, сопровождению и правилам эксплуатации базы данных на стороне Заказчика.

Возможен переход от одной к другой в процессе эксплуатации.

per-schema#

В этой модели используется один пользователь на каждую схему БД или на группу близких по назначению сущностей.

Это базовый вариант для типовой установки.

Требуемые роли:

  • smartcpd - основной пользователь сервисов SmartCPD для схемы public;
  • grafana - пользователь сервиса grafana для схемы grafana.

Итого: 2 роли и 2 пароля.

Плюсы:

  • минимальное количество пользователей;
  • простое разграничение доступа;
  • простая настройка и администрирование;
  • простые миграции: если новая роль не появляется, дополнительные действия обычно не требуются.

Когда использовать:

  • не требуется максимально подробное разграничение доступов между внутренними сервисами SmartCPD;
  • не требуется детальный аудит межсервисного доступа к объектам БД;
  • важнее простота сопровождения, чем максимальная изоляция ролей.

Ограничения:

  • один пользователь SmartCPD используется сразу несколькими сервисами;
  • возможности аудита ограничены;
  • владение и доступ к объектам БД контролируются менее детально.

per-service#

В этой модели отдельный логин используется для каждого сервиса SmartCPD.

Это более строгий вариант организации доступов.

Требуемые роли:

  • smartcpd - пользователь по умолчанию для портала и базового доступа к public;
  • grafana - пользователь сервиса grafana для схемы grafana;
  • billing - пользователь сервиса billing;
  • amd - пользователь сервиса amd;
  • markup - пользователь сервиса markup;
  • analyzer - пользователь сервиса analyzer;
  • grafana_ds - datasource-пользователь grafana для чтения продуктовых данных SmartCPD.

Итого: 7 ролей и 7 паролей.

Плюсы:

  • более точное разграничение прав;
  • более удобный аудит действий сервисов;
  • более понятный контроль ownership и доступа к объектам БД;
  • более прозрачная схема межсервисного взаимодействия через роли и grants.

Когда использовать:

  • требуется детальное разграничение доступов между сервисами;
  • важен аудит действий отдельных сервисов;
  • нужно отдельно контролировать ownership и grants по объектам БД.

Ограничения:

  • настройка и сопровождение сложнее, чем в per-schema;
  • при изменении схемы и ролевой модели нужно контролировать влияние миграций на права и ownership;
  • эксплуатационная модель требует большей дисциплины при сопровождении БД.

Организация схем и ролей#

Граница ответственности#

Управление БД SmartCPD ограничивается ролевой моделью, схемами, базовыми правами доступа и общей организацией DB-контура в соответствии с выбранной моделью доступа.

Контроль прикладного содержимого и его структуры выполняют сами сервисы SmartCPD. Это относится к таблицам, миграциям и дальнейшему изменению объектов, которыми сервисы владеют в рамках своей логики работы.

Разделение схем#

В PostgreSQL используется разделение схем по назначению.

  • public используется для данных и объектов, которыми управляют сервисы SmartCPD;
  • отдельные схемы используются для third-party компонентов и внешних по смыслу подсистем. Существующие схемы:
    • grafana - хранит настройки и исторические данный сервиса grafana

Такое разделение нужно, чтобы:

  • не смешивать прикладные сущности SmartCPD с внешними и служебными объектами;
  • упрощать контроль ownership и grants;
  • сохранять понятную структуру БД при сопровождении и расширении решения.

Дальнейшее расширение структуры#

В дальнейшем структура БД может расширяться по тому же принципу:

  • прикладные объекты SmartCPD остаются в public;
  • для third-party компонентов и внешних по смыслу подсистем используются отдельные схемы и отдельные роли.

Скрипты поставки#

В поставку SmartCPD входят SQL-скрипты для подготовки PostgreSQL и восстановления ролевой модели.

Использование скриптов поставки не является обязательным. Если подготовка PostgreSQL выполняется вручную, роли, схемы и grants должны быть приведены в соответствие с выбранной моделью доступа и таблицами доступов, приведенными ниже в этом документе.

В поставке они располагаются в каталоге:

db/postgres

Основные скрипты:

  • db/postgres/sql/00-create-db-once.sql создает БД. Скрипт используется однократно при первоначальной подготовке PostgreSQL.
  • db/postgres/sql/10-users-required.sql создает обязательные роли и применяет базовые права для минимальной модели.
  • db/postgres/sql/20-users-optional.sql добавляет роли и межсервисные grants для модели per-service.
  • db/postgres/sql/90-restore-single-user-ownership.sql возвращает владение объектами в public к схеме с единым владельцем.
  • db/postgres/sql/91-restore-billing-user-ownership.sql восстанавливает ownership объектов, относящихся к billing.
  • db/postgres/sql/92-restore-markup-user-ownership.sql восстанавливает ownership объектов, относящихся к markup.

Повторный запуск 10-users-required.sql и 20-users-optional.sql является штатным сценарием. Скрипт 20-users-optional.sql всегда выполняется только после 10-users-required.sql, в том числе при обновлениях. Эти скрипты используются для обновления паролей, восстановления grants и приведения ролевой модели к ожидаемому состоянию при обновлениях и миграциях.

Назначение и именование скриптов сохраняются от релиза к релизу, что позволяет использовать их в автоматизации, например через CI/CD, Ansible или аналогичные средства. Перед обновлением рекомендуется ознакомиться с примечаниями релиза и выполнить скрипты, соответствующие выбранной модели доступа.

Использование в IDE#

SQL-скрипты можно запускать из IDE, например DBeaver, DataGrip или pgAdmin.

При таком использовании:

  • значения DB_* параметров нужно подставлять явно перед выполнением скрипта;
  • обычно для этого либо заменяют плейсхолдеры в тексте скрипта на конкретные значения, либо используют механизм SQL-переменных самой IDE, если он поддерживается;
  • подключение должно выполняться под ролью с достаточными правами для выбранного сценария;
  • для 00-create-db-once.sql подключение выполняется к служебной БД postgres;
  • для остальных скриптов подключение выполняется к целевой БД SmartCPD.

Это удобно, когда нужно подготовить БД вручную, проверить результат выполнения или точечно повторить отдельный скрипт.

Использование в CLI#

Для запуска из командной строки используется psql с передачей переменных через -v.

Пример для создания БД:

psql -v ON_ERROR_STOP=1 -d postgres \
     -v DB_NAME=smartcpd \
     -f db/postgres/sql/00-create-db-once.sql

Пример для применения обязательных ролей:

psql -v ON_ERROR_STOP=1 -d smartcpd \
     -v DB_PORTAL_USER=smartcpd \
     -v DB_PORTAL_PASSWORD=... \
     -v DB_GRAFANA_USER=grafana \
     -v DB_GRAFANA_PASSWORD=... \
     -f db/postgres/sql/10-users-required.sql

Пример для модели per-service (строго после применения обязательных ролей):

psql -v ON_ERROR_STOP=1 -d smartcpd \
     -v DB_PORTAL_USER=smartcpd \
     -v DB_BILLING_USER=billing \
     -v DB_BILLING_PASSWORD=... \
     -v DB_AMD_USER=amd \
     -v DB_AMD_PASSWORD=... \
     -v DB_MARKUP_USER=markup \
     -v DB_MARKUP_PASSWORD=... \
     -v DB_ANALYZER_USER=analyzer \
     -v DB_ANALYZER_PASSWORD=... \
     -v DB_GRAFANA_DS_USER=grafana_ds \
     -v DB_GRAFANA_DS_PASSWORD=... \
     -f db/postgres/sql/20-users-optional.sql

Набор передаваемых переменных зависит от конкретного скрипта. Перед запуском рекомендуется открыть соответствующий SQL-файл и проверить список ожидаемых DB_* параметров.

Восстановление прав без суперпользователя#

Если у оператора нет прав на CREATE ROLE, ALTER OWNER и другие административные действия, можно использовать генераторы из db/postgres/utils:

  • db/postgres/utils/generate-ownership-restore.sql генерирует команды ALTER ... OWNER TO ...;
  • db/postgres/utils/generate-permissions-restore.sql генерирует команды GRANT и ALTER DEFAULT PRIVILEGES;
  • db/postgres/utils/list-object-owner.sql показывает текущих владельцев объектов в public.

Оба генератора возвращают набор команд, сгруппированных по роли, от имени которой их нужно выполнить, и в порядке, в котором эти команды должны применяться. Это позволяет поэтапно восстанавливать grants и ownership даже в ограниченном контуре доступа.

Таблица доступов#

per-schema#

В модели per-schema владение объектами организуется на уровне схем.

СхемаВладелец всех сущностей
publicsmartcpd
grafanagrafana

per-service#

В модели per-service для сервисов SmartCPD используются отдельные роли.

РольНазначениеБазовые праваДополнительные межсервисные права
portalПользователь по умолчаниюUSAGE/CREATE на public, search_path=publicНет
grafanaСервис GrafanaВладелец схемы grafana, USAGE/CREATE на grafana, search_path=grafanaНет
billingСервис биллингаCONNECT, USAGE на public, CREATE на public, search_path=publicВыдает SELECT для smartcpd, grafana_ds, analyzer; выдает SELECT/INSERT/UPDATE для amd
amdСервис AMDCONNECT, USAGE на public, search_path=publicИспользует таблицы и sequence, созданные billing
markupСервис markupCONNECT, USAGE на public, CREATE на public, search_path=publicВыдает SELECT для grafana_ds и analyzer на свои таблицы в public
analyzerСервис analyzerCONNECT, USAGE на public, search_path=publicПолучает SELECT на данные billing и markup в public
grafana_dsDatasource-пользователь GrafanaCONNECT, USAGE на public, search_path=publicПолучает SELECT на данные smartcpd, billing и markup в public

Часть таблиц SmartCPD является партиционированными, и их дочерние таблицы могут создаваться автоматически в процессе работы или миграций. Чтобы не требовать ручного вмешательства при каждом таком изменении, важно, чтобы новые сущности наследовали grants, уже заданные для соответствующих ролей и схем.

Дата формирования

Powered by Altuera