Приложение получает от Stronghold отдельного пользователя MySQL или MariaDB с правами только на свою базу данных. Stronghold создаёт пользователя при запросе учётных данных и удаляет его при отзыве или по истечении аренды. Постоянный пароль приложения не нужен.

Цель
Настроить выдачу динамических учётных данных MySQL или MariaDB приложению myapp: пользователь получает права SELECT, INSERT, UPDATE и DELETE на базу данных myapp, живёт 1 час с возможностью продления до 24 часов и удаляется после отзыва аренды.
Предварительные требования
Для выполнения примера нужны:
- Stronghold и токен с правами на настройку механизмов секретов и политик.
- Сервер MySQL 5.7 и выше или MariaDB, доступный из Stronghold, и база данных
myapp. - Клиент
mysqlи утилитаjqна рабочей станции для проверки.
Для MySQL 5.7.8 и новее и для MariaDB используйте mysql-database-plugin (имена пользователей до 32 символов), для MySQL 5.6 и старее — mysql-legacy-database-plugin (до 16 символов). Задайте root_rotation_statements, как описано в разделе «MySQL».
Шаг 1. Подготовьте служебную учётную запись в MySQL
Создайте учётную запись, от имени которой Stronghold будет создавать и удалять пользователей. Чтобы выдавать права на базу данных myapp, учётная запись должна сама иметь эти права с GRANT OPTION:
CREATE USER 'stronghold'@'%' IDENTIFIED BY '<INITIAL_PASSWORD>';
GRANT CREATE USER ON *.* TO 'stronghold'@'%';
GRANT SELECT, INSERT, UPDATE, DELETE ON myapp.* TO 'stronghold'@'%' WITH GRANT OPTION;<INITIAL_PASSWORD> — начальный пароль служебной учётной записи. На шаге 2 Stronghold заменит его сгенерированным.
Ограничьте хост '%' адресами узлов Stronghold, если это возможно.
Шаг 2. Настройте подключение
Включите механизм секретов database и подключите его к MySQL:
Включите механизм секретов, если он ещё не включён:
d8 stronghold secrets enable databaseНастройте подключение к серверу:
d8 stronghold write database/config/myapp-mysql plugin_name="mysql-database-plugin" connection_url="{{username}}:{{password}}@tcp(mysql.example.com:3306)/" allowed_roles="myapp-mysql" username="stronghold" password="<INITIAL_PASSWORD>"Для подключения по TLS добавьте параметр
tls_ca=@/path/to/ca.pem, а для аутентификации по клиентскому сертификату —tls_certificate_key=@/path/to/client.pem.Смените пароль служебной учётной записи, чтобы он был известен только Stronghold:
d8 stronghold write -force database/rotate-root/myapp-mysql
Шаг 3. Создайте роль
Роль задаёт SQL-запросы для создания и удаления пользователя и сроки жизни учётных данных:
d8 stronghold write database/roles/myapp-mysql db_name="myapp-mysql" creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT, INSERT, UPDATE, DELETE ON myapp.* TO '{{name}}'@'%';" revocation_statements="REVOKE ALL PRIVILEGES, GRANT OPTION FROM '{{name}}'@'%'; DROP USER '{{name}}'@'%';" default_ttl="1h" max_ttl="24h"creation_statements— запросы, которые Stronghold выполняет при выдаче учётных данных. Шаблоны{{name}}и{{password}}заменяются сгенерированными значениями;revocation_statements— запросы, которые выполняются при отзыве аренды;default_ttl— срок аренды при выдаче и при каждом продлении;max_ttl— максимальный срок жизни учётных данных, после которого пользователь удаляется.
Если в запросе нужны шаблоны имён баз данных с обратными кавычками (например, GRANT SELECT ON `myapp\_%`.* ...), передайте creation_statements в кодировке Base64, как описано в разделе «MySQL».
Шаг 4. Создайте политику
Создайте политику, которая разрешает читать учётные данные роли myapp-mysql:
d8 stronghold policy write myapp-mysql - <<'POLICY'
path "database/creds/myapp-mysql" {
capabilities = ["read"]
}
POLICYНазначьте политику роли метода аутентификации, через который входит приложение, например роли метода Kubernetes, как в руководстве «Динамические учётные данные PostgreSQL». Продление и отзыв собственных аренд разрешены встроенной политикой default.
Шаг 5. Получите учётные данные
Запросите учётные данные роли myapp-mysql и управляйте их арендой:
Запросите учётные данные:
d8 stronghold read database/creds/myapp-mysqlПример вывода:
Key Value --- ----- lease_id database/creds/myapp-mysql/2f6a614c-4aa2-7b19-24b9-ad944a8d4de6 lease_duration 1h lease_renewable true password yY-57n3X5UQhxnmFRP3f username v-token-myapp-mysq-crBWVqVh2Hc1xПродлите аренду до истечения
lease_duration. Каждое продление увеличивает срок наdefault_ttl, но не дальшеmax_ttl:d8 stronghold lease renew database/creds/myapp-mysql/2f6a614c-4aa2-7b19-24b9-ad944a8d4de6Когда учётные данные больше не нужны, отзовите аренду. Stronghold выполнит
revocation_statementsи удалит пользователя:d8 stronghold lease revoke database/creds/myapp-mysql/2f6a614c-4aa2-7b19-24b9-ad944a8d4de6
В рабочей среде продлением и повторным запросом учётных данных управляет Stronghold Agent. Пример шаблона для файла с переменными окружения:
{{ with secret "database/creds/myapp-mysql" }}
DB_USER={{ .Data.username }}
DB_PASSWORD={{ .Data.password }}
{{ end }}Конфигурация Agent в режиме sidecar приведена в разделе «Доставка секретов в поды Kubernetes», для виртуальных машин — в разделе «Приложение на ВМ». Требования к приложению при смене учётных данных такие же, как в руководстве «Динамические учётные данные PostgreSQL».
Проверка
Проверьте результат:
Запросите учётные данные в формате JSON и сохраните их в переменные:
creds="$(d8 stronghold read -format=json database/creds/myapp-mysql)" DB_USER="$(echo "$creds" | jq -r '.data.username')" DB_PASSWORD="$(echo "$creds" | jq -r '.data.password')" LEASE_ID="$(echo "$creds" | jq -r '.lease_id')"Подключитесь клиентом
mysqlи проверьте права пользователя:mysql -h mysql.example.com -u "$DB_USER" -p"$DB_PASSWORD" myapp -e "SELECT CURRENT_USER(); SHOW GRANTS;"Кроме
GRANT USAGE ON *.*, вывод содержит только праваSELECT, INSERT, UPDATE, DELETEнаmyapp.*.Убедитесь, что доступа к другим базам данных нет:
mysql -h mysql.example.com -u "$DB_USER" -p"$DB_PASSWORD" -e "SELECT * FROM mysql.user LIMIT 1;"Команда должна завершиться ошибкой
SELECT command denied.Отзовите аренду и проверьте, что пользователь удалён:
d8 stronghold lease revoke "$LEASE_ID" mysql -h mysql.example.com -u "$DB_USER" -p"$DB_PASSWORD" -e "SELECT 1;"Подключение должно завершиться ошибкой
Access denied.
Очистка
Удалите объекты, созданные в примере:
Отзовите все выданные учётные данные роли:
d8 stronghold lease revoke -prefix database/creds/myapp-mysql/Удалите роль, политику и подключение:
d8 stronghold policy delete myapp-mysql d8 stronghold delete database/roles/myapp-mysql d8 stronghold delete database/config/myapp-mysqlПри необходимости удалите служебную учётную запись в MySQL:
DROP USER 'stronghold'@'%';.