[英]Execute SSIS package from stored procedure as proxy user without xp_cmdshell
I am trying to run an SSIS package through a stored procedure, but I am getting an Access is denied
error when I try to import a CSV. 我试图通过存储过程运行SSIS包,但是当我尝试导入CSV时,我收到了Access is denied
错误。
I put the package inside a job and ran it and it worked as long as I used a proxy account. 我将包放在一个工作中并运行它,只要我使用代理帐户就可以工作。 I am trying to replicate that proxy account to the stored procedure call without using xp_cmdshell
. 我试图在不使用xp_cmdshell
情况下将该代理帐户复制到存储过程调用。 I also ran this package inside Visual Studio and it ran smoothly. 我还在Visual Studio中运行了这个包,它运行顺利。
My SSIS package is simple: It imports a CSV file from the network, converts the data to varchar
, and stores the data into a table. 我的SSIS包很简单:它从网络导入CSV文件,将数据转换为varchar
,并将数据存储到表中。
Even my sysadmin was not able to successfully run the stored procedure. 甚至我的sysadmin也无法成功运行存储过程。
My stored procedure looks like this: 我的存储过程如下所示:
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
My question is, how can I programmatically use a proxy user inside this stored procedure without using xp_cmdshell
? 我的问题是,如何在不使用xp_cmdshell
情况下以编程方式在此存储过程中使用代理用户?
UPDATE: 更新:
I am now trying to impersonate my proxy user thanks to billinkc , but now I am running into this error when I execute the SSIS package: 我现在正试图冒充我的代理用户感谢billinkc ,但现在我在执行SSIS包时遇到了这个错误:
The current security context cannot be reverted. 无法还原当前的安全上下文。 Please switch to the original database where 'Execute As' was called and try it again. 请切换到调用'Execute As'的原始数据库并再次尝试。
Here is my altered code: 这是我改变的代码:
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
I successfully tested EXECUTE AS LOGIN
and REVERT
without start_execution
by looking into a system table I wouldn't usually have access to. 我通过查看我通常无法访问的系统表,成功测试了EXECUTE AS LOGIN
和REVERT
而没有start_execution
。
I have come into a realization that since I am going to impersonate a user and that I am encouraged to use a job, it will be much easier to make a job to run this SSIS package on the server with a proxy account. 我已经意识到,由于我要模仿用户并鼓励我使用某个作业,因此使用代理帐户在服务器上运行此SSIS包会更容易。
Here is my solution that includes running a job: 这是我的解决方案, 包括运行工作:
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
This job code was based on this question, " Executing SQL Server Agent Job from a stored procedure and returning job result " 此作业代码基于此问题“ 从存储过程执行SQL Server代理作业并返回作业结果 ”
Findings : 调查结果 :
I have learned that you need to GRANT IMPERSONATE ON LOGIN::[domain\\ProxyUser] to [domain\\credentials]
from this MSDN source . 我了解到,您需要从此MSDN源 GRANT IMPERSONATE ON LOGIN::[domain\\ProxyUser] to [domain\\credentials]
。
ALTER DATABASE database_name SET TRUSTWORTHY ON
is another setting the sysadmin
needed to implement and this MSDN source helps explain the usage. ALTER DATABASE database_name SET TRUSTWORTHY ON
是sysadmin
实现所需的另一个设置,此MSDN源有助于解释其用法。
Remarks : 备注 :
This solution is based on the fact that I am the dbo
of the database and I had a sysadmin
grant impersonation of the proxy account to my windows security group. 此解决方案基于以下事实:我是数据库的dbo
,我有一个sysadmin
授予模拟代理帐户到我的Windows安全组。 I am using Windows authentication as well. 我也在使用Windows身份验证。
I have updated the question to not restrict the use of jobs for anyone that initially was working on this question. 我已经更新了问题,不限制最初正在处理这个问题的任何人使用工作。 If there is a solution that doesn't require jobs, I will be more than happy to take a look and even change the accepted solution on this question. 如果有一个不需要工作的解决方案,我将非常乐意看一看甚至改变这个问题的公认解决方案。
I've never tried it against a set of credentials, but you could look at EXECUTE AS 我从来没有尝试过一组凭据,但你可以看一下EXECUTE AS
ALTER PROCEDURE [dbo].[spImportFile]
WITH EXECUTE AS 'domain\credentials'
AS
BEGIN
...
END
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.