Service Broker, соединяемся через сертификаты

в 18:39, , рубрики: Песочница, метки: ,

Случилось так, что мне пришлось разобраться с тем, как в Service Broker сделать передачу сообщений, используя для аутентификации сертификаты.

Исходные:
— 2 компьютера mf-2007 и mf-1689 (названия взяты от балды [названия рабочих компов]);
— На обоих Microsoft SQL Server 2014.

Задача послать сообщение.

Решение под катом (пошаговая инструкция).

Итак, начнём с mf-1689. Для mf-2007 всё то же самое с точностью до цифр.
Выполнять нужно параллельно на 2-х машинах.

Создаём мастер ключ:

USE [master]
GO
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'mf_1689';

Создаём логин для пользователя, от имени которого будет проходить авторизация и аутентификация:

CREATE LOGIN sb_mf_1689 with password = 'Pa$$w0rd';

Создадим пользователя в мастере, к нему привяжем сертификат:

CREATE USER sb_mf_1689 FOR LOGIN sb_mf_1689;

Создадим сертификат для аутентификации и сохраним его открытый ключ:


CREATE CERTIFICATE mf_1689_cert
AUTHORIZATION sb_mf_1689
WITH SUBJECT = 'mf_1689';
GO
BACKUP CERTIFICATE mf_1689_cert
TO FILE = 'c:certsmf_1689.cer';

Этот ключик перепишем на соседний компьютер и восстановим из него сертификат для подключения:


CREATE CERTIFICATE pk_2007
AUTHORIZATION sb_mf_1689
FROM FILE = 'c:certsmf_2007.cer';

Создаём конечную точку для сервис брокера и предоставляем нашему пользователю право на коннект через эту конечную точку:


CREATE ENDPOINT mf_1689
 STATE = STARTED
AS TCP (LISTENER_PORT = 51001)
FOR SERVICE_BROKER (AUTHENTICATION = CERTIFICATE mf_1689_cert, ENCRYPTION = SUPPORTED ALGORITHM AES);
GO
GRANT CONNECT ON ENDPOINT::mf_1689 TO sb_mf_1689;

Создадим БД, в которой будем держать очереди и сервисы:


CREATE DATABASE sb_db2;
GO 
ALTER DATABASE sb_db2 set single_user with rollback immediate;
GO
ALTER DATABASE sb_db2 set new_broker;
GO
ALTER DATABASE sb_db2 set multi_user;
GO
USE sb_db2;
GO

Создадим мастер ключ в новой БД:


CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'mf_1689';
GO

Создадим пользователя:


CREATE USER sb_mf_1689 FOR LOGIN sb_mf_1689;
GO

Для авторизации пользователя внутри БД создадим сертификат и сохраним его:


CREATE CERTIFICATE dlg_1689
WITH SUBJECT = 'mf_1689'
ACTIVE FOR BEGIN_DIALOG = ON;
GO
BACKUP CERTIFICATE dlg_1689
TO FILE = 'c:certsdlg_1689.cer';
GO

Далее файлик с сертификатом перенесём на другой комп и создадим сертификат из файлика:


CREATE CERTIFICATE pkdlg_2007
AUTHORIZATION sb_mf_1689
FROM FILE = 'c:certsdlg_2007.cer';
GO

Создадим объекты брокера (очередь, тип сообщения, контракт, сервис, маршрут):


CREATE QUEUE dbo.Queue_2 WITH STATUS = ON , RETENTION = OFF;
GO
CREATE MESSAGE TYPE msg_sd
     VALIDATION = WELL_FORMED_XML;
GO
CREATE CONTRACT cntr_sb
      (msg_sd SENT BY ANY);
GO
CREATE SERVICE srv_sb_1689
   ON QUEUE dbo.Queue_2
   (cntr_sb);
GO
CREATE ROUTE route_srv_sb_db1
WITH SERVICE_NAME = 'srv_sb_2007', ADDRESS = N'TCP://mf-2007:51001';
GO

Создадим привязку для определения учётных данных безопасности:


CREATE REMOTE SERVICE BINDING route_2007
   TO SERVICE 'srv_sb_2007' 
   WITH  USER = sb_mf_1689;
GO

И дадим права пользователю на отправку сообщений:


GRANT SEND ON SERVICE::[srv_sb_1689] TO sb_mf_1689;
GO

Если вы проделали всё зеркально на 2-х машинах, то вы готовы к обмену сообщениями:


DECLARE @from_srv SYSNAME = N'srv_sb_1689',
@to_srv SYSNAME = N'srv_sb_2007',
@contract SYSNAME = N'cntr_sb',
@conversation_handle UNIQUEIDENTIFIER
SELECT @conversation_handle = ce.conversation_handle
FROM   sys.conversation_endpoints ce WITH (NOLOCK)
INNER JOIN sys.service_contracts sc WITH (NOLOCK)
ON  sc.service_contract_id = ce.service_contract_id
WHERE  ce.[state] NOT IN ('CD', 'ER', 'DI', 'DO')
AND ce.far_service = @to_srv
AND sc.name = @contract
IF @conversation_handle IS NULL
BEGIN
;BEGIN DIALOG CONVERSATION @conversation_handle
FROM SERVICE @from_srv
TO SERVICE @to_srv
ON CONTRACT @contract
WITH ENCRYPTION = OFF;
END;
DECLARE @message XML = '<body>test_from_sb_1689</body>';
SEND ON CONVERSATION @conversation_handle
MESSAGE TYPE [msg_sd] (@message);

Проверьте, что сообщение ушло в sys.transmission_queue и в очереди на другом компе.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js