/// <summary> /// The pattern used for the StartAsync: /// 1. Check if a validation was already started /// 2. Only if a validation was not started queue the message to be processed. /// 3. After the message is queued, update the ValidatorStatus for the <paramref name="request"/>. /// </summary> /// <param name="request">The request to be send to the validator job queue.</param> /// <returns>The validation status.</returns> public async Task <INuGetValidationResponse> StartAsync(INuGetValidationRequest request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var validatorStatus = await _validatorStateService.GetStatusAsync(request); // See issue https://github.com/NuGet/NuGetGallery/issues/6249 validatorStatus.ValidatingType = ValidatingType.SymbolPackage; if (validatorStatus.State != ValidationStatus.NotStarted) { _logger.LogWarning( "Symbol validation for {PackageId} {PackageNormalizedVersion} has already started.", request.PackageId, request.PackageVersion); return(validatorStatus.ToNuGetValidationResponse()); } // Due to race conditions or failure of method TryAddValidatorStatusAsync the same message can be enqueued multiple times // Log this information to postmortem evaluate this behavior _telemetryService.TrackSymbolsMessageEnqueued(request.PackageId, request.PackageVersion, ValidatorName.SymbolsValidator, request.ValidationId); await _symbolMessageEnqueuer.EnqueueSymbolsValidationMessageAsync(request); var result = await _validatorStateService.TryAddValidatorStatusAsync(request, validatorStatus, ValidationStatus.Incomplete); return(result.ToNuGetValidationResponse()); }
private async Task <ValidatorStatus> StartInternalAsync(INuGetValidationRequest request) { // Check that this is the first validation for this specific request. var validatorStatus = await _validatorStateService.GetStatusAsync(request); if (validatorStatus.State != ValidationStatus.NotStarted) { _logger.LogWarning( "Package Signing validation with validationId {ValidationId} ({PackageId} {PackageVersion}) has already started.", request.ValidationId, request.PackageId, request.PackageVersion); return(validatorStatus); } // Kick off the verification process. Note that the jobs will not verify the package until the // state of this validator has been persisted to the database. using (_telemetryService.TrackDurationToStartPackageSigningValidator(request.PackageId, request.PackageVersion)) { await _signatureVerificationEnqueuer.EnqueueProcessSignatureAsync(request, RequiresRepositorySignature); return(await _validatorStateService.TryAddValidatorStatusAsync(request, validatorStatus, ValidationStatus.Incomplete)); } }
public async Task <IValidationResult> StartAsync(IValidationRequest request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var validatorStatus = await _validatorStateService.GetStatusAsync(request); if (validatorStatus.State != ValidationStatus.NotStarted) { _logger.LogWarning( "Scan only validation with validation Id {ValidationId} ({PackageId} {PackageVersion}) has already started.", request.ValidationId, request.PackageId, request.PackageVersion); return(validatorStatus.ToValidationResult()); } if (ShouldSkipScan(request)) { return(ValidationResult.Succeeded); } await _scanAndSignEnqueuer.EnqueueScanAsync(request.ValidationId, request.NupkgUrl); var result = await _validatorStateService.TryAddValidatorStatusAsync(request, validatorStatus, ValidationStatus.Incomplete); return(result.ToValidationResult()); }
public async Task <INuGetValidationResponse> StartAsync(INuGetValidationRequest request) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var processorStatus = await GetProcessorStatusAsync(request); if (processorStatus.State != ValidationStatus.NotStarted) { _logger.LogWarning( "Scan and Sign validation with validation Id {ValidationId} ({PackageId} {PackageVersion}) has already started.", request.ValidationId, request.PackageId, request.PackageVersion); return(processorStatus.ToNuGetValidationResponse()); } var owners = FindPackageOwners(request); if (await ShouldRepositorySignAsync(request)) { _logger.LogInformation( "Repository signing {PackageId} {PackageVersion} with {ServiceIndex} and {Owners}", request.PackageId, request.PackageVersion, _configuration.V3ServiceIndexUrl, owners); await _scanAndSignEnqueuer.EnqueueScanAndSignAsync(request.ValidationId, request.NupkgUrl, _configuration.V3ServiceIndexUrl, owners); } else { if (ShouldSkipScan(request)) { return(NuGetValidationResponse.Succeeded); } await _scanAndSignEnqueuer.EnqueueScanAsync(request.ValidationId, request.NupkgUrl); } var result = await _validatorStateService.TryAddValidatorStatusAsync(request, processorStatus, ValidationStatus.Incomplete); return(result.ToNuGetValidationResponse()); }
public async Task <ValidationStatus> StartValidationAsync(IValidationRequest request) { // Check that this is the first validation for this specific request. var validatorStatus = await _validatorStateService.GetStatusAsync(request); if (validatorStatus.State != ValidationStatus.NotStarted) { _logger.LogWarning( "Package Signing validation with validationId {ValidationId} ({PackageId} {PackageVersion}) has already started.", request.ValidationId, request.PackageId, request.PackageVersion); return(validatorStatus.State); } // Kick off the verification process. Note that the jobs will not verify the package until the // state of this validator has been persisted to the database. await _signatureVerificationEnqueuer.EnqueueVerificationAsync(request); return(await _validatorStateService.TryAddValidatorStatusAsync(request, validatorStatus, ValidationStatus.Incomplete)); }
private async Task <ValidatorStatus> StartInternalAsync(IValidationRequest request) { var status = await _validatorStateService.GetStatusAsync(request); if (status.State != ValidationStatus.NotStarted) { _logger.LogWarning( "Package Certificates validation with validationId {ValidationId} ({PackageId} {PackageVersion}) has already started.", request.ValidationId, request.PackageId, request.PackageVersion); return(status); } var package = await FindPackageSigningStateAsync(request); if (package.SigningStatus == PackageSigningStatus.Unsigned) { _logger.LogInformation( "Package {PackageId} {PackageVersion} is unsigned, no additional validations necessary", request.PackageId, request.PackageVersion); return(await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Succeeded)); } else if (package.SigningStatus == PackageSigningStatus.Invalid) { // Do NOT validate the package if its status is already marked as invalid. To revalidate the package, // it MUST first pass the PackageSigningValidator. The PackageSigningValidator will mark the package's // signing status as Valid, thereby allowing this validator to revalidate the package if necessary. _logger.LogError( Error.PackageCertificateValidationAlreadyFailed, "Package {PackageId} {PackageVersion} has already failed validation", request.PackageId, request.PackageVersion); return(await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Failed)); } var isRevalidationRequest = await _validatorStateService.IsRevalidationRequestAsync(request); // Find the signatures used to sign the package and see if any certificates known to be revoked // invalidate any of these signatures. Note that a revoked certificate is assumed to remain // revoked forever. var signature = await FindSignatureAsync(request); if (ShouldInvalidateSignature(signature, isRevalidationRequest)) { InvalidatePackageSignature(request, package, signature); return(await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Failed)); } // Find the certificates that must be validated. A certificate must be validated if it has never been validated, // or, if it hasn't been validated in a while (and it hasn't been revoked). var certificates = FindCertificatesToValidateAsync(signature, isRevalidationRequest); if (certificates.Any()) { var stopwatch = Stopwatch.StartNew(); await StartCertificateValidationsAsync(request, certificates); var result = await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Incomplete); _telemetryService.TrackDurationToStartPackageCertificatesValidator(stopwatch.Elapsed); return(result); } else { PromoteSignature(request, signature); return(await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Succeeded)); } }
public async Task <ValidationStatus> StartValidationAsync(IValidationRequest request) { var status = await _validatorStateService.GetStatusAsync(request); if (status.State != ValidationStatus.NotStarted) { _logger.LogWarning( "Package Certificates validation with validationId {ValidationId} ({PackageId} {PackageVersion}) has already started.", request.ValidationId, request.PackageId, request.PackageVersion); return(status.State); } var package = await FindPackageSigningStateAsync(request); if (package.SigningStatus == PackageSigningStatus.Unsigned) { _logger.LogInformation( "Package {PackageId} {PackageVersion} is unsigned, no additional validations necessary", request.PackageId, request.PackageVersion); return(await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Succeeded)); } else if (package.SigningStatus == PackageSigningStatus.Invalid) { // Do NOT validate the package if its status is already marked as invalid. To revalidate the package, // it MUST first pass the PackageSigningValidator. The PackageSigningValidator will mark the package's // signing status as Valid, thereby allowing this validator to revalidate the package if necessary. _logger.LogError( Error.PackageCertificateValidationAlreadyFailed, "Package {PackageId} {PackageVersion} has already failed validation", request.PackageId, request.PackageVersion); return(await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Failed)); } var isRevalidationRequest = await _validatorStateService.IsRevalidationRequestAsync(request); // Find the signatures used to sign the package and see if any certificates known to be revoked // invalidate any of these signatures. Note that a revoked certificate is assumed to remain // revoked forever. var signatures = await FindSignaturesAsync(request); var invalidSignatures = FindSignaturesToInvalidate(signatures, isRevalidationRequest); if (invalidSignatures.Any()) { InvalidatePackageSignatures(request, package, invalidSignatures); return(await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Failed)); } // Find the certificates that must be validated. A certificate must be validated if it has never been validated, // or, if it hasn't been validated in a while (and it hasn't been revoked). var certificates = FindCertificatesToValidateAsync(signatures, isRevalidationRequest); if (certificates.Any()) { await StartCertificateValidationsAsync(request, certificates); return(await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Incomplete)); } else { _logger.LogInformation( "All certificates for package {PackageId} {PackageVersion} have already been validated, no additional validations necessary", request.PackageId, request.PackageVersion); // Promote signatures out of the "Unknown" state to either "Valid" or "InGracePeriod". PromoteSignatures(signatures); return(await _validatorStateService.TryAddValidatorStatusAsync(request, status, ValidationStatus.Succeeded)); } }