用于访问sys.dm_db_index_usage_stats的公共存储过程

时间:2016-06-24 05:38:07

标签: sql-server

我正在尝试为我的SQL Server中的所有用户提供sys.dm_db_index_usage_stats视图的某些部分。目标是在不破坏SQL Server安全性的情况下提供该信息。

我不是数据库专家,但我准备了这段代码:

CREATE PROCEDURE dbo.[LastTableUpdate]   
    @Table nvarchar(50)   
WITH EXECUTE AS OWNER 
AS   
SELECT 
    DB_NAME(database_id) as 'Database', 
    OBJECT_NAME(object_id) As TableName, 
    max(last_user_update) as user_update,
    max(last_system_update) as system_update
 FROM sys.dm_db_index_usage_stats WHERe database_ID=DB_ID() AND object_id=OBJECT_ID(@Table)
 GROUP BY database_id, object_id

接下来我授予权限

GRANT EXEC ON dbo.[LastTableUpdate] TO PUBLIC

但是当我打电话给它时

Msg 15562, Level 16, State 1, Procedure LastTableUpdate, Line 5
The module being executed is not trusted. Either the owner of the database of the module needs to be granted authenticate permission, or the module needs to be digitally signed.

你能帮助我吗,我该怎么办?正如我所提到的 - 我的目标是让DB尽可能安全。

1 个答案:

答案 0 :(得分:5)

模块签名(与pimpin'不同)很容易。基本上,你:

  1. 创建证书
  2. 根据该证书创建登录信息
  3. 授予该登录的权限
  4. 签署存储过程
  5. 利润
  6. use master;
    go
    create login [foobar] with password = 'f00bar!23';
    go
    CREATE PROCEDURE dbo.[LastTableUpdate]   
        @Table nvarchar(50)   
    AS   
    SELECT 
        DB_NAME(database_id) as 'Database', 
        OBJECT_NAME(object_id) As TableName, 
        max(last_user_update) as user_update,
        max(last_system_update) as system_update
     FROM sys.dm_db_index_usage_stats WHERe database_ID=DB_ID() AND object_id=OBJECT_ID(@Table)
     GROUP BY database_id, object_id
     go
     grant execute on dbo.LastTableUpdate to public
     go
    EXEC sp_ms_marksystemobject 'LastTableUpdate'
    go
     create certificate [CodeSigningCertificate]
        encryption by password = 'Sooper$ecretp@ssword123'
        with expiry_date = '2099-01-01',
        subject = 'Code Signing Cert'
    go
    create login [CodeSigningLogin] from certificate [CodeSigningCertificate]
    grant view server state to [CodeSigningLogin];
    go
    -- nothing up my sleeve
    execute as login = 'foobar';
    exec dbo.LastTableUpdate 'n'
    revert
    
    -- doesn't work - login [foobar] doesn't have permissions
    go
    -- here's the magic
    add signature to dbo.[LastTableUpdate]
        by certificate [CodeSigningCertificate]
        with password = 'Sooper$ecretp@ssword123';
    go
    
    execute as login = 'foobar';
    exec dbo.LastTableUpdate 'n'
    revert
    
    -- works now!
    

    注意:我从你的程序中取出了EXECUTE AS OWNER条款;您现在不需要它,调用者只能获得此VIEW SERVER STATE个存储过程上下文的权限。