Как выполнить sp_send_dbmail при ограничении разрешений - PullRequest
4 голосов
/ 10 февраля 2009

Есть ли способ предоставить пользователям в моей базе данных доступ для выполнения msdb.dbo.sp_send_dbmail без необходимости добавлять их в базу данных MSDB и DatabaseMailUserRole?

Я пробовал это:

ALTER PROCEDURE [dbo].[_TestSendMail]
(
  @To NVARCHAR(1000),
  @Subject NVARCHAR(100),
  @Body NVARCHAR(MAX)
)
WITH EXECUTE AS OWNER
AS 
    BEGIN
        EXEC msdb.dbo.sp_send_dbmail @profile_name = N'myProfile',
            @recipients = @To, @subject = @Subject, @body = @Body
    END

Но я получаю эту ошибку:

The EXECUTE permission was denied on the object 'sp_send_dbmail', database 'msdb', schema 'dbo'.

Спасибо!

Ответы [ 3 ]

5 голосов
/ 13 февраля 2009

Ваш подход в порядке, но ваш упаковщик должен находиться в базе данных msdb. Затем вы выполняете «EXEC msdb.dbo._TestSendMail»

Это все еще оставляет проблему с разрешениями для dbo._TestSendMail в msdb. Но public / EXECUTE будет достаточно: он предоставляет только 3 параметра, которые вам нужны.

Если сомневаетесь, добавьте WITH ENCRYPTION. Этого достаточно, чтобы остановить кого-либо без прав сисадмина при просмотре кода

USE msdb
GO
CREATE PROCEDURE [dbo].[_TestSendMail]
(
  @To NVARCHAR(1000),
  @Subject NVARCHAR(100),
  @Body NVARCHAR(MAX)
)
-- not needec WITH EXECUTE AS OWNER
AS 
    BEGIN
        EXEC dbo.sp_send_dbmail @profile_name = N'myProfile',
            @recipients = @To, @subject = @Subject, @body = @Body
    END
2 голосов
/ 25 ноября 2009

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

CREATE DATABASE TestDBMail
GO

USE [TestDBMail]
GO

CREATE PROCEDURE [dbo].[TestSendMail]
(       
        @To NVARCHAR(1000),  
        @Subject NVARCHAR(100),  
        @Body NVARCHAR(MAX)
)
WITH EXECUTE AS OWNER
AS
BEGIN
        EXEC msdb.dbo.sp_send_dbmail 
                        @profile_name = N'Database Mail Profile',
                        @recipients = @To, 
                        @subject = @Subject, 
                        @body = @Body    
END
GO

-- This should fail
EXECUTE [dbo].[TestSendMail] 'someemail@domain.com', 'test', 'body'

-- Create a certificate to sign stored procedures with
CREATE CERTIFICATE [DBMailCertificate]
ENCRYPTION BY PASSWORD = '$tr0ngp@$$w0rd'
WITH SUBJECT = 'Certificate for signing TestSendMail Stored Procedure';
GO

-- Backup certificate so it can be create in master database
BACKUP CERTIFICATE [DBMailCertificate]
TO FILE = 'd:\Backup\DBMailCertificate.CER';
GO

-- Add Certificate to Master Database
USE [master]
GO
CREATE CERTIFICATE [DBMailCertificate]
FROM FILE = 'd:\Backup\DBMailCertificate.CER';
GO

-- Create a login from the certificate
CREATE LOGIN [DBMailLogin]
FROM CERTIFICATE [DBMailCertificate];
GO

-- The Login must have Authenticate Sever to access server scoped system tables
-- per http://msdn.microsoft.com/en-us/library/ms190785.aspx
GRANT AUTHENTICATE SERVER TO [DBMailLogin]
GO

-- Create a MSDB User for the Login
USE [msdb]
GO
CREATE USER [DBMailLogin] FROM LOGIN [DBMailLogin]
GO

-- Add msdb login/user to the DatabaseMailUserRole
EXEC msdb.dbo.sp_addrolemember @rolename = 'DatabaseMailUserRole', @membername = 'DBMailLogin';
GO

USE [TestDBMail]
GO

-- Sign the procedure with the certificate's private key
ADD SIGNATURE TO OBJECT::[TestSendMail]
BY CERTIFICATE [DBMailCertificate] 
WITH PASSWORD = '$tr0ngp@$$w0rd';
GO

-- This will succeed
EXECUTE [dbo].[TestSendMail] 'someemail@domain.com', 'test', 'body'

/*
-- Cleanup
USE [msdb]
GO
DROP USER [DBMailLogin]
GO
USE [master]
GO
DROP LOGIN [DBMailLogin]
DROP CERTIFICATE [DBMailCertificate]
DROP DATABASE [TestDBMail]

-- Delete the certificate backup from disk

*/
1 голос
/ 11 февраля 2009

Одним из возможных решений является инкапсуляция почтового сообщения в виде хранимой процедуры, например. mail_error_as_MAILER (который вы позже позвоните) и еще одна хранимая процедура например,


ALTER PROCEDURE [dbo].[mail_error](@error_ID int)
SET NOCOUNT ON
declare @rc int
declare @object int
declare @src varchar(255)
declare @desc varchar(255)
declare @osql_cmd varchar(1000)
-- create shell object
exec @rc = sp_oacreate 'wscript.shell', @object out
if @rc0 
  begin
    exec sp_oageterrorinfo @object, @src out, @desc out
    return
  END

  DECLARE @user VARCHAR(50)
  DECLARE @password VARCHAR(50)
  DECLARE @database VARCHAR(50)
  DECLARE @server VARCHAR(50)
  DECLARE @sql varchar(200) 
 SET @user=MAILER,@password=XXXXXX,@database=XXXXXX,@server=XXXXX 
SET @sql= 'EXEC mail_ERROR_as_MAILER @error_ID=' + CAST(@error_id as varchar(10))
set @osql_cmd='osql -U'+@user+' -P'+@password+' -d'+@database+' -S"'+@server+'"  -Q"'
  +@sql+'"'

exec @rc= sp_oamethod @object, 'run', null, @osql_cmd
--print @rc
if @rc0 
  begin
    exec sp_oageterrorinfo @object, @src out, @desc out
    return
  end
-- destroy shell object
exec sp_oadestroy @object

Но для этого необходимо: * жесткий пароль (убедитесь, что пользователи не могут просматривать определение хранимой процедуры ...) * предоставление пользователям доступа к sp_oacreate и т. д. (открывает другие проблемы с безопасностью, например, DOS)

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

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

Или: дайте им разрешение на почту, но возьмите большой клуб с ржавыми шипами от оскорблений

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