"""Client certificate of a tag database connector (SIENTIAPDE-1974 D5). Mirrors the Orchestrator's `tag_database.resolve_certificate`, which puts the certificate in the read slot: the write lookup (ServerConfigResolver, D1) resolves a server that is not in the pool with the same rule, so a write uses the certificate the slot would have. Keep both in sync. """ from typing import Any # security fields of an OPC UA connector: the source of its OPC security (D4) SECURITY_FIELDS = ('mode', 'policy') CERTIFICATE_FIELDS = ('certificate_id', 'application_uri') CERTIFICATE_OBJECTS = ('cert', 'private_key') STORED_OBJECT_FIELDS = ('bucket', 'object_name') # opc_certificates lookup of a connectors aggregation: the certificate the connector's # security.client_certificate_id points to, only when it is active and of kind client. CERTIFICATE_LOOKUP = { '$lookup': { 'from': 'opc_certificates', 'let': {'certificate_id': '$security.client_certificate_id'}, 'pipeline': [ { '$match': { '$expr': {'$eq': ['$certificate_id', '$$certificate_id']}, 'status': 'active', 'kind': 'client', } }, { '$project': { '_id': 0, 'certificate_id': 1, 'application_uri': 1, 'cert.bucket': 1, 'cert.object_name': 1, 'private_key.bucket': 1, 'private_key.object_name': 1, } }, ], 'as': 'certificates', } } def _is_complete(document: Any, fields: tuple[str, ...]) -> bool: return isinstance(document, dict) and all( document.get(field) not in (None, '') for field in fields ) def _is_usable_certificate(certificate: Any) -> bool: return _is_complete(certificate, CERTIFICATE_FIELDS) and all( _is_complete(certificate.get(name), STORED_OBJECT_FIELDS) for name in CERTIFICATE_OBJECTS ) def client_certificate_id(connector: dict[str, Any]) -> Any: """The connector's security.client_certificate_id (None when it has none).""" security = connector.get('security') return security.get('client_certificate_id') if isinstance(security, dict) else None def has_security(connector: dict[str, Any]) -> bool: """Whether the connector has security.mode and security.policy (D4).""" return _is_complete(connector.get('security'), SECURITY_FIELDS) def resolve_certificate(connector: dict[str, Any]) -> dict[str, Any] | None: """ The client certificate of a connector from CERTIFICATE_LOOKUP, or None (D5). None means no certificate: the connection is opened without security. A connector whose client_certificate_id is set but has no usable certificate is most likely a registration error; the caller reports it (see client_certificate_id). Returns: dict[str, Any] | None: certificate_id, application_uri, and cert and private_key as {bucket, object_name}, as in the slot """ for certificate in connector.get('certificates') or []: if _is_usable_certificate(certificate): return { **{field: certificate[field] for field in CERTIFICATE_FIELDS}, **{ name: {field: certificate[name][field] for field in STORED_OBJECT_FIELDS} for name in CERTIFICATE_OBJECTS }, } return None