Konfigurácia gRPC API

Konfigurácia gRPC API

SmartWeb sprístupňuje server-to-server gRPC API (HTTP/2), ktoré umožňuje klientom volať D2000 RPC procedúry, odoberať zmeny hodnôt objektov, streamovať archívne a EDA dáta a prijímať RPC volania, ktoré D2000 iniciuje smerom ku klientovi. Spustiť je možné viacero nezávislých inštancií gRPC servera na rôznych portoch, každú s vlastnou TLS konfiguráciou a prístupovým filtrom.

gRPC API vychádza zo štandardného gRPC proto kontraktu; gRPC služba má názov D2Api.

Metódy služby D2Api

Metóda

gRPC kardinalita

Účel

Metóda

gRPC kardinalita

Účel

rpc

unary

Vykonanie jednej D2000 RPC procedúry a prijatie výsledku

rpcConversation

bidirectional streaming

Viackroková RPC konverzácia medzi klientom a D2000

rpcSBA

unary

Vykonanie RPC typu Simple Byte Array (binárne)

subscribeObject

server streaming

Real-time odber zmien hodnoty D2000 objektu

loadArchive

server streaming

Čítanie historických archívnych riadkov pre časový interval

loadEdaVector

server streaming

Čítanie hodnôt EDA vektora

updateEdaVector

unary

Zápis hodnôt s časovou značkou do EDA vektora

subscribeToRpc

server streaming

Príjem RPC volaní, ktoré D2000 iniciuje smerom ku klientovi

Okrem toho každá inštancia gRPC servera registruje aj:

  • grpc.reflection.v1alpha.ServerReflection — umožňuje introspekciu cez grpc_cli / Postman

  • grpc.health.v1.Health — štandardný gRPC health protokol (viď gRPC health checky)

Konfigurácia

gRPC API sa konfiguruje pod smartweb.application.grpcApi.configItems[]. Každý záznam spustí nezávislý gRPC server s vlastnou väzobnou adresou, portom, TLS nastaveniami, hlavičkami odpovede a prístupovým filtrom.

smartweb: application: grpcApi: configItems: - enabled: true host: "0.0.0.0" # väzobná adresa; "0.0.0.0" počúva na všetkých rozhraniach port: 9090 socketTimeoutMs: 60000 # keep-alive čas na spojení httpHeaders: # statické metadáta vkladané do každej odpovede - "X-Server: SmartWeb-gRPC" - "X-Api-Version: 1.0" ssl: enabled: true keyStore: path: cert/keystore.p12 password: changeit keyAlias: smartweb trustStore: path: cert/truststore.p12 password: changeit clientAuth: REQUIRE # NONE | OPTIONAL | REQUIRE accessFilter: allowedD2RpcEventNames: - "E.MyRpc" allowedD2RpcMethodNames: - "Calculate" - "GetStatus" allowedD2EdaVectorReadCodes: - "*" allowedD2EdaVectorUpdateCodes: - "*"

Vlastnosť

Popis

Predvolené

Vlastnosť

Popis

Predvolené

enabled

Zapína alebo vypína túto inštanciu gRPC servera

true

host

Väzobná adresa

0.0.0.0

port

Počúvajúci port

9090

socketTimeoutMs

keep-alive čas v milisekundách

httpHeaders

Statické metadátové hlavičky vkladané do každej odpovede, formát "Kľúč: Hodnota"

žiadne

ssl.enabled

Zapnúť TLS pre túto inštanciu

false

ssl.keyStore.path

Cesta k PKCS12 keystore (absolútna alebo relatívna voči adresáru config)

ssl.keyStore.password

Heslo keystore

changeit

ssl.keyAlias

Alias kľúča (ak je vynechaný, použije sa prvý alias v keystore)

ssl.trustStore.path

Cesta k truststore (potrebné pre validované mTLS)

ssl.trustStore.password

Heslo truststore

changeit

ssl.clientAuth

NONE (bez klientskeho certifikátu), OPTIONAL (certifikát je akceptovaný, ale nie je vyžadovaný), REQUIRE (plné mTLS)

NONE

accessFilter.allowedD2RpcEventNames

Wildcard zoznam povolených názvov D2000 eventov

["*"]

accessFilter.allowedD2RpcMethodNames

Wildcard zoznam povolených názvov RPC metód

["*"]

accessFilter.allowedD2EdaVectorReadCodes

Wildcard zoznam kódov EDA vektorov, ktoré je možné čítať

["*"]

accessFilter.allowedD2EdaVectorUpdateCodes

Wildcard zoznam kódov EDA vektorov, do ktorých je možné zapisovať

["*"]

[!NOTE] Každý záznam configItems vytvára nezávislý gRPC server. Môžete tak v rámci jedného SmartWeb procesu spustiť napríklad inštanciu so striktným mTLS na porte 9090 pre externých partnerov, internú inštanciu len s TLS na porte 9091 a nešifrovanú inštanciu na porte 9092 naviazanú na privátne rozhranie.

Prístupový filter

Prístupový filter sa aplikuje na každé jednotlivé volanie, vrátane každej správy v rámci obojsmernej konverzácie. Wildcard porovnávanie nerozlišuje veľkosť písmen:

Vzor

Zodpovedá

Vzor

Zodpovedá

*

Ľubovoľnej hodnote

E.TRAY_*

Ľubovoľnému názvu eventu začínajúcemu na E.TRAY_

Calculate

Presne názvu metódy Calculate

Zamietnuté volanie vráti Status.PERMISSION_DENIED a ukončí stream.

Príklad — obmedzenie prístupu na trojkrokový konverzačný tok (Register("User_01")Calculate(...)CloseE()):

accessFilter: allowedD2RpcEventNames: - "E.TRAY_testSender1" allowedD2RpcMethodNames: - "Register" - "Calculate" - "CloseE"

Hlavičky v metadátach odpovede

Zoznam httpHeaders sa vkladá do metadát odpovede každého gRPC volania.

httpHeaders: - "X-Server: SmartWeb-gRPC" - "X-Api-Version: 1.0" - "Access-Control-Allow-Origin: *"

[!NOTE] Kľúče gRPC metadát sú interne normalizované na malé písmená.

TLS / mTLS

Každá inštancia gRPC servera má vlastnú TLS konfiguráciu. Keď je clientAuth OPTIONAL alebo REQUIRE, reťazec TLS certifikátu protistrany sa sprístupní autentifikačnej vrstve aplikácie.

Self-signed vývojový certifikát

keytool -genkeypair -alias smartweb -keyalg RSA -keysize 2048 \ -storetype PKCS12 -keystore keystore.p12 -validity 365 \ -storepass changeit \ -dname "CN=localhost, OU=d2000, O=Ipesoft, L=Zilina, ST=SK, C=SK" \ -ext "SAN=dns:localhost,ip:127.0.0.1"

Plné mTLS nastavenie (server + CA + klient)

# Keystore servera keytool -genkeypair -alias smartweb -keyalg RSA -keysize 2048 -storetype PKCS12 \ -keystore keystore.p12 -validity 365 -storepass changeit \ -dname "CN=localhost, OU=d2000, O=Ipesoft, L=Zilina, ST=SK, C=SK" \ -ext "SAN=dns:localhost,ip:127.0.0.1" # Keystore CA keytool -genkeypair -alias ca -keyalg RSA -keysize 2048 -storetype PKCS12 \ -keystore ca-keystore.p12 -validity 3650 -storepass changeit \ -dname "CN=MyCA, OU=d2000, O=Ipesoft, L=Zilina, ST=SK, C=SK" \ -ext "BasicConstraints:critical=ca:true" # Export certifikátu CA keytool -exportcert -alias ca -keystore ca-keystore.p12 -storepass changeit -rfc -file ca.crt # Keystore klienta keytool -genkeypair -alias smartweb-client -keyalg RSA -keysize 2048 -storetype PKCS12 \ -keystore client-keystore.p12 -validity 365 -storepass changeit \ -dname "CN=smartweb-client, OU=d2000, O=Ipesoft, L=Zilina, ST=SK, C=SK" # CSR klienta keytool -certreq -alias smartweb-client -keystore client-keystore.p12 -storepass changeit -file client.csr # CA podpíše CSR klienta keytool -gencert -alias ca -keystore ca-keystore.p12 -storepass changeit \ -infile client.csr -outfile client-signed.crt -validity 365 -rfc \ -ext "KeyUsage=digitalSignature" -ext "ExtendedKeyUsage=clientAuth" # Import CA + podpísaného klientskeho certifikátu do keystore klienta (reťazec dôvery) keytool -importcert -alias ca -file ca.crt -keystore client-keystore.p12 -storepass changeit -noprompt keytool -importcert -alias smartweb-client -file client-signed.crt \ -keystore client-keystore.p12 -storepass changeit -noprompt # Truststore servera — použitý na overenie klientskych certifikátov keytool -importcert -alias ca -file ca.crt -keystore truststore.p12 \ -storetype PKCS12 -storepass changeit -noprompt

Súbor

Účel

Potrebný za behu

Súbor

Účel

Potrebný za behu

keystore.p12

Privátny kľúč servera + certifikát servera

Server

ca-keystore.p12

Privátny kľúč CA + certifikát CA (použité len na podpisovanie)

Offline

ca.crt

Verejný certifikát CA

Použitý len na zostavenie truststore

client-keystore.p12

Privátny kľúč klienta + CA-podpísaný certifikát

Klient

truststore.p12

Truststore servera obsahujúci certifikát CA

Server (len mTLS)

[!WARNING] Keď je clientAuth OPTIONAL alebo REQUIRE, ale nie je nakonfigurovaný žiadny truststore, klientsky certifikát nie je overovaný voči žiadnemu CA reťazcu — len sa sprístupní aplikačnej vrstve na inšpekciu. Túto konfiguráciu nepoužívajte v produkcii.

gRPC health checky

Každá inštancia gRPC servera implementuje štandardnú službu grpc.health.v1.Health. Health stav sa vyhodnocuje dynamicky pri každom volaní Check.

Názov služby

Zdroj stavu

Názov služby

Zdroj stavu

"" (prázdne)

Celkový — SERVING len ak sú D2 API, EDA (ak je nakonfigurované) a všetky konektory v poriadku

"d2api"

Pripojenie na D2000

"eda"

EDA pripojenie (vráti SERVING, ak EDA nie je nakonfigurované)

"connector_<name>"

Pomenovaný D2 service konektor

Neznáme názvy služieb vrátia Status.NOT_FOUND.

Príklad kontroly cez grpc_cli:

grpc_cli call localhost:9090 grpc.health.v1.Health/Check "service: 'd2api'" grpc_cli call localhost:9090 grpc.health.v1.Health/Check "service: ''"

Príklady konfigurácie

Viacero inštancií: striktné mTLS, interné TLS a nešifrované

server: port: 8443 smartweb: connections: - host: localhost port: 3120 authentication: authModes: - AUTH_CREDENTIALS_IN_SESSION - AUTH_CERTIFICATE_REMOTELY apiKeys: enabled: true application: serverSsl: enabled: true keyStore: path: cert/keystore.p12 password: changeit keyAlias: smartweb trustStore: path: cert/truststore.p12 password: changeit clientAuth: REQUIRE grpcApi: configItems: # Inštancia 1 — mTLS na porte 9090, povolené všetky eventy a metódy - enabled: true host: "0.0.0.0" port: 9090 socketTimeoutMs: 60000 httpHeaders: - "X-Server: SmartWeb-gRPC" - "X-Api-Version: 1.0" ssl: enabled: true keyStore: path: cert/keystore.p12 password: changeit keyAlias: smartweb trustStore: path: cert/truststore.p12 password: changeit clientAuth: REQUIRE accessFilter: allowedD2RpcEventNames: ["*"] allowedD2RpcMethodNames: ["*"] # Inštancia 2 — jednosmerné TLS na porte 9091, obmedzené na eventy E.TRAY_* - enabled: true host: "0.0.0.0" port: 9091 socketTimeoutMs: 60000 ssl: enabled: true keyStore: path: cert/keystore.p12 password: changeit keyAlias: smartweb clientAuth: OPTIONAL accessFilter: allowedD2RpcEventNames: - "E.TRAY_*" allowedD2RpcMethodNames: - "*" # Inštancia 3 — nešifrovaná, len interné rozhranie, predvolený filter (všetko povolené) - enabled: true host: "127.0.0.1" port: 9092 ssl: enabled: false

Tesne ohraničený filter — jeden konverzačný tok

smartweb: application: grpcApi: configItems: - enabled: true host: "0.0.0.0" port: 9090 ssl: enabled: true keyStore: path: cert/keystore.p12 password: changeit clientAuth: REQUIRE accessFilter: allowedD2RpcEventNames: - "E.TRAY_testSender1" - "E.RPC_TEST_FUNCTIONS" allowedD2RpcMethodNames: - "Register*" - "Calculate" - "CloseE" - "OutputParams"

Diagnostické logovanie gRPC vrstvy

logging: level: io.grpc.netty: WARN io.grpc.services: WARN com.ipesoft.smartweb.core.grpc: DEBUG

Príklad Java klienta

Nasledujúci príklad volá RPC procedúru OutputParams, definovanú v D2000 v ESL skripte. Procedúra má šesť výstupných (OUT) parametrov vrátane štruktúrovaného parametra typu SD.TestSmart:

RPC PROCEDURE OutputParams(BOOL _bool, INT _int, REAL _real, TIME _time, TEXT _text, RECORD NOALIAS (SD.TestSmart) _struct) _bool := @TRUE _int := 63 _real := 3.14 _time := SysTime _text := %GenD2UID() REDIM _struct[1] _struct[1]^Bool := @TRUE _struct[1]^Int := 2 _struct[1]^Real := 2.324 _struct[1]^ATime := SysTime - 60 * 60 _struct[1]^RTime := 1024 _struct[1]^Text := "TEST" END OutputParams

Štruktúra SD.TestSmart má šesť stĺpcov: Bool (BOOL), Int (INT), Real (REAL), ATime (absolútny čas), RTime (relatívny čas) a Text (TEXT).

Keďže všetky parametre procedúry sú výstupné, pre každý z nich klient pošle placeholder UnivalValue s nastaveným typom (type) a názvom (returnAs), pod ktorým sa výstupná hodnota objaví v mape RpcResponse.values:

ManagedChannel channel = ManagedChannelBuilder .forAddress("smartweb.example.com", 9090) .useTransportSecurity() .build(); D2ApiGrpc.D2ApiBlockingStub stub = D2ApiGrpc.newBlockingStub(channel) .withCallCredentials(new ApiKeyCredentials("my-api-key")); RpcResponse response = stub.rpc(RpcCall.newBuilder() .setEventName("E.RPC_TEST_FUNCTIONS") .setName("OutputParams") .addParameter(UnivalValue.newBuilder().setType(UnivalType.Bool).setReturnAs("bool")) .addParameter(UnivalValue.newBuilder().setType(UnivalType.Int).setReturnAs("int")) .addParameter(UnivalValue.newBuilder().setType(UnivalType.Real).setReturnAs("real")) .addParameter(UnivalValue.newBuilder().setType(UnivalType.Time).setReturnAs("time")) .addParameter(UnivalValue.newBuilder().setType(UnivalType.Text).setReturnAs("text")) .addParameter(UnivalValue.newBuilder().setType(UnivalType.Record).setReturnAs("struct")) .build()); // Skalárne výstupné parametre — z mapy RpcResponse.values pod názvami returnAs Map<String, UnivalValue> out = response.getValuesMap(); BoolValue bool = out.get("bool").getBoolValue(); // False / True / Oscilate long i = out.get("int").getIntValue(); // 63 double real = out.get("real").getRealValue(); // 3.14 Timestamp time = out.get("time").getTime(); String text = out.get("text").getText(); // Štruktúrovaný (RECORD) výstupný parameter typu SD.TestSmart RecordValue struct = out.get("struct").getRecordValue(); RecordRow row = struct.getRow(0); // prvý riadok (REDIM _struct[1]) // poradie stĺpcov zodpovedá definícii štruktúry SD.TestSmart: BoolValue colBool = row.getValue(0).getBoolValue(); // Bool long colInt = row.getValue(1).getIntValue(); // Int double colReal = row.getValue(2).getRealValue(); // Real Timestamp colATime = row.getValue(3).getTime(); // ATime — absolútny čas Duration colRTime = row.getValue(4).getTimespan(); // RTime — relatívny čas String colText = row.getValue(5).getText(); // Text