regenerate and copy CRL during reissue; run restorecon after every CRL copy
Reissue internally revokes the old cert (revoke_issued), which makes the published CRL immediately stale, but neither the CLI --reissue path nor the TUI renew flow ever regenerated/copied it — only standalone revoke and "Regenerate CRL" did. A cert revoked as part of a reissue could keep authenticating against OpenVPN until someone remembered to regenerate the CRL by hand. Both reissue paths now call gen_crl()+copy_crl() right after a successful revoke_issued(), same as standalone revoke. This isn't gated on the subsequent build_client_full() succeeding, since the CRL is already stale the moment the old cert is revoked. A CRL-regen failure here is reported as a warning and the reissue continues to build the replacement cert — a new cert is more urgent than a fresh CRL, and "Regenerate CRL"/--gen-crl remain available to retry. Also add a RESTORECON_BINARY setting (default "restorecon", "" to disable): copy_crl() now runs it on the destination file after every copy, everywhere copy_crl() is called. Best-effort like is_ca_key_encrypted() — a missing/misconfigured binary is swallowed rather than breaking CRL deployment on non-SELinux systems. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,7 +26,7 @@ Edit the `SETTINGS` block at the top of `openvpncertupdate.py` before first run.
|
||||
| Flag | Effect |
|
||||
|---|---|
|
||||
| `--create CN` | Issue new cert (requires `--email`) |
|
||||
| `--reissue CN` | Revoke + reissue cert (`--email` optional, falls back to stored) |
|
||||
| `--reissue CN` | Revoke + regenerate CRL + reissue cert (`--email` optional, falls back to stored) |
|
||||
| `--revoke CN` | Revoke cert and regenerate CRL |
|
||||
| `--gen-crl` | Regenerate and copy CRL only |
|
||||
| `--list` | List recently-expired/soon-to-expire CNs (per `DAYS_PAST`/`DAYS_AHEAD`) with email; read-only, no CA passphrase needed |
|
||||
@@ -67,8 +67,8 @@ python3 -m pytest tests/test_pki.py::test_sorted_ascending -v # single test
|
||||
## Re-issue workflow
|
||||
|
||||
1. `revoke-issued <CN>` — archives old key + CSR to `pki/revoked/`
|
||||
2. `build-client-full <CN> --passout=pass:<pw>` — generates new key + cert
|
||||
3. CRL **not** auto-updated during renewal; use "Regenerate CRL" menu item or `r` hotkey
|
||||
2. CRL regenerated and copied to `CRL_DEST_PATH` immediately after the revoke succeeds — the old cert is already revoked at this point, so the published CRL would otherwise be stale until a separate manual regen. Not fatal: a failure here is reported but the workflow continues to step 3 (a new cert is more urgent than a fresh CRL, and "Regenerate CRL" / `--gen-crl` remain available to retry)
|
||||
3. `build-client-full <CN> --passout=pass:<pw>` — generates new key + cert
|
||||
|
||||
## TUI key bindings
|
||||
|
||||
@@ -88,7 +88,7 @@ python3 -m pytest tests/test_pki.py::test_sorted_ascending -v # single test
|
||||
- EasyRSA called with `--batch`; `--passin=pass:<passphrase>` omitted when the resolved passphrase is empty
|
||||
- CA passphrase resolution (`resolve_ca_passphrase()`, run once in `main()` right after arg parsing, before dispatch): `CA_PASSPHRASE=""` → auto-detect via `is_ca_key_encrypted()` (checks `<PKI_DIR>/private/ca.key` PEM header for `ENCRYPTED`) and prompt only if encrypted; `"!empty"` → never check/prompt, passphrase is `""`; `"!ask"` → always prompt, skip detection; any other value → used literally. `--list`/`--list-all` skip this resolution entirely since they only read `index.txt` and never touch the CA
|
||||
- Cryptgeon: matches the `occulto` browser client — `key=os.urandom(32)` used directly (no derivation) for AES-256-GCM; `contents` = `base64(b"AES-GCM") + "--" + base64(nonce) + "--" + base64(ciphertext)`; `meta` = JSON string `{"type": "text"}`; URL = `<base>/note/<id>#<key.hex()>`
|
||||
- `copy_crl()` does `chmod 644` after copy
|
||||
- `copy_crl()` does `chmod 644` after copy, then runs `RESTORECON_BINARY` (default `restorecon`) on the copied file — best-effort like `is_ca_key_encrypted()`: a missing/misconfigured binary is swallowed, not fatal. Set `RESTORECON_BINARY=""` to disable on non-SELinux systems
|
||||
- Password: pos 1=uppercase, pos 2=lowercase (no j), pos 3-27=alphanumeric, pos 28=lowercase (no j); `oO01lIQ5S2Z8B` banned everywhere
|
||||
- Inline file path: `<PKI_DIR>/inline/private/<CN>.inline`
|
||||
- User emails are not stored separately: `build_client_full()` sets `EASYRSA_REQ_EMAIL` whenever an email is known, which EasyRSA embeds as `emailAddress=` in the cert subject — so it round-trips through `<PKI_DIR>/index.txt` itself. `get_email()` reads it back from there; there is no `openvpncertupdate-metadata.json`
|
||||
|
||||
Reference in New Issue
Block a user