只允许用户执行特定程序

问题描述 投票:0回答:1

我正在寻找一种解决方案,其中用户允许其执行a过程。在下面的示例中,该过程是

lowlevel.ZipFile
(主过程)。问题是该过程本身执行其他过程,从而导致错误。只要用户执行“主过程”而不是任何嵌套过程本身,我希望它获得批准。 我环顾四周,发现拒绝访问执行其他存储的最简单方法是创建一个新模式。然后,我创建了另一个有权访问嵌套过程的用户,并创建了我的 main procedure WITH EXECUTE AS 签名给具有访问权限的用户。但是,当我与该用户执行
主程序
时,他突然没有执行嵌套程序的权限? 下面的代码用于测试目的。

请注意

,如果您在主数据库中有名为“SiteDatabase44”的数据库、名为“LowLevelUser_Executor”的用户或名为“___ZipFile”的过程。最后注释了清理脚本。 SET NOCOUNT ON USE master; IF NOT EXISTS(SELECT 1 FROM sys.databases WHERE Name = 'SiteDatabase44') EXECUTE('CREATE DATABASE SiteDatabase44') IF NOT EXISTS (SELECT 1 FROM sys.syslogins WHERE NAME = 'LowLevelUser_Executor') BEGIN CREATE LOGIN [LowLevelUser_Executor] WITH PASSWORD = N'ShouldNeverBeLoggedInAs_asdasd', CHECK_POLICY = OFF; GRANT CONNECT SQL TO [LowLevelUser_Executor] END GO CREATE OR ALTER PROCEDURE dbo.___ZipFile @Filepath varchar(500) NULL AS SELECT 22 GO IF NOT EXISTS(SELECT 1 FROM sys.sysusers WHERE name = 'LowLevelUser_Executor') CREATE USER LowLevelUser_Executor FOR LOGIN LowLevelUser_Executor WITH DEFAULT_SCHEMA = dbo GRANT EXECUTE ON [dbo].___ZipFile TO [LowLevelUser_Executor] USE [SiteDatabase44]; IF NOT EXISTS(SELECT 1 FROM sys.schemas WHERE [name] = 'lowlevel') EXECUTE('CREATE SCHEMA lowlevel') GO IF NOT EXISTS(SELECT 1 FROM sys.sysusers WHERE name = 'LowLevelUser_Executor') CREATE USER [LowLevelUser_Executor] FOR LOGIN [LowLevelUser_Executor] WITH DEFAULT_SCHEMA = dbo GO CREATE OR ALTER PROCEDURE lowlevel.ZipFile @Filepath varchar(500) NULL WITH EXECUTE AS 'LowLevelUser_Executor' AS SELECT 'Zipping file...' EXECUTE master.dbo.___ZipFile @Filepath GO GRANT SELECT, EXECUTE ON SCHEMA::lowlevel TO [LowLevelUser_Executor] WITH GRANT OPTION; EXECUTE AS LOGIN = 'LowLevelUser_Executor' exec master.dbo.___ZipFile @Filepath = '' -- Works as expected EXECUTE [lowlevel].ZipFile @Filepath = '' -- Doesn't work? Get's this error: The EXECUTE permission was denied on the object '___ZipFile', database 'master', schema 'dbo'. go REVERT; /* CLEAN UP USE MASTER; DROP DATABASE SiteDatabase44 GO DROP PROCEDURE dbo.___ZipFile GO DROP USER [LowLevelUser_Executor] GO DROP LOGIN [LowLevelUser_Executor] */


t-sql permissions database-schema sql-grant
1个回答
0
投票
可以

进行配置,但这样的设置会带来(多个)安全隐患,因此在不了解您的环境的情况下,我不能推荐它。 因此,另一种选择是实施证书。这是一个简化的示例,例如,您可能希望/需要使用密码加密您的证书。如果这样做,则在第二个数据库中创建私钥时,需要将私钥传递给 CREATE CERTIFICATE 语句(可以使用

CERTPRIVATEKEY

 获取)。这是实现最终目标的最简单
步骤;您可能需要更具体的以满足您的需求。
首先,让我们创建几个测试数据库和一个测试登录: USE master; GO CREATE DATABASE SomeDatabase; GO CREATE LOGIN AnotherLogin WITH PASSWORD = '123abc*()'; GO CREATE DATABASE AnotherDatabase; GO

现在我将在两个数据库中创建一个过程,一个引用另一个数据库。然后我将创建一个

USER
 来测试 
LOGIN

并授予他们

GRANT
引用另一个过程的权限
EXECUTE
USE SomeDatabase;
GO
CREATE PROC dbo.SomeProc AS
BEGIN
    SELECT [name]
    FROM sys.objects;
END;
GO
USE AnotherDatabase;
GO

CREATE PROC dbo.AnotherProc AS
BEGIN

    EXEC SomeDatabase.dbo.SomeProc;
END;
GO
CREATE USER AnotherUser FOR LOGIN AnotherLogin;
GO
太好了,现在我们有了与您类似的设置。我们现在可以测试看看事情是否有效(他们不会):

GRANT EXECUTE ON dbo.AnotherProc TO Anotheruser;
GO
EXECUTE AS LOGIN = 'AnotherLogin'
GO
EXEC dbo.AnotherProc --Fails, no access to the other database
GO
REVERT;
GO

消息 916,级别 14,状态 2,过程 dbo.AnotherProc,第 5 行 [批处理起始行 32]
服务器主体“AnotherLogin”无法在当前安全上下文下访问数据库“SomeDatabase”。

所以是的,这是预料之中的。

那么,让我们创建一个证书。由于这是一个新的测试数据库,我需要创建一个
MASTER KEY

,但这很可能已经存在于您的数据库中(如果存在,您不需要再次创建一个,但出于这里的目的,我这样做)。然后我还签署了我们之前创建的程序。

如前所述,证书未加密,但这是您可能想要/需要做的事情

CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'abc123!"£'; --As this is a new db, we need a master key. Obviously you'd use a better password
GO
--Create a cert
CREATE CERTIFICATE AnotherCert WITH SUBJECT = N'Allow Cross Database Queries between AnotherDB and SomeDB';
GO

ADD SIGNATURE TO dbo.AnotherProc BY CERTIFICATE AnotherCert;
GO

太好了,但现在我们还需要在 

other
 数据库中创建该证书。幸运的是,这比 SQL Server 2008 时代要容易得多,我们可以使用 
CERTENCODED

获取证书的二进制值。然而,由于 CREATE CERTIFICATE 需要一个文字值,我们将获取该值并将其连接到“动态”批处理,并使用

sys.sp_executesql
执行该批处理。
像以前一样,因为这是一个测试,它会创建一个 
MASTER KEY
,但您很可能不需要这样做。
DECLARE @CertBinary varbinary(8000) = CERTENCODED(CERT_ID(N'AnotherCert'));

DECLARE @SQL nvarchar(MAX) = N'CREATE MASTER KEY ENCRYPTION BY PASSWORD = ''abc123!"£'';' + NCHAR(13) + NCHAR(10) + --As this is a new db, we need a master key. Obviously you'd use a better password
                             N'CREATE CERTIFICATE AnotherCert FROM BINARY = ' + CONVERT(varchar(8000),@CertBinary,1) + N';';

EXEC SomeDatabase.sys.sp_executesql @SQL; --Will create in SomeDatabase
GO
太好了,我们

几乎
就到了。最后,我们需要根据另一个数据库中的证书创建一个 
USER

SomeDatabase,并为数据库中的

USER
LOGIN
创建一个
AnotherLogin
。但请注意,我没有向
USER
授予任何权限,但它们仍然需要能够连接到其他数据库。最后,我将证书的
USER
权限授予
EXECUTE
程序,(注意它不是
 
AnotherUser
)。 CREATE USER AnotherCertUser FROM CERTIFICATE AnotherCert; CREATE USER AnotherUser FROM LOGIN AnotherLogin; --They still need to exist in the DB, edven if they have no access GO GRANT EXECUTE ON dbo.SomeProc TO AnotherCertUser;
好的,我们现在可以再次测试了:

USE AnotherDatabase;
GO
EXECUTE AS LOGIN = 'AnotherLogin'
GO
EXEC dbo.AnotherProc --Works, permissions of tbhe certificate are used
GO
EXEC SomeDatabase.dbo.SomeProc; --To demonstrate it doesn't work.
GO
REVERT;
GO

成功!该过程执行

calls
 
SomeDatabase.dbo.SomeProc

的过程,但直接调用该过程失败。

清洁:

USE master; GO DROP DATABASE SomeDatabase; DROP DATABASE AnotherDatabase; DROP LOGIN AnotherLogin;

当然,另一种方法是只授予
LOGIN

USER

master
执行
dbo.___ZipFile
的权限,但看来您明确
不想
想要这样做。
    
© www.soinside.com 2019 - 2024. All rights reserved.