TSQL CREATE ASSEMBLY FROM varbinary прерывает параметр class_name - PullRequest
0 голосов
/ 02 марта 2019

Я перенес свои локальные базы данных SQL Server 2008 R2 в управляемый экземпляр Azure SQL Server (SQL Server 2017).Одна база данных является архивной (только для чтения), одна - базой данных OLTP, а третья - служебной базой данных, в которой хранятся общие функции, хранимые процедуры и сценарии обслуживания.Все прошло очень гладко для всех трех БД, за исключением сборки CLR в служебной БД.Сборка обеспечивает функциональность Regex в коде TSQL - очень полезно!Я основал это на коде Фила Фактора здесь .Первоначально он был загружен в локальную БД из скомпилированной DLL.Это работает как чемпион там.Но в SQL MI я получаю следующую ошибку при запуске SP, который использует одну из функций CLR:

Сообщение 10314, уровень 16, состояние 11, процедура dbo.globalSearch, строка 22 [Пакетный запускСтрока 2]
Произошла ошибка в Microsoft .NET Framework при попытке загрузить идентификатор сборки 65541. Возможно, на сервере не хватает ресурсов или сборка не является доверенной.Запустите запрос еще раз или просмотрите документацию, чтобы узнать, как решить проблемы доверия к сборке.Дополнительные сведения об этой ошибке:
System.IO.FileLoadException: не удалось загрузить файл или сборку 'regexsqlclr, версия = 0.0.0.0, Culture = нейтральный, PublicKeyToken = null' или одну из ее зависимостей.Произошла ошибка, связанная с безопасностью.(Исключение из HRESULT: 0x8013150A)
System.IO.FileLoadException:
в System.Reflection.RuntimeAssembly._nLoad (AssemblyName fileName, расположение строки кода, свидетельство AssemblySecurity, местоположение RuntimeAssemblyHint, StackCrawlMarkleotFoundPhieldParkPhieldParkPhieldPackPackPackPhieldPackPackPackPackforIntrospection, булевы suppressSecurityChecks)
на System.Reflection.RuntimeAssembly.InternalLoadAssemblyName (AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark & ​​stackMark, IntPtr pPrivHostBinder, булевой throwOnFileNotFound, Boolean, Boolean forIntrospection suppressSecurityChecks)
в System.Reflection.RuntimeAssembly.InternalLoad (String assemblyString, Evolution AssemblySecurity, StackCrawlMark & ​​stackMark, IntPtr pPrivHostBinder, логическое значение forIntrospection)
в System.Reflection.RuntimeAssembly.InternalLoad (строковая строка AssemblyString, Evidence Assembly_Security, BoostanSpectionMell для StormMellMarSMM)em.Reflection.Assembly.Load (String assemblyString)

Я попытался решить проблемы доверия к сборке, используя шаги в этом сообщении MSDN, в частности, выполняя

sys.sp_add_trusted_assembly

, который преуспевает, но ничего не меняет.Тогда я подумал, что, поскольку он предполагает, что он не может загрузить файл, который кажется разумным, поскольку файл не существует в SQL MI, где у меня нет доступа к файловой системе, я должен попытаться удалитьи воссоздание с varbinary.Я только сказал, что , кажется, имеет смысл, потому что файл также не существует ни на одном из моих других локальных серверов, кроме того, с которого я первоначально загрузил его, и он прекрасно работает на всех них.Но я готов попробовать что угодно!Поэтому, используя SSMS, я записал ассемблер в виде DROP и CREATE, который использует синтаксис FROM BINARY, а также выполнил сценарий для всех функций.CREATE ASSEMBLY успешно, так что я думаю, что я на правильном пути.Затем я пытаюсь создать первую функцию и BAM, еще одна ошибка!На этот раз ошибка читает

Msg 6505, уровень 16, состояние 2, процедура RegexIndex, строка 2
Не удалось найти тип 'RegexSQLCLR.RegularExpressionFunctions' в сборке 'RegexFunctions'.

Я часами гуглял, пытаясь найти решение этой проблемы, и мне не повезло.Хотя этот синтаксис для части класса в предложении EXTERNAL NAME отлично работает для сборки, загруженной из файла.Я убедился, что сценарий varbinary, создаваемый SSMS, идентичен двоичному файлу исходной библиотеки DLL.Кто-то на форуме Microsoft предложил мне убедиться, что DLL была скомпилирована с опцией Any CPU - так и было.В качестве проверки работоспособности я проделал ту же процедуру на одном из локальных серверов, то есть DROP и CREATE ASSEMBLY FROM BINARY, и получил точно такой же результат: я не могу загрузить ни одну из функций CLR!Я перепробовал все мыслимые изменения имен классов, которые я могу придумать, но безрезультатно.Вот код для CREATE ASSEMBLY и CREATE FUNCTION

CREATE ASSEMBLY [RegexFunction]
AUTHORIZATION [dbo]
FROM 0x4D5A90000 *truncated_for_brevity*
WITH PERMISSION_SET = SAFE

CREATE FUNCTION RegExIndex
   (
    @Pattern NVARCHAR(4000),
    @Input NVARCHAR(MAX),
    @Options int
   )
RETURNS int
AS EXTERNAL NAME 
   RegexFunction.[RegexSQLCLR.RegularExpressionFunctions].RegExIndex
GO

RegexSQLCLR - это имя исходной DLL, а RegularExpressionFunctions - имя класса.RegexSQLCLR также является именем, указанным в столбце name sys.assembly_files после использования CREATE ASSEMBLY FROM BINARY;в противном случае полный путь к исходной DLL находится в столбце name.

1 Ответ

0 голосов
/ 02 марта 2019

Итак, здесь есть ряд проблем:

  1. Первая проблема заключается в том, что неподписанные сборки (или даже подписанные сборки, которые также не имеют подходящего имени входа на основе сигнатуры, котороебыло предоставлено разрешение UNSAFE ASSEMBLY) и больше не считаются «БЕЗОПАСНЫМИ» из-за потенциальных (но, возможно, недоказанных) проблем безопасности.Итак, начиная с SQL Server 2017, был введен новый параметр конфигурации на уровне сервера под названием «Строгая безопасность CLR», который заставляет все сборки соответствовать требованиям сборок, помеченных как UNSAFE.Опции PERMISSION_SET SAFE и EXTERNAL_ACCESS по-прежнему работают, как и раньше, это просто проблема загрузки сборок и выполнения из них объектов SQLCLR.Проблема, с которой вы столкнулись, заключалась в том, что SAFE сборки никогда не нужно было подписывать (хотя они могли бы быть такими, как все сборки в моей библиотеке SQL # SQLCLR, и есть преимущества для их подписания,даже если они содержат только код SAFE и останутся как PERMISSION_SET = SAFE), и поэтому большинство из них не были подписаны, но теперь они должны быть.Таким образом, при обновлении / переносе БД с версии до 2017 года до SQL Server 2017 или новее выдается ошибка безопасности.

    Один из вариантов - просто отключить «CLR строгую безопасность», или другой вариант - включить TRUSTWORTHY для БД, где живет сборка.Оба варианта менее безопасны.Я не уверен, насколько «небезопасным» является отключение «строгой безопасности CLR» на самом деле (на практике это может быть чрезмерной реакцией со стороны Microsoft), но, безусловно, предпочтение состоит в том, чтобы оставить это включенным.Включение TRUSTWORTHY, безусловно, является очень плохим вариантом: ПОЖАЛУЙСТА, пожалуйста, пожалуйста, прекратите использование олицетворения, TRUSTWORTHY и цепочки владения несколькими базами данных .

    Механизм, которыйMicrosoft выпустила для решения этой ситуации функцию «доверенных сборок».К сожалению, эта функция также является плохим вариантом: она очень никогда не требовалась (ну, она нужна только для базы данных SQL Azure, которая больше не поддерживает SQLCLR, но код «доверенных сборок» уже был написан) и стала доступной только потому, чтоникто не понимал, что существующая функциональность уже решает эту ситуацию, и гораздо лучше. См. SQLCLR против SQL Server 2017, часть 4: «Доверенные сборки» - разочарование .В этом посте подробно рассматриваются проблемы с «доверенными сборками» и то, как должен решить проблему существующих неподписанных сборок (т. Е. Создать сертификат в БД со сборкой, подписать сборку, создатьтот же сертификат в master только из открытого ключа, создайте логин из сертификата в master и, наконец, предоставьте этому логину разрешение UNSAFE ASSEMBLY).

  2. I 'Мы пытались решить проблемы доверия сборки, используя ... sys.sp_add_trusted_assembly, что успешно, но ничего не меняет.

    Я не уверен, какое значение вы использовали для хэша, но эта хранимая процедура неубедитесь, что хеш соответствует чему-либо.Он просто загружает хеш во внутреннюю таблицу, из которой будут считываться позже при ссылке на сборку.Затем он увидит, соответствует ли значение хеша сборки значению во внутренней таблице сохраненных хешей.Таким образом, он всегда должен быть успешным (если вы дали ему действительное двоичное значение, которое может быть хешем SHA2_256).

  3. Я думал, что так как он предполагает, что онневозможно загрузить из файла, что, кажется, имеет смысл, поскольку файл не существует в SQL MI, где у меня нет доступа к файловой системе

    Это просто неверное толкование.Вы правы, что в управляемых экземплярах базы данных SQL Azure нет доступа к файловой системе, но файловая система в этом случае является внутренней таблицей, в которой хранится сборка, загруженная с помощью CREATE ASSEMBLY.Ошибка говорит о том, что сборка не может быть загружена из таблицы в память.И это было связано с проблемой безопасности, упомянутой выше в пункте № 1. Поэтому удаление и повторное создание сборки фактически ничего не делает.

  4. Кто-то на форуме Microsoft предложил мне убедиться, что DLL была скомпилирована с опцией Any CPU

    Я понятия не имею, почему это вообще произошло.Опять же, здесь нет ничего плохого в любом из приведенных здесь кодов.

  5. AS EXTERNAL NAME RegexFunction.[RegexSQLCLR.RegularExpressionFunctions].RegExIndex

    Не уверен, почему туда было вставлено RegexSQLCLR,но формат (без пространства имен):

    AssemblyName.ClassName.MethodName

    или (с пространством имен):

    AssemblyName.[NameSpaceName.ClassName].MethodName

  6. Опять же, TRUSTWORTHY ON - это плохой выбор, и совершенно ненужный .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...