Skip to content

Commit 281c624

Browse files
committed
docs(enroll): scope the CERTInext SAN measurements to the sandbox
The probe ran against sandbox-us, but the comments and the non-DNS warning read as though the behaviour were established generally. The customer this fix is for is on production, so the distinction matters. * The non-DNS finding (CERTInext accepts an email/IP/URI verbatim as an order domain rather than rejecting it) is explicitly sandbox-only and flagged unverified on production. The operator-facing warning no longer promises a parked order — it names the offending SANs and says the order will either be rejected or fail validation, noting what the sandbox did. * The CN-collapse finding is likewise marked sandbox-only, which strengthens rather than weakens the case for de-duplicating on our side: we should not depend on undocumented CA behaviour we have not seen in production. * The CSR-SAN finding — CERTInext ignores the CSR's subjectAltName entirely — is noted as corroborated by production independently of the probe: the report that prompted this work was a production UCC order whose CSR carried the SANs and whose certificate came back holding only the CN. * Probe header now says how to re-run against production, and warns that product numbering is per-account (Constants.Products holds defaults, not guarantees). No functional change.
1 parent 35deb42 commit 281c624

3 files changed

Lines changed: 40 additions & 23 deletions

File tree

CERTInext.IntegrationTests/SanSubmissionProbeTests.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,16 @@
1919
// and issuance to complete.
2020
//
2121
// ---------------------------------------------------------------------------------------
22-
// MEASURED RESULTS — sandbox-us, account 4951571271, product 844 (OV SSL UCC), 2026-08-12.
23-
// (Product 840 / DV UCC is not enabled on that account: "Invalid Product Code".)
22+
// MEASURED RESULTS — SANDBOX ONLY: sandbox-us, account 4951571271, product 844 (OV SSL UCC),
23+
// 2026-08-12. (Product 840 / DV UCC is not enabled on that account: "Invalid Product Code".)
24+
//
25+
// These are sandbox observations. Re-run against production before treating B or C as
26+
// settled there — point ~/.env_certinext at the production account and set
27+
// CERTINEXT_SAN_PROBE_PRODUCTS to a UCC code that account can actually order (product
28+
// numbering is per-account; the codes in Constants.Products are defaults, not guarantees).
29+
// Finding A and the CSR-SAN result below are separately corroborated by production: the
30+
// customer report that prompted this work was a production UCC order whose CSR carried the
31+
// SANs and whose issued certificate held only the CN.
2432
//
2533
// A. CONFIRMED. additionalDomains is what puts extra names on the order. Submitting
2634
// CN + extra1.<cn> registered BOTH domains.

CERTInext/CERTInextCAPlugin.cs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,11 +2130,14 @@ private static int MapRevocationReasonStringToCode(string reason)
21302130
/// reaches the order.
21312131
///
21322132
/// Parsing the CSR here is not redundant with sending the CSR to CERTInext.
2133-
/// CERTInext ignores the CSR's subjectAltName extension outright — measured in
2134-
/// <c>SanSubmissionProbeTests</c>: a CSR carrying two DNS names, submitted with
2135-
/// <c>additionalDomains</c> omitted, produced an order with only the CN registered.
2136-
/// Re-submitting the CSR's names through <c>additionalDomains</c> is the only way a
2137-
/// SAN that exists solely in the CSR reaches the issued certificate.
2133+
/// CERTInext ignores the CSR's subjectAltName extension outright — measured on the
2134+
/// US sandbox in <c>SanSubmissionProbeTests</c>: a CSR carrying two DNS names,
2135+
/// submitted with <c>additionalDomains</c> omitted, produced an order with only the
2136+
/// CN registered. Production behaves the same way: the customer report that prompted
2137+
/// this fix was a production UCC order whose CSR carried the SANs and whose issued
2138+
/// certificate held only the CN. Re-submitting the CSR's names through
2139+
/// <c>additionalDomains</c> is the only way a SAN that exists solely in the CSR
2140+
/// reaches the issued certificate.
21382141
///
21392142
/// History (UCC SANs silently dropped): the gateway keys this dictionary
21402143
/// <c>dnsname</c>, not <c>dns</c>. <see cref="MapSanType"/> did not recognize
@@ -2212,22 +2215,27 @@ void Add(string type, string value)
22122215
// them would issue a certificate silently missing names the subscriber asked for,
22132216
// which is the worse failure.
22142217
//
2215-
// Measured behaviour (SanSubmissionProbeTests, product 844, 2026-08-12): CERTInext
2216-
// does NOT reject these at order placement. It accepts the order and registers the
2217-
// value verbatim as an order domain — an email address, an IP literal and a URI all
2218-
// came back as domainVerification keys. The order then cannot pass domain validation,
2219-
// so it parks pending instead of failing fast. Say that plainly, because "the
2220-
// enrollment did not error but the order will never issue" is the confusing case.
2218+
// Measured on the US SANDBOX only (SanSubmissionProbeTests, product 844,
2219+
// 2026-08-12): CERTInext did NOT reject these at order placement. It accepted the
2220+
// order and registered the value verbatim as an order domain — an email address, an
2221+
// IP literal and a URI all came back as domainVerification keys. The order then
2222+
// cannot pass domain validation, so it parks pending instead of failing fast.
2223+
//
2224+
// Production is UNVERIFIED for this case and may reject the order outright instead.
2225+
// The warning below therefore describes the sandbox outcome as the expected one
2226+
// without promising it: either way the operator is told which SANs are the problem,
2227+
// which is the part that matters for diagnosis.
22212228
var nonDns = result.Where(s => !string.Equals(s.Type, "dns", StringComparison.OrdinalIgnoreCase)).ToList();
22222229
if (nonDns.Count > 0)
22232230
{
22242231
_logger.LogWarning(
22252232
"{Count} requested SAN(s) are not DNS names: {Sans}. CERTInext's additionalDomains " +
2226-
"field takes domain names, and it accepts these verbatim rather than rejecting them — " +
2227-
"the order will be created but is not expected to pass domain validation, so it will " +
2228-
"sit pending rather than issue. They are submitted rather than dropped on purpose: a " +
2229-
"visibly stuck order is preferable to a certificate issued without names the subscriber " +
2230-
"requested. Remove them from the CSR or the enrollment pattern if the order should proceed.",
2233+
"field takes domain names, so this order will either be rejected outright or be " +
2234+
"created and then fail domain validation and sit pending — on the US sandbox it was " +
2235+
"accepted verbatim and parked pending. They are submitted rather than dropped on " +
2236+
"purpose: a visible failure is preferable to a certificate issued without names the " +
2237+
"subscriber requested. Remove them from the CSR or the enrollment pattern if the " +
2238+
"order should proceed.",
22312239
nonDns.Count, string.Join("; ", nonDns.Select(s => $"{s.Type}:{s.Value}")));
22322240
}
22332241

CERTInext/Client/CERTInextClient.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,11 +1487,12 @@ private static string ExtractCnFromSubject(string subject)
14871487
/// before we get here.
14881488
///
14891489
/// <paramref name="domainName"/> is the value already going out as the order's primary
1490-
/// domain, and Command normally includes the CN in the SAN set as well. CERTInext was
1491-
/// measured to collapse that repetition itself (SanSubmissionProbeTests: CN submitted
1492-
/// twice came back registered once), so excluding it here is defence in depth rather
1493-
/// than a correctness requirement — it keeps the submitted body matching what we log
1494-
/// and avoids depending on undocumented CA-side de-duplication.
1490+
/// domain, and Command normally includes the CN in the SAN set as well. On the US
1491+
/// sandbox CERTInext was measured to collapse that repetition itself
1492+
/// (SanSubmissionProbeTests: CN submitted twice came back registered once), but that is
1493+
/// undocumented and unverified against production — which is exactly why we exclude it
1494+
/// here rather than relying on CA-side de-duplication. It also keeps the submitted body
1495+
/// matching what we log.
14951496
/// </summary>
14961497
private List<string> BuildAdditionalDomains(
14971498
System.Collections.Generic.List<SanEntry> sans,

0 commit comments

Comments
 (0)