2.5. Управление доступом

В кластере Shardman действует традиционная модель безопасности PostgreSQL, дополненная функциональностью распределённых СУБД. В этом разделе описана данная функциональность, а также даётся общее представление об управлении доступом в кластере Shardman.

2.5.1. Параметры инициализации кластера по настройке управления доступом

Параметры кластера Shardman, связанные с безопасностью, берутся из файла инициализации. Можно изменить их позднее, но это следует делать с осторожностью, помня, что в большинстве случаев любое изменение потребует перезапуска СУБД.

В кластере Shardman есть два специальных пользователя: администратор и пользователь репликации. Shardman и stolon управляют экземплярами СУБД через администраторов. Репликация между контролируемыми экземплярами СУБД осуществляется stolon через пользователей репликации.

Параметры безопасности в файле инициализации задают:

  • Методы аутентификации для администраторов и пользователей репликации — PgSuAuthMethod, PgReplAuthMethod.

  • Имена для администраторов и пользователей репликации — PgSuUsername, PgReplUsername

  • Пароли для администраторов и пользователей репликации — PgSuPassword, PgReplPassword

  • Правила в файле pg_hba.conf, используемые экземплярами СУБД — StolonSpec.pgHBA

Более подробно эти параметры рассматриваются в описании sdmspec.json.

Чтобы задать параметры безопасности, выполните следующие действия:

  1. Проверьте, что пользователь, который будет указан в PgReplUsername/PgSuUsername, имеет права REPLICATION/SUPERUSER во всех группах репликации в кластере, и укажите его действующий пароль в PgReplPassword/PgSuPassword.

  2. Если всё верно, создайте дамп ключа etcd shardman/cluster0/data/cluster (здесь и далее имя кластера Shardmancluster0). Например:

    $ etcdctl --endpoints etcdserver:2379 get --print-value-only  shardman/cluster0/data/cluster |jq . > clusterdata.json
    

    В этом примере создаётся дамп ключа data/cluster для кластера Shardman с именем cluster0 с сервера etcd etcdserver, принимающего подключения через порт 2379, дамп форматируется при помощи jq и сохраняется в файл clusterdata.json.

  3. При необходимости отредактируйте дамп и сохраните его обратно в etcd:

    $ cat clusterdata.json | etcdctl --endpoints etcdserver:2379 put shardman/cluster0/data/cluster
    

Изменение этих параметров приведёт к перезапуску СУБД.

В отличие от вышеуказанных параметров, параметр StolonSpec.pgHBA может быть изменён без перезапуска СУБД. Чтобы изменить его, выполните следующие действия:

  1. Извлеките определение StolonSpec из shardman/cluster0/data/cluster, сохраните в какой-нибудь файл, измените при необходимости и обновите параметры кластера командой shardmanctl config update:

    $ etcdctl --endpoints etcdserver:2379 get --print-value-only  shardman/cluster0/data/cluster | jq .Spec.StolonSpec . > stolonspec.json
    
  2. Отредактируйте в файле stolonspec.json определение StolonSpec.pgHBA соответствующим образом, например:

    "pgHBA": [
            "host all postgres 0.0.0.0/0 scram-sha-256",
            "host replication postgres 0.0.0.0/0 scram-sha-256",
            "host replication postgres ::0/0 scram-sha-256",
            "host all someuser 0.0.0.0/0 scram-sha-256"
          ],
  3. Примените изменения, внесённые в файл stolonspec.json:

    $ shardmanctl --store-endpoints etcdserver:2379 --cluster-name cluster0 config update -f stolonspec.json
    

2.5.2. Управление пользователями и ролями

Пользователи и роли в кластере Shardman — это обычные пользователи и роли PostgreSQL. Можно управлять ими отдельно на каждом сервере или глобально, используя DDL на уровне кластера. В Shardman также используются понятия глобальных пользователей и глобальных ролей. И только глобальные пользователи (или роли) могут создавать другие объекты Shardman и владеть ими на уровне кластера, такими как сегментированные или глобальные таблицы. Операции таких пользователей всегда выполняются одновременно на всех группах репликации. Например, когда глобальная роль включается в какую-то другую роль или удаляется, эта операция будет выполняться для всех групп репликации.

Можно создать глобального пользователя, используя оператор CREATE USER ... IN ROLE global, например:

CREATE USER someuser ENCRYPTED PASSWORD 'somepass' IN ROLE global;

При создании глобального пользователя Shardman автоматически создаёт сопоставление пользователя во всех группах репликации и предоставляет этому пользователю доступ ко всем сторонним серверам, входящим в существующие группы репликации. Поэтому при создании глобального пользователя нужно либо задать незашифрованный пароль, чтобы его можно было сохранить в пользовательском сопоставлении, либо вообще не задавать пароль. Глобальные роли (в том числе глобальные пользователи), для которых не задан пароль, не могут получить доступ к сторонним серверам. Однако глобальной роли можно выдать нужный набор разрешений, чтобы затем предоставлять их пользователям, включая их в эту роль. Кроме того, можно задать пароль для глобального пользователя позже.

Глобальных пользователей может создавать только пользователь с правом CREATEROLE на всех узлах кластера.

Операторы ALTER и DROP для глобальных пользователей транслируются всем группам репликации. Когда роль предоставляется глобальному пользователю, эта операция также транслируется. Переименование глобального пользователя не поддерживается, поскольку это делает недействительными пароли md5/scram-sha-256, хранящиеся в сопоставлениях пользователей.

Список глобальных пользователей хранится в таблице shardman.users.

Роль, заданная в PgSuUsername (обычно postgres), также создаётся как глобальная во время инициализации кластера. Однако роль, заданная в PgReplUsername, создаётся как локальная в каждой группе репликации.

Роль global зарезервирована и не может напрямую использоваться в кластере Shardman. Обратите внимание, что «global» является не фактически заданной ролью, а просто зарезервированным словом.

2.5.3. Управление разрешениями в сегментированных таблицах

В Shardman сегментированная таблица — это по сути секционированная таблица, где секции представляют собой либо локальные сегменты, либо сторонние таблицы, ссылающиеся на сегменты в других группах репликации.

Разрешения, установленные для сегментированной таблицы, транслируются для всех групп репликации и всех секций таблицы.

Когда в кластер добавляется новая группа репликации, клиент shardmanctl копирует схему из случайной существующей группы репликации в новую. Он также создаёт сторонний сервер для новой группы репликации во всех существующих группах репликации и пересоздаёт сторонние серверы в новых группах репликации. Разрешения для созданных сторонних серверов и сопоставления пользователей копируются со случайного стороннего сервера в существующей группе репликации. В новой группе репликации для каждой секции сегментированной таблицы shardmanctl создаёт стороннюю таблицу, ссылающуюся на существующий сегмент, и заменяет секцию этой сторонней таблицей. Позже некоторые из этих сторонних таблиц могут быть заменены на реальные таблицы. Это происходит на этапе перебалансировки команды shardmanctl nodes add, если перебалансировка включена. Данные для этих секций переносятся с существующих узлов с использованием логической репликации. Когда shardmanctl создаёт таблицы (или сторонние таблицы), он копирует разрешения из родительской таблицы. В родительской таблице уже должны быть правильные разрешения, поскольку они были скопированы из существующей группы репликации.

2.5.3.1. Примеры

Для выполнения команд в данном примере требуются права администратора.

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

CREATE USER someuser ENCRYPTED PASSWORD 'somepass' IN ROLE global;
CREATE TABLE pgbench_branches (
       bid integer NOT NULL PRIMARY KEY,
       bbalance integer,
       filler character(88)
)
WITH (distributed_by = 'bid', num_parts = 8);
GRANT SELECT ON pgbench_branches TO someuser;

Чтобы разрешить пользователю someuser доступ к кластеру Shardman, необходимо задать соответствующие параметры в pg_hba.conf (как было показано здесь).

Теперь предположим, что командой shardmanctl nodes add в кластер добавлено новое звено, например:

$ shardmanctl --store-endpoints http://etcdserver:2379 --cluster-name cluster0 nodes add -n newnode1,newnode2

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

DROP USER someuser;