Pairing OpenELIS with the Analyzer Bridge
OpenELIS and the Analyzer Bridge authenticate each other by certificate, not by password. They pair once, and from then on each side accepts only the other's certificate in both directions:
- OpenELIS calls the Bridge (connections, profiles, probes, undelivered results) presenting its own certificate, and trusts only the Bridge certificate it pinned.
- The Bridge delivers results to
/analyzer/fhirpresenting its own certificate. OpenELIS accepts a delivery only from the paired Bridge's certificate and records it as the system user. An OpenELIS password or session is refused there.
Neither side needs a certificate authority, and host names play no part: each side trusts the other's certificate by its SHA-256 fingerprint.
Pairing
The Bridge accepts a pairing only with its pairing code, and only once per code.
The code is either configured (BRIDGE_PAIRING_CODE on the Bridge) or generated
when an unpaired Bridge starts, in which case the Bridge prints it in its log.
OpenELIS pairs in one of two ways:
- With a configured code. When
ANALYZER_BRIDGE_PAIRING_CODE(propertyanalyzer.bridge.pairing-code) is set to the Bridge's code, OpenELIS pairs on startup, and on its first call to the Bridge if it is still unpaired or its pin is stale (see "Pairing again"). Giving both containers the same value pairs them with no manual step. A configured code the Bridge refuses, because it is wrong or already used, is not tried again, so the Bridge keeps its attempts for the code entered on the page. - On the Analyzers page. A Global Admin enters the code there. The page shows whether OpenELIS is paired, the Bridge address, the start of the Bridge's certificate fingerprint and when it paired, and why a code was refused.
While pairing, OpenELIS sends the code and the fingerprint of the HTTPS certificate it serves, presents its own certificate, and pins the certificate the Bridge presented once the Bridge confirms it. Results the Bridge receives before pairing wait in its outbox and are delivered once it is paired.
The first pairing trusts whichever certificate answers at the Bridge address: the code is not yet bound to either side's certificate, so something that can intercept the link at that moment could pair in the Bridge's place. Pair where nothing can sit between them, such as the Compose stack's own network. Binding the code to both certificates needs a change to the Bridge's pairing protocol.
Identities
OpenELIS creates its own key pair the first time it pairs and keeps it in the database, with the private key encrypted. It does not reuse the certificate it serves HTTPS with, so renewing that certificate does not break the pairing.
The Bridge keeps its key pair and pairing record on its state volume. When it is configured with a server keystore, it uses that instead.
The Bridge trusts OpenELIS's HTTPS certificate either by the fingerprint OpenELIS sent while pairing or because its trust store validates it. In the Compose stacks the Bridge is given the stack's trust store, so OpenELIS stays trusted after its certificate is regenerated.
Pairing again
A paired Bridge refuses its current code. To pair again, for example after reinstalling either side, configure a new code on the Bridge, restart it, and enter that code on the Analyzers page or set it as OpenELIS's configured code. OpenELIS reads the pairing from its database wherever it checks it, so the new pairing applies to result delivery at once, without a restart.
OpenELIS checks its pin against the Bridge at the configured address, through
the Bridge's GET /pairing, each time the Analyzers page loads and on the
configured-code schedule. The pin is stale when the Bridge presents a
certificate other than the pinned one, as after a database copied from another
stack or a Bridge reinstalled with a new identity, or when the Bridge presents
the pinned certificate but reports itself unpaired, as after its state volume
was replaced. The Analyzers page then says which of the two it is and asks for
the code. With a configured code, OpenELIS pairs again on its own, replacing the
stored pin and logging the replacement; a code the Bridge refuses is not tried
again. The first-pairing caveat above applies to this pairing too. An
unreachable Bridge leaves the pin as it is.
Tomcat
OpenELIS's HTTPS connector requests a client certificate without requiring one,
and accepts any certificate in the handshake through
org.openelisglobal.tomcat.AnyClientCertificateTrustManager, which the OpenELIS
images install in Tomcat's lib directory. The handshake still proves the
client holds the certificate's private key; OpenELIS then admits only the paired
Bridge's certificate. Browsers and the proxy present no certificate and are
unaffected.
A server.xml that does not request client certificates, such as one installed by the Linux installer template, leaves OpenELIS unable to receive results from a paired Bridge.