CertmPlatform — Verification Status Report

Where the project actually stands on certificate renewal, ACME-issued renewal, and connector renewal — distinguishing code that exists from code that has been verified working end-to-end on real infrastructure.

Generated: 2026-06-09 · updated 2026-06-11 (ACME wildcard DNS-01 pass) Scope: renewal · ACME · SSL servers · connectors Basis: source code + project memory + live endpoint-renewal verification (2026-06-09) and a live connector-renewal verification attempt (2026-06-10) on dev-25 Reference env: dev-25 (WIN-IFC99HHBD1M)
Verified — tested working end-to-end on live infra Exists — built & builds, not yet verified live Missing / blocked — not implemented or can't run N/A — not applicable to this row
22
Verified live (now incl. ACME endpoint renewal ×5)
8
Built, not verified (incl. ACME wildcard DNS-01)
1
Not coded (Alteon)
6
Planned (roadmap)
6
Endpoint server types renewed live (Tomcat PKCS12 + JKS, nginx, Apache, IIS) on 2026-06-09

Headline: the renewal machinery is broadly built and CA-type-agnostic. The known code gaps have largely been closed — JKS keystore write, Tomcat 10.1+ <SSLHostConfig> discovery, Tomcat catalina.base detection, and AWS Route 53 + Azure DNS providers all landed on branch feature/ssl-renewal-gaps (only Alteon's REST paths remain, blocked on hardware). That branch was deployed to dev-25 on 2026-06-08 (app deploy, dashboard + whoami 200). Live checks run that day: the new Route 53 + Azure DNS provider wiring is verified end-to-end on dev-25 (create → server-side validation → encrypted-at-rest → list-without-secrets → delete, plus the Settings UI rendering both providers); the Tomcat discovery live run was blocked by dev-25's host AV (Bitdefender ASR refuses to launch a fresh agent exe from a remote session), so Parts 2 & 3 stay unit-test-verified; and — the headline result — live ACME is now proven end-to-end. Against Comda's internal ComSign ACME CA (EAB-protected), CertM completed a full EAB account bootstrap → HTTP-01 issue → renew (re-issue) → revoke cycle on 2026-06-08 (real certs, issuer CN=ComSign Dev CA Issuing, distinct serials, both revoked + cleaned up). That live run also surfaced two real bugs, now fixed: a DbContext-lifetime bug (Acme.cs cached a request-scoped AppDbContext in a process-wide singleton → ObjectDisposedException on every call after the first, commit 9702b68) and a broken HTTP-01 rewrite rule (parent-site Rewrite across an app-pool boundary → HTTP 403.18; must be a 302 Redirect, commit c7a6738). And on 2026-06-09 the endpoint-agent (PkiAgent) renewal path was proven live end-to-end on dev-25: all three test Tomcats (9/10.1/11, PKCS12, including the nested <SSLHostConfig> form) and an isolated IIS site (HTTP.sys rebind) renewed discover→issue→deploy→reload→serve, each live port serving the new MSCA-issued cert. That run found and fixed three more real agent bugs that had silently broken file-based renewal (discovered-name = image path not FQDN d37a1e5; multi-instance UNIQUE(KIND,IPPORT) collision 437918d; the WS frame gate dropping file/install-pfx types 39fe0f8). A follow-up run later on 2026-06-09 extended the endpoint proof to every file-fronted server type: a JKS Tomcat (BouncyCastle keystore write), a live nginx (PEM write + nginx -s reload), and a live Apache httpd (PEM write + service restart) all renewed end-to-end via MSCA with the live port serving the new cert — fixing three more agent bugs (Apache ServerRoot discovery 04529b0; nginx server_name ;-strip; a (KIND,IPPORT) store-upsert key a75ebb2; a WMI-image fallback + svchost-reload guard 4970ff2). ACME-issued endpoint renewal is now proven live across all five server types. Once Comda's PKI lead provisioned the test domain on the ComSign EAB account, the four file-fronted types (Tomcat PKCS12 + JKS, nginx, Apache) re-renewed via the ComSign ACME CA (comsign\acme, EAB, HTTP-01) with each live port serving a ComSign-issued cert; IIS followed once the KSP CSR re-sign bug was fixed (03bb273 — the re-sign was dropping the SAN, so ComSign saw the wrong domain set) and the issuance quota was raised — live :8544 now serves a ComSign cert via the HTTP.sys rebind (see 2). The bottleneck remains verification, not implementation: F5, ACME issuance, and the full endpoint renewal pipeline (6 server types, ACME on all 5 applicable) are proven against real backends. Counts are an indicative cell tally, not exact.

Matrix 2 update (2026-06-10): a live connector-renewal verification pass was attempted on dev-25, scoped to throwaway / lab targets only (no production customer infrastructure). Outcome: no cells flipped — the bottleneck is environmental/external, not code. F5 is reachable and a real over-restrictive cert-read gate was found + fixed (it hard-rejected the TMOS /var/run/key_mgmt/ staging path certs report as their sourcePath), but a fresh end-to-end re-run was blocked because the lab F5's only renewable certs are key_mgmt-managed (PEM not file-readable) — the 2026-05-31 device-verified ✓ stands. Imperva's API key now returns res=9415 "Operation not allowed" on the basic /account ping (account/credentials non-functional — external), and there is no add-site API to stand up a throwaway. Front Door's profile holds only live production customer secrets, and a safe throwaway needs creating a KV cert + unbound FD secret in the customer's tenant — which our code (import/rotate on an existing secret only) and our access don't allow. Alteon remains ✗ (no device). The relevant axis for connectors is now Workflow-issued renewal (renewed cert → Workflow fan-out to the connector target) rather than which CA issued the cert — the install/rebind step is CA-agnostic. That Workflow fan-out path is built for all four connectors; F5 is now live-verified (2026-06-11) — a PFX-source Workflow deployed to the lab F5's /Common/test-client profile and a device re-read confirmed the rebind — while Alteon / Imperva / Front Door remain blocked on device/credentials as above.

ACME wildcard pass (2026-06-11): the ask was wildcard certificate issuance, which forces DNS-01 validation (HTTP-01 can't prove control of *.). Investigation found the DNS-01 multi-provider stack already built (Cloudflare + Route 53 + Azure DNS), but two real bugs that made every wildcard order fail: (1) the challenge record name was built as _acme-challenge.*.example.com instead of the RFC 8555 §8.4 base name _acme-challenge.example.com (the leading *. must be stripped) — this broke wildcard on all providers; and (2) a wildcard cert that also covers the apex (example.com + *.example.com) puts two distinct challenge values at the same TXT name, but Route 53's UPSERT and Azure's CreateOrUpdate replaced the whole record set — clobbering the sibling value (Cloudflare's POST was already additive). Both fixed (b4a1b76, de0a638); the decision logic was extracted into pure helpers (AcmeDnsChallenge.Fqdn / AcmeTxtRecordSet) shared by both providers and covered by 19 unit tests in a new CertmPlatform.Tests project — the web app's first. Branch feature/acme-wildcard-dns01 (off develop, 4 commits, not pushed), deployed to dev-25 and about to be live-tested via Let's Encrypt staging + a Cloudflare zone. Not yet live-verified. Honest residual: a Cloudflare-only run proves the FQDN fix + the wildcard/apex flow end-to-end and the Route 53/Azure additive logic is unit-tested, but the R53/Azure live SDK paths stay unproven until a zone on those providers is available.

MATRIX 1 SSL-server renewal (endpoint PkiAgent)

Renewal of certs on web/app servers via the endpoint agent: discover the binding, enroll a new cert, deploy & reload.

SSL / web server Discovery Renewal (code) Renewal verified ACME-issued renewal Notes
IIS HTTP.sys cert store Verified live on dev-25 (2026-06-09) on an isolated test IIS site (:8544) via the KSP path: KSP keygen → CSR → issue → CertRebinderHttpSysBindingService deleted+re-added the HTTP.sys binding; live port served the new cert. Proven via MSCA (old 72BF3E0D → new EF358620) and via ACME (comsign\acme, HTTP-01) — old 13641B72 → new BC0A0F1F, live :8544 served a ComSign-issued cert. Auto-renew sweep wired (SslMonitorService). ACME-via-KSP required fixing 03bb273: WindowsKspKeyManager.SignCsrAsync loaded the inbound CSR without UnsafeLoadCertificateExtensions, rebuilding a CN-only CSR — ComSign rejected the wrong domain set (rejectedIdentifier) and every renewed IIS/KSP cert was silently losing its SANs; the fix restores SAN/EKU/KU on the re-sign. 2
Apache httpd PEM files + reload Verified live on dev-25 (2026-06-09) against Apache httpd 2.4.67 (installed as service CertmApacheTest, vhost :8447, PEM cert). Discover → CSR → issue → FileCertDeployer wrote the PEM cert+key → service restart → live :8447 served the new thumbprint. Proven via MSCA (comda-ca) and, once ComSign provisioned the domain, via ACME (comsign\acme, HTTP-01) — live :8447 served a ComSign-issued cert (thumb 7873CC8D). Live run required + validated an Apache discovery fix: httpd.exe runs from <root>\bin so the parser must recover ServerRoot (parent-of-bin / -d / -f) — commit 04529b0. 2
nginx PEM files + reload Verified live on dev-25 (2026-06-09) against nginx 1.27.4 (:8446, PEM cert). Discover → CSR → issue → wrote cert.pem+key.pemnginx -s reload (the bare-process reload fallback in WindowsServiceReloader) → live :8446 served the new thumbprint. Proven via MSCA and, once ComSign provisioned the domain, via ACME (comsign\acme, HTTP-01) — live :8446 served a ComSign-issued cert (thumb B293146C). Live run fixed the server_name trailing-; discovery bug and a reloader that must not treat a svchost-hosted service as the listener's owner. 2
Tomcat (PKCS12) keystore swap Verified live end-to-end on dev-25 (2026-06-09) against all three test Tomcats: 9 (:9443, legacy flat keystoreFile), 10.1 (:9444) and 11 (:9445) (nested <SSLHostConfig>). Each: discover → CSR → issue → write keystore.p12 → restart the Tomcat service → live port served the new thumbprint (matched expectedThumb). Proven via MSCA (comda-ca) and, once ComSign provisioned the domain, via ACME (comsign\acme, HTTP-01) — live :9445 served a ComSign-issued cert (thumb 43937558). 1 2
Tomcat (JKS) Java keystore Verified live on dev-25 (2026-06-09). Reconfigured the test Tomcat 9 (:9443) to a JKS keystore; discovery reported format=JKS; renewed → BouncyCastle JksStore write to keystore.jks (FileCertPayloadBuilder) → CertmTomcat9 service restart → live :9443 served the new thumbprint. The JKS write was previously unit-tested only. Proven via MSCA and, once ComSign provisioned the domain, via ACME (comsign\acme, HTTP-01) — live :9443 served a ComSign-issued cert (thumb 4C19464F). 2
WebLogic config.xml JKS write now unblocks the renewal payload. Caveat: WebLogic isn't a standard Windows service, so the post-write reload step still needs wiring (follow-up). Discovery parser is WebLogicConfigParser.cs.
WebSphere Liberty server.xml Discovery parser exists; renewal only if keystore is PKCS12 (else unsupported format).

1 Now verified live on dev-25 (2026-06-09). The new agent build was deployed and started as its installed Windows service via the SCM — which sidesteps the Bitdefender ASR rule that only blocks launching a fresh exe from a WinRM child process (the 2026-06-08 blocker). Discovery then matched all three Tomcats and each renewed end-to-end. The live run surfaced and fixed three real agent bugs that had silently broken file-based renewal: (a) discovered services were keyed by the process image path, which can't match a server row or be a valid cert CN — now the host FQDN, matching IisConfigReader (commit d37a1e5); (b) the local SQLite store keyed file services by an unset ipPort, so multiple Tomcats on one host collided on the UNIQUE(KIND,IPPORT) index and aborted discovery — now falls back to the port (commit 437918d); (c) the WebSocket frame gate dropped type:"file" / install-pfx renewals before they reached the dispatcher (commit 39fe0f8). The earlier <SSLHostConfig>-discovery and catalina.base-recovery work is confirmed live by this run.

2 ACME-issued endpoint renewal — proven live for the four file-fronted types; IIS rate-limited (2026-06-09). Endpoint enrollment is CA-agnostic: AgentEnrollmentController dispatches the agent's CSR to whichever CA module the chosen issuer names, and Acme.cs runs the full ACME v2 order (HTTP-01 inline) for an agent-supplied CSR. Initially ComSign rejected every order with rejectedIdentifier — "No certificate is provisioned for this exact set of domains" (the EAB account had not pre-provisioned win-ifc99hhbd1m.comda.co.il). After Comda's PKI lead added the domain in ComSign's enrollment portal, an endpoint renewal driven with issuer comsign\acme issued live for Tomcat-PKCS12 (:9445, thumb 43937558), Tomcat-JKS (:9443, 4C19464F), nginx (:8446, B293146C) and Apache (:8447, 7873CC8D) — each live port served a CN=ComSign…Issuing cert. IIS/KSP needed one fix first: the KSP CSR re-sign loaded the inbound CSR without UnsafeLoadCertificateExtensions, so SignCsrAsync rebuilt a CN-only CSR and ComSign saw the wrong domain set (this also meant every renewed IIS/KSP cert was silently losing its SANs) — fixed in 03bb273. With the SAN restored, ComSign accepted the identifier set; after the issuance quota was raised the IIS site issued live too (old 13641B72 → new BC0A0F1F, CertRebinder swapped the HTTP.sys binding, live :8544 served the ComSign cert). The earlier file run also fixed three further agent bugs: the local store upsert now keys on (KIND,IPPORT) and refreshes the platform ID (a75ebb2); ProcessPortMapper falls back to the WMI executable path when MainModule is inaccessible cross-account (4970ff2); and WindowsServiceReloader no longer mistakes a svchost-hosted service for a bare server's owner (4970ff2+).

MATRIX 2 Connector renewal

Renewal against managed connectors: generate CSR → issue via the configured CA → install & rebind on the device/service. All share the same CA-agnostic IssueCertificate(csr, template) call — so which CA issued the cert (ACME or otherwise) is invisible to the connector. The axis that matters here is whether the renewed cert can reach the connector via a Workflow (renewal source → fan-out to connector targets), which is the operational delivery path.

Connector Connector working Renewal (code) Renewal verified Workflow-issued renewal Notes
F5 BIG-IP Workflow-verified live (2026-06-11) on dev-25 / lab F5 (200.0.0.100): created a PFX-source Workflow targeting the throwaway /Common/test-client profile and ran Deploy now — the platform installed the uploaded cert+key and rebound the profile via BindProfileCertKeyAsync (the unconditional-bind path, not the RebindProfileCertAsync exercised by the 2026-05-31 direct sweep). Independent device re-read confirms /Common/test-client moved → /Common/test-cert→ /Common/wf-f5-verify-…; run history recorded 1 ok / 0 failed. The direct server-side path was also verified end-to-end on 2026-05-31 (F5RenewalService + F5BigIpMonitorService sweep), re-read on device. Full pipeline + auto-renew sweep (F5BigIpMonitorService). Re-confirmation attempted 2026-06-10: device reachable, cert/profile listing live, and a real cert-read bug was found + fixed — F5BigIpClient.IsSafeAbsolutePath hard-rejected the TMOS /var/run/key_mgmt/<token>/ssl.crt/ staging path certs report as their filestore sourcePath, so renewal couldn't read any cert staged there (commit 997a0a8). A fresh end-to-end re-run was then blocked by the lab's current cert state: the only two renewable certs on the box (test-cert, Comsigntrust) are key_mgmt-managed and their PEM isn't file-materialized (cat … No such file or directory) — only freshly-installed certs (which the 2026-05-31 proof created) land at /config/ssl/ssl.crt/ and read. The 2026-05-31 device-verified result stands; cell unchanged.
Alteon Workflow: fan-out code is generic so Alteon can be a Workflow target, but unverifiable — no lab Alteon device. Full mirror of F5 contract incl. SAN preservation. REST write paths still carry // TODO: verify against /restdoc/.
Imperva Workflow: Imperva is a valid Workflow fan-out target in code, but not live-verified (same external creds blocker below). Renewal builds CSR locally → MSCA/CA issue → ImpervaClient.UploadCustomCertAsync; deploy path not yet live-verified. Verification attempted 2026-06-10 — externally blocked: the configured API key now returns res=9415 "Operation not allowed" on even the /account ping, so the account/credentials are currently non-functional (external — not our code), and the renewal path can't map siteId→domain via /sites/list. There is also no add-site API to stand up a throwaway test site, so a safe (non-production) renewal couldn't be run. Cell unchanged.
Azure Front Door Workflow: Front Door is a valid Workflow fan-out target in code, but not live-verified (no safe throwaway target — see below). Cross-tenant connector verified live (Signer1 tenant, customer-managed KV certs). Renewal (ImportKvCertAsyncRotateSecretToVersionAsync) not yet live-verified. Verification attempted 2026-06-10 — no safe path: cross-tenant SPN auth still works and lists the profile's secrets, but the profile holds only two live production customer certs (*.signer1.com, *.comsigntrust.com, both useLatestVersion — renewing them would auto-swap the live cert). A throwaway target needs a new KV cert + unbound FD secret created in the customer's tenant, which our code only exposes import/rotate on an existing secret (no create path) and we lack cross-tenant create access. Not run to avoid production impact. Cell unchanged.

MATRIX 3 CA modules — issuance & revocation

The pluggable CA layer that every renewal pathway calls into. Renewal correctness ultimately depends on these.

CA module Issue Revoke CRL Verified live Notes
MSCA Microsoft CA (COM) Primary CA in use; issue/revoke/CRL exercised in the lab via the Scanner (comda.co.il).
MSCA_Foreign remote-domain MSCA Routed via Scanner; caType populates end-to-end after the two-segment URL fix (e0afba8).
EJBCA Hand-written REST+SOAP client present; not verified against a live EJBCA instance.
ACME RFC 8555 / Certes Real Certes client (EAB + no-EAB, DNS-01/HTTP-01). Verified live end-to-end against Comda's ComSign ACME CA (2026-06-08): EAB bootstrap → HTTP-01 issue (issuer CN=ComSign Dev CA Issuing) → renew → revoke (both certs → revoked). CRL is N/A in ACME. Renewal = re-issue (no dedicated method). Fixes 9702b68 (DbContext lifetime) + c7a6738 (HTTP-01 redirect) landed from this run.

MATRIX 4 ACME readiness detail

ACME renewal is just re-issuance, re-running the challenge each time. These are the building blocks behind every "ACME-issued renewal" cell above.

CapabilityStateNotes
Account bootstrap — no-EAB (public CAs e.g. Let's Encrypt)Code path present; key DataProtection-encrypted at rest.
Account bootstrap — EAB (kid/HMAC, internal CAs)Verified live against the ComSign ACME CA (2026-06-08) — EAB account created at a real account URL. HMAC normalized base64→base64url for vendor compatibility.
DNS-01 challenge — CloudflarePublishes/cleans _acme-challenge TXT; 90s validation poll. Already additive (one POSTed record per value, content-scoped delete), so a wildcard+apex cert's two values coexist at one name with no change.
DNS-01 — AWS Route 53 & Azure DNSImplemented (commit 03998ab): Route53 + Azure DNS providers wired end-to-end (factory, validation, Settings UI). Wiring verified live on dev-25 (2026-06-08) — create → validation (201 / 400 on bad shape) → encrypted-at-rest (CfDJ8… blob) → list-without-secrets → delete; deployed bundle renders both in the Settings dropdown. Made additive (read-merge-write) for the wildcard+apex case (commit de0a638; unit-tested) — a blind UPSERT/CreateOrUpdate had clobbered the sibling value. Live DNS-01 issuance still pending (no cloud creds). Other providers (Google, etc.) still ✗.
Wildcard issuance (*.domain) via DNS-01Built + unit-tested (2026-06-11), not yet live. Fixes the challenge-record name to the RFC 8555 §8.4 base name (strip leading *.; had broken every wildcard order) and makes Route 53/Azure additive so a wildcard cert covering the apex keeps both challenge values at the shared TXT name (Cloudflare already additive). Logic extracted to pure helpers + 19 unit tests; branch feature/acme-wildcard-dns01, deployed to dev-25. About to live-test via Let's Encrypt staging + a Cloudflare zone (*.test.<zone> and test.<zone>+*.test.<zone>).
HTTP-01 challengeVerified live (2026-06-08): ComSign validated an HTTP-01 challenge end-to-end. Required fixing the parent-site rule from Rewrite (HTTP 403.18 across the app-pool boundary) to a 302 Redirect (commit c7a6738), plus IIS Anonymous Auth on the [AllowAnonymous] challenge path.
Live issue→renew→revoke vs a real ACME CADone (2026-06-08) against Comda's ComSign ACME CA — was the single biggest gap for trusting ACME renewal. (A Let's Encrypt-staging dry-run over the public internet is still untried, but the protocol path is now proven against a real EAB ACME server.)

GAPS Implementation gaps — 4 of 5 now closed in code

These were the genuinely not-written items. Four were implemented on branch feature/ssl-renewal-gaps (June 2026) and now sit at ◐ built, pending live verification; only Alteon remains ✗ (blocked on hardware).

AreaGapStateStatus
Renewal / SSL JKS keystore write Done + verified live (2026-06-09) (commit 0692b73) — FileCertPayloadBuilder writes a JKS via BouncyCastle. Confirmed end-to-end on dev-25: the test Tomcat 9 was reconfigured to a JKS keystore, discovered as format=JKS, and renewed (write → service restart → live :9443 served the new MSCA cert).
Renewal / SSL Tomcat 10.1+ <SSLHostConfig> discovery Done + verified live (2026-06-09) (commit 4af1290) — parser reads the nested <SSLHostConfig><Certificate> form. The live dev-25 Tomcat 10.1 (:9444) and 11 (:9445) instances use this form and were both discovered and renewed end-to-end.
Renewal / SSL Tomcat working-dir detection Done + verified live (2026-06-09) (commit afb1e61) — ProcessPortMapper captures the command line; the parser recovers -Dcatalina.base (then cwd, then cwd/.. when cwd ends in bin). The live procrun Tomcats expose no -Dcatalina.base, so the bin→parent fallback is exactly what resolved server.xml in the live run.
ACME DNS providers beyond Cloudflare Done + wiring verified live (commit 03998ab) — Route53DnsProvider (AWSSDK) and AzureDnsProvider (Azure RM SDK) added, wired into the factory + controller validation + Settings UI. On dev-25 (2026-06-08): create→validate→encrypted-at-rest→list→delete confirmed, both render in the UI. Live DNS-01 issuance still pending cloud creds.
Connector Alteon REST write paths Still blocked. Not a code-absence so much as unproven — install/rebind endpoints still carry // TODO: verify against /restdoc/. Clearing it requires a lab Alteon device, which doesn't exist.

NEXT Verify-later backlog

Ranked, ready-to-run verification work. The ACME wildcard DNS-01 live test is next up; items 1–4 are done, 5–6 blocked on external creds/hardware.

ROADMAP Planned / future work

Legacy-parity features deliberately deferred — intended future work, not defects. Most need external deps or hardware. Tracked here so they aren't mistaken for the gaps above.

CONTEXT Broader feature snapshot

Adjacent capabilities, for the team's overall picture (from project memory).

AreaStateNotes
All-in-one server installer (.exe)Clean silent install verified on dev-165 (2026-05-31, ~79s, app serves + whoami authenticated).
PkiAgent remote install via WinRMNew Agent wizard pushes installer over WinRM; uninstall verified live on LMS-MNG-DEV.
Windows Auth + custom authorizationNegotiate/NTLM working on dev-25; AD-group + DB permissions, transitive memberOf fix.
Workflows (replaced Auto Deployment)pfx / directory / renewal sources + connector fan-out; builds + agent tests pass, not live-verified.
Auto-renew monitor sweepsF5 / Alteon / SSL-server sweeps wired; only F5 sweep proven against real renewal.
Code signing (EV "Comda Ltd")signtool flow working; smoke test passed (Valid, SHA-256, DigiCert-timestamped).