Управление правами для работы с функциями и представлениями (Views) в MySQL

Контроль доступа к процедурам и просмотрам в MySQLПеревод в своем изложении Access Control for Stored Programs and Views Определенные в БД хранимые программы (процедуры, функции, триггеры и события) и просмотры (представления, Views) выполняются в контексте безопасности, который определяется привилегиями вызывающего. Эти привилегии контролируются через атрибут DEFINER и, при необходимости, атрибутом SQL SECURITY. В примерах ниже, работа идет в БД world (стандартная демонстрационная БД от MySQL)

Например, в первой строке указывается автор процедуры :

  1. CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1()
  2. SQL SECURITY DEFINER
  3. BEGIN
  4. UPDATE t1 SET counter = counter + 1;

Все сохраненные программы (процедуры, функции, триггеры и события) и представления могут иметь атрибут DEFINER с именем учетной записи MySQL. Если атрибут DEFINER в хранимой процедуре или представлении не используется, то учетной записью по умолчанию является пользователь, создающий один из перечисленных объектов.

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

  1. CREATE
  2. DEFINER = CURRENT_USER
  3. VIEW show_user AS SELECT * FROM mysql.user

Кроме того, хранимые процедуры (процедуры и функции) и представления могут иметь характеристику SQL SECURITY со значениями DEFINER или INVOKER,для указания того выполняется ли объект в авторском контексте или он работает в другом контексте. Если характеристика SQL SECURITY опущена, контекстом по умолчанию является авторский контекст.

Триггеры и события не имеют характеристики SQL SECURITY и всегда выполняются в контексте автора (DEFINER). Сервер автоматически вызывает эти объекты по мере необходимости, поэтому нет пользователя который бы запускал эти объекты.

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

  • Хранимые процедуры или представления, используемые в контексте безопасности автора, работают с привилегиями учетной записи с атрибутом DEFINER. Эти привилегии могут полностью отличаться от вызывающего пользователя. Вызывающий должен иметь соответствующие права для возможности ссылаться на объект (например, EXECUTE для вызова хранимой процедуры или SELECT для выборки данных из представления), но когда объект выполняется, привилегии другого вызывающего игнорируются и только DEFINER определяет необходимые текущие привилегии. Если эта учетная запись имеет меньше привилегий, объект, соответственно, ограничен в операциях, которые он может выполнять. Если учетная запись DEFINER имеет много привилегий (например, учетная запись root), объект может выполнить мощные операции независимо от того, кто его вызывает.
  • Хранимая программа или представление, выполняемые не в авторском контексте могут выполнять только операции которым соответствуют привилегии вызывающего (не автора программы или представления). Атрибут DEFINER может быть указан, но не влияет на объекты, которые выполняются в контексте вызывающего.

Рассмотрим следующую хранимую процедуру:

  1. CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1()
  2. SQL SECURITY DEFINER
  3. BEGIN
  4. UPDATE t1 SET counter = counter + 1;

Любой пользователь, который имеет привилегию EXECUTE на над процедурой p1 может вызвать ее с помощью оператора CALL. Однако, когда p1 выполняется, она делает это в контексте безопасности DEFINER и, следовательно, выполняется с привилегиями 'admin'@'localhost' , учетной записи, указанной в атрибуте DEFINER. Эта учетная запись должна иметь привилегию EXECUTE для p1 , а также UPDATE привилегии для таблицы t1 . В противном случае, процедура не выполняется.

Теперь рассмотрим эту хранимую процедуру, которая идентична p1 за исключением того, что его характеристика SQL SECURITY содержит INVOKER :

  1. CREATE DEFINER = 'admin'@'localhost' PROCEDURE p2()
  2. SQL SECURITY INVOKER
  3. BEGIN
  4. UPDATE t1 SET counter = counter + 1;

p2 , в отличие от p1 , выполняется в контексте безопасности INVOKER. Атрибут DEFINER не имеет значения и p2 выполняется с привилегиями вызывающего пользователя. p2 не выполняется, если вызывающий не хватает EXECUTE привилегий для p2 или UPDATE привилегии для таблицы t1 .

MySQL использует следующие правила для контроля учетной записи которые можно указать на атрибут DEFINER:

Вы можете задать значение DEFINER, на свои учетные записи, только если у вас есть SUPER привилегии.

Если вы не имеете SUPER привилегий, единственным законным пользователем объекта будет своя собственная учетная запись, либо указанная буквально или CURRENT_USER вместо неё . Вы не можете установить автора на другую учетную запись.

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

  • Для хранимой подпрограммы или представления, используйте SQL SECURITY INVOKER в определении объекта, когда можно быть уверенными, что объект может быть использован только пользователи с правами подходящими для операций, выполняемых на объекте.
  • Если вы создаете хранимую программу или представление в контексте автора, при использовании учетной записи, имеющей SUPER привилегии, явно указывайте атрибут DEFINER, который указывает учетные записи, обладающие только привилегии, необходимые для операций, выполняемых на объекте. Укажите сверхпривилегированным DEFINER учетные записи только тогда, когда это абсолютно необходимо.
  • Администраторы могут запретить пользователям указанием привилегированным DEFINER счета, не предоставив им SUPER привилегий.
  • Авторский контекст объектов должен быть написан, имея в виду, что они могут получить доступ к данным, для которых вызывающий пользователь не имеет привилегий. В некоторых случаях, вы можете предотвратить ссылки на эти объекты не предоставления неавторизованным пользователям особые привилегии:
    • Хранимая процедура или функция не может ссылаться на пользователя, который не имеет EXECUTE честь для него.
    • Представление не может ссылаться на пользователей, которые не имеют соответствующих привилегий для него ( SELECT чтобы выбрать из него, INSERT чтобы вставить в него, и так далее).

Тем не менее, подобного контроля не существует для триггеров, поскольку пользователи не ссылаться на них напрямую. Триггер всегда выполняется в контексте автора и активирует доступ к таблице, с которой он связан, даже обычный стол доступ пользователям без особых привилегий. Если DEFINER счет весьма привилегированный, триггер может выполнять чувствительные или опасные операции. Это остается верным, если SUPER и TRIGGER привилегии, необходимые для создания триггера отозван из учетной записи пользователя, который ее создал. Администраторы должны быть особенно осторожны в предоставлении пользователям сочетание привилегий.

Пример1. Создание процедуры и ее использование
---------------------------------------------------
Создаю от имени root процедуру считающую кол-во пользователей в MySQL (бд world)

  1. DELIMITER |
  2. CREATE DEFINER = 'root'@'localhost' PROCEDURE account_count()
  3. SQL SECURITY INVOKER
  4. BEGIN
  5. SELECT 'Число учетных записей:', COUNT(*) FROM mysql.user;
  6. |
  7. DELIMITER ;

Выполняю от имени root:
  1. CALL account_count();

Создаю нового пользователя

  1. CREATE USER 'some'@'localhost' IDENTIFIED BY 'password2';
  2. GRANT SELECT ON world.* TO 'some'@'localhost';
  3.  
  4. mysql -usome -ppassword2 world

Вызываю
  1. CALL account_count();

Получаю: не имею прав для работы с account_count

Даю права

  1. GRANT CREATE ROUTINE ON world.* TO 'some'@'localhost';
  2. GRANT EXECUTE ON PROCEDURE world.account_count TO 'some'@'localhost';
  3.  
  4. SHOW GRANTS FOR 'some'@'localhost'

Но не хватает прав для выборки из mysql.user!
Даю права GRANT SELECT ON mysql.user TO 'some'@'localhost';
Все работает!

  1. DROP PROCEDURE IF EXISTS account_count;
  2. DROP USER 'some'@'localhost';

Пример 2 Создание функции и использование ее в контексте автора
---------------------------------------------------
Теперь работаю с DEFINER
Создаю от имени root процедуру считающую кол-во пользователей в MySQL (бд world)

  1. DELIMITER |
  2. CREATE DEFINER = 'root'@'localhost' PROCEDURE account_count()
  3. SQL SECURITY DEFINER
  4. BEGIN
  5. SELECT 'Число учетных записей:', COUNT(*) FROM mysql.user;
  6. |
  7. DELIMITER ;

Выполняю от имени root:
  1. CALL account_count();

Создаю нового пользователя

  1. CREATE USER 'some'@'localhost' IDENTIFIED BY 'password2';
  2. GRANT SELECT ON world.* TO 'some'@'localhost';
  3.  
  4. mysql -usome -ppassword2 world

Вызываю CALL account_count();
Получаю: не имею прав для работы с account_count

Даю права

  1. GRANT CREATE ROUTINE ON world.* TO 'some'@'localhost';
  2. GRANT EXECUTE ON PROCEDURE world.account_count TO 'some'@'localhost';

Все работает! Не потребовались права для работы с mysql.user!

  1. DROP PROCEDURE IF EXISTS account_count;
  2. DROP USER 'some'@'localhost';

Отправить комментарий

CAPTCHA
Этот вопрос задается для того, чтобы выяснить, пьёте ли Вы кофе или рассылаете спам
2 + 6 =
Решите эту простую математическую задачу и введите результат. То есть для 1+3, введите 4.