User guide
Certificates
Looking for what it does rather than how to use it? Read the SSL Certificate Management overview .
The Certificates section gives an organization — and the MSP that manages it — one place for every TLS/SSL certificate it depends on: public certificates from any CA, certificates from an internal CA, the CAs themselves, and certificates bought through Tridacom. It knows where each one is installed, whether the private key is in the password manager, whether the chain and revocation status are sound, and when to rotate.
Where: /msp/certificates (across managed clients) and /org/certificates. Platform configuration for Tridacom SSL products lives at /platform/integrations/certificate-services (the distribution partner account itself is shared with /platform/integrations/domain-registrar).
What a certificate row knows
| Area | Facts | Source |
|---|---|---|
| X.509 | subject (CN, O, OU, C, ST, L), issuer, serial, validity, every SAN (DNS, IP, email), key algorithm/size/curve, signature algorithm, key usage, extended key usage, CA / path length, SKI / AKI, OCSP / CRL / CA-issuer URLs, policy OIDs (→ DV / OV / EV), CT SCT presence, one-way hash / SHA-1 fingerprints, SPKI fingerprint (what the private key is matched against), wildcard, self-signed | parsed from the PEM |
| Chain | ordered intermediates and root, VALID / INCOMPLETE / UNTRUSTED / BROKEN / EXPIRED_LINK, publicly trusted (platform root store) vs privately trusted (a CA the tenant registered as a trust anchor); a missing intermediate is fetched from the CA’s AIA URL and kept so exports carry the full chain. A hop is only followed when the issuer is allowed to be one: CA flag, keyCertSign, path length, name constraints and extended key usage all have to permit it, and extended key usage nests — a CA restricted to clientAuth or emailProtection cannot complete the chain for a serverAuth certificate, and a chain that keeps some other purpose but loses serverAuth is reported as unusable for TLS | chain check |
| Revocation | OCSP: GOOD / REVOKED (with time and reason) / UNKNOWN / CHECK_FAILED | chain check |
| Private key | which password-manager item holds it (by reference), verified / mismatch / unverified, or “held outside Solidlio” | vault link + verification |
| Business | owner, technical contact, criticality, environment, purpose, renewal automation (by hand / ACME / vendor-managed / Tridacom), auto-renew, vendor, renewal cost, reminder thresholds, contract, site, linked domain, tags, notes | people |
| History | every change to a tracked fact (expiry, key, chain status, status, owner, …), every check run | checks / users |
X.509 facts are never editable — they come from the certificate. Business fields are never touched by a check.
The one rule about private keys
Solidlio never stores a private key. Not encrypted, not cached, not in a job payload. A certificate points at the item in the tenant’s password manager (1Password today) that holds the key. When the key is needed:
- Generate a CSR creates the key pair in memory, writes the key straight into the chosen vault as a Secure Note with a concealed
private keyfield (plus common name, SANs, key algorithm and SPKI fingerprint as plain fields), records the reference, and returns only the CSR. Nobody sees the key. This needs the 1Password connection’s Allow certificate key writes setting on and a vault mapped to the organization. - Verify does the same reveal to confirm the vault key belongs to the certificate (SPKI comparison) and records the result.
- Import a PKCS#12 opens the container in memory; the certificate and chain land in the inventory; the key goes to the vault you pick — or is discarded, and the page says so.
- Link a vault item attaches an existing item (e.g. a key an engineer stored by hand); verification then says whether it matches.
A PEM paste that contains a private key is parsed for the certificate only; the key is dropped and the preview warns you.
Four ways a certificate arrives
- Paste / upload (
Add certificate → Paste PEM): a leaf, or a bundle (the first non-CA certificate is the leaf; the rest become the chain). Facts are parsed, the chain is checked and any missing intermediate fetched. - Discover from a host (
Add certificate → Discover): probehost:port(with SNI) and record what it serves. - Import a .pfx / .p12 (
Add certificate → Import): certificate + chain into the inventory, key into the vault (or discarded). - Issued through Tridacom: an order that completes lands the certificate on the pending row the CSR created, with the CA’s intermediate bundle.
Internal-CA certificates work exactly the same way. Add the CA certificate (root and/or issuing CA) and mark it Trust anchor: private chains ending there validate as VALID with the PRIVATE_CHAIN note, and the issuing CA row is linked as the issuer.
Rotation, tracked
That is the finding that catches “renewed but never installed”.
Exports
| Format | Contents | Typical consumers |
|---|---|---|
| PEM | leaf only | Apache, nginx, Linux services |
| PEM chain | leaf + intermediates | nginx ssl_certificate, Postfix |
| DER (.cer) | leaf, binary | Windows, Java keytool, Cisco, Juniper |
| PKCS#7 (.p7b, PEM or DER) | certificate-only bundle | IIS Complete Certificate Request, Exchange, Tomcat, F5, Citrix |
| PKCS#12 (.pfx) — modern | key + certificate + chain, AES-256 / one-way hash, password | IIS, Exchange, Azure, Java 8u301+, FortiGate, Palo Alto, Synology, UniFi |
| PKCS#12 (.pfx) — legacy | 3DES / SHA-1 | Cisco ASA / IOS, Windows Server 2012 R2 and older, Java < 8u301, older SonicWall / WatchGuard firmware |
| PEM bundle with key | key + leaf + chain in one file | HAProxy, Traefik, Envoy, Ubiquiti |
RSA and EC keys both work in every format. Certificate-only formats download from the certificate page directly; key formats go through the vault reveal.
Monitoring and notifications
- On demand: Check now.
- Notices (
certificate-expiry-notifications, 07:30 UTC): expiry at each certificate’s own thresholds (default 30 / 14 / 7 / 3 / 1 days; ACME- and vendor-managed certificates only at 7 and 3, because a 90-day certificate three weeks from expiry is normal), rotation not applied, health under 50, revocation. - Renewals (
/renewals): every certificate appears on the same window as licences, warranties, contracts and domains.
Tridacom SSL services (distribution partner distribution partner trust service)
Tridacom is the distribution partner reseller; the same platform account as domains. Products: Sectigo (PositiveSSL, EssentialSSL, InstantSSL, PremiumSSL, EV, wildcards), DigiCert / GeoTrust / Thawte / RapidSSL (DV, OV, EV, wildcard, multi-domain SAN), Trustwave and Actalis — every product_type distribution partner documents for sw_register, with the contact blocks each one requires (admin / organization / signer / tech) known to the order form.
Not everything on the trust service is a TLS certificate. The same sw_register also sells DigiCert code signing and the SiteLock website- security tiers (Find / Fix / Prevent / 911) plus Malware Scan, and the order is a different shape for each, so products carry a category:
| Category | CSR | Domain | Validation | Issues |
|---|---|---|---|---|
SSL | required | read from the CSR | DV email / DNS / file | a certificate |
CODE_SIGNING | required | CN is the legal name | organization, on contacts | a certificate |
WEBSITE_SECURITY | none | typed by the customer | none | nothing — a subscription |
The order form names its steps after what it actually asks for (Website instead of CSR, Options instead of Validation), and the order path forks with it: a website-security order sends no csr, no dv_auth_method and no approver_email — the CA rejects those rather than ignoring them — carries end_user_auth_info with the administrative contact’s address (address only: sending a username for an account that already exists fails the whole command, and distribution partner emails the dashboard credentials there), creates no pending inventory row, and on completion is marked issued without a get_cert call. Attempting one would throw, pinning the order in progress and unbilled. Invoice lines say “Website security” or “Code signing certificate” rather than “SSL certificate”.
malwarescan is enabled on the account but is not in the documented sw_register product-type list — it is modelled and priceable, but confirm with distribution partner before putting it on sale.
Pricing has three layers, frozen on every order: wholesale (entered by a platform admin from the distribution partner price sheet — there is genuinely no price API for trust products: get_capabilities only says which products the account may sell, and get_products is a portfolio query of certificates already issued, in an expiry window, with no price field. Both were checked against the live account), MSP price, and customer price (MSP price + the MSP’s certificate markup, falling back to its domain markup; or retail for a direct customer). Multi-domain products carry a per-SAN add-on with the same three layers. The list refuses to sell below cost.
Buying (Buy through Tridacom): pick a product and term → CSR (a pending certificate whose CSR was generated into the vault, or a pasted CSR — parse_csr-style validation warns about wildcard / SAN / key-size mismatches) → the contacts the product needs → validation method (email to a query_approver_list address, DNS TXT, or HTTP file; the CA’s exact record / file is shown on the order) → quote → order. distribution partner is called with sw_register handle=process. The order then moves through awaiting validation → CA is vetting → issued → completed as the 15-minute poll (certificate-order-reconcile, get_order_info + get_cert return_ca_certs=1) lands the certificate on the pending row and bills it.
Cancelled / declined orders retire their pending row and bill nothing.
Renewals. Tridacom-issued certificates with auto-renew on are renewed by certificate-auto-renewals inside the lead window (autoRenewLeadDays, shared with domains; distribution partner allows renewal from 60 days before expiry) with the same CSR and contacts, billed to the account that placed the last order. Renewal by hand: Renew through Tridacom on the certificate. Re-issue (new CSR for the same order) is not available through the distribution partner API and has to be done in the distribution partner control panel — the page says so rather than pretending.
Reseller portfolio (Portfolio tab). Certificates issued on Tridacom’s distribution partner account that were never ordered here — bought in the control panel, or predating Solidlio — have no organization, and TlsCertificate requires one, so they were invisible in the product. registrar-portfolio-sync lists them (GET_PRODUCTS, an expiry window, no price field) and a platform admin places each on an organization. Placing downloads the certificate with get_cert and files it through the same ingestCertificate path an order uses, carrying tridacomProductId — so expiry, chain checks, reconciliation and renewal attach to it exactly as if it had been bought here. The private key is not included and cannot be (distribution partner never had it): the row lands keyLocation: EXTERNAL, which is the honest state. Ones ordered through Solidlio link themselves by product id. See the domains guide for the shared tenancy reasoning.
Platform admin (/platform/integrations/certificate-services): sync the product list from distribution partner, set cost / MSP / retail (and SAN add-on) prices per product, enable what is for sale, and read the order ledger with wholesale and margin.
A product cannot be put on sale until it has a wholesale cost and is enabled on the distribution partner account. Both are refused with a 400: “not below cost” is satisfied trivially when cost is 0, and a sync creates every row at 0 — so enabling a freshly synced product used to sell a certificate whose margin nobody could compute. Ordering a product get_capabilities does not list fails at sw_register after the customer is billed, so that is refused too (only once a sync has run — before the first one, enabledAtProvider: false means “not asked yet”, not “no”).
Service boundaries
- @solidlio/utils/x509, x509-formats and ocsp hold the pure X.509 code (parsing, chain building, CSR/key generation, PKCS#12 and PKCS#7 assembly and parsing for RSA and EC keys, OCSP request/response) and are covered by unit tests against OpenSSL-produced fixtures.