Можно ли создать асимметричный ключ для сборки платформы .NET в SQL Server 2014?

Я разрабатываю проект базы данных SQL Server в Visual Studio, который на самом деле является пользовательской функцией. В этот проект я включил Json.NET в качестве эталона (используя NuGet).

Мне удалось опубликовать (и заставить работать) мою сборку и UDF в моем экземпляре SQL Server, сначала повернув базу данных TRUSTWORTHY ON (поскольку мой проект НЕ БЕЗОПАСЕН), а затем запустив это:

CREATE ASSEMBLY [System.Runtime.Serialization] 
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Runtime.Serialization.dll'
WITH PERMISSION_SET = UNSAFE;

Что оказывается сборкой, от которой зависит Json.NET (если я этого не сделаю, я получаю сообщение об ошибке)

Тем временем я читал о том, как плохо включать НАДЕЖНЫЙ может быть, и я попытался использовать асимметричный ключ, чтобы не включать его.

Еще до того, как подписать свою собственную сборку, я знаю, что мне придется создать ключ для System.Runtime.Serialization, так как мой проект зависит от Json.Net, который, в свою очередь, зависит от него, но когда я запускаю его, я получаю следующее:

USE [master];
GO
  CREATE ASYMMETRIC KEY [SystemRuntimeSerializationKey]
    AUTHORIZATION [dbo]
    FROM EXECUTABLE FILE = 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Runtime.Serialization.dll';
GO

Msg 15468, Level 16, State 5, Line 3
An error occurred during the generation of the asymmetric key.

Что мне мало помогает.

Итак, возможно ли сгенерировать такой ключ для сборок .NET framework или существует обходной путь, отличный от включения TRUSTWORTHY ON?


person MaxiWheat    schedule 15.03.2016    source источник
comment
Кстати, SQL Server 2016 еще не совсем вышел, но он будет иметь встроенную поддержку JSON, что может означать, что вся эта проблема исчезнет для вас — в зависимости от того, что вы делаете с JSON, конечно.   -  person Jeroen Mostert    schedule 15.03.2016


Ответы (2)


Нет, я так и не нашел способ сделать это. Ключ, используемый для подписи сборки .NET Framework, является внутренним/приватным для Microsoft. Варианты пробовал:

  • Извлечь закрытый ключ/загрузить в SQL Server: невозможно, иначе ключ не будет «закрытым». Система подписи/строгого именования эффективна, потому что посторонние не могут утверждать, что они подписали код.

  • #P3# <блочная цитата> #P4# #P5#
  • Удалить текущую подпись и добавить новую: я попытался использовать ILDASM для дизассемблирования System.Runtime.Serialization.dll, а затем добавить новый закрытый ключ, созданный из sn -k, а затем повторно связать с помощью ILASM, но это не удалось на шаге ILASM (и у меня нет времени исследовать дальше).

    Но, как и в приведенном выше варианте, даже если это сработает, вам придется изменить ссылку на проект Json.NET для System.Runtime.Serialization, чтобы она была этой новой DLL, перекомпилировать ее, затем изменить ссылку на ваш проект, чтобы она была новой DLL, а затем перекомпилировать это . Но это только даст вам возможность загружать библиотеки DLL чисто, это не гарантирует, что они будут работать, если у них есть внешние зависимости, ожидающие исходной подписи Microsoft.

По сути, если вы загружаете библиотеки DLL, над которыми у вас нет контроля с точки зрения подписи, то единственная надежда состоит в том, чтобы декомпилировать с помощью ILDASM и перекомпилировать с помощью ILASM, указав новый файл snk, но это не сработает, если другие сборки связаны с тем, что перекомпилируется. И, безусловно, библиотеки DLL .NET Framework попадают в эту категорию.

Проще говоря: если вы загружаете неподдерживаемые библиотеки DLL .NET Framework, вам необходимо установить TRUSTWORTHY ON.

НО: имейте в виду, что даже если это помогло загрузить все через асимметричный ключ или сертификат, это не означает, что вы не столкнетесь с функциональными проблемами. Есть причина, по которой эти библиотеки не были одобрены/проверены. В них есть код, делающий вещи, которые могут работать не так, как вы ожидаете, например, сохраняя данные в статических полях. В приложениях для Windows и консоли это не проблема, так как это одно использование для каждого домена приложения. Но SQLCLR использует общий домен приложений, поэтому несколько сеансов SQL Server будут совместно использовать эти статические переменные. Возможно, методы, вызываемые библиотекой Json.NET, не используют эти небезопасные вещи, но узнать об этом невозможно, и даже если бы мы знали, мы мало что можем с этим поделать :-(.


Одна вещь, которую я обдумывал, — это отследить методы, вызываемые в неподдерживаемой .NET Framework DLL, и предположить, что она не делает ничего небезопасного, скопировав этот код непосредственно в проект. Теоретически это должно работать, если вызовы System.Runtime.Serialization не вызывают другие неподдерживаемые библиотеки DLL или не делают «небезопасных» вещей и т. д. Но у меня не было времени проверить это.

person Solomon Rutzky    schedule 15.03.2016
comment
Жаль нет механизма тоже можно сказать что-то типа Ну я знаю что эта сборка официально не поддерживается (безопасна), у меня нет ключа к ней (подписано), но я все же хочу чтобы мои пользователи пользовались это без необходимости включать TRUSTWHORTHY для базы данных и, кстати, как бы снижает безопасность всего моего сервера. - person MaxiWheat; 16.03.2016

Мне удалось сделать это на SQL Server 2014 (версия 11.0.6248.0) для .Net Framework 4 Systen.Drawing.dll, используя следующий скрипт

USE MASTER
GO

CREATE 
    ASYMMETRIC KEY SystemDrawingKey 
    FROM EXECUTABLE FILE = N'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Drawing.dll'   

CREATE 
    LOGIN SystemDrawingKeyLogin 
    FROM ASYMMETRIC KEY SystemDrawingKey   

GRANT UNSAFE ASSEMBLY TO SystemDrawingKeyLogin

USE MY_DATABASE
GO 

CREATE ASSEMBLY [SystemDrawing]
FROM N'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Drawing.dll' WITH PERMISSION_SET = UNSAFE
GO 

SQL Server принимает эту сборку, но выдает предупреждение:

Предупреждение. Сборка Microsoft .NET Framework «system.drawing, версия = 4.0.0.0, культура = нейтральная, publickeytoken = b03f5f7f11d50a3a, процессорная архитектура = msil». который вы регистрируете, не полностью протестирован в среде размещения SQL Server и не поддерживается. В будущем, если вы обновите или обслуживаете эту сборку или .NET Framework, ваша процедура интеграции CLR может перестать работать. Дополнительные сведения см. в электронной документации по SQL Server.

Чтобы убедиться, что эта настройка отключена, я выполнил следующий запрос из Предупреждение о параметре НАДЕЖНАЯ база данных:

SELECT name, is_trustworthy_on
FROM sys.databases
WHERE name <> 'msdb'
AND is_trustworthy_on = 1

Что не дало результатов. Конечно, сейчас у меня WITH PERMISSION_SET = UNSAFE, но это кажется менее проблематичным.

System.Drawning.dll — это зависимость, которая мне нужна для сторонней сборки. Я почти уверен, что методы, которые я вызываю, ничего не вызывают в System.Drawing, поэтому пока я придерживаюсь этого мнения.

Также у меня возникла ошибка при создании собственной пользовательской сборки. Я потерял точную ошибку, но упомянул Синхронизацию и ссылался на System.Diagnostics, что помогло мне найти вызов Debug.WriteLine. После этого сборка могла быть создана, и все работало нормально.

person R. Schreurs    schedule 16.06.2017