migrate DAQ URLs to HTTPS and simplify Kerberos SPNEGO token authentication

This commit is contained in:
2026-06-10 10:18:38 +02:00
parent f031e011ae
commit 11a56addee
5 changed files with 17 additions and 55 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ gui:
gonio_camera_id: "1"
daq:
daq_url: "http://mx-x06da-queue-01.psi.ch:5210"
daq_url: "https://mx-x06da-queue-01.psi.ch"
shared:
jfjoch:
+1 -1
View File
@@ -8,7 +8,7 @@ gui:
gonio_camera_id: ""
daq:
daq_url: "http://mx-x06sa-queue-01.psi.ch:5210"
daq_url: "https://mx-x06sa-queue-01.psi.ch"
shared:
jfjoch:
+1 -1
View File
@@ -9,7 +9,7 @@ gui:
gonio_camera_id: "1"
daq:
daq_url: "http://mx-x10sa-queue-01.psi.ch:5210"
daq_url: "https://mx-x10sa-queue-01.psi.ch"
shared:
jfjoch:
+11 -49
View File
@@ -8,7 +8,6 @@ from aare.common.logger_config import setup_logger
logger = setup_logger('aareGUI')
APACHE_URL = "https://mx-x10sa-queue-01.psi.ch/"
CACERT = "/sls/x10sa/misc/.cert/10s.crt"
def auth(base_url: str | None) -> str:
@@ -20,58 +19,15 @@ def auth(base_url: str | None) -> str:
pgroups=["p16371", "p22233"])
return jwt.encode(token_data.model_dump(), "ABC123")
# Step 1: SPNEGO against Apache, dump response headers, discard body
try:
apache_result = subprocess.run(
['curl', '-sk', '--cacert', CACERT,
'--negotiate', '-u', ':',
'-D', '-', '-o', '/dev/null',
APACHE_URL],
capture_output=True,
text=True,
timeout=18.0,
)
except subprocess.TimeoutExpired as e:
logger.error(f"Apache auth curl timed out: {e}")
raise RuntimeError(
"Cannot reach Apache server (timeout). "
"Please check the server is running and your connection."
) from e
except FileNotFoundError as e:
logger.error(f"curl not found: {e}")
raise RuntimeError("curl not found on this system.") from e
except OSError as e:
logger.error(f"Apache auth curl OS error: {e}")
raise RuntimeError(
"Cannot reach Apache server (OS error). "
"Please check the server is running and your connection."
) from e
if apache_result.returncode != 0:
logger.error(f"Apache curl exited {apache_result.returncode}. stderr: {apache_result.stderr[:500]}")
raise RuntimeError(
f"Apache authentication failed (curl exit {apache_result.returncode}). "
"Check Kerberos ticket is valid (kinit)."
)
# Parse X-Remote-User from response headers (stdout = headers due to -D -)
remote_user = None
for line in apache_result.stdout.splitlines():
if line.lower().startswith('x-remote-user:'):
remote_user = line.split(':', 1)[1].strip()
break
if not remote_user:
logger.error(f"X-Remote-User not found in Apache response headers. Headers: {apache_result.stdout[:500]}")
raise RuntimeError("Apache authentication failed (no X-Remote-User in response).")
# Step 2: Call FastAPI /token with the authenticated username
# Single call: Kerberos SPNEGO through Apache, which proxies to the DAQ server.
# Apache injects X-Remote-User; the DAQ server reads it from the localhost-proxied request.
url = f"{base_url}/token"
try:
token_result = subprocess.run(
['curl', '-sk', '--cacert', CACERT,
'--negotiate', '-u', ':',
'-X', 'POST', url,
'-d', f'username={remote_user}&password=',
'-d', 'username=&password=',
'-H', 'Content-Type: application/x-www-form-urlencoded'],
capture_output=True,
text=True,
@@ -83,6 +39,9 @@ def auth(base_url: str | None) -> str:
"Cannot reach AareDAQ server (timeout). "
"Please check the server is running and your connection."
) from e
except FileNotFoundError as e:
logger.error(f"curl not found: {e}")
raise RuntimeError("curl not found on this system.") from e
except OSError as e:
logger.error(f"Token request curl OS error: {e}")
raise RuntimeError(
@@ -92,7 +51,10 @@ def auth(base_url: str | None) -> str:
if token_result.returncode != 0:
logger.error(f"Token curl exited {token_result.returncode}. stderr: {token_result.stderr[:500]}")
raise RuntimeError(f"Token request failed (curl exit {token_result.returncode}).")
raise RuntimeError(
f"Token request failed (curl exit {token_result.returncode}). "
"Check Kerberos ticket is valid (kinit) and server is reachable."
)
try:
response_json = json.loads(token_result.stdout)
+3 -3
View File
@@ -45,21 +45,21 @@ def main():
#TODO if zmq and pred stream come from same source, do not need images from both streams, can combine
match mx_beamline():
case MXBeamline.X06DA:
default_url = cfg_get("gui.daq.daq_url", "http://mx-x06da-queue-01.psi.ch:5210")
default_url = cfg_get("gui.daq.daq_url", "https://mx-x06da-queue-01.psi.ch")
default_zmq_addr = cfg_get("gui.cameras.sample_camera_zmq_url", "tcp://x06da-pserv-01:9089")
default_pred_zmq_addr = cfg_get("gui.cameras.prediction_zmq_url", "tcp://mx-ml:9091")
default_beamline_cam_addr = cfg_get("gui.cameras.beamline_camera_url", "x06da-axis-1.psi.ch")
default_gonio_cam_addr = cfg_get("gui.cameras.gonio_camera_url", "axis-accc8ed2972e.psi.ch")
default_gonio_camera_id = int(cfg_get("gui.cameras.gonio_camera_id", 3))
case MXBeamline.X10SA:
default_url = cfg_get("gui.daq.daq_url", "http://mx-x10sa-queue-01.psi.ch:5210")
default_url = cfg_get("gui.daq.daq_url", "https://mx-x10sa-queue-01.psi.ch")
default_zmq_addr = cfg_get("gui.cameras.sample_camera_zmq_url", "tcp://x10sa-spark-01:9091")
default_pred_zmq_addr = cfg_get("gui.cameras.prediction_zmq_url", "tcp://x10sa-spark-01:9091")
default_beamline_cam_addr = cfg_get("gui.cameras.beamline_camera_url", "axis-accc8eb02488.psi.ch")
default_gonio_cam_addr = cfg_get("gui.cameras.gonio_camera_url", "axis-accc8ea5e463.psi.ch")
default_gonio_camera_id = int(cfg_get("gui.cameras.gonio_camera_id", 1))
case MXBeamline.X06SA:
default_url = cfg_get("gui.daq.daq_url", "http://mx-x06sa-queue-01.psi.ch:5210")
default_url = cfg_get("gui.daq.daq_url", "https://mx-x06sa-queue-01.psi.ch")
default_zmq_addr = cfg_get("gui.cameras.sample_camera_zmq_url", "")
default_pred_zmq_addr = cfg_get("gui.cameras.prediction_zmq_url", "")
default_beamline_cam_addr = cfg_get("gui.cameras.beamline_camera_url", "")