...
gRPC-запросы формируются на основе proto-файлов.
| Note |
|---|
|
Описанный способ выполнения прямых gRPC-запросов применим только для стандартного типа установки ПК Интеллект Х Сервер и клиент. В отказоустойчивом режиме сертификаты хранятся в Consul, поэтому прямое подключение к gRPC-сервису на порту 20109 без дополнительной настройки не поддерживается. |
Подготовка окружения
Перед началом работы необходимо:
- Установить интерпретатор языка Python и при необходимости IDE.
Через pip установить зависимости:
| Code Block |
|---|
pip>=21.1.2
grpcio-tools>=1.38.0
googleapis-common-protos
pyOpenSSL==19.1.0 |
Создание proto-классов
Для создания proto-классов необходимо:
- Получить в службе технической поддержки proto-файлы.
Сохранить скрипт в виде py-файла:
script.py.
- В папке со скриптом создать папку grpc-proto-files. В эту папку поместить папки ITV и Google вместе с их содержимым из полученного архива с proto-файлами.
- Запустить скрипт.
В результате в папке со скриптом появится папка ITV с proto-классами, которые будут использоваться для работы через gRPC-канал.
...
Авторизация возможна только к Серверу серверу из сертификата.
Ниже приводится пример авторизации и пример запроса ConfigurationService.ListUnits для получения корневого юнита.
| Expand |
|---|
| title | Пример авторизации и запроса ConfigurationService.ListUnits |
|---|
|
| Code Block |
|---|
import grpc
from OpenSSL import crypto
from grpc._channel import _InactiveRpcError
from axxonsoft.bl.config.ConfigurationService_pb2 import ListUnitsRequest
from axxonsoft.bl.config.ConfigurationService_pb2_grpc import ConfigurationServiceStub
from axxonsoft.bl.auth.Authentication_pb2 import AuthenticateRequest
from axxonsoft.bl.auth.Authentication_pb2_grpc import AuthenticationServiceStub
def get_channel_credentials(cert_path):
with open(cert_path, 'rb') as f:
certificate = f.read()
creds = grpc.ssl_channel_credentials(root_certificates=certificate)
cert = crypto.load_certificate(crypto.FILETYPE_PEM, certificate)
common_name = cert.get_subject().CN
return creds, common_name
def get_ssl_channel(server, channel_creds, override_cn, auth_creds=None):
channel_creds = grpc.composite_channel_credentials(channel_creds, auth_creds) if auth_creds else channel_creds
return grpc.secure_channel(server, channel_creds, options=(('grpc.ssl_target_name_override', override_cn),))
def get_auth_credentials(simple_channel, username, password):
client = AuthenticationServiceStub(simple_channel)
auth_request = AuthenticateRequest(user_name=username, password=password)
response = client.Authenticate(auth_request)
auth_header = (response.token_name, response.token_value)
auth_creds = grpc.metadata_call_credentials(
lambda _, cb: cb([auth_header], None))
return auth_creds
def get_authorized_channel(certificate_path, ip="127.0.0.1", port=20109, username="root", password="root"):
server = f"{ip}:{port}"
channel_creds, cert_common_name = get_channel_credentials(certificate_path)
try:
simple_channel = get_ssl_channel(server, channel_creds, cert_common_name)
auth_creds = get_auth_credentials(simple_channel, username, password)
return get_ssl_channel(server, channel_creds, cert_common_name, auth_creds)
except _InactiveRpcError as ex:
print(f"Unable to connect to server. Details:\n{ex.details()}")
if __name__ == '__main__':
print('This script need to provide a path to the certificate')
path = r"C:\ProgramData\ITV\IntellectX\Tickets\Node.crt"
channel = get_authorized_channel(path)
config_service = ConfigurationServiceStub(channel)
request = ListUnitsRequest(unit_uids=["root"])
response = config_service.ListUnits(request)
print(f"Found {len(response.units)} units:\n{response.units}") |
|
Функция get_authorized_channel в качестве параметров принимает:
- certificate_path
– - — путь к сертификату;
- ip – IP-адрес Сервера (по умолчанию "127.0.0.1");
- port – порт gRPC API (по умолчанию 20109);
- username – имя пользователя (по умолчанию "root");
- password – пароль пользователя (по умолчанию "root").
| Info |
|---|
|
Импортируемые proto-классы из папки ITV были созданы на предыдущем шаге. |
Выполнение прямых gRPC-запросов с помощью ПО Postman
Стандартные gRPC-запросы (gRPC API) выполняются через web-сервер (порт 80). Также поддерживается отправка прямых gRPC-запросов на порт 20109 с использованием ПО Postman.
Для выполнения прямых gRPC-запросов с помощью ПО Postman требуется:
запрос AuthenticationService / Authenticate — для получения токена аутентификации (время жизни токена – 5 минут);
целевой gRPC-запрос — использует полученный токен.
Настройка запроса в Postman
В ПО Postman нужно нажать на кнопку New → gRPC.
На вкладке Service definition:
Нажать на кнопку Next.
В поле Enter URL указать адрес сервера с портом 20109. Например, 127.0.0.1:20109.
В поле Select a method выбрать требуемый метод из списка доступных.
- Нажать на вкладку Message и задать тело запроса.
| Info |
|---|
|
Пример для метода ListUnitsStream: | Code Block |
|---|
{
"unit_uids": [
"hosts/SERVER1/MultimediaStorage.AliceBlue"
]
} |
|
- Нажать на вкладку Authorization и задать параметры аутентификации:
- В поле Auth Type выбрать значение API Key.
- В поле Key указать имя токена.
- В поле Value указать значение токена.
- Выполнить запрос, нажав на кнопку Invoke.
В результате в интерфейсе отобразится:
стрелка вверх — отправленный запрос;
стрелка вниз — ответ сервера.
Сохранение токена аутентификации в системные переменные Postman
В ПО Postman время жизни токена составляет 5 минут. Для использования токена в запросах без необходимости вводить его вручную каждый раз заново, токен можно сохранить в системные переменные. Для это нужно:
- На вкладке Message задать тело запроса. В параметре password указать пароль пользователя Интеллект Х, в параметре user_name – имя пользователя.
| Code Block |
|---|
{
"password": "your_root_password",
"user_name": "root"
} |
- На вкладке Authorization в поле Auth Type выбрать значение No Auth.
- На вкладке Scripts нужно:
- Выбрать значение After response.
- В области для кода ввести:
| Code Block |
|---|
var data = pm.response.messages.idx(0).data
pm.globals.set("token_name", data.token_name);
pm.globals.set("token_value", data.token_value); |
где в параметрах "token_name" и "token_value" указать имя и значение токена.
После выполнения запроса токен сохранится в системные переменные Postman. Токен действителен в течение 5 минут.