Sql-Server

從 SQL Server 中的證書載入程序集

  • October 5, 2021

我們收到了來自外部供應商的組件

CREATE ASSEMBLY MYCALC_DLL
AUTHORIZATION dbo
FROM 0x42A728....<300,000 binary values> 
WITH PERMISSION_SET = UNSAFE
GO

這個 DLL 是從 SP 呼叫的。

我們不想為數據庫設置 TRUSTWORTHY ON 以將此程序集載入到 SQL Server DB 中,並且正在探索選項。遇到這些連結 https://nielsberglund.com/2017/07/01/sqlclr-and-certificates/

https://sqlquantumleap.com/2017/08/09/sqlclr-vs-sql-server-2017-part- 2-clr-strict-security-solution-1/

https://sqlquantumleap.com/2017/08/16/sqlclr-vs-sql-server-2017-part-3-clr-strict-security-solution-2/

然而,這些連結使用的工具如 MAKECERT(由 new-selfsignedcertificate 代替)、pvk2pfx.exe 和 signtool.exe 在我們的 win2016 伺服器上不存在。

也可以用這種方法呼叫 DLL

在數據庫中啟用 TRUSTWORTHY -> 在數據庫中安裝程序集 AS WITH PERMISSION_SET = UNSAFE-> 在數據庫中禁用 TRUSTWORTHY

我想這是一個愚蠢的問題,但是我將程序集載入為不安全,那麼禁用 TRUSTWORTHY 有什麼意義呢?糾正我..​​.

我們想使用證書。如何進一步進行?並且這些數據庫將很快配置為 AlwaysOn,會有任何並發症嗎?謝謝

現在開發者給了這些文件 裝配文件

—–它是這樣工作的。這是正確的方法嗎?——–

<這是我第一次使用VS>

  1. 已下載 Visual Studio 社區版 2019
  2. 從上面的一組文件中,打開工程文件
  3. 建構 CALC 項目
  4. 它創建了一個 .dll 文件
  5. 在項目的屬性中,簽名選項卡 簽約 創建了一個新的強名稱密鑰文件**沒有選中復選框“使用密碼保護我的密鑰文件”並選擇 sha256RSA 作為簽名算法保存項目並建構,它會創建一個 .snk文件
  6. 將 DLL 和 snk 文件複製到 SQL Server 框
  7. 執行以下腳本
USE [Master]
GO

CREATE ASYMMETRIC KEY CLR_SP_Key
FROM EXECUTABLE FILE = 'H:\CLR_SP\CALC.dll'
GO

CREATE LOGIN CLR_SP_Login FROM ASYMMETRIC KEY CLR_SP_Key
GO

GRANT UNSAFE ASSEMBLY TO CLR_SP_Login
GO

USE [target_database]
GO
CREATE USER CLR_SP_Login FOR LOGIN CLR_SP_Login
GO

CREATE ASSEMBLY DBCALC_DLL FROM 'H:\CLR_SP\CALC.dll'
WITH PERMISSION_SET=UNSAFE
GO
CREATE function dbo.Proc_CLR_SP
(
@name as nvarchar(200) ,
@name2 as nvarchar(200)
)
RETURNS nvarchar(200)
AS EXTERNAL NAME DBCALC_DLL

鑑於您收到的是一個腳本化程序集而不是一個 DLL(我們目前知道,開發人員沒有對它簽名),在作業系統級別上簽名並不容易(首選方法),因為您首先需要從該程序集中創建一個真正的二進製文件(有一些方法,只是沒有內置到 Windows 中)。

因此,在這種情況下,您可以做的下一個最好的事情是在 SQL Server 中對程序集進行簽名。步驟是:

  1. TRUSTWORTHY為將載入程序集的數據庫啟用(這是臨時的!)
  2. 執行腳本以載入程序集
  3. 禁用TRUSTWORTHY
  4. 在載入程序集的數據庫中創建證書(使用CREATE CERTIFICATE
CREATE CERTIFICATE [{cert_name}]
  ENCRYPTION BY PASSWORD = '{password}'
  WITH SUBJECT = 'Allow assembly to be loaded',
  EXPIRY_DATE = '20991031';  
  1. 使用簽名程序集ADD SIGNATURE
ADD SIGNATURE TO ASSEMBLY::[MYCALC_DLL]
  BY CERTIFICATE [{cert_name}]
  WITH PASSWORD = '{password}';
  1. 將證書複製到[master](僅限公鑰)
  2. 從該證書創建登錄
  3. 授予該登錄UNSAFE ASSEMBLY權限(以下程式碼處理最後 3 個步驟
DECLARE @Cert NVARCHAR(MAX);
SET @Cert = CONVERT(NVARCHAR(MAX), CERTENCODED(CERT_ID(N'ObjectSigner')), 1);

EXEC (N'USE [master]
CREATE CERTIFICATE [{cert_name}]
FROM BINARY = ' + @Cert + N';

CREATE LOGIN [{cert_name}]
  FROM CERTIFICATE [{cert_name}];

GRANT UNSAFE ASSEMBLY TO [{cert_name}];');

現在一切都應該沒問題。

筆記

  1. 如果您有實際的 DLL 二進製文件在作業系統級別進行簽名,則您只需要makecert.exepvk2pfk.exesigntool.exe 。其中之一應該已經存在於您的機器上(即使不在 PATH 中),我相信它是signtool
  2. 您可以從 Windows SDK 中獲取其他兩個實用程序(我將很快發布一篇文章,其中包含指向位置的連結以及要獲取哪些特定包,以便不需要全部獲取它們)。
  3. TRUSTWORTHY並且UNSAFE是兩個非常不同的東西。啟用TRUSTWORTHY是一種廣泛的方法,例如使用模擬(即EXECUTE AS),因為它並不特定於它所授予的內容。
  4. !!現在,這個程序集的開發者實際上可能做了強名稱和/或簽名。完成上述步驟以載入程序集後,您可以通過嘗試從中創建非對稱密鑰和證書來檢查它是否已簽名。如果其中任何一個工作,那麼您可能有更多選項來再次載入此程序集,特別是如果它已使用證書籤名(將來,如果您可以要求開發人員對其進行簽名,那將是理想的)。您可以通過以下方式嘗試:
CREATE ASYMMETRIC KEY [_test_key] FROM ASSEMBLY [MYCALC_DLL];

CREATE CERTIFICATE [_test_cert] FROM ASSEMBLY [MYCALC_DLL];

回复:問題中添加了新程式碼

我不確定您是否節省了開發人員向您發送所有項目文件的時間或精力(向您發送強命名的 DLL 二進製文件會容易得多),但基於您在問題中添加的內容:

  1. 在 Visual Studio 中打開時,我會打開解決方案文件(即**.sln**)而不是項目文件(即**.proj*)。
  2. 有趣的是它是一個**.csproj文件而不是一個.sqlproj**文件,但如果它有效,那麼它就有效。
  3. 在 Visual Studio 中的“簽名”選項卡上:我從未嘗試過使用密碼保護 SNK 文件,但我認為它應該仍然可以工作,因為它只是保護私鑰,但導入 SQL 時只需要公鑰伺服器。
  4. 您不需要將**.snk文件複製到 SQL Server 電腦,因為它不會被使用。可以.snk**文件載入到 SQL Server的公鑰也在強命名/簽名的 DLL 本身中,因此您只需要 DLL(您已經根據腳本創建了非對稱密鑰)顯示在問題中)。
  5. 無需在其中創建使用者,[target_database]因為它不會被使用或不需要使用。目前,它沒有被使用,因此可以跳過該步驟。
  6. 創建程序集:我會PERMISSION_SET = SAFE先看看它是否有效。如果是這樣,那就堅持下去。如果您在創建程序集時遇到錯誤,請嘗試UNSAFE. 如果SAFE適用於載入程序集但隨後執行 proc 得到權限錯誤(文件系統很可能給出了某些原始碼文件的名稱),則將程序集更改為具有PERMISSION_SET = EXTERNAL_ACCESS而不是SAFE.
  7. 不確定該CREATE PROCEDURE聲明是否完整或已編輯,但該AS EXTERNAL NAME部分不完整。您目前只有程序集名稱 ,DBCALC_DLL當您還需要您正在呼叫的方法所在的類的名稱,然後是您正在呼叫的方法的名稱(例如DBCALC_DLL.class.method)時。
  8. 只是出於好奇,為什麼將其稱為“PROC”,即使名稱中有“_SP”,但它是一個函式?😉

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