AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 31885
Accepted
Ed Leighton-Dick
Ed Leighton-Dick
Asked: 2009-06-26 13:28:37 +0800 CST2009-06-26 13:28:37 +0800 CST 2009-06-26 13:28:37 +0800 CST

从存储过程调用 sp_start_job

  • 772

我们的开发人员需要能够从他们的 .Net 代码启动 SQL Server 代理作业。我知道我可以调用msdb..sp_start_job来做到这一点,但我不想让一般用户帐户直接访问运行作业。

我想做的是使用 WITH EXECUTE AS 子句在应用程序的数据库中创建一个存储过程来模拟代理帐户。我们拥有的程序是:

CREATE PROCEDURE dbo.StartAgentJob 
    WITH EXECUTE AS 'agentProxy'
AS
BEGIN
    EXEC msdb.dbo.sp_start_job N'RunThisJob';
END

但是,当我们运行它时,我们会收到以下消息:

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

有任何想法吗?这甚至是在 SQL2005 中执行此操作的最佳方法吗?

sql-server sql-server-2005 sql
  • 5 5 个回答
  • 21189 Views

5 个回答

  • Voted
  1. Remus Rusanu
    2009-07-20T11:56:16+08:002009-07-20T11:56:16+08:00

    很高兴您解决了这个问题,但所有权链接不是推荐的解决方案。由于您似乎确实担心所涉及权利的安全性和适当的粒度,因此我将添加此回复,尽管迟了,作为对正在发生的事情以及如何解决此问题的参考。

    EXECUTE AS 模拟范围

    EXECUTE AS 子句有两种形式:EXECUTE AS LOGIN 和 EXECUTE AS USER。EXECUTE AS LOGIN 由服务器进行身份验证,是整个 SQL 实例(服务器范围)信任的模拟上下文:

    使用 EXECUTE AS LOGIN 语句模拟主体时,或使用 EXECUTE AS 子句在服务器范围的模块中模拟主体时,模拟的范围是服务器范围的。这意味着在上下文切换之后,可以访问模拟登录具有权限的服务器中的任何资源。

    EXECUTE AS USER 由数据库进行身份验证,并且是仅受该数据库信任的模拟上下文(数据库范围):

    但是,当使用 EXECUTE AS USER 语句或在数据库范围的模块中使用 EXECUTE AS 子句模拟主体时,默认情况下模拟的范围仅限于数据库。这意味着对数据库范围之外的对象的引用将返回错误。

    具有 EXECUTE AS 子句的存储过程将创建一个数据库范围的模拟上下文,因此将无法引用数据库外部的对象,例如您将无法引用msdb.dbo.sp_start_job,因为在msdb. 还有许多其他可用示例,例如尝试访问服务器范围 DMV、尝试使用链接服务器或尝试将 Service Broker 消息传递到另一个数据库。

    使数据库范围的模拟能够访问通常不允许的资源,模拟上下文的身份验证器必须被信任。对于数据库范围的模拟,身份验证器是数据库 dbo。这可以通过两种可能的方式来实现:

    • 通过打开对模拟上下文进行身份验证的数据库(即发出 EXECUTE AS 子句的数据库)上的 TRUSTWORTHY 属性。
    • 通过使用代码签名。

    这些详细信息在 MSDN:Extended Database Impersonation by Using EXECUTE AS中进行了描述。

    当您通过跨数据库所有权链接解决问题时,您已在整个服务器级别启用了跨数据库链接,这被认为存在安全风险。实现预期结果的最受控制、最细粒度的方法是使用代码签名:

    • 在应用程序数据库中创建自签名证书
    • dbo.StartAgentJob用这个证书签名
    • 删除证书的私钥
    • 将证书导出到磁盘
    • 将证书导入msdb
    • 从导入的证书创建派生用户msdb
    • 向派生用户授予 AUTHENTICATE 权限msdb

    这些步骤确保过程的 EXECUTE AS 上下文dbo.StartAgentJob现在是受信任的msdb,因为该上下文是由具有 AUTHENTICATE 权限的主体签署的msdb。这解决了一半的难题。另一半是实际授予对msdb.dbo.sp_start_job现在受信任的模拟上下文的 EXECUTE 权限。有几种方法可以做到这一点:

    1. 映射模拟用户agentProxy用户msdb并授予他执行权限msdb.dbo.sp_start_job
    2. 授予msdb验证者证书派生用户执行权限
    3. 向过程添加新签名,为其派生一个用户msdb并将执行权限授予该派生用户

    方案1.简单,但有一个很大的缺点:agentProxy用户现在可以随意执行msdb.dbo.sp_start_job,他真正被授予访问权限msdb并具有执行权限。

    选项 3 是正确的,但我觉得是不必要的矫枉过正。

    所以我的首选是选项 2:将 EXECUTE 权限授予在msdb.dbo.sp_start_job中创建的证书派生用户msdb。

    下面是对应的SQL:

    use [<appdb>];
    go
    
    create certificate agentProxy 
        ENCRYPTION BY PASSWORD = 'pGFD4bb925DGvbd2439587y'
        with subject = 'agentProxy'
       , start_date='01/01/2009';
    go
    
    ADD SIGNATURE TO OBJECT::[StartAgentJob]
          BY CERTIFICATE [agentProxy]
            WITH PASSWORD = 'pGFD4bb925DGvbd2439587y';
    go
    
    alter certificate [agentProxy] 
      remove private key;
    go
    
    backup certificate [agentProxy] 
     to file='c:\temp\agentProxy.cer';
    go
    
    use msdb
    go
    
    create certificate [agentProxy] 
      from file='c:\temp\agentProxy.cer';
    go
    
    create user [agentProxyAuthenticator] 
     from certificate [agentProxy];
    go
    
    grant authenticate to [agentProxyAuthenticator];
    grant execute on msdb.dbo.sp_start_job to [agentProxyAuthenticator];
    go
    
    use [<appdb>];
    go
    
    exec dbo.StartAgentJob;
    go
    

    我的博客有一些关于这个主题的文章,写在 Service Broker 激活过程的上下文中(因为它们需要一个 EXECUTE AS 子句):

    • 签署激活的程序
    • 从激活的过程中调用另一个数据库中的过程
    • 为什么功能……在激活状态下不起作用?
    • 证书尚未生效

    顺便说一句,如果你想测试我的脚本并且你住在东半球,或者在英国夏令时,一定要阅读我在测试之前链接的最后一篇文章。

    • 9
  2. Best Answer
    mrdenny
    2009-06-26T15:07:07+08:002009-06-26T15:07:07+08:00

    您是否将 agentProxy 登录名放入 msdb 数据库并授予它运行 sp_start_job 的权限?如果没有,您需要为 msdb 数据库和您的用户数据库启用数据库权限链接。

    您最好将登录名放入 msdb 数据库并授予它正确的权限。

    • 5
  3. KPWINC
    2009-06-26T14:25:29+08:002009-06-26T14:25:29+08:00

    由于您尝试从 .NET 代码启动 SQL Server 代理,因此对于 StackOverflow,这可能是一个更好的问题?

    http://www.stackoverflow.com

    • 0
  4. Andrew
    2009-07-10T15:59:44+08:002009-07-10T15:59:44+08:00

    检查网络 SQLAgentOperatorRole 上的随机 SQL 实例不会直接为您提供 sp_start_job 权限,它从 SQLAgentUserRole 继承它们。

    使用以下命令仔细检查:

    select dp.NAME AS principal_name,
                     dp.type_desc AS principal_type_desc,
                     o.NAME AS object_name,
                     p.permission_name,
                     p.state_desc AS permission_state_desc 
        from    sys.database_permissions p
        left    OUTER JOIN sys.all_objects o on p.major_id = o.OBJECT_ID
        inner   JOIN sys.database_principals dp on p.grantee_principal_id = dp.principal_id
        where o.name = 'sp_start_job'
    

    在 MSDB 中运行它并仔细检查您没有继承任何显式拒绝访问。

    hth。

    • 0
  5. Robert van den Berg
    2016-09-30T05:46:52+08:002016-09-30T05:46:52+08:00

    在不授予额外权限的情况下实现此目的的一种方法:不要让存储过程直接启动作业,而只允许存储过程在表中翻转一点(在应用程序数据库中);然后,让作业每分钟左右运行一次,检查位是否翻转,如果是,则执行工作并再次翻转位。如果作业发现该位未翻转,则作业将退出。

    如果您不介意延迟(并且工作经常运行),它就像一个魅力。

    • 0

相关问题

  • 从 MySQL 迁移到 SQL Server 的最佳方法或工具

  • 如何启用与 SQL Server 实例的加密连接?

  • Vanilla Powershell 是否足以成为 Windows 和 DB 服务器管理员的语言?

  • 在 SQL Server 中,何时应将 PRIMARY Data FileGroup 拆分为辅助数据文件?

  • 如何从 SQL Server 2008 中的备份中排除索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    从 IP 地址解析主机名

    • 8 个回答
  • Marko Smith

    如何按大小对 du -h 输出进行排序

    • 30 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    Windows 中执行反向 DNS 查找的命令行实用程序是什么?

    • 14 个回答
  • Marko Smith

    如何检查 Windows 机器上的端口是否被阻塞?

    • 4 个回答
  • Marko Smith

    我应该打开哪个端口以允许远程桌面?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    MikeN 在 Nginx 中,如何在维护子域的同时将所有 http 请求重写为 https? 2009-09-22 06:04:43 +0800 CST
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    0x89 bash中的双方括号和单方括号有什么区别? 2009-08-10 13:11:51 +0800 CST
  • Martin Hope
    kch 如何更改我的私钥密码? 2009-08-06 21:37:57 +0800 CST
  • Martin Hope
    Kyle Brandt IPv4 子网如何工作? 2009-08-05 06:05:31 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve