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 |
|---|---|---|
| unary | Vykonanie jednej D2000 RPC procedúry a prijatie výsledku |
| bidirectional streaming | Viackroková RPC konverzácia medzi klientom a D2000 |
| unary | Vykonanie RPC typu Simple Byte Array (binárne) |
| server streaming | Real-time odber zmien hodnoty D2000 objektu |
| server streaming | Čítanie historických archívnych riadkov pre časový interval |
| server streaming | Čítanie hodnôt EDA vektora |
| unary | Zápis hodnôt s časovou značkou do EDA vektora |
| 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 cezgrpc_cli/ Postmangrpc.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é |
|---|---|---|
| Zapína alebo vypína túto inštanciu gRPC servera |
|
| Väzobná adresa |
|
| Počúvajúci port |
|
| keep-alive čas v milisekundách | — |
| Statické metadátové hlavičky vkladané do každej odpovede, formát | žiadne |
| Zapnúť TLS pre túto inštanciu |
|
| Cesta k PKCS12 keystore (absolútna alebo relatívna voči adresáru config) | — |
| Heslo keystore |
|
| Alias kľúča (ak je vynechaný, použije sa prvý alias v keystore) | — |
| Cesta k truststore (potrebné pre validované mTLS) | — |
| Heslo truststore |
|
|
|
|
| Wildcard zoznam povolených názvov D2000 eventov |
|
| Wildcard zoznam povolených názvov RPC metód |
|
| Wildcard zoznam kódov EDA vektorov, ktoré je možné čítať |
|
| 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á |
|---|---|
| Ľubovoľnej hodnote |
| Ľubovoľnému názvu eventu začínajúcemu na |
| Presne názvu metódy |
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 -nopromptSúbor | Účel | Potrebný za behu |
|---|---|---|
| Privátny kľúč servera + certifikát servera | Server |
| Privátny kľúč CA + certifikát CA (použité len na podpisovanie) | Offline |
| Verejný certifikát CA | Použitý len na zostavenie truststore |
| Privátny kľúč klienta + CA-podpísaný certifikát | Klient |
| 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 |
|---|---|
| Celkový — |
| Pripojenie na D2000 |
| EDA pripojenie (vráti |
| 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: falseTesne 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: DEBUGPrí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