web-dev-qa-db-ja.com

TRUSTWORTHYを有効にせずにアセンブリSystem.DirectoryServices.AccountManagement.dllを作成する

まず、これはSQL Server 2016の場合です。2017以降の場合、sp_add_trusted_Assemblyを使用します。質問する前にそれを明確にしたかっただけです。

TRUSTWORTHY ONを使用せずに、アセンブリSystem.DirectoryServices.AccountManagement.dllをどのように登録しますか? 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.
*/
3
SpaceGhost440

いいえ、非対称キーは機能しません。おそらく、.NET 4.5またはその周辺で強力な名前付けアセンブリが変更されたため、SQL ServerのCLRホストではサポートされない(強力な名前付け)になりました。ここでは機能しません)。

キーは証明書を使用することです。 DLLからmasterに証明書を作成してから、その証明書からログインを作成し、最後にUNSAFE Assembly権限をそのログインに付与します。

これは単純なはずです(もちろん、DLLは純粋なMSILであり、SQL Serverにロードできるのは純粋なMSILアセンブリのみであるため、混合されていないと仮定します)。

また:

  1. メインアセンブリから参照されていると想定して、メインアセンブリより多くを追加/ドロップする必要はありません。 DLL(16進バイト/ 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の厳密なセキュリティ」-問題 。もちろん、この特定のケースでは、適切なアプローチが上記のようにCertificateメソッドを使用しているため、これは問題点です。

同様の質問に対する他の回答では、自分が回答したか他の回答があったかに関わらず、常にTRUSTWORTHYを有効にする必要があるという回答でした。これは、最近まで気付かなかった、Microsoftのドキュメントから提供された誤った情報が原因でした。私は以前の回答とそのドキュメントの両方を修正する作業をしています。

7
Solomon Rutzky

この回答は、上記のSolomonsの提案に基づいています。クレジットはすべて彼のものです。私は彼が提案したように私のスクリプトを書き直しました、そしてそれは今うまくいきます!!! TY SOLOMON!私の後に来る他の人のための例としてそれを投稿しています。

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.certificates WHERE name = 'MSFT_CLR_Cert'))
BEGIN
    --DROP ASYMMETRIC KEY [ClrKey]
    RAISERROR( 'DROP CERTIFICATE [MSFT_CLR_Cert]', 0, 1) WITH NOWAIT
    DROP CERTIFICATE [MSFT_CLR_Cert] 
END
GO

/*************************************************************************************/
-- CREATE THE OBJECTS
/*************************************************************************************/
USE [master]
GO

RAISERROR( 'CREATE CERTIFICATE [MSFT_CLR_Cert]', 0, 1) WITH NOWAIT
CREATE CERTIFICATE [MSFT_CLR_Cert] FROM EXECUTABLE FILE = 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.DirectoryServices.dll'

RAISERROR( 'CREATE LOGIN [MSFT_CLR_Login]', 0, 1) WITH NOWAIT
CREATE LOGIN [MSFT_CLR_Login] FROM CERTIFICATE [MSFT_CLR_Cert]

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

USE CLR_Test
GO

RAISERROR( 'CREATE USER [MSFT_CLR_Login]', 0, 1) WITH NOWAIT
CREATE USER [MSFT_CLR_Login] FOR LOGIN [MSFT_CLR_Login]


/*************************************************************************************/
-- 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
4
SpaceGhost440