Build Packages / Create release (push) Successful in 21s
Build Packages / build:rugnux-tgz (x86_64) (push) Successful in 9m40s
Build Packages / build:rugnux:aarch64 (cross) (push) Successful in 9m49s
Build Packages / build:viewer-tgz:cpu (push) Successful in 11m37s
Build Packages / build:viewer-tgz:cuda (push) Successful in 12m40s
Build Packages / build:windows:nocuda (push) Successful in 17m44s
Build Packages / build:windows:cuda (push) Successful in 20m13s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 14m41s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 25m59s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 15m5s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 14m35s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 15m53s
Build Packages / build:rugnux:windows (push) Successful in 11m29s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 18m51s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 18m43s
Build Packages / Generate python client (push) Successful in 51s
Build Packages / build:rpm (rocky8) (push) Successful in 18m51s
Build Packages / Build documentation (push) Successful in 1m21s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 18m38s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 18m24s
Build Packages / build:rpm (rocky9) (push) Successful in 19m19s
Build Packages / Unit tests (push) Successful in 1h37m15s
* Building Jungfraujoch no longer needs zlib or Eigen installed on the machine, and the dependencies the build fetches are pinned and updated to current releases. * rugnux: improvements in indexing, lattice selection and geometry post-refinement, which index crystals that previously returned no lattice and keep the better of the two geometries a run measures. * rugnux: improvements in beam-centre measurement, beam-stop detection and space-group determination. * rugnux: the unit cell reported with a determined space group now obeys that group - a cell whose symmetry was confirmed from the intensities is re-refined under it, and a cell the group cannot describe is reported with a warning rather than as it stands. * rugnux drops the stretches of a rotation sweep whose removal measurably improves the merged intensities and reports what became of every frame, and decides the resolution cut on the crystal's own diffraction rather than on its ice rings. * The rugnux results report is machine-readable - every line that is not `KEY= value` data starts with `#` - and states the build it was written by, its authorship and its terms of use (`REPORT_VERSION= 8`). * `jfjoch_viewer`: improvements in the file manager (CBF frames beside HDF5 datasets, a remembered root), the dataset plots, the inspector and the image statistics, plus a settable font size, a view of the rugnux results report, usable performance over a remote display (`ssh -X`) and a reset of all settings to defaults; the reciprocal-space window is removed. * Broker fixes around DECTRIS collections and dark-mask calibration: re-initialising after a run that never started no longer freezes the broker, a cancelled calibration is abandoned instead of reported as done, and a collection whose start message never arrives ends by itself. Reviewed-on: #79 Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
117 lines
7.5 KiB
Markdown
117 lines
7.5 KiB
Markdown
# Security
|
|
|
|
Jungfraujoch is a data-acquisition and analysis system for X-ray detectors, designed to run
|
|
**inside a controlled facility network**. This document describes what the software does and does
|
|
not protect against, the current known limitations, and the authentication work in progress.
|
|
|
|
## Threat model and scope
|
|
|
|
The security model targets a **semi-trusted internal facility network**. The concern is a peer on
|
|
that network reaching a Jungfraujoch service with **little or no effort** — a mistyped host/port, a
|
|
curious colleague, a mis-pointed script, a stray browser tab — not a determined attacker and not
|
|
passive wire capture (which is the responsibility of the network layer: 802.1x, VLANs, facility
|
|
infrastructure).
|
|
|
|
The asset that matters most is the **confidentiality of live analysis data**: the diffraction
|
|
images and derived metadata (unit cell, resolution, spot counts, sample name) that reveal *which
|
|
sample is being measured*. This matters for industrial and proprietary experiments. By contrast,
|
|
**acquisition control** (start / stop / configure) is treated as low risk — scientists operate their
|
|
own experiments and there is little to gain from restricting it.
|
|
|
|
Security is **best-effort**: measures that materially impede normal operation get turned off, so the
|
|
design favours a few high-value, low-friction controls over comprehensive lockdown.
|
|
|
|
> **Out of scope.** Jungfraujoch is **not** designed to be exposed to an untrusted network or the
|
|
> public internet. Do not do this.
|
|
|
|
## 1. Good practice — what is and is not protected
|
|
|
|
### What you can secure (and should)
|
|
|
|
These controls work and a deployment should apply them (see also `DEPLOYMENT.md`):
|
|
|
|
- **Network isolation.** Keep the broker and its data streams on a controlled segment. The
|
|
broker ↔ writer ↔ receiver traffic should run on a **dedicated back-end network**, with the
|
|
data-socket addresses pinned to that interface and the ports firewalled.
|
|
- **Reverse proxy for TLS.** The broker speaks plain HTTP. To get HTTPS, put a reverse proxy
|
|
(Apache / nginx) in front that terminates TLS and pin the broker to `localhost` behind it. The
|
|
desktop viewer supports `https://` endpoints — choose the scheme in the *Open HTTP Connection*
|
|
dialog.
|
|
- **Filesystem confinement of written data.** The writer creates NXmx HDF5 files on shared
|
|
storage. Confidentiality of that data **at rest** is enforced by the filesystem: run the writer
|
|
under a dedicated identity and use directory ownership / ACLs (and setgid) so that only the owning
|
|
experiment can read its files.
|
|
- **Firewall the ZeroMQ ports.** The image / preview / metadata / republish streams have no access
|
|
control of their own (see below), so restrict who can reach those ports at the network layer.
|
|
|
|
### What the software does NOT provide
|
|
|
|
The gaps are listed explicitly so a deployment does not assume protection that is not there:
|
|
|
|
- **No authentication or authorization in the broker.** The HTTP/REST API currently has **no login,
|
|
token, or access control**. Anyone who can reach the broker's host and port has full read access
|
|
(live images, unit cell, resolution, sample metadata) and full write access (start, cancel,
|
|
reconfigure). Confidentiality currently depends **entirely** on network/firewall isolation. This
|
|
is being addressed — see §3.
|
|
- **No transport encryption in the broker.** The broker serves plain HTTP; there is no built-in TLS.
|
|
Encryption must be provided by a reverse proxy.
|
|
- **No access control or encryption on the ZeroMQ streams.** The preview, metadata, image, and
|
|
republish streams are unauthenticated sockets. Any peer that can connect can subscribe to live
|
|
data. For the image `PUSH` stream specifically, an accidental extra consumer does not merely
|
|
eavesdrop — a `PULL` peer is load-balanced into the stream and will *divert* images away from the
|
|
real writer.
|
|
- **No per-user isolation.** The broker has no concept of users; it cannot separate one operator's
|
|
access from another's.
|
|
- **No application-level audit trail** of who accessed or changed what.
|
|
|
|
### Recommended deployment checklist
|
|
|
|
- [ ] Broker and back-end streams on an isolated network; **never** exposed to a general/untrusted network.
|
|
- [ ] ZeroMQ data-socket addresses pinned to the back-end interface; ports firewalled to known peers.
|
|
- [ ] TLS terminated by a reverse proxy; broker bound to `localhost` behind it.
|
|
- [ ] Writer run under a dedicated identity; data directories owned / ACL'd per experiment (setgid) so users read only their own data.
|
|
- [ ] ZeroMQ compatibility streams (preview / metadata / republish) enabled only if actually consumed, and only on the trusted back-end.
|
|
|
|
## 2. Known issues
|
|
|
|
| # | Issue | Impact | Mitigation today |
|
|
|---|-------|--------|------------------|
|
|
| 1 | Broker HTTP API has no authentication | Anyone who can reach it has full read (confidential live data) + write (control) | Network / firewall isolation; §3 in progress |
|
|
| 2 | Broker binds all interfaces, plain HTTP | Reachable from anywhere routable; no encryption | Expose only on the trusted segment; TLS via reverse proxy |
|
|
| 3 | ZeroMQ preview / metadata / image / republish streams are unauthenticated and unencrypted | Live-data exfiltration; a rogue `PULL` on the image stream diverts/steals images | Firewall the ports; run only on the back-end network |
|
|
| 4 | Web frontend assumes an open API | The bundled UI has no auth and expects to reach an open broker | Serve and reach it only on the trusted network |
|
|
|
|
**Input robustness.** Services parse framed data from peers on the (trusted) data path. Hardening of
|
|
untrusted-frame handling (size caps, overflow guards) is ongoing; these paths are not intended to
|
|
face an untrusted network.
|
|
|
|
## 3. Work in progress — authenticated read access
|
|
|
|
The main gap (issue #1) is being closed with a **best-effort, low-friction** scheme that protects the
|
|
confidential **read** endpoints while leaving acquisition control open.
|
|
|
|
**Enabling step (done): viewer HTTP client on libcurl.** The desktop viewer's broker client was
|
|
migrated from a plain-HTTP library to **libcurl**, which gives it HTTPS plus the ability to
|
|
authenticate. The build stays self-contained per platform: on **Windows**, TLS and Kerberos come
|
|
from the operating system (Schannel + SSPI, no external dependencies); on **Linux**, from system
|
|
OpenSSL + **Kerberos (GSSAPI / krb5)**. This is why the Linux build now needs the Kerberos
|
|
development headers (`libkrb5-dev` on Debian/Ubuntu, `krb5-devel` on RHEL/Rocky).
|
|
|
|
**Planned enforcement (not yet implemented).** Two complementary options, both gating only the
|
|
sensitive read endpoints (live images, scan result, preview plots, statistics) and leaving writes
|
|
open:
|
|
|
|
- **Per-experiment Bearer token.** An optional token supplied at acquisition start (`/start`); when
|
|
set, the broker requires it (`Authorization: Bearer …`) on the read endpoints. No token set → no
|
|
enforcement (backward compatible). The token is minted externally and handed to the authorised
|
|
viewer(s); the broker only compares strings. A rotated per-experiment token segments one
|
|
experiment's data from the next.
|
|
- **Kerberos / GSSAPI single sign-on.** A pass-through reverse proxy performs Kerberos/SPNEGO
|
|
authentication (service keytab) and forwards the authenticated user name to a `localhost`-pinned
|
|
broker as a trusted header. This gives Active Directory single sign-on with no token to carry, at
|
|
the cost of a proxy deployment. The viewer's libcurl client can negotiate Kerberos directly against
|
|
such a proxy.
|
|
|
|
Neither enforcement path is in the broker yet. Until then, confidentiality relies on the network and
|
|
filesystem controls in §1.
|