【问题标题】:Execute SSIS package from stored procedure as proxy user without xp_cmdshell在没有 xp_cmdshell 的情况下以代理用户身份从存储过程执行 SSIS 包
【发布时间】:2015-02-16 13:50:32
【问题描述】:

我正在尝试通过存储过程运行 SSIS 包,但在尝试导入 CSV 时收到 Access is denied 错误。

我将包放入作业中并运行它,只要我使用代理帐户,它就可以工作。我正在尝试使用xp_cmdshell 将该代理帐户复制到 的存储过程调用。我也在 Visual Studio 中运行了这个包,它运行得很顺利。

我的 SSIS 包很简单:它从网络导入一个 CSV 文件,将数据转换为varchar,并将数据存储到一个表中。

即使是我的系统管理员也无法成功运行存储过程。

我的存储过程如下所示:

ALTER PROCEDURE [dbo].[spImportFile] 
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @execution_id bigint
    EXEC SSISDB.CATALOG.create_execution
        @folder_name = 'folder_name',
        @project_name = 'project_name',
        @package_name = 'package_name.dtsx',
        @use32bitruntime = 1,
        @execution_id = @execution_id output

    EXEC SSISDB.CATALOG.start_execution @execution_id
END

我的问题是,如何在不使用 xp_cmdshell 的情况下以编程方式在此存储过程中使用代理用户?


更新:

感谢billinkc,我现在正试图冒充我的代理用户,但现在我在执行 SSIS 包时遇到了这个错误:

当前的安全上下文无法恢复。请切换到调用 'Execute As' 的原始数据库,然后重试。

这是我修改后的代码:

ALTER PROCEDURE [dbo].[spImportFile] 
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    EXECUTE AS LOGIN = 'domain\credentials'

    DECLARE @execution_id bigint
    EXEC SSISDB.CATALOG.create_execution
        @folder_name = 'folder_name',
        @project_name = 'project_name',
        @package_name = 'package_name.dtsx',
        @use32bitruntime = 1,
        @execution_id = @execution_id output

    EXEC SSISDB.CATALOG.start_execution @execution_id -- <<<< ERROR HERE!

    REVERT

END

通过查看我通常无法访问的系统表,我成功地测试了没有start_executionEXECUTE AS LOGINREVERT

【问题讨论】:

  • 关于您在 UPDATE 中遇到的“切换到原始数据库”错误,在连接到 SSISDB 数据库之前,我遇到了同样的问题。对于未来的 Google 员工,遵循这些说明对我们有用:stackoverflow.com/a/60850142/1703887

标签: sql-server stored-procedures ssis impersonation sql-server-2014


【解决方案1】:

我从未针对一组凭据尝试过,但您可以查看EXECUTE AS

ALTER PROCEDURE [dbo].[spImportFile] 
WITH EXECUTE AS 'domain\credentials'
AS
BEGIN
    ...
END

【讨论】:

  • 我用我当前的问题更新了问题。谢谢你带领我走向正确的方向
【解决方案2】:

我已经意识到,由于我要模拟一个用户并且我被鼓励使用一个工作,所以使用代理帐户在服务器上运行这个 SSIS 包会更容易。

这是我的解决方案,包括运行作业:

ALTER PROCEDURE [dbo].[spImportFile] 
    @intStatus int output
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    SELECT user_name() -- test before execute

    EXECUTE AS LOGIN = 'domain\credentials'

    SELECT user_name() -- test after execute

    -- Start job
    DECLARE @job_name VARCHAR(100) = 'JobName'
    EXEC msdb.dbo.sp_start_job @job_name = @job_name

    -- Wait for job to finish
    DECLARE @job_history_id AS INT = NULL
    DECLARE @intLimit AS INT = 10
    DECLARE @intAttempt AS INT = 1

    WHILE @intAttempt < @intLimit
    BEGIN
        SELECT TOP 1 @job_history_id = activity.job_history_id
        FROM msdb.dbo.sysjobs jobs
        INNER JOIN msdb.dbo.sysjobactivity activity ON activity.job_id = jobs.job_id
        WHERE jobs.name = @job_name
        ORDER BY activity.start_execution_date DESC

        IF @job_history_id IS NULL
        BEGIN
            WAITFOR DELAY '00:00:01'
            CONTINUE
        END
        ELSE
        BEGIN
            BREAK
        END

        SET @intAttempt = @intAttempt + 1
    END

    -- Check exit code
    SELECT @intStatus = history.run_status
    FROM msdb.dbo.sysjobhistory history
    WHERE history.instance_id = @job_history_id

    REVERT

    SELECT user_name() -- test after revert

END

这个职位代码是基于这个问题,"Executing SQL Server Agent Job from a stored procedure and returning job result"


调查结果
我从这个MSDN source 了解到你需要GRANT IMPERSONATE ON LOGIN::[domain\ProxyUser] to [domain\credentials]

ALTER DATABASE database_name SET TRUSTWORTHY ONsysadmin 需要实现的另一个设置,这个MSDN source 有助于解释用法。

备注
这个解决方案是基于我是数据库的dbo 并且我有一个sysadmin 将代理帐户模拟授予我的Windows 安全组的事实。我也在使用 Windows 身份验证。

我已更新问题,以不限制最初从事此问题工作的任何人使用工作。如果有不需要工作的解决方案,我将非常乐意查看甚至更改此问题上已接受的解决方案。

【讨论】:

  • 嗨,你成功了吗?我的意思是不使用 JOB 和 xp_cmdshell
猜你喜欢
  • 1970-01-01
  • 2013-04-30
  • 2010-11-08
  • 1970-01-01
  • 2012-07-05
  • 2010-10-29
  • 1970-01-01
  • 2011-01-23
  • 1970-01-01
相关资源
最近更新 更多