【问题标题】:Cannot create stored procedures with EXECUTE AS using a Certificate-based Principal无法使用基于证书的主体创建带有 EXECUTE AS 的存储过程
【发布时间】:2017-04-02 19:24:50
【问题描述】:

我正在尝试重新创建一个过期的证书,该证书在我们的服务器上用于创建原则,然后这些原则与模拟一起用于执行存储过程。

这就是我正在做的事情(当然在生产上要复杂得多,但这个确切的测试也失败了)。

Use ReportingDb
GO

CREATE CERTIFICATE MyCertTest ENCRYPTION BY PASSWORD = 'acrazygoodpassword'
   WITH SUBJECT = 'Stored procedure signing for Reports'
      ,EXPIRY_DATE = '11/18/2019';
GO

BACKUP CERTIFICATE MyCertTest TO FILE = 'D:\MyCertTest.CER';
GO

CREATE USER TestReportUser
FROM CERTIFICATE MyCertTest;
GO

EXEC sp_addrolemember 'db_datareader','TestReportUser';

GRANT AUTHENTICATE
   TO TestReportUser;
GO

GRANT EXECUTE
   TO TestReportUser;
GO


USE Master;
GO

CREATE CERTIFICATE MyCertTest
FROM FILE = 'D:\MyCertTest.CER';
GO
CREATE USER TestReportUser
FROM CERTIFICATE MyCertTest;
GO
EXEC sp_addrolemember 'db_datareader','TestReportUser';

GRANT AUTHENTICATE
   TO TestReportUser;

GRANT EXECUTE
   TO TestReportUser;
GO


use ReportingDb
GO

CREATE PROCEDURE dbo.Reports_DC_Project_sp
WITH EXECUTE AS 'TestReportUser'
AS
SELECT 1
GO

不确定我是否真的需要主数据库。这一切都成功了,直到创建存储过程,然后:

消息 15517,级别 16,状态 1,程序 Reports_DC_Project_sp,第 47 行
无法作为数据库主体执行,因为主体“TestReportUser”不存在,无法模拟此类主体,或者您没有权限。

我还尝试使用 EXECUTE AS 'dbo' 创建存储过程。效果很好......然后将签名添加到存储过程中,最后更改存储过程以作为我的证书用户执行。上一步同样的错误。

是否有我遗漏的设置/步骤?

【问题讨论】:

  • 您好。你能让这个工作吗?我在下面发布了answer,解释了为什么会发生这种情况以及如何解决它。

标签: sql sql-server sql-server-2012 impersonation digital-certificate


【解决方案1】:

使用[数据库名称]

EXEC sp_changedbowner 'sa'

【讨论】:

    【解决方案2】:

    我正在尝试重新创建一个过期的证书,该证书在我们的服务器上用于创建原则...

    嗯,不。从它们创建主体时,不会检查/验证证书到期日期,甚至在将它们与 ADD SIGNATURE 一起使用来签署模块时也不会检查/验证。

    然后这些原则被用于模拟来执行存储过程。

    绝对没有。这没有发生,因为技术上不可能发生;基于证书和非对称密钥的主体不能用于模拟。

    不确定我是否真的需要主数据库。

    不,不是。在这种用法中它没有做任何事情。如果您想将服务器(即实例)级权限(甚至是sysadmin 角色的成员资格)关联到证书和由它签名的每个模块,那么您可以将证书恢复到master,如您所示,但随后您将从该证书创建一个登录名并为其授予适当的权限。在master 中创建用户不会做任何事情,除非master 数据库中有用户需要与之交互的特定内容。但就你的测试而言,它完全无关紧要。

    此外,将AUTHENTICATE 授予基于证书的主体完全不相关且无用,因为基于证书和非对称密钥的主体无法进行身份验证。完全没有。永远。

    然后将签名添加到存储过程,最后更改存储过程以作为我的证书用户执行。

    即使可以执行为证书或基于非对称密钥的主体,添加签名之前使用EXECUTE AS 子句更改存储过程也是没有意义的,因为@987654328 @ 语句将自动使签名无效。当模块的定义或EXECUTE AS 子句发生更改时,签名会自动删除。您必须在 ALTER 语句之后重新签名模块,因此事先添加签名没有用。

    是否有我遗漏的设置/步骤?

    您没有错过任何一步,因为没有办法完成这项工作。但是,您误解了这里的概念。模拟(通过EXECUTE AS)和模块签名(通过ADD SIGNATURE)是相互排斥的。事实上,模块签名几乎取代/淘汰了模拟。

    不能模拟或验证基于证书和基于非对称密钥的主体(登录名和用户)。因此,您会收到以下错误(强调添加):

    无法作为数据库主体执行,因为主体“TestReportUser”不存在,无法模拟此类主体,或者您没有权限。

    这是使模块签名比模拟更安全的框架的部分原因。

    所以去掉以下内容:

    1. GRANT AUTHENTICATE
    2. master 中正在执行的所有语句
    3. EXECUTE AS 子句

    你会没事的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 2013-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多