F#以sqlclr以合理安全的方式和脚本化程序集

时间:2017-04-04 23:20:47

标签: sql-server f# sqlclr

有一些博客文章介绍了如何在SQL Server中使用带有SQLCLR的F#,这些帖子非常有用:http://richardminerich.com/2015/12/a-safer-way-to-use-f-with-sql-clr/http://thelastexpression.blogspot.com/2012/04/f-agents-and-sqlclr.htmlhttps://rojepp.wordpress.com/2011/08/03/f_on_sqlclr/Can the F# core libs be SQLCLR-approved? 对于C#方法:http://www.sqlservercentral.com/Authors/Articles/Solomon_Rutzky/294002/

我想知道/希望随着时间的推移,有一篇博文在那里,我还没有找到或在这里找到答案,它解决了如何使用F#和SQLCLR这样组装可以使用Visual Studio(或其他一些工具)编写成十六进制文件,就像使用C#部署一样(我无法通过SQL Server Management Studio在服务器上安装代码),并且至少比使用'更安全'值得信赖的'或'不安全'。之前我编写了F#和许多T-SQL,我在Common Lisp中编写的原型(现在必须存在于SQL Server中)将更好地映射到F#(并且让我比使用C#更快乐。)

1 个答案:

答案 0 :(得分:3)

我对第一个链接(http://richardminerich.com/2015/12/a-safer-way-to-use-f-with-sql-clr/)中显示的方法持怀疑态度,因为它没有直接显示 FSharp.Core 库的加载,因此不清楚作者不必设置TRUSTWORTHY ON以至少使该部分正常工作。似乎非常可疑的是,在第5步中,基于非对称密钥的登录被授予了错误的权限:

GRANT EXTERNAL ACCESS ASSEMBLY TO FSHARP_CLR_Login

授予EXTERNAL ACCESS ASSEMBLY 允许将程序集设置为UNSAFE 需要UNSAFE ASSEMBLY权限。在撰写帖子时可能是一个复制/粘贴错误,但没有显示sys.databases TRUSTWORTHY当前OFF的证据,或者在创建登录并授予其权限之前,作者的代码无效。

所以,我只是通过安装最新版本的FSharp.Core - 4.1.2来尝试这个 - 这就是我发现的:

  1. 通过以下方式确认TRUSTWORTHYOFF(即0):

    SELECT [name], is_trustworthy_on FROM sys.databases WHERE [database_id] = DB_ID();
    
  2. 尝试将 FSharp.Core 加载为SAFE,只是为了查看它是否有效:

    USE [TestDB];
    
    CREATE ASSEMBLY [FSharp.Core]
    FROM N'C:\path\to\project\packages\FSharp.Core.4.1.2\lib\net45\FSharp.Core.dll'
    WITH PERMISSION_SET = SAFE;
    

    收到以下错误:

      

    Msg 6211,Level 16,State 1,Line 32
      CREATE ASSEMBLY失败,因为安全程序集“FSharp.Core”中的类型“Microsoft.FSharp.Collections.FSharpMap`2”具有静态字段“empty”。安全程序集中静态字段的属性必须在Visual C#,Visual Basic中的ReadOnly或Visual C ++和中间语言中的initonly中标记为只读。

  3. 尝试再次加载 FSharp.Core ,但是UNSAFE

    USE [TestDB];
    
    CREATE ASSEMBLY [FSharp.Core]
    FROM N'C:\path\to\project\packages\FSharp.Core.4.1.2\lib\net45\FSharp.Core.dll'
    WITH PERMISSION_SET = UNSAFE;
    

    有效。但是,我没有将数据库设置为TRUSTWORTHY ON,也没有创建登录并授予EXTERNAL ACCESS ASSEMBLY权限。含义:可能通过运行时验证而不是加载时验证来发现违规。我无法超越这部分进行测试,但我希望会发生错误。

  4. 如果关于此程序集的UNSAFE权限集确实发生错误,那么您可以处理该问题而无需设置TRUSTWORTHY ON,但您需要在master中创建一个证书,基于证书的登录:

    USE [master];
    
    CREATE CERTIFICATE [FSharpCert45]
    FROM EXECUTABLE FILE =
            N'C:\path\to\project\packages\FSharp.Core.4.1.2\lib\net45\FSharp.Core.dll';
    
    CREATE LOGIN [FSharpLogin45] FROM CERTIFICATE [FSharpCert45];
    
    GRANT UNSAFE ASSEMBLY TO [FSharpLogin45];
    
  5. 如果您的程序集也需要标记为UNSAFE,那么您可以从master中的DLL创建非对称密钥,然后从该非对称密钥创建基于密钥的登录,然后授予基于密钥的登录UNSAFE ASSEMBLY权限。 (这假定您的程序集已签名 - 并使用密码保护)

  6. 当然,以上所有假设您都可以将DLL放到服务器上,或者至少放到SQL Server服务帐户可以访问的共享上,并且您确实提到要通过十六进制字节部署它。这应该是可能的:

    1. 在Visual Studio中,在“解决方案资源管理器”中的“参考”下,转到 FSharp.Core 的“属性”,并将模型识别设置为{{1 }和权限设置True。这将导致发布过程将DLL包含在构建脚本中。
    2. 如果DLL已经在目标数据库中,那么它可能不会为此程序集生成Unsafe语句,因为发布脚本是增量更改。如果是这种情况,请转到项目属性,然后在项目设置下,选中创建脚本(.sql文件)(如果尚未选中)框。这将导致构建过程始终生成 _Create.sql 脚本,并且肯定会有 FSharp.Core CREATE ASSEMBLY语句。
    3. 显然会使用CREATE ASSEMBLY语句将程序集加载到目标数据库中(即程序集也被加载到其中)。
    4. CREATE ASSEMBLY [FSharp.Core] FROM 0x...语句 也是<{1}}中创建对象的门票,如下所示:

      CREATE ASSEMBLY [FSharp.Core] FROM 0x...

      这在SQL Server 2012上对我有用,唯一的区别是我使用的是文件路径而不是十六进制字节。