public async Task WaitsForPackageAvailabilityInGalleryDBWithCheckValidator()
        {
            var messageData             = PackageValidationMessageData.NewCheckValidator(Guid.NewGuid());
            var validationConfiguration = new ValidationConfiguration();
            var validationSet           = new PackageValidationSet {
                PackageKey = 42, ValidatingType = ValidatingType.SymbolPackage
            };

            ValidationSetProviderMock
            .Setup(ps => ps.TryGetParentValidationSetAsync(messageData.CheckValidator.ValidationId))
            .ReturnsAsync(validationSet)
            .Verifiable();
            CoreSymbolPackageServiceMock
            .Setup(ps => ps.FindPackageByKey(validationSet.PackageKey))
            .Returns <SymbolPackage>(null)
            .Verifiable();

            var handler = CreateHandler();

            var result = await handler.HandleAsync(messageData);

            ValidationSetProviderMock.Verify(
                ps => ps.TryGetParentValidationSetAsync(messageData.CheckValidator.ValidationId),
                Times.Once);
            CoreSymbolPackageServiceMock.Verify(
                ps => ps.FindPackageByKey(validationSet.PackageKey),
                Times.Once);

            Assert.False(result, "The handler should not have succeeded.");
        }
Пример #2
0
        public async Task DropsMessageIfPackageIsSoftDeletedForCheckValidator()
        {
            var messageData             = PackageValidationMessageData.NewCheckValidator(Guid.NewGuid());
            var validationConfiguration = new ValidationConfiguration();
            var package = new Package {
                Key = 42, PackageStatusKey = PackageStatus.Deleted
            };
            var packageValidatingEntity = new PackageValidatingEntity(package);
            var validationSet           = new PackageValidationSet {
                PackageKey = package.Key, ValidatingType = ValidatingType.Package
            };

            ValidationSetProviderMock
            .Setup(ps => ps.TryGetParentValidationSetAsync(messageData.CheckValidator.ValidationId))
            .ReturnsAsync(validationSet)
            .Verifiable();
            CorePackageServiceMock
            .Setup(ps => ps.FindPackageByKey(package.Key))
            .Returns(packageValidatingEntity);

            var handler = CreateHandler();

            var result = await handler.HandleAsync(messageData);

            Assert.True(result);
            ValidationSetProviderMock.Verify(
                vsp => vsp.TryGetParentValidationSetAsync(messageData.CheckValidator.ValidationId),
                Times.Once);
            CorePackageServiceMock.Verify(
                ps => ps.FindPackageByKey(package.Key),
                Times.Once);
        }
Пример #3
0
            public HandleCheckValidatorAsync(ITestOutputHelper output) : base(output)
            {
                ValidationId = new Guid("1f25a05c-4bbb-4366-a0bf-d9acef69cca1");
                Message      = PackageValidationMessageData.NewCheckValidator(ValidationId);

                ValidationSetProvider
                .Setup(x => x.TryGetParentValidationSetAsync(It.IsAny <Guid>()))
                .ReturnsAsync(() => ValidationSet);
            }
            public void ProducesExpectedMessageForCheckValidator()
            {
                // Arrange
                var input = PackageValidationMessageData.NewCheckValidator(ValidationId);

                // Act
                var output = _target.SerializePackageValidationMessageData(input);

                // Assert
                Assert.Contains(SchemaVersionKey, output.Properties.Keys);
                Assert.Equal(SchemaVersion1, output.Properties[SchemaVersionKey]);
                Assert.Contains(SchemaName, output.Properties.Keys);
                Assert.Equal(CheckValidatorType, output.Properties[SchemaName]);
                var body = output.GetBody();

                Assert.Equal(TestData.SerializedCheckValidatorData, body);
            }
        public async Task WaitsForValidationSetAvailabilityInValidationDBWithCheckValidator()
        {
            var messageData             = PackageValidationMessageData.NewCheckValidator(Guid.NewGuid());
            var validationConfiguration = new ValidationConfiguration();

            ValidationSetProviderMock
            .Setup(ps => ps.TryGetParentValidationSetAsync(messageData.CheckValidator.ValidationId))
            .ReturnsAsync((PackageValidationSet)null)
            .Verifiable();

            var handler = CreateHandler();

            var result = await handler.HandleAsync(messageData);

            ValidationSetProviderMock.Verify(
                ps => ps.TryGetParentValidationSetAsync(messageData.CheckValidator.ValidationId),
                Times.Once);

            Assert.False(result, "The handler should not have succeeded.");
        }
        public async Task RejectsNonSymbolPackageValidationSetWithCheckValidator()
        {
            var messageData             = PackageValidationMessageData.NewCheckValidator(Guid.NewGuid());
            var validationConfiguration = new ValidationConfiguration();
            var validationSet           = new PackageValidationSet {
                PackageKey = 42, ValidatingType = ValidatingType.Package
            };

            ValidationSetProviderMock
            .Setup(ps => ps.TryGetParentValidationSetAsync(messageData.CheckValidator.ValidationId))
            .ReturnsAsync(validationSet)
            .Verifiable();

            var handler = CreateHandler();

            var result = await handler.HandleAsync(messageData);

            ValidationSetProviderMock.Verify(
                ps => ps.TryGetParentValidationSetAsync(messageData.CheckValidator.ValidationId),
                Times.Once);

            Assert.False(result, "The handler should not have succeeded.");
        }
Пример #7
0
        private async Task <bool> HandleAsync(SignatureValidationMessage message, CancellationToken cancellationToken)
        {
            using (_logger.BeginScope("Handling signature validation message for package {PackageId} {PackageVersion}, validation {ValidationId}",
                                      message.PackageId,
                                      message.PackageVersion,
                                      message.ValidationId))
            {
                // Find the signature validation entity that matches this message.
                var validation = await _validatorStateService.GetStatusAsync(message.ValidationId);

                // A signature validation should be queued with ValidatorState == Incomplete.
                if (validation == null)
                {
                    _logger.LogInformation(
                        "Could not find validation entity, requeueing (package: {PackageId} {PackageVersion}, validationId: {ValidationId})",
                        message.PackageId,
                        message.PackageVersion,
                        message.ValidationId);

                    // Message may be retried.
                    return(false);
                }
                else if (validation.State == ValidationStatus.NotStarted)
                {
                    _logger.LogWarning(
                        "Unexpected signature verification status '{ValidatorState}' when 'Incomplete' was expected, requeueing (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                        validation.State,
                        message.PackageId,
                        message.PackageVersion,
                        message.ValidationId);

                    // Message may be retried.
                    return(false);
                }
                else if (validation.State != ValidationStatus.Incomplete)
                {
                    _logger.LogWarning(
                        "Terminal signature verification status '{ValidatorState}' when 'Incomplete' was expected, dropping message (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                        validation.State,
                        message.PackageId,
                        message.PackageVersion,
                        message.ValidationId);

                    // Consume the message.
                    return(true);
                }

                // Validate package
                using (var packageStream = await _packageDownloader.DownloadAsync(message.NupkgUri, cancellationToken))
                {
                    var result = await _signatureValidator.ValidateAsync(
                        validation.PackageKey,
                        packageStream,
                        message,
                        cancellationToken);

                    validation.State = result.State;

                    // Save any issues if the resulting state is terminal.
                    if (validation.State == ValidationStatus.Failed ||
                        validation.State == ValidationStatus.Succeeded)
                    {
                        validation.ValidatorIssues = validation.ValidatorIssues ?? new List <ValidatorIssue>();
                        foreach (var issue in result.Issues)
                        {
                            validation.ValidatorIssues.Add(new ValidatorIssue
                            {
                                IssueCode = issue.IssueCode,
                                Data      = issue.Serialize(),
                            });
                        }
                    }

                    // Save the .nupkg URL if the resulting state is successful.
                    if (validation.State == ValidationStatus.Succeeded &&
                        result.NupkgUri != null)
                    {
                        validation.NupkgUrl = result.NupkgUri.AbsoluteUri;
                    }
                }

                // The signature validator should do all of the work to bring this validation to its completion.
                if (validation.State != ValidationStatus.Succeeded &&
                    validation.State != ValidationStatus.Failed)
                {
                    _logger.LogError("The signature validator should have set the status 'Succeeded' or 'Failed', not " +
                                     "'{ValidatorState}' (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                                     validation.State,
                                     message.PackageId,
                                     message.PackageVersion,
                                     message.ValidationId);

                    return(false);
                }

                // Save the resulting validation status.
                var completed = await SaveStatusAsync(validation, message);

                if (completed && _featureFlagService.IsQueueBackEnabled())
                {
                    _logger.LogInformation("Sending queue-back message for validation {ValidationId}.", message.ValidationId);
                    var messageData = PackageValidationMessageData.NewCheckValidator(message.ValidationId);
                    await _validationEnqueuer.SendMessageAsync(messageData);
                }

                return(completed);
            }
        }
        /// <summary>
        /// Perform the certificate validation request, including online revocation checks.
        /// </summary>
        /// <param name="message">The message requesting the certificate validation.</param>
        /// <returns>Whether the validation completed. If false, the validation should be retried later.</returns>
        public async Task <bool> HandleAsync(CertificateValidationMessage message)
        {
            using (_logger.BeginScope("Handling validate certificate message {CertificateKey} {ValidationId}",
                                      message.CertificateKey,
                                      message.ValidationId))
            {
                var validation = await _certificateValidationService.FindCertificateValidationAsync(message);

                if (validation == null)
                {
                    _logger.LogInformation(
                        "Could not find a certificate validation entity, failing (certificate: {CertificateKey} validation: {ValidationId})",
                        message.CertificateKey,
                        message.ValidationId);

                    return(false);
                }

                if (validation.Status != null)
                {
                    // A certificate validation should be queued with a Status of null, and once the certificate validation
                    // completes, the Status should be updated to a non-null value. Hence, the Status here SHOULD be null.
                    // A non-null Status may indicate message duplication.
                    _logger.LogWarning(
                        "Invalid certificate validation entity's status, dropping message (certificate: {CertificateThumbprint} validation: {ValidationId})",
                        validation.EndCertificate.Thumbprint,
                        validation.ValidationId);

                    return(true);
                }

                if (validation.EndCertificate.Status == EndCertificateStatus.Revoked)
                {
                    if (message.RevalidateRevokedCertificate)
                    {
                        _logger.LogWarning(
                            "Revalidating certificate that is known to be revoked " +
                            "(certificate: {CertificateThumbprint} validation: {ValidationId})",
                            validation.EndCertificate.Thumbprint,
                            validation.ValidationId);
                    }
                    else
                    {
                        // Do NOT revalidate a certificate that is known to be revoked unless explicitly told to!
                        // Certificate Authorities are not required to keep a certificate's revocation information
                        // forever, therefore, revoked certificates should only be revalidated in special cases.
                        _logger.LogError(
                            "Certificate known to be revoked MUST be validated with the " +
                            $"{nameof(CertificateValidationMessage.RevalidateRevokedCertificate)} flag enabled " +
                            "(certificate: {CertificateThumbprint} validation: {ValidationId})",
                            validation.EndCertificate.Thumbprint,
                            validation.ValidationId);

                        return(true);
                    }
                }

                CertificateVerificationResult result;

                using (var certificates = await LoadCertificatesAsync(validation))
                {
                    switch (validation.EndCertificate.Use)
                    {
                    case EndCertificateUse.CodeSigning:
                        result = _certificateVerifier.VerifyCodeSigningCertificate(
                            certificates.EndCertificate,
                            certificates.AncestorCertificates);
                        break;

                    case EndCertificateUse.Timestamping:
                        result = _certificateVerifier.VerifyTimestampingCertificate(
                            certificates.EndCertificate,
                            certificates.AncestorCertificates);
                        break;

                    default:
                        throw new InvalidOperationException($"Unknown {nameof(EndCertificateUse)}: {validation.EndCertificate.Use}");
                    }
                }

                // Save the result. This may alert if packages are invalidated.
                if (!await _certificateValidationService.TrySaveResultAsync(validation, result))
                {
                    _logger.LogWarning(
                        "Failed to save certificate validation result " +
                        "(certificate: {CertificateThumbprint} validation: {ValidationId}), " +
                        "retrying validation...",
                        validation.EndCertificate.Thumbprint,
                        validation.ValidationId);

                    return(false);
                }

                var completed = HasValidationCompleted(validation, result);
                if (completed && message.SendCheckValidator && _featureFlagService.IsQueueBackEnabled())
                {
                    _logger.LogInformation("Sending queue-back message for validation {ValidationId}.", message.ValidationId);
                    var messageData = PackageValidationMessageData.NewCheckValidator(message.ValidationId);
                    await _validationEnqueuer.SendMessageAsync(messageData);
                }

                return(completed);
            }
        }
Пример #9
0
        public async Task <bool> HandleAsync(SymbolsValidatorMessage message)
        {
            using (_logger.BeginScope("{ValidatorName}: Handling message for {PackageId} {PackageVersion} validation set {ValidationId}",
                                      ValidatorName.SymbolsValidator,
                                      message.PackageId,
                                      message.PackageNormalizedVersion,
                                      message.ValidationId))
            {
                if (message == null)
                {
                    throw new ArgumentNullException(nameof(message));
                }
                var validation = await _validatorStateService.GetStatusAsync(message.ValidationId);

                // A validation should be queued with ValidatorState == Incomplete.
                if (validation == null)
                {
                    _logger.LogInformation(
                        "{ValidatorName} : Could not find validation entity, requeueing (package: {PackageId} {PackageVersion}, validationId: {ValidationId})",
                        ValidatorName.SymbolsValidator,
                        message.PackageId,
                        message.PackageNormalizedVersion,
                        message.ValidationId);

                    // Message may be retried.
                    return(false);
                }
                else if (validation.State == ValidationStatus.NotStarted)
                {
                    _logger.LogWarning(
                        "{ValidatorName}:Unexpected status '{ValidatorState}' when 'Incomplete' was expected, requeueing package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                        ValidatorName.SymbolsValidator,
                        validation.State,
                        message.PackageId,
                        message.PackageNormalizedVersion,
                        message.ValidationId);

                    // Message may be retried.
                    return(false);
                }
                // Final states
                else if (validation.State == ValidationStatus.Failed || validation.State == ValidationStatus.Succeeded)
                {
                    _logger.LogWarning(
                        "{ValidatorName}:Terminal symbol verification status '{ValidatorState}' when 'Incomplete' was expected, dropping message (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                        ValidatorName.SymbolsValidator,
                        validation.State,
                        message.PackageId,
                        message.PackageNormalizedVersion,
                        message.ValidationId);

                    // Consume the message.
                    return(true);
                }

                var validationResult = await _symbolValidatorService.ValidateSymbolsAsync(message, CancellationToken.None);

                if (validationResult.Status == ValidationStatus.Failed || validationResult.Status == ValidationStatus.Succeeded)
                {
                    validation.State           = validationResult.Status;
                    validation.ValidatorIssues = validation.ValidatorIssues ?? new List <ValidatorIssue>();
                    foreach (var issue in validationResult.Issues)
                    {
                        validation.ValidatorIssues.Add(new ValidatorIssue
                        {
                            IssueCode = issue.IssueCode,
                            Data      = issue.Serialize(),
                        });
                    }

                    if (validationResult.NupkgUrl != null)
                    {
                        validation.NupkgUrl = validationResult.NupkgUrl;
                    }

                    var completed = await SaveStatusAsync(validation, message, MaxDBSaveRetry);

                    if (completed && _featureFlagService.IsQueueBackEnabled())
                    {
                        _logger.LogInformation("Sending queue-back message for validation {ValidationId}.", message.ValidationId);
                        var messageData = PackageValidationMessageData.NewCheckValidator(message.ValidationId);
                        await _validationEnqueuer.SendMessageAsync(messageData);
                    }

                    return(completed);
                }

                _logger.LogWarning(
                    "{ValidatorName}:The validation did not return a complete status for package {PackageId} {PackageVersion} for validation id: {ValidationId} .",
                    ValidatorName.SymbolsValidator,
                    message.PackageId,
                    message.PackageNormalizedVersion,
                    message.ValidationId);
                return(false);
            }
        }