Skip to main content

Overview

Validation.PackageSigning.RevalidateCertificate is a standalone .NET 4.7.2 console application that runs as a scheduled Windows service. It performs two complementary maintenance tasks that keep the NuGet package-signing trust model up to date:
  1. Signature promotion — scans PackageSignature rows that are in the InGracePeriod status and advances any that are now fully promotable to Valid.
  2. Certificate revalidation — finds end-certificates whose last verification timestamp is older than the configured staleness window and re-enqueues them for fresh verification by the certificate validation pipeline.
The job is designed to run repeatedly in short bursts; each execution processes one configurable batch of signatures and one configurable batch of certificates, then exits. Multiple executions are expected before the backlog is fully cleared.
Revoked certificates are explicitly excluded from revalidation. Certificate Authorities do not drop revocation status, so re-checking a revoked certificate would be wasteful and could produce misleading results.

Upstream: Package Signing Pipeline

Packages receive InGracePeriod signatures when they are first signed. This job promotes those signatures to Valid once all certificate chain checks pass.

Downstream: Certificate Validator

Certificate revalidation messages are published to an Azure Service Bus topic. A separate certificate validator service consumes those messages and updates EndCertificate status in the shared validation database.

Shared DB: Validation Entities

Reads and writes PackageSignature, EndCertificate, and EndCertificateValidation rows via IValidationEntitiesContext — the EF6-based context owned by Validation.PackageSigning.Core.

Observability: Application Insights

All major operations are wrapped with duration tracking and error metrics via ITelemetryService, surfacing data to Application Insights through NuGet.Services.Logging.

Key Files and Classes

FileClass / InterfacePurpose
Program.csProgramEntry point; delegates immediately to NuGet.Jobs.JobRunner.
Job.csJob : ValidationJobBaseWires DI registrations and implements the two-phase Run() loop (promote then revalidate).
CertificateRevalidator.csCertificateRevalidatorCore orchestration logic for both signature promotion and certificate revalidation, including polling and timeout handling.
ICertificateRevalidator.csICertificateRevalidatorAbstraction over PromoteSignaturesAsync() and RevalidateStaleCertificatesAsync().
ValidateCertificateEnqueuer.csValidateCertificateEnqueuerBuilds a CertificateValidationMessage and sends it to the Azure Service Bus topic via ITopicClient.
IValidateCertificateEnqueuer.csIValidateCertificateEnqueuerAbstraction over the Service Bus enqueue operation.
RevalidationConfiguration.csRevalidationConfigurationStrongly-typed POCO for all tuneable thresholds (batch sizes, timeouts, poll intervals). Bound to the "RevalidateJob" config section.
TelemetryService.csTelemetryServiceWraps ITelemetryClient with named metrics prefixed RevalidateCertificate.*.
ITelemetryService.csITelemetryServiceContract for duration tracking and warning/timeout counters.
Scripts/PostDeploy.ps1Octopus Deploy post-deployment script that installs the job as a Windows service using NSSM.

Dependencies

Internal Project References

ProjectAssemblyRole
Validation.Common.JobNuGet.Services.Validation.Common.JobValidationJobBase, DI bootstrap, NuGet.Jobs.JobRunner integration.
Validation.PackageSigning.CoreNuGet.Jobs.Validation.PackageSigningShared signing models (PackageSignature, EndCertificate), IValidationEntitiesContext, and CertificateValidationMessageSerializer.

Transitive NuGet Packages (key ones)

PackageConsumed ViaPurpose
Autofac / Autofac.Extensions.DependencyInjectionValidation.Common.JobDI container used by the job host.
Microsoft.Extensions.DependencyInjectionValidation.Common.JobIServiceCollection registration surface.
Microsoft.Extensions.Options.ConfigurationExtensionsValidation.Common.JobBinds RevalidationConfiguration from IConfiguration.
NuGet.Services.ServiceBusValidation.Common.JobITopicClient, TopicClientWrapper, IBrokeredMessageSerializer<T>.
NuGet.Services.LoggingValidation.Common.JobITelemetryClient (Application Insights wrapper).
NuGet.Services.ValidationValidation.PackageSigning.CoreEF6 entity types and IValidationEntitiesContext.
NuGet.Jobs.CommonValidation.Common.JobJobRunner, ValidationJobBase base class.

Configuration Reference

All settings live under the "RevalidateJob" key in the job’s configuration source.
"RevalidateJob": {
  "SignaturePromotionScanSize": 500,
  "SignaturePromotionBatchSize": 200,
  "CertificateRevalidationBatchSize": 100,
  "RevalidationPeriodForCertificates": "7.00:00:00",
  "CertificateRevalidationPollTime": "00:00:10",
  "CertificateRevalidationTrackAfter": "00:05:00",
  "CertificateRevalidationTimeout": "00:30:00"
}
SettingTypeDescription
SignaturePromotionScanSizeintMax signatures fetched per inner scan loop iteration.
SignaturePromotionBatchSizeintTotal promotable signatures targeted per job run.
CertificateRevalidationBatchSizeintMax certificates revalidated per job run.
RevalidationPeriodForCertificatesTimeSpanMinimum age of LastVerificationTime before a cert is considered stale.
CertificateRevalidationPollTimeTimeSpanDelay between database polls while waiting for validations to complete.
CertificateRevalidationTrackAfterTimeSpanElapsed time after which a slow-validation warning metric is emitted.
CertificateRevalidationTimeoutTimeSpanHard ceiling on how long the job waits for in-flight validations.

Notable Patterns and Implementation Details

Chunked, iterative design. Neither PromoteSignaturesAsync nor RevalidateStaleCertificatesAsync processes every eligible record in a single pass. The job is expected to be scheduled frequently (e.g. every few minutes) so that the total work is spread across many executions without holding long-running transactions or overwhelming Service Bus.
Signature promotion uses a nested scan loop. FindPromotableSignaturesAsync pages through InGracePeriod author signatures in creation order, accumulating promotable ones until the batch size is reached or all candidates are exhausted. This avoids a single unbounded query while still being precise about which signatures qualify.
Certificate revalidation is synchronous within a run. After enqueuing all certificate validation messages and persisting EndCertificateValidation rows, the job polls the database in a tight loop until all rows transition away from null status — or the configured timeout is hit. If the downstream validator is slow or unavailable, the job will log an error and emit a timeout metric but will not retry in the same execution.
All-or-nothing Service Bus enqueue. StartCertificateValidationsAsync fans out all enqueue tasks with Task.WhenAll before calling SaveChangesAsync. If any single enqueue fails, SaveChangesAsync is never called and no EndCertificateValidation rows are persisted — ensuring the database and queue stay consistent. However, partially-sent messages (if the exception surfaces mid-fan-out) are not rolled back from the bus.
The revalidateRevokedCertificate: false and sendCheckValidator: false flags on CertificateValidationMessage are intentional: this job never re-checks revoked certs and does not trigger the secondary “check validator” workflow. These are hard-coded, not configurable.

Telemetry Metrics

Metric NameKindEmitted When
RevalidateCertificate.PromoteSignatureDurationDurationWraps the entire signature promotion phase.
RevalidateCertificate.CertificateRevalidationDurationDurationWraps the entire certificate revalidation phase including polling.
RevalidateCertificate.CertificateRevalidationTakingTooLongCounterEmitted each poll cycle after CertificateRevalidationTrackAfter elapses.
RevalidateCertificate.CertificateRevalidationReachedTimeoutCounterEmitted once when CertificateRevalidationTimeout is exceeded.

Deployment

The job ships as a NuGet package (Validation.PackageSigning.RevalidateCertificate) containing the compiled net472 binaries and four deployment artifacts:
  • Scripts/PreDeploy.ps1 — pre-deployment teardown hook (Octopus Deploy).
  • Scripts/PostDeploy.ps1 — installs or reconfigures the job as a Windows service via NSSM.
  • Scripts/Functions.ps1 — shared PowerShell helpers (Install-NuGetService).
  • Scripts/nssm.exe — Non-Sucking Service Manager binary, bundled for zero-dependency service installation.