Как написать хорошие сценарии грантов Mysql - PullRequest
6 голосов
/ 05 октября 2011

Я использую сценарии для создания баз данных и таблиц Mysql. Эти сценарии содержат разделы грантов, такие как:

GRANT SELECT ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
REVOKE ALL PRIVILEGES ON my_database.* FROM my_user@"%";
GRANT SELECT, UPDATE ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';

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

Затем я столкнулся со следующей проблемой: всякий раз, когда я запускал скрипт на «свежей» установке Mysql, отзыв не выполнялся, потому что пользователь еще не существовал. Поэтому я добавил «фиктивный» грант перед отменой.

Вопрос: Есть ли лучший способ сделать это? Мои «настоящие» сценарии содержат много пользователей и множество баз данных, и их трудно читать, потому что мне нужно три строки для каждого набора привилегий, которые я хочу назначить. Я хотел бы использовать только одну строку.

Изменить (на основе отзывов и ответов):

Я ищу кратчайший способ сказать что-то вроде

SET PRIVILEGES SELECT, UPDATE
ON my_database.*
TO my_user@"%"
IDENTIFIED BY 'my_password';

где my_user может

  • уже существует (но может быть новым)
  • в настоящее время имеют привилегии, расширяющие те, которые я хочу, чтобы он имел
  • имеют права доступа к другим базам данных, которые должны оставаться неизменными

Ответы [ 4 ]

5 голосов
/ 13 октября 2011

Вы можете использовать процедуру для создания нового пользователя при необходимости и предоставления привилегий для базы данных. Я использовал подготовленные операторы и операторы GRANT. Подготовленные операторы в MySQL 5.5 поддерживают GRANT. Если вы используете более раннюю версию, вы можете переписать команду GRANT для INSERT INTO.

ИСПОЛЬЗОВАНИЕ теста;

DELIMITER $$

CREATE PROCEDURE procedure_user(
  IN host_name VARCHAR(60),  IN user_name VARCHAR(60),
  IN db_name   VARCHAR(255),
  IN db_privs  VARCHAR(255))
BEGIN
  SELECT 1 INTO @exist FROM mysql.user WHERE user = user_name AND host = host_name;

  -- Create new user, generate command like this: CREATE USER 'user1'@'%';;
  IF @exist IS NULL THEN

    SET @sql = CONCAT('CREATE USER ''', user_name, '''@''', host_name, '''');
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END IF;

  -- Generate command like this: GRANT INSERT, UPDATE ON database1.* TO 'user1'@'%';
  SET @sql = CONCAT('GRANT ', db_privs, ' ON ', db_name, '.* TO ''', user_name, '''@''', host_name, '''');
  PREPARE stmt FROM @sql;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
END
$$

DELIMITER ;

Использование примеров:

-- First command will create new user user1@% and will grant SELECT, INSERT, UPDATE privileges to database1.
CALL procedure_user('%', 'user1', 'database1', 'SELECT, INSERT, UPDATE');

-- Second command just will grant SELECT, INSERT, UPDATE privileges to database2 to that user.
CALL procedure_user('%', 'user1', 'database2', 'SELECT, INSERT, UPDATE');
3 голосов
/ 14 октября 2011

Извините за длинный ответ, который на самом деле комментарий, но я его не понимаю. Ваша команда GRANT "третьей линии" хорошо работает для меня. Вот два случая, которые должны работать. Было бы здорово, если бы вы могли опубликовать несколько тестовых команд, которые воспроизводят ошибку. По крайней мере, я мог бы извлечь уроки из этого:)

Случай № 1, пользователь не существует:

mysql> SHOW GRANTS FOR my_user@"%";
ERROR 1141 (42000): There is no such grant defined for user 'my_user' on host '%'

ОК, пользователь не существует.

mysql> create database my_database;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT SELECT ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW GRANTS FOR my_user@"%";
+-----------------------------------------------------------------------+
| Grants for my_user@%                                                  |
+-----------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'my_user'@'%' IDENTIFIED BY PASSWORD '*CC...18' | 
| GRANT SELECT ON `my_database`.* TO 'my_user'@'%'                      | 
+-----------------------------------------------------------------------+
2 rows in set (0.00 sec)

ОК, у него есть разрешение SELECT.

Случай № 2, пользователь существует и имеет права на other_database и my_database тоже:

mysql> SHOW GRANTS FOR my_user@"%";
ERROR 1141 (42000): There is no such grant defined for user 'my_user' on host '%'

ОК, пользователь не существует.

mysql> create database my_database;
Query OK, 1 row affected (0.00 sec)

mysql> create database other_database;
Query OK, 1 row affected (0.01 sec)

mysql> GRANT SELECT ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT SELECT ON other_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW GRANTS FOR my_user@"%";
+-----------------------------------------------------------------------+
| Grants for my_user@%                                                  |
+-----------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'my_user'@'%' IDENTIFIED BY PASSWORD '*CC...18' | 
| GRANT SELECT ON `other_database`.* TO 'my_user'@'%'                   | 
| GRANT SELECT ON `my_database`.* TO 'my_user'@'%'                      | 
+-----------------------------------------------------------------------+
3 rows in set (0.00 sec)

Выше приведено тестовое устройство, и теперь мы предоставляем новое разрешение UPDATE пользователю:

mysql> GRANT UPDATE ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW GRANTS FOR my_user@"%";
+-----------------------------------------------------------------------+
| Grants for my_user@%                                                  |
+-----------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'my_user'@'%' IDENTIFIED BY PASSWORD '*CC...18' | 
| GRANT SELECT ON `other_database`.* TO 'my_user'@'%'                   | 
| GRANT SELECT, UPDATE ON `my_database`.* TO 'my_user'@'%'              | 
+-----------------------------------------------------------------------+
3 rows in set (0.00 sec)

Его разрешение не изменилось на other_database, и он получил новое разрешение UPDATE на my_database и прежнее SELECT.


На основании комментариев должно быть только UPDATE без SELECT.

К сожалению, в текущих версиях MySQL это невозможно сделать только одной командой. GRANT не имеет предложения REMOVE EXISTING.

Я думаю, что лучшее решение - @ eswald's GRANT USAGE ON ..., но это все еще 3 команды. Другое решение -

DELETE FROM mysql.db WHERE user = 'my_user' AND host ='%' AND db = 'my_database'

но ему нужно FLUSH PRIVILEGES, поэтому это также 3 команды.

Обходным решением может быть скрипт bash, который генерирует три команды, о которых идет речь:

#!/bin/bash

function grant {
    USER=$1
    PASSWORD=$2
    DB=$3
    PERMISSIONS=$4

    echo "GRANT USAGE ON $DB TO $USER IDENTIFIED BY '$PASSWORD';"
    echo "REVOKE ALL PRIVILEGES ON $DB FROM $USER;"
    echo "GRANT $PERMISSIONS ON $DB TO $USER IDENTIFIED BY '$PASSWORD';"
}

grant "my_user@'%'" "my_password" "my_database.*" "SELECT, UPDATE"

Он печатает:

GRANT USAGE ON my_database.* TO my_user@'%' IDENTIFIED BY 'my_password';
REVOKE ALL PRIVILEGES ON my_database.* FROM my_user@'%';
GRANT SELECT, UPDATE ON my_database.* TO my_user@'%' IDENTIFIED BY 'my_password';

(я изменил первый GRANT SELECT на USAGE.)

3 голосов
/ 07 октября 2011

Чтобы убедиться, что пользователь существует без предоставления каких-либо привилегий:

GRANT USAGE ON *.* TO my_user@"%" IDENTIFIED BY 'my_password';

Если вы действительно хотите выполнить предоставление и отзыв за один шаг, вам, возможно, придется напрямую перебрать внутреннюю таблицу хранения разрешений:

INSERT INTO `mysql`.`db` (
    `Host`, `Db`, `User`,
    `Select_priv`, `Insert_priv`, `Update_priv`, `Delete_priv`,
    `Create_priv`, `Drop_priv`, `Grant_priv`, `References_priv`, `Index_priv`, `Alter_priv`,
    `Create_tmp_table_priv`, `Lock_tables_priv`, `Create_view_priv`, `Show_view_priv`,
    `Create_routine_priv`, `Alter_routine_priv`, `Execute_priv`)
VALUES (
    'my_user', '%', 'my_database',
    'Y', 'N', 'Y', 'N',
    'N', 'N', 'N', 'N', 'N', 'N',
    'N', 'N', 'N', 'N',
    'N', 'N', 'N')
ON DUPLICATE KEY UPDATE
    `Select_priv` = 'Y', `Insert_priv` = 'N', `Update_priv` = 'Y', `Delete_priv` = 'N',
    `Create_priv` = 'N', `Drop_priv` = 'N', `Grant_priv` = 'N', `References_priv` = 'N', `Index_priv` = 'N', `Alter_priv` = 'N',
    `Create_tmp_table_priv` = 'N', `Lock_tables_priv` = 'N', `Create_view_priv` = 'N', `Show_view_priv` = 'N',
    `Create_routine_priv` = 'N', `Alter_routine_priv` = 'N', `Execute_priv` = 'N';

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

Чтобы помочь с проблемой читабельности, вы можете создать своего рода CSV с учетными записями и разрешениями, сгенерировав из этого сценарий SQL.

0 голосов
/ 07 октября 2011

Мне просто интересно, ты бежал FLUSH PRIVILEGES?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...