Skip to content

Commit ad6c969

Browse files
committed
feat(config): add DcvTimeoutMinutes with CERTINEXT_DCV_TIMEOUT_MINUTES env var override
1 parent 3928720 commit ad6c969

5 files changed

Lines changed: 45 additions & 4 deletions

File tree

CERTInext/CERTInextCAPlugin.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -725,10 +725,10 @@ private async Task<EnrollmentResult> EnrollNewAsync(
725725
{
726726
// SOX CC7.3: bound the entire DCV flow with a hard timeout so a stuck
727727
// DNS provider or extreme propagation delay cannot hold a gateway worker
728-
// thread indefinitely. The timeout is generous (10 minutes) to accommodate
729-
// slow DNS zones; it is separate from the per-request HTTP timeout.
730-
// Log the limit so an auditor can confirm the configured ceiling.
731-
const int dcvTimeoutMinutes = 10;
728+
// thread indefinitely. Configurable via DcvTimeoutMinutes (config or
729+
// CERTINEXT_DCV_TIMEOUT_MINUTES env var); defaults to 10 minutes.
730+
// Log the resolved limit so an auditor can confirm the configured ceiling.
731+
int dcvTimeoutMinutes = _config.GetEffectiveDcvTimeoutMinutes();
732732
_logger.LogInformation(
733733
"Starting DCV for order {OrderNumber}. DcvTimeoutMinutes={Timeout}",
734734
orderNumber, dcvTimeoutMinutes);

CERTInext/CERTInextCAPluginConfig.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,15 @@ public static Dictionary<string, PropertyConfigInfo> GetCAConnectorAnnotations()
196196
Hidden = false,
197197
DefaultValue = 30,
198198
Type = "Number"
199+
},
200+
[Constants.Config.DcvTimeoutMinutes] = new PropertyConfigInfo
201+
{
202+
Comments = $"OPTIONAL: Maximum minutes to wait for the entire DCV flow (DNS publish + propagation + verify) " +
203+
$"before timing out the enrollment. Can also be set via the {Constants.Config.DcvTimeoutMinutesEnvVar} " +
204+
$"environment variable; the env var takes precedence when both are set. Default: 10.",
205+
Hidden = false,
206+
DefaultValue = 10,
207+
Type = "Number"
199208
}
200209
};
201210
}
@@ -470,5 +479,25 @@ public class CERTInextConfig
470479
/// </summary>
471480
[JsonPropertyName("DcvPropagationDelaySeconds")]
472481
public int DcvPropagationDelaySeconds { get; set; } = 30;
482+
483+
/// <summary>
484+
/// Maximum minutes for the entire DCV flow before the enrollment is cancelled.
485+
/// Overridden by the <c>CERTINEXT_DCV_TIMEOUT_MINUTES</c> environment variable when set.
486+
/// Default: 10.
487+
/// </summary>
488+
[JsonPropertyName("DcvTimeoutMinutes")]
489+
public int DcvTimeoutMinutes { get; set; } = 10;
490+
491+
/// <summary>
492+
/// Returns the effective DCV timeout, preferring the environment variable over the
493+
/// config field so operators can adjust the ceiling without a connector reconfiguration.
494+
/// </summary>
495+
public int GetEffectiveDcvTimeoutMinutes()
496+
{
497+
var env = System.Environment.GetEnvironmentVariable(Constants.Config.DcvTimeoutMinutesEnvVar);
498+
if (!string.IsNullOrEmpty(env) && int.TryParse(env, out int envVal) && envVal > 0)
499+
return envVal;
500+
return DcvTimeoutMinutes > 0 ? DcvTimeoutMinutes : 10;
501+
}
473502
}
474503
}

CERTInext/Constants.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ public static class Config
3131
public const string DcvEnabled = "DcvEnabled";
3232
public const string DcvTxtRecordTemplate = "DcvTxtRecordTemplate";
3333
public const string DcvPropagationDelaySeconds = "DcvPropagationDelaySeconds";
34+
public const string DcvTimeoutMinutes = "DcvTimeoutMinutes";
35+
36+
// Environment variable that overrides DcvTimeoutMinutes when set.
37+
public const string DcvTimeoutMinutesEnvVar = "CERTINEXT_DCV_TIMEOUT_MINUTES";
3438

3539
// Auth mode values
3640
public const string AuthModeAccessKey = "AccessKey"; // default; authKey = SHA256(accessKey+ts+txn)

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ The following fields are presented in the Keyfactor Command Management Portal wh
243243
| `IgnoreExpired` | Optional | If `true`, expired certificates are skipped during synchronization and are not imported into Keyfactor Command. Default: `false`. | N/A | `false` |
244244
| `PageSize` | Optional | Number of orders to retrieve per page during synchronization. Default: `100`. Maximum: `500`. Reduce this value if synchronization requests time out. | N/A | `100` |
245245
| `Enabled` | Optional | Enables or disables the CA connector. Setting this to `false` allows the connector record to be created before all credentials are available, without triggering a live connectivity test. Default: `true`. | N/A | `true` |
246+
| `DcvEnabled` | Optional | When `true`, the gateway performs DNS-based Domain Control Validation (DCV) during enrollment for orders that require it. Requires a DNS provider plugin (e.g. `azure-azuredns-dnsplugin`) to be deployed on the gateway. Default: `false`. | N/A | `false` |
247+
| `DcvTxtRecordTemplate` | Optional | Format string for the DNS TXT record hostname published during DCV. `{0}` is replaced with the domain being validated. Default: `_emsign-validation.{0}`. | N/A | `_emsign-validation.{0}` |
248+
| `DcvPropagationDelaySeconds` | Optional | Seconds to wait after publishing the DNS TXT record before asking CERTInext to verify it. Increase for zones with slow propagation. Default: `30`. | N/A | `30` |
249+
| `DcvTimeoutMinutes` | Optional | Maximum minutes to wait for the entire DCV flow (DNS publish + propagation + verify) before cancelling the enrollment. Can also be set via the `CERTINEXT_DCV_TIMEOUT_MINUTES` environment variable; the environment variable takes precedence when both are set. Default: `10`. | N/A | `10` |
246250
247251
> Note: `AccountNumber` and group-level identifiers are distinct values. The `AccountNumber` is your top-level user account identifier. CERTInext groups (cost centers or departments) each have their own `groupNumber`, which is passed per-order and is separate from any organization number displayed on the Organizations page.
248252

docsource/configuration.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ The following fields are presented in the Keyfactor Command Management Portal wh
113113
| `IgnoreExpired` | Optional | If `true`, expired certificates are skipped during synchronization and are not imported into Keyfactor Command. Default: `false`. | N/A | `false` |
114114
| `PageSize` | Optional | Number of orders to retrieve per page during synchronization. Default: `100`. Maximum: `500`. Reduce this value if synchronization requests time out. | N/A | `100` |
115115
| `Enabled` | Optional | Enables or disables the CA connector. Setting this to `false` allows the connector record to be created before all credentials are available, without triggering a live connectivity test. Default: `true`. | N/A | `true` |
116+
| `DcvEnabled` | Optional | When `true`, the gateway performs DNS-based Domain Control Validation (DCV) during enrollment for orders that require it. Requires a DNS provider plugin (e.g. `azure-azuredns-dnsplugin`) to be deployed on the gateway. Default: `false`. | N/A | `false` |
117+
| `DcvTxtRecordTemplate` | Optional | Format string for the DNS TXT record hostname published during DCV. `{0}` is replaced with the domain being validated. Default: `_emsign-validation.{0}`. | N/A | `_emsign-validation.{0}` |
118+
| `DcvPropagationDelaySeconds` | Optional | Seconds to wait after publishing the DNS TXT record before asking CERTInext to verify it. Increase for zones with slow propagation. Default: `30`. | N/A | `30` |
119+
| `DcvTimeoutMinutes` | Optional | Maximum minutes to wait for the entire DCV flow (DNS publish + propagation + verify) before cancelling the enrollment. Can also be set via the `CERTINEXT_DCV_TIMEOUT_MINUTES` environment variable; the environment variable takes precedence when both are set. Default: `10`. | N/A | `10` |
116120

117121
> Note: `AccountNumber` and group-level identifiers are distinct values. The `AccountNumber` is your top-level user account identifier. CERTInext groups (cost centers or departments) each have their own `groupNumber`, which is passed per-order and is separate from any organization number displayed on the Organizations page.
118122

0 commit comments

Comments
 (0)