如何签署我使用的不安全的C#CLR和程序集,而不是让数据库值得信任

时间:2017-09-28 15:02:57

标签: c# .net visual-studio sqlclr unsafe

我在C#CLR代码中使用.NET DirectoryServices和DirectoryServices.AccountManagement。我想作为不安全的CLR存储过程发布到我的SQL Server数据库。在Visual Studio中,我签署了我的CLR项目。我想避免转向值得信赖。我如何签署组件? 我知道这听起来很简单,但我在google上搜索了4个小时而没有得到答案。当我将Stairway下载到CLR时,我认为我非常接近,但是在那里找不到答案。

2 个答案:

答案 0 :(得分:3)

首先:感谢您不使用简单路线并启用TRUSTWORTHY。认真。正确地做这件事并不是那么多工作,所以我(和你的雇主)感谢你做更多的研究,当你无法做得更远时,伸出援助之手。

如果您指的是SQL Server Central上的“Stairway to SQLCLR”系列,那么我就是这些文章的作者。如果不容易理解这些信息,我很抱歉。我将概述这里的步骤:

  1. 在Visual Studio中,使用强名称密钥对程序集进行签名,并使用密码保护它(根据问题,您已经这样做了)
  2. 根据您的工作和总体要求,您可以在此处选择一些选项:

    1. 如果您的程序集使用的代码在通过CREATE ASSEMBLY创建时在验证步骤中标记了违规,那么您可以从技术上将程序集加载到[master],标记为{{ 1}},从中创建非对称密钥(这里不执行代码,因此不需要在此处标记为SAFE)。
    2. 如果您的代码未通过验证(意思是:它只能在标记为UNSAFE时创建),那么我发现最好创建一个单独的空程序集,也使用相同的强名称密钥文件进行签名(即用于主程序集的UNSAFE文件)。然后我将那个空的但已签名的装配加载到.pfx,标记为[master]
    3. 如果您需要处理SQL Server 2017,那么这需要一个额外的步骤,我将在稍后提及。
  3. SAFE中创建的程序集使用用于签署主[master]程序集的相同.pfx文件进行签名后,您只需创建,在UNSAFE中,来自该大会的非对称密钥。

  4. 从该非对称密钥创建登录

  5. 授予基于密钥的登录[master]权限

  6. 这些步骤适用于SQL Server 2005 - 2016,我在Stairway to SQLCLR Level 7: Development and Security文章中提供了有关如何自动执行此操作的说明(上面的选项2 - 使用单独的,空的,已签名的程序集)。 (顺便说一下,我确实认识到第7级中描述的步骤确实有点多,但是它们确实提供了使用Visual Studio的自动化方法,并且可以通过使用T4模板来简化它们 - 它随VS一起提供 - 但是我的避风港还没有时间写出简化的方法 - 希望很快就会这么做。)

    但是,如果您需要考虑SQL Server 2017(或者更新,可能),那么上述步骤将无法正常工作UNSAFE ASSEMBLY可以再创建程序集而无需签名并具有相应的签名基于SAFE权限的登录。而且,遗憾的是,UNSAFE ASSEMBLY不允许从十六进制字节字符串/ CREATE ASYMMETRIC KEY文字创建,因此您需要使用允许以这种方式创建的证书。在这些方面,我有两个博客文章,详细,一步一步,如何实现这一点,通过Visual Studio完全自动化(甚至不使用Visual Studio):

    无论你做什么,都会被SQL Server 2017的新“受信任的程序集”功能所迷惑,因为它有很多问题,如下所述:SQLCLR vs. SQL Server 2017, Part 4: “Trusted Assemblies” – The Disappointment和一个我正在研究的更多帖子。

    为了帮助改善这种不必要的痛苦过程,请支持我的改进请求以改进VARBINARY和SSDT:

答案 1 :(得分:1)

我们有几个需要它的旧项目。直到本周我花时间搞清楚这一点,我们一直在使用可怕的可信赖旗帜。

经过一系列的研究,我能够通过在我的Visual Studio项目中使用预部署sql脚本和一些一次性设置来将其设置为相当轻松。 This article对我帮助最大。

我已经测试并证实了这项工作:

  • SQL Server 2008 R2
  • SQL Server 2012
  • SQL Server 2014
  • SQL Server 2016

步骤:

  1. 使用Visual Studio的Developer命令提示符创建一个新的强名称密钥,然后输入:

    sn -k ".\CLRKey.snk"
    
  2. 在Visual Studio项目设置的SQLCLR区域中,单击“签名”按钮,然后选择通过浏览到刚刚创建的密钥文件对程序集进行签名:enter image description here

  3. CLRKey.snk复制到每个目标SQL Server的C:\,或者服务器可以读取的其他路径。

  4. 将此预部署脚本添加到Visual Studio项目中,调整密钥路径和密码以适合您的环境:

    DECLARE @sp nvarchar(255) = '$(DatabaseName)..sp_executesql';
    DECLARE @create_user nvarchar(4000) = N'CREATE USER [CLRExtensionLogin] FOR LOGIN [CLRExtensionLogin]'
    DECLARE @MSG varchar(8000)
    
    use master;
    BEGIN TRY
    BEGIN TRAN
    
        IF NOT EXISTS (select 1 from sys.asymmetric_keys where name=N'CLRExtensionKey') BEGIN
            create asymmetric key CLRExtensionKey
            from file = 'c:\CLRKey.snk'
            encryption by password = '<invent a password>'
            RAISERROR( 'Key created.', 0, 1 ) WITH NOWAIT
        END ELSE BEGIN
            RAISERROR( 'Key exists.', 0, 1 ) WITH NOWAIT
        END
    
        IF NOT EXISTS (SELECT * FROM sys.syslogins WHERE name=N'CLRExtensionLogin') BEGIN
            CREATE LOGIN CLRExtensionLogin FROM ASYMMETRIC KEY CLRExtensionKey;
            EXEC @sp @create_user
            RAISERROR( 'User created.', 0, 1 ) WITH NOWAIT
        END ELSE BEGIN
            RAISERROR( 'User exists.', 0, 1 ) WITH NOWAIT
        END
    
        GRANT EXTERNAL ACCESS ASSEMBLY, UNSAFE ASSEMBLY TO [CLRExtensionLogin];
        COMMIT TRAN
    
        SET @MSG = 'Assembly access granted.' + CHAR(10) + 'Done.'
        RAISERROR( @MSG, 0, 1 ) WITH NOWAIT
    END TRY
    BEGIN CATCH
        SET @MSG = ERROR_MESSAGE() + CHAR(10) + 'Aborted.'
        RAISERROR( @MSG, 16, 1 )
        IF @@TRANCOUNT > 0 ROLLBACK
    END CATCH
    
    USE [$(DatabaseName)];
    
  5. 只要SQL Server可以在脚本第一次运行时读入该密钥文件,您就可以自由发布到同一服务器,而不必再担心所有这些。

    如果您有其他项目发布到同一服务器,您所要做的就是使用与步骤2中相同的密钥对其进行签名,但最佳做法是链接到同一个预部署脚本在所有项目中,以防您希望在某个时刻将其中一个发布到不同的服务器。希望这有帮助!