Publish CRL for the unprivileged OpenVPN user so crl_verify works
- ovpmon-helper: new publish-crl command (validated copy of pki/crl.pem to /etc/openvpn/crl.pem, root:root 644); crl-verify allowlisted only for that path; CRL is refreshed on service start/restart. - Profiler: publish after gen-crl (init/revoke) and on server/configure; generator renders the published path when running unprivileged. - doas rule for publish-crl; docs and helper copy updated. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6f9e800779
commit
9ffdbfa259
8 files changed
+103
-9
No files matched your search
@@ -25,6 +25,10 @@ def generate_server_config(db: Session, output_path: str = "server.conf"):
|
||||
file_dh_path = os.path.join(PKI_DIR, "dh.pem")
|
||||
file_ta_path = os.path.join(PKI_DIR, "ta.key")
|
||||
file_crl_path = os.path.join(PKI_DIR, "crl.pem")
|
||||
from .process import is_container
|
||||
if os.geteuid() != 0 and not is_container():
|
||||
# unprivileged API: OpenVPN (nobody) cannot enter the 0700 pki dir, use the copy published by the helper
|
||||
file_crl_path = "/etc/openvpn/crl.pem"
|
||||
|
||||
# Render template
|
||||
ctx = dict(
|
||||
|
||||
@@ -146,7 +146,8 @@ def init_pki(db: Session):
|
||||
|
||||
# Gen CRL
|
||||
_run_easyrsa(["gen-crl"], env)
|
||||
|
||||
_publish_crl()
|
||||
|
||||
return "PKI Initialized"
|
||||
|
||||
def clear_pki(db: Session):
|
||||
@@ -183,9 +184,20 @@ def build_client(username: str, db: Session):
|
||||
_run_easyrsa(["build-client-full", username, "nopass"], env)
|
||||
return True
|
||||
|
||||
def _publish_crl():
|
||||
"""Make the fresh CRL readable by OpenVPN when the API runs unprivileged (see ovpmon-helper)."""
|
||||
from .process import publish_crl
|
||||
ok, msg = publish_crl()
|
||||
if not ok:
|
||||
logger.error(f"CRL was generated but could not be published: {msg}")
|
||||
return ok
|
||||
|
||||
|
||||
def revoke_client(username: str, db: Session):
|
||||
validate_username(username)
|
||||
env = _get_easyrsa_env(db)
|
||||
_run_easyrsa(["revoke", username], env)
|
||||
_run_easyrsa(["gen-crl"], env)
|
||||
if not _publish_crl():
|
||||
raise RuntimeError("Certificate revoked, but the CRL could not be published to OpenVPN")
|
||||
return True
|
||||
@@ -48,6 +48,19 @@ def install_config():
|
||||
return False, msg
|
||||
|
||||
|
||||
def publish_crl():
|
||||
"""Publish pki/crl.pem to a root-owned location readable by the OpenVPN user (nobody).
|
||||
No-op when running as root/in a container (OpenVPN reads the PKI directly). Returns (ok, message)."""
|
||||
if is_container() or os.geteuid() == 0:
|
||||
return True, "not required"
|
||||
rc, data, raw = _run_helper(["publish-crl"])
|
||||
if rc == 0 and data and data.get("status") == "ok":
|
||||
return True, "CRL published"
|
||||
msg = (data or {}).get("error") or raw or "helper failed"
|
||||
logger.error(f"[PROCESS] publish-crl failed: {msg}")
|
||||
return False, msg
|
||||
|
||||
|
||||
def control_service(action: str):
|
||||
"""
|
||||
Action: start, stop, restart
|
||||
|
||||
Reference in new issue
Block a user