sql-server - 以相当安全的方式使用 sqlclr 和脚本程序集的 F#

标签 sql-server f# sqlclr

有一些关于如何在 SQL Server 中使用 F# 和 SQLCLR 的博客文章很有帮助:http://richardminerich.com/2015/12/a-safer-way-to-use-f-with-sql-clr/ , http://thelastexpression.blogspot.com/2012/04/f-agents-and-sqlclr.html , https://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 中编写的原型(prototype)(现在必须存在于 SQL Server 中)会更好地映射到 F#(并且让我比使用 C# 更快乐)。

最佳答案

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

GRANT EXTERNAL ACCESS ASSEMBLY TO FSHARP_CLR_Login

授予 EXTERNAL ACCESS ASSEMBLY不允许将程序集设置为 UNSAFE .这需要 UNSAFE ASSEMBLY允许。写帖子时可能是复制/粘贴错误,但没有显示(即来自 sys.databases 的证据)证明 TRUSTWORTHY目前是 OFF ,或者作者的代码在创建该登录名并授予该权限之前无法正常工作。

所以,我只是通过安装 FSharp.Core 的最新版本 - 4.1.2 来尝试这个 - 这是我发现的:
  • 确认 TRUSTWORTHYOFF (即 0 )通过:

    SELECT [name], is_trustworthy_on FROM sys.databases WHERE [database_id] = DB_ID();
    
  • 尝试加载 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 failed because type 'Microsoft.FSharp.Collections.FSharpMap`2' in safe assembly 'FSharp.Core' has a static field 'empty'. Attributes of static fields in safe assemblies must be marked readonly in Visual C#, ReadOnly in Visual Basic, or initonly in Visual C++ and intermediate language.

  • 尝试加载 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允许。含义:违规可能是通过运行时验证而不是加载时验证发现的。而且我没有办法在这部分之外进行测试,但我预计会发生错误。
  • 如果确实发生关于 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];
    
  • 如果您的程序集也需要标记为 UNSAFE ,然后您可以从 master 中的 DLL 创建一个非对称 key 然后来自该非对称 key 的基于 key 的登录,然后授予该基于 key 的登录 UNSAFE ASSEMBLY允许。 (假设您的程序集已签名——并使用密码保护)
  • 当然,以上所有假设您可以将 DLL 放到服务器上,或者至少放到 SQL Server 服务帐户可以访问的共享上,并且您确实提到希望通过十六进制字节部署它。这应该可以通过以下方式实现:
  • 在 Visual Studio 中,在“解决方案资源管理器”的“引用”下,转到 的“属性”。 FSharp.Core 并设置 模型感知 True权限集 Unsafe .这将导致发布过程将 DLL 包含在构建脚本中。
  • 如果 DLL 已经在您的目标数据库中,那么它可能不会生成 CREATE ASSEMBLY此程序集的声明,因为发布脚本是增量更改。如果是这种情况,请转到项目属性,并在 下项目设置 ,勾选创建脚本(.sql 文件) (如果尚未检查)。这将导致构建过程总是产生 _Create.sql 脚本,里面肯定会有CREATE ASSEMBLY 的声明FSharp.Core .
  • CREATE ASSEMBLY [FSharp.Core] FROM 0x...语句显然将用于将程序集加载到目标数据库中(即您的程序集也被加载到的位置)。
  • CREATE ASSEMBLY [FSharp.Core] FROM 0x...声明也将是您在 master 中创建对象的门票。如下:

    USE [master];
    
    CREATE ASSEMBLY [FSharp.Core]
    FROM 0x4D....
    WITH PERMISSION_SET = UNSAFE;
    
    CREATE CERTIFICATE [FSharpCert45]
    FROM ASSEMBLY [FSharp.Core];
    
    DROP ASSEMBLY [FSharp.Core];
    
    CREATE LOGIN [FSharpLogin45] FROM CERTIFICATE [FSharpCert45];
    
    GRANT UNSAFE ASSEMBLY TO [FSharpLogin45];
    

    这在 SQL Server 2012 上对我有用,唯一的区别是我使用了文件路径而不是十六进制字节。
  • 关于sql-server - 以相当安全的方式使用 sqlclr 和脚本程序集的 F#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43219334/

    相关文章:

    sql - 从 SQL Server 中的文本中提取数字

    sql - 将多个 csv 文件导入到一张表中

    SQL Server 按日期和时间分组

    f# - 将代码从 Lisp 转换为 F#

    在 SQL Server 中使用 HTML 模板引擎?

    sql - 表中身份列的显式值错误?

    dependency-injection - 将函数注入(inject)计算表达式

    .net - 使用 F# 和 Eto.Forms 捕获箭头键

    sql-server - 在 SQL Server 中对超过 8000 字节进行哈希处理

    sql-server - 如何找到在SQL Server中注册的程序集?