Example #1
0
        /// <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());
        }
Example #2
0
        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));
        }
Example #6
0
        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));
            }
        }
Example #7
0
        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));
            }
        }