Certificate-signature-interceptor#

Interceptor предназначен для подписи сообщения с помощью X509 сертификата для контроля целостности сообщений.

Принцип работы#

Interceptor может работать в двух режимах:

  • public-key;

  • certificate-serial.

Public-key#

  1. Producer-interceptor получает приватный ключ и сертификат.

  2. Producer-interceptor подписывает value сообщения и добавляет подпись (signature), алгоритм подписи (algorithm) и публичный ключ (public key) сертификата в заголовки сообщения.

  3. Consumer-interceptor проверяет подпись сообщения (signature), используя алгоритм (algorithm) и публичный ключ (public key) из заголовков сообщения.

Certificate-serial#

  1. Producer-interceptor получает приватный ключ и сертификат.

  2. Producer-interceptor подписывает value сообщения и добавляет подпись (signature), алгоритм подписи (algorithm) и серийный номер (certificate serial) сертификата в заголовки сообщения.

  3. Consumer-interceptor получает публичный ключ сертификата по его серийному номеру, указанному в заголовке сообщения из локального хранилища (JKS или текстового файла).

  4. Consumer-interceptor проверяет подпись сообщения (signature), используя алгоритм (algorithm) и полученный публичный ключ.

Важно! При использовании certificate-signature-interceptor возможно значительное падение производительности в связи с высокой математической сложностью алгоритма подписи сертификата х509. Для установления конкретных показателей для определенного взаимодействия необходимо проведение НТ.

Конфигурация#

Для конфигурирования interceptor возможно сформировать файл *.properties с необходимыми параметрами.

Certificate-signature-interceptor поддерживает следующие параметры:

Настройка

Назначение

Дефолтное значение

Комментарии

signature.certificate.mode

Режим работы interceptor

-

Обязательная

signature.certificate.algorithm

Алгоритм подписи

SHA256withRSA

Обязательная

signature.certificate.key.alias

Алиас приватного ключа

-

Обязательная

signature.certificate.cert.alias

Алиас сертификата

-

Обязательная

signature.certificate.keystore.type

Хранилище сертификатов(jks, pem, vault)

-

Обязательная

signature.certificate.truststore.type

Хранилище сертификатов(jks, pem, vault)

-

Обязательная

signature.certificate.algorithm.attribute

Имя загловка с используемым алгоритмом подписи

algorithm

Опциональная

signature.certificate.public.key.attribute

Имя заголовка с публичным ключом для проверки подписи

public.key

Опциональная

signature.certificate.serial.attribute

Имя заголовка с используемым серийным номером сертификата

certificate.serial

Опциональная

signature.certificate.allowed.serial

Проверка серийного номера сертификата в списке разрешенных серийных номеров

false

Опциональная

signature.certificate.allowed.serial.file

Расположение списка разрешенных серийных номеров сертификата

-

Опциональная

signature.certificate.ssl.provider

ssl-провайдер

-

Настройки SSL

signature.certificate.ssl.keystore.location

Хранилище сертификата и приватного ключа для сервера

-

Настройки SSL

signature.certificate.ssl.keystore.type

Тип хранилища сертификатов

-

Настройки SSL

signature.certificate.ssl.keystore.password

Пароль от хранилища сертификатов

-

Настройки SSL

signature.certificate.ssl.key.password

Пароль от ключа

-

Настройки SSL

signature.certificate.ssl.truststore.location

Путь до хранилища доверенных сертификатов

-

Настройки SSL

signature.certificate.ssl.truststore.password

Пароль к хранилищу доверенных сертификатов

-

Настройки SSL

В случае использования хранилища сертификатов vault, в параметрах необходимо указать параметры подключения, указанные в ssl-context-builder.

Поведение при ошибках#

В случае, если сообщение не прошло проверку подписи при получении (на стороне consumer-interceptor), поведение настраивается с помощью параметра failMode:

  • filter: сообщение об ошибке будет залогировано в error, клиент не получит невалидное сообщение;

  • addErrorHeader: сообщение, полученное consumer, будет иметь заголовок signature.error с ошибкой проверки подписи.

Примеры подключения interceptor к core-клиенту#

Подключение исходящего certificate-signature-interceptor на producer#

CertificateSignatureInterceptor outgoingInterceptor = CertificateSignatureInterceptor.newBuilder()
        .setSignatureMode("public-key")
        .setAlgorithm("SHA256WithRSA")
        .setKeyStoreType("jks")
        .setSSLKeystoreLocation("path/to/cert/keystore.jks")
        .setSSLKeystorePassword("password")
        .setSSLKeyPassword("password")
        .build();

ServerLocator locator = ActiveMQClient.createServerLocator("tcp://host::port?TranspotConfiguration");

locator.addOutgoingInterceptor(outgoingInterceptor);
ClientSessionFactory factory =  locator.createClientSessionFactory();
ClientSession session = factory.createSession();

// addressName=example, queueName=example 

ClientProducer producer = session.createProducer("example");

ClientMessage message = session.createMessage(Message.TEXT_TYPE, config.durable);
TextMessageUtil.writeBodyText( ((CoreMessage) clientMessage).getBodyBuffer, "Hello");

producer.send(message);

Подключение входящего certificate-signature-interceptor на consumer#

CertificateSignatureInterceptor incomingInterceptor = CertificateSignatureInterceptor.newBuilder()
        .setSignatureMode("public-key")
        .setAlgorithm("SHA256WithRSA")
        .setKeyStoreType("jks")
        .setSSLKeystoreLocation("path/to/cert/keystore.jks")
        .setSSLKeystorePassword("password")
        .setSSLKeyPassword("password")
        .build();

ServerLocator locator = ActiveMQClient.createServerLocator("tcp://host::port?TranspotConfiguration");

locator.addIncomingInterceptor(incomingInterceptor);
ClientSessionFactory factory =  locator.createClientSessionFactory();
ClientSession session = factory.createSession();

// addressName=example, queueName=example

ClientConsumer consumer = session.createConsumer("example");
session.start();
ClientMessage msgReceived = consumer.receive();