feat: Private ACME server support, installed-CA viewer, and CA install into the system trust store (freepbx 17) - #15
Conversation
…I option to install a CA certificate into the system trust store (via privileged sysadmin hook).
- Escape the certificate CN in result messages (it is rendered as HTML), preventing stored XSS from a crafted certificate subject. - Reject private keys, multi-certificate bundles and oversized input; only a single CA certificate may be installed at a time. - Trust the privileged hook's result: it now checks the exit code of update-ca-trust/update-ca-certificates, rolls back the anchor on failure, and the PHP side reports success only on a real "OK". - Restrict the root hook to the staged file via an explicit argument, wipe stale staged files before each run, and ignore staged files older than 5 minutes (defence in depth). - Include the certificate fingerprint in the stored filename to avoid collisions between different CAs sharing a Common Name.
…neration and GraphQL API System trust-store CA management - Store trusted CAs as desired state in the module KVStore (Certman now extends \FreePBX\DB_Helper) instead of staging files; the privileged reconcile installs/removes anchors as root and refreshes the trust store. - Two-step workflow in the "Installed CA's" page: load a certificate, then Install / Uninstall / Remove it from the system per-CA. Drift between the managed state and the OS trust store is flagged with a "Reconcile now" action. - Simplify hooks/install-ca to a one-line privileged trigger that runs "fwconsole certificates --reconcile-system-cas"; add that console command. - Self-heal on module install (reconcile as root) so CAs survive trust-store wipes (e.g. OS updates). Installed CAs viewer - Convert the managed-CAs and trusted-CAs tables to AJAX bootstrap-table grids (getManagedCAsGrid / getSystemCAsGrid) with search, sorting and refresh. - Move the "Load a CA Certificate" form into a modal; reorder the page with Trust Stores on top; fix column proportions and action-button layout. Backup / Restore - Include the module KVStore in backups via dumpKVStore()/importKVStore() and reconcile the system CAs on restore. Let's Encrypt generation - Run new/edit LE generation in the background from a progress modal: launch via AJAX (generateLEStart), poll the captured log (generateLEStatus), show a coloured progress bar (success/error) and redirect to the main page on success; restore the toolbar Submit button on failure/close. - Add a GraphQL mutation generateLetsEncrypt supporting the public service and a private/self-hosted ACME server (directory URL). - Only the host name is required; the public service additionally requires country and email, a private ACME server (acmeUrl) needs only the host. Applied consistently across the web form, JS, CLI and GraphQL. Cleanup - Remove the obsolete DST Root CA X3 workaround (hooks/fix-le-root-ca, its install.php call, and the "Remove DST Root CA X3" option in the LE form). - Drop the now-redundant #[\AllowDynamicProperties] (inherited from DB_Helper).
Update — follow-up changesThis revision reworks the "install a CA into the system trust store" feature and adds several related capabilities. The headline change is moving the privileged CA install from a staging-file + incron hook design to a KVStore desired-state + reconcile model. Why move CA management to the KVStoreThe original design staged the PEM as a file and had the incron hook read it, copy it into the trust anchors and refresh. In practice that approach proved fragile:
The KVStore model fixes all of this:
CA management UI is now two-step
Backup / Restore
Let's Encrypt generation runs in the background
GraphQL API
Field requirements (public vs private)
Cleanup
New / notable files
|
|
Hi @kapilgupta01, |
Summary
Adds the ability to issue Let's Encrypt certificates against a private / self-hosted ACME server (not only the public service) over the existing
http-01challenge, plus tooling to manage the CA certificates the server trusts.Motivation: many deployments run an internal ACME-compatible CA (step-ca, Boulder, Pebble, …) and need certman to talk to it instead of
acme-v02.api.letsencrypt.org.What's included
1. Private / self-hosted ACME server support
fwconsoleoptions):AcmeHttpClienttransport implementingAnalogic\ACME\ClientInterface(does not patch the vendoredlescript, so it survives composer updates). It supports an explicit directory URL (so non-standard paths like step-ca's/acme/<provisioner>/directoryor Pebble's/dirwork), a custom CA bundle (CURLOPT_CAINFO) and an optional insecure mode.updateLE()points lescript at the configured directory and skips the publicmirror1.freepbx.orgreachability probe when a custom server is used (it's only meaningful for the public service). Settings are persisted per certificate and inherited automatically by the renewal paths (cron + web).fwconsole certificates --generate --type le ... --acme-url=<dir> [--acme-ca=<pem>] [--acme-insecure].2. Installed-CA viewer
3. Install a CA into the system trust store (web + CLI)
hooks/install-ca): the web side stages the PEM and the hook copies it into the distribution trust anchors and runsupdate-ca-trust/update-ca-certificates. Installation is confirmed by re-scanning the trust store by fingerprint.fwconsole certificates --install-ca=/path/to/ca.pem(runs the hook directly when root).Security notes
Files of note
Acme/AcmeHttpClient.php(new) — custom ACME transport.hooks/install-ca(new) — privileged CA install hook.views/systemcas.php(new) — Installed CAs page + install form.Certman.class.php,Console/Certman.class.php,views/le.php,views/certgrid.php,assets/js/certman.js,module.xml.Testing
http-01: issued and renewed against the configured directory.fwconsole --install-capath (root, no hook) works.Known limitations / pending testing