创建汇编 System.DirectoryServices.AccountManagement.dll 而不启用 TRUSTWORTHY

Spa*_*440 3 security sql-server sql-clr active-directory sql-server-2016

首先,这是针对 SQL Server 2016 的。如果我在 2017+ 上,我会使用sp_add_trusted_assembly. 在问这个问题之前只是想澄清一下。

如何在不使用 的情况下注册程序集System.DirectoryServices.AccountManagement.dllTRUSTWORTHY ON?我无法使用System.DirectoryServices.dll生成的非对称密钥使其工作。AccountManagement dll 的签名与System.DirectoryServices.dll不同。

我什至尝试从System.DirectoryServices.AccountManagement.dll创建一个单独的非对称密钥,但这会导致:

消息 15468,级别 16,状态 7,行 XXXXX
在生成非对称密钥期间出错。

这是我为尝试创建此程序集而编写的测试脚本。

USE master

IF DB_ID('CLR_Test') IS NULL BEGIN
    CREATE DATABASE CLR_Test
END
GO

USE [CLR_Test]
GO

EXEC sp_configure @configname=clr_enabled, @configvalue=1
GO
RECONFIGURE
GO

/*************************************************************************************/
-- DROP OBJECTS IF FOUND FIRST
/*************************************************************************************/

-- DROP System.DirectoryServices.AccountManagement
IF EXISTS(SELECT 1 FROM sys.assemblies WHERE name = 'System.DirectoryServices.AccountManagement') BEGIN 
    RAISERROR( 'DROP ASSEMBLY [System.DirectoryServices.AccountManagement]', 0, 1) WITH NOWAIT
    DROP ASSEMBLY [System.DirectoryServices.AccountManagement]
END

-- DROP System.DirectoryServices.Protocols
IF EXISTS(SELECT 1 FROM sys.assemblies WHERE name = 'System.DirectoryServices.Protocols') BEGIN 
    RAISERROR( 'DROP ASSEMBLY [System.DirectoryServices.Protocols]', 0, 1) WITH NOWAIT
    DROP ASSEMBLY [System.DirectoryServices.Protocols]
END

-- DROP System.DirectoryServices
IF EXISTS(SELECT 1 FROM sys.assemblies WHERE name = 'System.DirectoryServices') BEGIN 
    RAISERROR( 'DROP ASSEMBLY [System.DirectoryServices]', 0, 1) WITH NOWAIT
    DROP ASSEMBLY [System.DirectoryServices]
END
GO
IF EXISTS(SELECT 1 FROM sys.database_principals dp WHERE dp.name = 'MSFT_CLR_Login') 
BEGIN
    RAISERROR( 'DROP USER [MSFT_CLR_Login]', 0, 1) WITH NOWAIT
    DROP USER [MSFT_CLR_Login] 
END
GO
USE [master]
GO
IF (EXISTS(SELECT 1 FROM master.sys.syslogins WHERE name = 'MSFT_CLR_Login'))
BEGIN
    RAISERROR( 'DROP LOGIN [MSFT_CLR_Login]', 0, 1) WITH NOWAIT
    DROP LOGIN [MSFT_CLR_Login] 
END
GO
IF (EXISTS(SELECT 1 FROM master.sys.asymmetric_keys WHERE name = 'MSFT_CLR_Key'))
BEGIN
    --DROP ASYMMETRIC KEY [ClrKey]
    RAISERROR( 'DROP ASYMMETRIC KEY [MSFT_CLR_Key]', 0, 1) WITH NOWAIT
    DROP ASYMMETRIC KEY [MSFT_CLR_Key] 
END
GO

/*************************************************************************************/
-- CREATE THE OBJECTS
/*************************************************************************************/
USE [master]
GO
IF (NOT EXISTS(SELECT 1 FROM master.sys.asymmetric_keys WHERE name = 'MSFT_CLR_Key'))
BEGIN
    --DROP ASYMMETRIC KEY [ClrKey]
    RAISERROR( 'CREATE ASYMMETRIC KEY [MSFT_CLR_Key]', 0, 1) WITH NOWAIT
    CREATE ASYMMETRIC KEY [MSFT_CLR_Key] 
    FROM EXECUTABLE FILE = 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.DirectoryServices.dll'
END
GO
IF (NOT EXISTS(SELECT 1 FROM master.sys.syslogins WHERE name = 'MSFT_CLR_Login'))
BEGIN
    RAISERROR( 'CREATE LOGIN [MSFT_CLR_Login]', 0, 1) WITH NOWAIT
    CREATE LOGIN [MSFT_CLR_Login] FROM ASYMMETRIC KEY [MSFT_CLR_Key]
END
GO

RAISERROR( 'GRANT UNSAFE ASSEMBLY', 0, 1) WITH NOWAIT
GRANT UNSAFE ASSEMBLY TO [MSFT_CLR_Login]
GO
RAISERROR( 'GRANT EXTERNAL ASSEMBLY', 0, 1) WITH NOWAIT
GRANT EXTERNAL ACCESS ASSEMBLY TO [MSFT_CLR_Login]
GO

USE CLR_Test
GO

IF NOT EXISTS(SELECT 1 FROM sys.database_principals dp WHERE dp.name = 'MSFT_CLR_Login') 
BEGIN
    RAISERROR( 'CREATE USER [MSFT_CLR_Login]', 0, 1) WITH NOWAIT
    CREATE USER [MSFT_CLR_Login] FOR LOGIN [MSFT_CLR_Login]
END
GO

/*************************************************************************************/
-- CREATE THE CLR OBJECTS
/*************************************************************************************/

USE CLR_Test
GO

/****************************************************************************/
-- [System.DirectoryServices]
/****************************************************************************/
CREATE ASSEMBLY [System.DirectoryServices] 
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.DirectoryServices.dll'
WITH PERMISSION_SET = UNSAFE

/****************************************************************************/
-- [System.DirectoryServices.Protocols]
/****************************************************************************/
CREATE ASSEMBLY [System.DirectoryServices.Protocols] 
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.DirectoryServices.Protocols.dll'
WITH PERMISSION_SET = UNSAFE

/****************************************************************************/
-- [System.DirectoryServices.AccountManagement]
/****************************************************************************/
CREATE ASSEMBLY [System.DirectoryServices.AccountManagement] 
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.DirectoryServices.AccountManagement.dll'
WITH PERMISSION_SET = UNSAFE



/*
-- NOR CAN YOU CREATE AN ASSYMETRIC KEY OFF System.DirectoryServices.AccountManagement.dll

CREATE ASYMMETRIC KEY [MSFT_SDA_CLR_Key] 
FROM EXECUTABLE FILE = 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.DirectoryServices.AccountManagement.dll'

-- results in:
--      Msg 15468, Level 16, State 7, Line 130
--      An error occurred during the generation of the asymmetric key.
*/
Run Code Online (Sandbox Code Playgroud)

Sol*_*zky 7

不,非对称密钥不起作用,很可能是因为强命名程序集在 .NET 4.5 或附近的某个地方发生了变化,现在是增强的强命名,SQL Server 的 CLR 主机不支持它(不是没有辞职,它不会在这里工作)。

关键是使用证书。master从 DLL创建一个证书,然后从该证书创建登录,最后授予该UNSAFE ASSEMBLY登录的权限。

应该就是这么简单(当然,假设 DLL 是纯 MSIL 而不是混合的,因为只有纯 MSIL 程序集才能加载到 SQL Server 中)。

还:

  1. 假设它们被主程序集引用,您不必添加/删除比主程序集更多的内容。通过 DLL(而不是十六进制字节/VARBINARY文字)添加程序集时,SQL Server 将获取同一文件夹中的任何引用程序集。它将所有这些自动添加的程序集设置为“visible = 0”。如果主程序集被删除,主程序集引用的设置为“visible = 0”的程序集将被自动删除。
  2. 您不需要为基于签名的登录同时授予UNSAFE ASSEMBLYEXTERNAL ACCESS ASSEMBLY权限。该UNSAFE ASSEMBLY权限假定该EXTERNAL ACCESS ASSEMBLY权限,以便您可以将程序集设置为PERMISSION_SET具有该UNSAFE ASSEMBLY权限的任一者。
  3. 如果使用 SQL Server 2017 或更高版本,则无需使用“受信任的程序集”功能。请参阅我的帖子,了解为什么以及应该做什么:SQLCLR 与 SQL Server 2017,第 1 部分:“CLR 严格安全性” - 问题。当然,在这种特殊情况下,这是一个有争议的问题,因为正确的方法是使用如上所述的证书方法。

请注意,在其他类似问题的答案中,无论是我自己还是其他人的回答,答案始终是TRUSTWORTHY必须启用的。这是由于 Microsoft 文档提供的错误信息,我直到最近才意识到。我正在努力更正我以前的答案和该文档。