Проблема с разрешениями базы данных для sp_send_mail

8

Я пытаюсь отправить почту из базы данных, но получаю EXECUTE permission denied on the object 'sp_send_dbmail' database 'msdb', schema 'dbo'.. Я использую следующий код:

SELECT SUSER_NAME(), USER_NAME();
Create USER kyle_temp FOR LOGIN Foo
EXECUTE AS USER = 'kyle_temp';
SELECT SUSER_NAME(), USER_NAME();
EXEC msdb.dbo.sp_send_dbmail @profile_name = 'Mail Profile',
            @recipients = 'test@test.com',
            @subject = 'Test',
              @body = 'Test'
REVERT;
DROP USER kyle_temp

Вход в Foo показывает, что он сопоставлен с пользователем Foo в msdb. Когда я смотрю на пользователя foo в msdb, я вижу, что у него проверено «DatabaseMailUserRole» и есть Execute on dbo sp_send_dbmail.

Что мне не хватает?

Кайл Брандт
источник

Ответы:

10

Вы работаете в страшном «изолированном» режиме EXECUTE ASконтекста, как описано в разделе Расширение олицетворения базы данных с помощью EXECUTE AS . В коротком коде, запущенном в EXECUTE AS USER ..., доверяют только внутри контекста базы данных , а не в контексте экземпляра.

Есть три выхода:

  • самый простой способ: пометить текущую базу данных как TRUSTWORTHY ALTER DATABASE [...] SET TRUSTWORTHY ON;
  • правильный выход: используйте подпись кода
  • чит: использовать EXECUTE AS LOGIN

Если в вашей среде dboтекущая база данных является доверенной, вы можете использовать TRUSTWORTHY. Это будет работать, но если это свойство установлено, то любой db_ownerв текущей БД может поднять себя до уровня администратора сервера.

Если вы хотите «правильное» решение, тогда:

  1. переместить этот код в сохраненный процесс
  2. подписать сохраненный протокол сертификатом
  3. отбросьте закрытый ключ (чтобы он никогда больше не использовался для подписи)
  4. экспортировать открытый ключ, импортировать его в [msdb]
  5. создать пользователя в [msdb]производном от этого сертификата
  6. предоставить необходимые разрешения (AUTHENTICATE, EXECUTE для sp_send_mail) пользователю, получающему сертификат

Тривиально, а? Кстати, каждый раз, когда вы изменяете подписанный сохраненный протокол, подпись теряется, и процедуру необходимо повторить. См. Пример вызова процедуры в другой базе данных из активированной процедуры .

Я полностью не рекомендую использовать EXECUTE AS LOGINвместо этого.

Ремус Русану
источник
В долгосрочной перспективе я пытаюсь выполнить это как триггер, поэтому мой EXECUTE AS - это способ тестирования в краткосрочной перспективе ...
Кайл Брандт,
1
Самый простой способ - иметь локальный хранимый процесс в вашей БД и иметь вызов msdb.dbo.sp_send_mailв этом локальном теле SP. Пусть триггер вызовет этот локальный SP. Кодовый знак ИП.
Ремус Русану