Sql-Server

在不啟用 TRUSTWORTHY 的情況下創建組件 System.DirectoryServices.AccountManagement.dll

  • February 28, 2019

首先,這是針對 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.
*/

不,非對稱密鑰不起作用,很可能是因為強命名程序集在 .NET 4.5 或那裡的某個地方發生了變化,現在是增強型強命名,SQL Server 的 CLR 主機不支持(不是不辭職,這不會在這里工作)。

關鍵是使用證書。從 DLL創建一個證書master,然後從該證書創建登錄,最後授予該UNSAFE ASSEMBLY登錄的權限。

應該就是這麼簡單(當然,假設 DLL 是純 MSIL 而不是混合的,因為只有純 MSIL 程序集可以載入到 SQL Server 中)。

還:

  1. 假設它們被主程序引用,您不必添加/刪除比主程序集更多的內容。通過 DLL 添加程序集(而不是十六進製字節/VARBINARY文字)時,SQL Server 將抓取同一文件夾中的任何引用程序集。它將所有這些自動添加的程序集設置為“可見 = 0”。如果主程序集被刪除,設置為“可見 = 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 文件提供的錯誤資訊。我正在糾正我以前的答案和該文件。

引用自:https://dba.stackexchange.com/questions/230993