SIENTIAPDE-1973
SIENTIAPDE-1973: Implement per-connector OPC client certificates and remove legacy read engine. This update overhauls certificate management, transitioning from a single platform certificate to individual client certificates defined in the slot configuration. The CertProvider now downloads certificates from MinIO based on certificate_id, applying dynamic security policies (mode, policy) from the slot. The legacy READ_ENGINE=legacy option and OpcManager have been entirely removed, standardizing on the ServerReader with strict slot v2 enforcement. Write command resolution (ServerConfigResolver) now consistently uses connectors joined with opc_certificates. The CERT_BUCKET environment variable is no longer used.
This commit is contained in:
@@ -9,7 +9,7 @@ from sientia_do.observability.sientia_monitoring import SientiaMonitoring
|
||||
import ingestor.metrics as metrics
|
||||
from ingestor.connection.certs import CertProvider
|
||||
from ingestor.connection.clock import MonotonicClock
|
||||
from ingestor.connection.security import apply_security
|
||||
from ingestor.connection.security import apply_security, is_secured
|
||||
|
||||
|
||||
class OpcConnectionPool(SientiaMonitoring):
|
||||
@@ -65,11 +65,10 @@ class OpcConnectionPool(SientiaMonitoring):
|
||||
"""Warn when a caller asks for a server with other connection settings than
|
||||
the pooled client was opened with. The client is reused as is: reconnecting
|
||||
on every mismatch would let one malformed write command drop the reads.
|
||||
Config changes from the slot evict the client first (ServerReader.shutdown)."""
|
||||
Config changes from the slot (security, certificate) evict the client first:
|
||||
the IngestorManager re-initializes the reader (ServerReader.shutdown)."""
|
||||
opened = self._configs.get(server_id, {})
|
||||
diff = [
|
||||
k for k in ('url', 'server_uri', 'use_security') if opened.get(k) != server_cfg.get(k)
|
||||
]
|
||||
diff = [k for k in ('url', 'security', 'certificate') if opened.get(k) != server_cfg.get(k)]
|
||||
if diff:
|
||||
self.logger.warning(
|
||||
f'OPC server {server_id}: reusing the pooled connection, but {diff} differ '
|
||||
@@ -98,10 +97,10 @@ class OpcConnectionPool(SientiaMonitoring):
|
||||
try:
|
||||
client = await self._connect(server_cfg)
|
||||
except Exception:
|
||||
if server_cfg.get('use_security'):
|
||||
if is_secured(server_cfg):
|
||||
# The cached certificate may be the cause (replaced in MinIO,
|
||||
# rejected by the server): download it again on the next attempt.
|
||||
self.cert_provider.invalidate()
|
||||
self.cert_provider.invalidate(server_cfg['certificate']['certificate_id'])
|
||||
await self.emit_metric(
|
||||
metric_object=metrics.OPC_CONNECTIONS_FAILED,
|
||||
tags={'pod_id': self.pod_id, 'server_name': server_id},
|
||||
@@ -123,13 +122,12 @@ class OpcConnectionPool(SientiaMonitoring):
|
||||
pod_uri = self.pod_id.replace('-', ':')
|
||||
client.product_uri = pod_uri
|
||||
client.application_uri = pod_uri
|
||||
server_uri = server_cfg.get('server_uri')
|
||||
if server_uri:
|
||||
# Must match the certificate's SAN URI (KEPServer: BadCertificateUriInvalid).
|
||||
client.application_uri = server_uri
|
||||
if server_cfg.get('use_security'):
|
||||
cert, key = await self.cert_provider.fetch()
|
||||
await apply_security(client, server_cfg.get('server_uri'), cert, key, None)
|
||||
# Security only with a client certificate (SIENTIAPDE-1974 D5); apply_security
|
||||
# sets the certificate's application URI, which must match its SAN URI.
|
||||
if is_secured(server_cfg):
|
||||
certificate = server_cfg['certificate']
|
||||
cert, key = await self.cert_provider.fetch(certificate)
|
||||
await apply_security(client, server_cfg['security'], certificate, cert, key)
|
||||
await client.connect()
|
||||
return client
|
||||
|
||||
|
||||
Reference in New Issue
Block a user