Как прочитать столбец SQL с постоянным шифрованием из классического ASP

Я поддерживаю классическое приложение ASP (да, я знаю, что мы над ним работаем), и мне нужен доступ к столбцам Always Encrypted в SQL 2017.

Я импортировал сертификат и протестировал его в SSMS и PowerShell, и это работает. Лучшее, что мне удалось сделать в ASP, — это получить зашифрованное значение в виде массива байтов. Я пробовал больше комбинаций строк подключения, чем могу вспомнить. Моя коробка разработчика ASP — Windows 10; сервер данных - SQL 2017.

cnn = "Provider=MSOLEDBSQL; DataTypeCompatibility=80; " _
    & "DRIVER={ODBC Driver 17 for SQL Server}; " _
    & "SERVER=xxxx; UID=xxxxx; PWD=xxxxx; DATABASE=xxxx; " _
    & "ColumnEncryption=Enabled; Column Encryption Setting=Enabled;"
Set oDB = CreateObject( "ADODB.Connection" )
oDB.Open cnn
set oCmd = Server.CreateObject("ADODB.Command") 
oCmd.ActiveConnection = cnn
oCmd.CommandText = "SELECT top 10 ID, Enc FROM tbl1"
set rst = oCmd.Execute()

Код работает без ошибок, но зашифрованный столбец (Enc, varchar(50)) возвращается в виде массива байтов. Кажется, я получаю зашифрованное значение, когда я должен получить значение обычного текста. Я также пытался вызвать хранимую процедуру с теми же результатами. В запросе нет фильтра, поэтому параметризовать нечего. Есть идеи, что попробовать дальше?


Ответ:
1) Импортируйте сертификат от имени того же пользователя, что и удостоверение пула приложений для этого веб-приложения.
2) Установите авторизацию Anon для веб-приложения на удостоверение пула приложений.
3) Используйте эту строку подключения:

  cnn = "Provider=MSDASQL;" _
      & "Extended Properties=""Driver={ODBC Driver 17 for SQL Server};" _
      & "SERVER=***; UID=***; PWD=***;" _
      & "DATABASE=***;ColumnEncryption=Enabled;"" "

person Len    schedule 17.04.2019    source источник
comment
Сертификат был установлен в приватном магазине под моей учетной записью. Пул приложений обычно находится под AppPoolIdentity; изменил его на свою учетную запись без каких-либо изменений в результатах. Насколько я понимаю, ADO использовала OleDB для подключения через ODBC к SQL; это неправильно? Я пробовал несколько комбинаций PROVIDER и DRIVER, но безуспешно.   -  person Len    schedule 18.04.2019
comment
Добавлен комментарий, чтобы отметить, что это соединение не может получать данные varChar(MAX). Отладчик показывает, что он получает \b вместо ожидаемых данных. Пока нет решения, кроме изменения типа данных или соединения.   -  person Len    schedule 26.06.2019


Ответы (1)


Новый поставщик Microsoft OleDb для SQL Server (MSOLEDBSQL) не поддерживает AlwaysEncrypted (в настоящее время). Вам придется использовать ODBC, что означает, что поставщик OleDb должен быть поставщиком Microsoft OleDb для ODBC (MSDASQL). Таким образом, вы можете настроить системный DSN с помощью Microsoft® ODBC Driver 17 для SQL Server со строкой подключения, например:

cnn = "Provider=MSDASQL;DSN=testdb;"

или внедрить все параметры драйвера ODBC в «Расширенные свойства» строки подключения MSDASQL. Нравится

cnn = "Provider=MSDASQL;Extended Properties=""Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=testdb;Trusted_Connection=yes;ColumnEncryption=Enabled;"" "

Вот пошаговое руководство с использованием первого VBScript для тестирования перед тестированием с помощью ASP.

Начиная с:

create database testdb
go
use testdb

create table tbl1(id int, Enc varchar(200))

insert into tbl1(id,enc) values (1,'Hello')

Затем запустите мастер шифрования столбцов в SSMS, в котором хранится сертификат для текущего пользователя, на компьютере, на котором работает SSMS:

gif мастера шифрования столбцов

Затем листинг query.vbs:

cnn = "Provider=MSDASQL;Extended Properties=""Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=testdb;Trusted_Connection=yes;ColumnEncryption=Enabled;"" "
Set oDB = CreateObject( "ADODB.Connection" )
oDB.Open cnn
set oCmd = CreateObject("ADODB.Command") 
oCmd.ActiveConnection = cnn
oCmd.CommandText = "SELECT top 10 ID, Enc FROM tbl1"
set rst = oCmd.Execute()
rst.MoveFirst()
msgbox( cstr(rst("Enc")) )

Который можно запустить из командной строки с помощью:

cscript  .\query.vbs

Чтобы сделать это из ASP, вам дополнительно потребуется поместить сертификат в хранилище сертификатов пользователя учетной записи пула приложений IIS в соответствии с документами здесь. Обратите внимание, что относительный путь к сертификату должен быть одинаковым для всех пользователей. Вы не можете сохранить его в хранилище компьютера в поле IIS, если вы изначально настроили его для хранения в хранилище сертификатов пользователя. SQL Server хранит key_path ключа и указывает клиентам, где найти сертификат, например CurrentUser/my/388FF64065A96DCF0858D84A88E1ADB5A927DECE.

Итак, откройте ключевой путь главного ключа столбца

select name, key_path from sys.column_master_keys

Затем экспортируйте сертификат с машины, на которой он есть:

 PS C:\Windows> $path = "cert:\CurrentUser\My\388FF64065A96DCF0858D84A88E1ADB5A927DECE"
 PS C:\Windows> $mypwd = ConvertTo-SecureString -String "xxxxxxx" -Force -AsPlainText
 PS C:\Windows> Export-PfxCertificate -Cert $path -FilePath c:\temp\myexport.pfx -ChainOption EndEntityCertOnly  -Password $mypwd

Запустив от имени пользователя удостоверения пула приложений на сервере IIS, импортируйте его.

PS C:\WINDOWS> $mypwd = ConvertTo-SecureString -String "xxxxxxx" -Force -AsPlainText
PS C:\WINDOWS> Import-PfxCertificate -FilePath C:\temp\myexport.pfx -CertStoreLocation Cert:\LocalMachine\My -Password $mypwd

И если вы используете аутентификацию Anonymous/Forms, убедитесь, что вы настроили анонимную аутентификацию IIS для запуска под идентификатором пула приложений, а не IUSR по умолчанию.

Диалоговое окно редактирования анонимной аутентификации IIS

Вот страница ASP для тестирования:

<!DOCTYPE html>
<html>
<body>

<p>Output :</p>

<%

Set objNetwork = CreateObject("Wscript.Network")
Response.write("The current user is " & objNetwork.UserName)

cnn = "Provider=MSDASQL;Extended Properties=""Driver={ODBC Driver 17 for SQL Server};Server=localhost;Database=testdb;Trusted_Connection=yes;ColumnEncryption=Enabled;"" "
Set oDB = CreateObject( "ADODB.Connection" )
oDB.Open cnn
set oCmd = CreateObject("ADODB.Command") 
oCmd.ActiveConnection = cnn
oCmd.CommandText = "SELECT top 10 ID, Enc FROM tbl1"
set rst = oCmd.Execute()
rst.MoveFirst()
Response.write(cstr(rst("Enc")) )

%>

</body>
</html>
person David Browne - Microsoft    schedule 17.04.2019
comment
Это работает как файл VBS, но в ASP я получаю это: Microsoft OLE DB Provider for ODBC Drivers error '80004005' [Microsoft] [Диспетчер драйверов ODBC] Указанный DSN содержит несоответствие архитектуры между драйвером и приложением. AppPool установлен для 32-битные приложения. - person Len; 18.04.2019
comment
Вам обязательно понадобится для загрузки 32-битного драйвера. Но он должен быть установлен вместе с 64-битным драйвером. Пакет установки x86 не будет работать даже в 64-битной Windows. Возможно проблема с системным путем. Я проверю. - person David Browne - Microsoft; 18.04.2019
comment
Попытка установить msocbcsql_17.3.2.2_x86 не удалась: установка этого продукта не удалась, так как он не поддерживается в этой операционной системе. Я на Windows 10 Корпоративная. - person Len; 18.04.2019
comment
Убедитесь, что 32-битный драйвер установлен в правильном месте: dir C:\Windows\SysWOW64\msodbcsql17.dll Эта папка отображается как `c:\windows\system32' для 32-битных процессов. И убедитесь, что нет копии этого файла, где он может быть сохранен, прежде чем искать в системной папке. - person David Browne - Microsoft; 18.04.2019
comment
Особенно убедитесь, что копия 64-битного драйвера не появляется в папке «C:\Windows\SysWOW64\inetsrv\», которая является каталогом приложения для w3wp.exe. - person David Browne - Microsoft; 18.04.2019
comment
Ошибка с моей стороны - случайно создал DSN как 64-битный вместо 32-х. Исправил это, и соединение работает в ASP, но зашифрованные данные по-прежнему представляют собой массив байтов. Драйвер ODBC 17 отображается как версия 2017.172.00.1. Все еще ищу другие способы импортировать сертификат ... - person Len; 18.04.2019