🚧 Add CA and server cert management
This commit is contained in:
+37
-15
@@ -12,7 +12,7 @@ from dataclasses import dataclass, field
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models import BrokerSettings, ListenerConfig
|
||||
from app.models import BrokerSettings, Certificate, ListenerConfig
|
||||
|
||||
_BOOL = {True: "true", False: "false"}
|
||||
|
||||
@@ -34,7 +34,9 @@ def _global_section(db: Session, warnings: list[str]) -> list[str]:
|
||||
return lines
|
||||
|
||||
|
||||
def _listener_block(listener: ListenerConfig, warnings: list[str]) -> list[str]:
|
||||
def _listener_block(
|
||||
listener: ListenerConfig, db: Session, warnings: list[str]
|
||||
) -> list[str]:
|
||||
lines: list[str] = []
|
||||
if not listener.enabled:
|
||||
return lines
|
||||
@@ -51,18 +53,38 @@ def _listener_block(listener: ListenerConfig, warnings: list[str]) -> list[str]:
|
||||
if listener.max_connections != -1:
|
||||
lines.append(f"max_connections {listener.max_connections}")
|
||||
if listener.tls_enabled:
|
||||
# TLS blocks only become valid once PKI ships (Release 2); we
|
||||
# generate them now so the model is forward-compatible, but warn.
|
||||
warnings.append(
|
||||
f"listener '{listener.name}': TLS requested but PKI is not "
|
||||
"available in Release 1; certfile/keyfile not set"
|
||||
)
|
||||
if listener.tls_min_version:
|
||||
lines.append(f"tls_version {listener.tls_min_version}")
|
||||
if listener.require_certificate:
|
||||
lines.append("require_certificate true")
|
||||
if listener.use_identity_as_username:
|
||||
lines.append("use_identity_as_username true")
|
||||
# Real PKI material (spec section 30): when a certificate is bound,
|
||||
# the deploy pipeline publishes cert/key/CA files under
|
||||
# /mosquitto/certs/<id>.crt|key BEFORE the config referencing
|
||||
# them is activated, so validation sees real files.
|
||||
cert = db.get(Certificate, listener.cert_id) if listener.cert_id else None
|
||||
ca = db.get(Certificate, cert.parent_id) if cert and cert.parent_id else None
|
||||
if cert is not None:
|
||||
cert_dir = "/mosquitto/certs"
|
||||
lines.append(f"certfile {cert_dir}/{cert.id}.crt")
|
||||
lines.append(f"keyfile {cert_dir}/{cert.id}.key")
|
||||
if ca is not None:
|
||||
lines.append(f"cafile {cert_dir}/{ca.id}.crt")
|
||||
if listener.tls_min_version:
|
||||
lines.append(f"tls_version {listener.tls_min_version}")
|
||||
if listener.require_certificate:
|
||||
lines.append("require_certificate true")
|
||||
if listener.use_identity_as_username:
|
||||
lines.append("use_identity_as_username true")
|
||||
else:
|
||||
# TLS requested but no certificate bound: forward-compatible
|
||||
# block without certfile/keyfile, with an actionable warning.
|
||||
warnings.append(
|
||||
f"listener '{listener.name}': TLS requested but no certificate "
|
||||
"is bound; certfile/keyfile not set. Issue a server certificate "
|
||||
"and bind it to this listener."
|
||||
)
|
||||
if listener.tls_min_version:
|
||||
lines.append(f"tls_version {listener.tls_min_version}")
|
||||
if listener.require_certificate:
|
||||
lines.append("require_certificate true")
|
||||
if listener.use_identity_as_username:
|
||||
lines.append("use_identity_as_username true")
|
||||
return lines
|
||||
|
||||
|
||||
@@ -101,7 +123,7 @@ def generate_config(db: Session) -> GenerationResult:
|
||||
if enabled:
|
||||
lines.append("# --- Listeners ---")
|
||||
for listener in enabled:
|
||||
block = _listener_block(listener, warnings)
|
||||
block = _listener_block(listener, db, warnings)
|
||||
if block:
|
||||
lines.append(f"# listener: {listener.name}")
|
||||
lines.extend(block)
|
||||
|
||||
Reference in New Issue
Block a user