feat(backend): self-managed TLS identity for the native app's encrypted LAN link
services/tls_identity.py creates an EC P-256 key + self-signed cert (10y,
SAN localhost/127.0.0.1/HOST_IP) under <data dir>/tls at startup, and
re-issues the cert with the SAME key when < 2 years remain. A cert that
doesn't belong to the key is replaced. Nothing to renew by hand; a backup of
the data directory keeps the identity. Runs in lifespan before the app is
healthy, so the proxy (which waits for healthy) always finds the files.
/api/system/identity and /api/system/status now include
tls: {port: TLS_PORT (default 8443), spki_sha256} - the base64 SHA-256 of the
public key that phones pin. Adds cryptography==46.0.4.
Tests: create / restart (no change) / renewal 8 years later keeps the key
and pin / foreign cert replaced; pin equals openssl's SPKI sha256.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@ from models.table import Table, TableGroup
|
||||
from services import printer_service
|
||||
from services.cloud_sync import _sync_once, _push_menu_snapshot
|
||||
from services.lan_ip import OVERRIDE_KEY, resolve_lan_ip, validate_lan_ip
|
||||
from services.tls_identity import tls_info
|
||||
from middleware.license_check import license_state
|
||||
from config import settings
|
||||
|
||||
@@ -50,6 +51,8 @@ def identity(db: Session = Depends(get_db)):
|
||||
"venue_name": (venue.value if venue and venue.value else None),
|
||||
"version": settings.VERSION,
|
||||
"api_version": API_VERSION,
|
||||
# Encrypted LAN endpoint for the native app: https://<ip>:<port>, pin spki_sha256
|
||||
"tls": tls_info(),
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +113,7 @@ def system_status(db: Session = Depends(get_db), user: User = Depends(get_curren
|
||||
"site_id": settings.SITE_ID or None,
|
||||
"lan_ip": lan.get("effective"),
|
||||
"lan_ip_info": lan,
|
||||
"tls": tls_info(),
|
||||
"printers": printer_statuses,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user