模組簽名和 SSIS 目錄內部過程的問題
我正在嘗試設置一個儲存過程來執行 SSIS 包。我想允許使用者只執行這個儲存過程,所以我需要它以不同的使用者身份執行。
我發現這篇文章詳細介紹了創建證書和簽署模組,以便特權登錄可以執行它。
當我嘗試執行任何模擬登錄的命令時,我收到以下錯誤:
無法作為伺服器主體執行,因為主體“CrossDbCertLogin”不存在,無法模擬此類主體,或者您沒有權限。
這是重現問題的腳本:
create certificate CrossDatabaseCert ENCRYPTION BY PASSWORD = 'passA' WITH SUBJECT = 'Certificate for Cross-Database Database Impersonation' GO CREATE Login CrossDbCertLogin FROM CERTIFICATE CrossDatabaseCert GO backup certificate CrossDatabaseCErt to file='C:\temp\CrossDatabaseCert.CER' WITH PRIVATE KEY ( FILE = 'C:\temp\CrossDatabaseCert.PVK', DECRYPTION BY PASSWORD = 'passA', ENCRYPTION BY PASSWORD = 'passB' ) go use msdb create certificate CrossDatabaseCert from file='C:\temp\CrossDatabaseCert.CER' WITH PRIVATE KEY ( FILE = 'C:\temp\CrossDatabaseCert.PVK', DECRYPTION BY PASSWORD = 'passB', ENCRYPTION BY PASSWORD = 'passA' ) Go EXECUTE AS LOGIN=N'CrossDbCertLogin'; SELECT 1
最終我將證書添加到儲存過程中,但似乎模擬甚至沒有執行,所以我試圖先讓它工作。
我究竟做錯了什麼?
編輯:關於我的程序的更多資訊。
當我將其更改為“EXECUTE AS OWNER”(與我遵循的範例相同的形式)時,我收到以下錯誤。
消息 27123,級別 16,狀態 1,過程 create_execution,第 39 行該操作無法由使用 SQL Server 身份驗證的帳戶啟動。使用使用 Windows 身份驗證的帳戶啟動操作。
消息 27123,級別 16,狀態 1,過程 set_execution_parameter_value,第 34 行 使用 SQL Server 身份驗證的帳戶無法啟動操作。使用使用 Windows 身份驗證的帳戶啟動操作。
消息 27123,級別 16,狀態 1,過程 start_execution,第 32 行 使用 SQL Server 身份驗證的帳戶無法啟動操作。使用使用 Windows 身份驗證的帳戶啟動操作。
在我的過程中,我呼叫了三個內部 SSIS 目錄過程:
Create_Execution
、Set_Execution_Parameter_Value
和Start_Execution
.當我將過程更改為作為 SQL 代理服務帳戶執行時,我收到以下錯誤:
消息 15199,級別 16,狀態 1,過程 prepare_execution,第 34 行目前的安全上下文無法恢復。請切換到呼叫“執行為”的原始數據庫並重試。
EDIT2:我最終使用 SQLCLR SProc 來呼叫我原來的 proc,這解決了所有問題。
兩個想法,都圍繞著模仿:
- 從問題的描述以及錯誤消息來看,它們都處理與嘗試模擬/執行 AS 相關的錯誤。這種切換執行上下文的嘗試可能是整個問題。你為什麼用
EXECUTE AS LOGIN = N'CrossDbCertLogin'
?該登錄名(和相關的證書等)作為代理存在以獲得隱含的權限,而不是直接執行任何事情。如果您更仔細地查看您從 sqlxdetails.com 遵循的範例,您會注意到從來沒有呼叫EXECUTE AS LOGIN = N'HighPrivCertLogin'
.因此,我將從:
- 不再嘗試
EXECUTE AS LOGIN = N'CrossDbCertLogin'
- 呼叫三個 SSIS 目錄過程的儲存過程應該沒有
EXECUTE AS
子句或EXECUTE AS CALLER
(如果未指定,則為預設值)- 將每個 SSIS 儲存過程的執行權限授予
[SSISDB]
數據庫中基於證書的使用者。這些是您的受限登錄將從使用映射到具有必要權限的使用者的證書籤名的 proc 之間的連結中獲取的隱含權限*:*USE [SSISDB]; GRANT EXECUTE ON [Create_Execution] TO [CrossDbCertUser]; GRANT EXECUTE ON [Set_Execution_Parameter_Value] TO [CrossDbCertUser]; GRANT EXECUTE ON [Start_Execution] TO [CrossDbCertUser];
然,您的範常式式碼沒有顯示在`[msdb]`或中創建本地數據庫使用者`[SSISDB]`,但我假設這些使用者是創建的。如果沒有,那麼至少您需要在其中創建使用者,`[SSISDB]`因為這是需要數據庫級別權限的地方(即執行 3 個 SSIS 過程)。但是,在其中創建基於證書的使用者可能也沒有什麼壞處`[msdb]`。 2. 如果由於某種原因(也許 SSIS,作為外部程序,不能使用模擬的身份驗證令牌?)執行上下文本身需要具有特權*和*可模擬(是的,這是一個完美的詞;-),那麼目前的方法不會像您嘗試的那樣工作: 模擬不能具有執行上下文的登錄(即基於證書和非對稱密鑰的登錄) 通過無法還原的`EXECUTE AS`子句的子句進行模擬(我不知道為什麼有人想要還原,但這是您在嘗試此操作時收到的錯誤消息)。`CREATE PROCEDURE`所以,這裡有兩件事要嘗試(再次,假設上面的選項#1 不能解決問題): 創建一個 SQLCLR 儲存過程,它只通過“trusted_connection = true;”的連接字元串進行連接 (它將連接到預設實例,可能是您目前所在的實例)並執行您的儲存過程,`[msdb]`其中執行三個 SSIS 過程。這將起作用,因為除非您明確編碼使用模擬,否則預設情況下它將作為執行 SQL Server 程序的 Windows/Active Directory 帳戶(即服務中的“登錄為”帳戶)建立外部連接,並且該帳戶應該能夠執行那些 SSIS 程序。此選項不需要任何證書或登錄,因為您將`GRANT EXECUTE`在此 SQLCLR 儲存過程上連接到該受限登錄,並且此儲存過程作為特權登錄建立新的獨立連接。此 SQLCLR 過程只有一個目的,即作為特權登錄名登錄不會構成安全威脅。另一個關鍵部分是:由於連接是由非模擬上下文建立的,因此*可以*將身份驗證令牌傳遞給外部機器。但是是的,Assembly 將需要 a `PERMISSION_SET`of `EXTERNAL_ACCESS`,這應該通過對 Assembly 進行簽名,然後從該程序集創建一個非對稱密鑰,然後基於該非對稱密鑰創建一個登錄名,然後授予該`EXTERNAL_ACCESS ASSEMBLY`登錄名的權限來完成。 果在程序集/非對稱密鑰步驟的數據庫方面需要幫助,我寫了一篇文章,[SQLCLR 級別 4 的階梯:安全性(外部和不安全的程序集)](http://www.sqlservercentral.com/articles/SQLCLR/112888/)(需要免費註冊),其中包含一個分步範例這樣做;它只是沒有顯示在 Visual Studio 中創建私鑰。 要麼** 創建您的受限登錄有權`INSERT`進入的隊列表。然後創建一個檢查隊列表的 SQL 代理作業,如果找到“新”記錄,則將狀態更新為“處理中”,呼叫`[msdb]`呼叫三個 SSIS 過程的儲存過程,然後完成,更新隊列記錄再次“完成”。在這種方法中,SQL 代理通過來自非模擬上下文的新連接執行儲存過程;因此,身份驗證令牌*可以*傳遞給外部機器。