Esempio n. 1
0
            public async Task AcceptsRepositorySignedPackage()
            {
                // Arrange
                _configuration.AllowedRepositorySigningCertificates = new List <string> {
                    TestResources.Leaf1Thumbprint
                };
                _packageStream = TestResources.GetResourceStream(TestResources.RepoSignedPackageLeaf1);

                TestUtility.RequireUnsignedPackage(_corePackageService, TestResources.RepoSignedPackageLeafId, TestResources.RepoSignedPackageLeaf1Version);

                _message = new SignatureValidationMessage(
                    TestResources.RepoSignedPackageLeafId,
                    TestResources.RepoSignedPackageLeaf1Version,
                    new Uri($"https://unit.test/{TestResources.RepoSignedPackageLeaf1.ToLowerInvariant()}"),
                    Guid.NewGuid());

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Succeeded, PackageSigningStatus.Valid);
                Assert.Empty(result.Issues);
            }
            public async Task RejectsSignedPackagesWithFailedMinimalVerifyResult()
            {
                // Arrange
                _packageStream       = TestResources.GetResourceStream(TestResources.SignedPackageLeaf1);
                _mimimalVerifyResult = new VerifySignaturesResult(valid: false);
                _message             = new SignatureValidationMessage(
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    new Uri($"https://unit.test/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                    Guid.NewGuid());

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);
                Assert.Empty(result.Issues);
                _fullPackageSignatureVerifier.Verify(
                    x => x.VerifySignaturesAsync(It.IsAny <ISignedPackageReader>(), It.IsAny <CancellationToken>(), It.IsAny <Guid>()),
                    Times.Never);
            }
Esempio n. 3
0
            public ValidateAsync()
            {
                _packageMock = new Mock <ISignedPackageReader>();
                _packageMock
                .Setup(x => x.IsSignedAsync(It.IsAny <CancellationToken>()))
                .ReturnsAsync(false);

                _validation = new ValidatorStatus
                {
                    PackageKey = 42,
                    State      = ValidationStatus.NotStarted,
                };
                _message = new SignatureValidationMessage(
                    "NuGet.Versioning",
                    "4.3.0",
                    new Uri("https://example/nuget.versioning.4.3.0.nupkg"),
                    new Guid("b777135f-1aac-4ec2-a3eb-1f64fe1880d5"));
                _cancellationToken = CancellationToken.None;

                _packageSigningStateService = new Mock <IPackageSigningStateService>();
                _certificates = new Mock <IEntityRepository <Certificate> >();
                _logger       = new Mock <ILogger <SignatureValidator> >();

                _certificates
                .Setup(x => x.GetAll())
                .Returns(Enumerable.Empty <Certificate>().AsQueryable());

                _target = new SignatureValidator(
                    _packageSigningStateService.Object,
                    _certificates.Object,
                    _logger.Object);
            }
            public async Task StripsAndRejectsPackagesWithRepositorySignatureWhenPackageMustBeAuthorSigned()
            {
                _packageStream = TestResources.GetResourceStream(TestResources.RepoSignedPackageLeaf1);
                TestUtility.RequireSignedPackage(_corePackageService, TestResources.RepoSignedPackageLeafId);
                _message = new SignatureValidationMessage(
                    TestResources.RepoSignedPackageLeafId,
                    TestResources.RepoSignedPackageLeaf1Version,
                    new Uri($"https://unit.test/{TestResources.RepoSignedPackageLeaf1.ToLowerInvariant()}"),
                    Guid.NewGuid());

                Stream uploadedStream = null;

                _packageFileService
                .Setup(x => x.SaveAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Guid>(), It.IsAny <Stream>()))
                .Returns(Task.CompletedTask)
                .Callback <string, string, Guid, Stream>((_, __, ___, s) => uploadedStream = s);

                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                Validate(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);
                Assert.Equal(1, result.Issues.Count);
                var issue = Assert.IsType <NoDataValidationIssue>(result.Issues[0]);

                Assert.Equal(ValidationIssueCode.PackageIsNotSigned, issue.IssueCode);
            }
Esempio n. 5
0
            public async Task WhenRepositorySigningIsRequired_FailsValidationOfSignedPackagesWithNoRepositorySignature()
            {
                // Arrange
                _packageStream = TestResources.GetResourceStream(TestResources.SignedPackageLeaf1);
                TestUtility.RequireSignedPackage(
                    _corePackageService,
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    TestResources.Leaf1Thumbprint);
                _message = new SignatureValidationMessage(
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    new Uri($"https://unit.test/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                    Guid.NewGuid(),
                    requireRepositorySignature: true);

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Failed, PackageSigningStatus.Valid, shouldExtract: true);
                Assert.Empty(result.Issues);
            }
Esempio n. 6
0
            public async Task AcceptsSignedPackagesWithUnknownCertificatesOnRevalidation()
            {
                // Arrange
                _packageStream = TestResources.GetResourceStream(TestResources.SignedPackageLeaf1);
                TestUtility.RequireSignedPackage(
                    _corePackageService,
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    TestResources.Leaf2Thumbprint,
                    PackageStatus.Available);

                _message = new SignatureValidationMessage(
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    new Uri($"https://unit.test/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                    Guid.NewGuid());

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Succeeded, PackageSigningStatus.Valid);
                Assert.Empty(result.Issues);
            }
            public async Task RejectsSignedPackagesWithUnknownCertificates()
            {
                // Arrange
                _packageStream = TestResources.GetResourceStream(TestResources.SignedPackageLeaf1);
                TestUtility.RequireSignedPackage(
                    _corePackageService,
                    TestResources.SignedPackageLeafId,
                    TestResources.Leaf2Thumbprint);
                _message = new SignatureValidationMessage(
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    new Uri($"https://unit.test/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                    Guid.NewGuid());

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);
                Assert.Single(result.Issues);
                var issue = Assert.IsType <UnauthorizedCertificateFailure>(result.Issues[0]);

                Assert.Equal(ValidationIssueCode.PackageIsSignedWithUnauthorizedCertificate, issue.IssueCode);
                Assert.Equal(TestResources.Leaf2Sha1Thumbprint, issue.Sha1Thumbprint);
            }
        public ActionResult DigitalSignatureValidation()
        {
            SignatureValidationMessage message = new SignatureValidationMessage();

            message.Message = string.Empty;
            return(View("DigitalSignatureValidation", message));
        }
Esempio n. 9
0
        public async Task RejectsUntrustedSigningCertificate()
        {
            // Arrange
            TestUtility.RequireSignedPackage(_corePackageService, TestResources.SignedPackageLeafId, TestResources.Leaf1Thumbprint);
            _packageStream = TestResources.GetResourceStream(TestResources.SignedPackageLeaf1);

            _message = new SignatureValidationMessage(
                TestResources.SignedPackageLeafId,
                TestResources.SignedPackageLeaf1Version,
                new Uri($"https://unit.test/validation/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                Guid.NewGuid());

            // Act
            var result = await _target.ValidateAsync(
                _packageKey,
                _packageStream,
                _message,
                _token);

            // Assert
            VerifyPackageSigningStatus(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);
            var issue       = Assert.Single(result.Issues);
            var clientIssue = Assert.IsType <ClientSigningVerificationFailure>(issue);

            Assert.Equal("NU3012", clientIssue.ClientCode);
            Assert.Equal(
                "A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.",
                clientIssue.ClientMessage);
        }
Esempio n. 10
0
            public async Task WhenRepositorySigningIsRequired_FailsValidationOfPackageWhoseRepositorySignatureIsStripped(
                string resourceName,
                string packageId,
                string packageVersion,
                PackageSigningStatus signingStatus,
                bool allowSignedPackage)
            {
                // Arrange
                _packageStream = TestResources.GetResourceStream(resourceName);
                if (allowSignedPackage)
                {
                    TestUtility.RequireSignedPackage(_corePackageService, packageId, packageVersion, TestResources.Leaf1Thumbprint);
                }
                else
                {
                    TestUtility.RequireUnsignedPackage(_corePackageService, packageId, packageVersion);
                }
                _message = new SignatureValidationMessage(
                    packageId,
                    packageVersion,
                    new Uri($"https://unit.test/{TestResources.RepoSignedPackageLeafId.ToLowerInvariant()}"),
                    Guid.NewGuid(),
                    requireRepositorySignature: true);

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Failed, signingStatus, shouldExtract: signingStatus == PackageSigningStatus.Valid);
                Assert.Empty(result.Issues);
            }
            public async Task RejectsSignedPackagesWithKnownCertificatesButFailedFullVerifyResult()
            {
                // Arrange
                _packageStream = TestResources.GetResourceStream(TestResources.SignedPackageLeaf1);
                TestUtility.RequireSignedPackage(
                    _corePackageService,
                    TestResources.SignedPackageLeafId,
                    TestResources.Leaf1Thumbprint);
                _fullVerifyResult = new VerifySignaturesResult(valid: false);
                _message          = new SignatureValidationMessage(
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    new Uri($"https://unit.test/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                    Guid.NewGuid());

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);
                Assert.Empty(result.Issues);
            }
Esempio n. 12
0
        private async Task HandleSignedPackageAsync(
            ISignedPackageReader signedPackageReader,
            ValidatorStatus validation,
            SignatureValidationMessage message,
            CancellationToken cancellationToken)
        {
            // Block packages that don't have exactly one signature.
            var packageSignatures = await signedPackageReader.GetSignaturesAsync(cancellationToken);

            if (packageSignatures.Count != 1)
            {
                _logger.LogInformation(
                    "Signed package {PackageId} {PackageVersion} is blocked for validation {ValidationId} since it has {SignatureCount} signatures.",
                    message.PackageId,
                    message.PackageVersion,
                    message.ValidationId,
                    packageSignatures.Count);

                await RejectAsync(validation, message);

                return;
            }

            // Block packages with any unknown signing certificates.
            var packageThumbprints = GetThumbprints(packageSignatures);
            var knownThumbprints   = _certificates
                                     .GetAll()
                                     .Where(c => packageThumbprints.Contains(c.Thumbprint))
                                     .Select(c => c.Thumbprint)
                                     .ToList();

            var unknownThumbprints = packageThumbprints.Except(knownThumbprints);

            if (unknownThumbprints.Any())
            {
                _logger.LogInformation(
                    "Signed package {PackageId} {PackageVersion} is blocked for validation {ValidationId} since it has unknown certificate thumbprints: {UnknownThumbprints}",
                    message.PackageId,
                    message.PackageVersion,
                    message.ValidationId,
                    unknownThumbprints);

                await RejectAsync(validation, message);

                return;
            }

            // For now, we assume safe-listed certificates are totally valid.
            _logger.LogInformation(
                "Signed package {PackageId} {PackageVersion} is accepted for validation {ValidationId} with certificate thumbprints: {PackageThumbprints}",
                message.PackageId,
                message.PackageVersion,
                message.ValidationId,
                packageThumbprints);

            await AcceptAsync(validation, message, PackageSigningStatus.Valid);

            return;
        }
Esempio n. 13
0
            public ValidateAsync(ITestOutputHelper output)
            {
                _packageStream = TestResources.GetResourceStream(TestResources.UnsignedPackage);
                _packageKey    = 42;
                _message       = new SignatureValidationMessage(
                    "NuGet.Versioning",
                    "4.3.0",
                    new Uri("https://example/nuget.versioning.4.3.0.nupkg"),
                    new Guid("b777135f-1aac-4ec2-a3eb-1f64fe1880d5"));
                _cancellationToken = CancellationToken.None;

                _packageSigningStateService = new Mock <IPackageSigningStateService>();
                _formatValidator            = new Mock <ISignatureFormatValidator>();

                _minimalVerifyResult = new VerifySignaturesResult(valid: true, signed: true);
                _formatValidator
                .Setup(x => x.ValidateMinimalAsync(It.IsAny <ISignedPackageReader>(), It.IsAny <CancellationToken>()))
                .ReturnsAsync(() => _minimalVerifyResult);

                _fullVerifyResult = new VerifySignaturesResult(valid: true, signed: true);
                _formatValidator
                .Setup(x => x.ValidateAllSignaturesAsync(It.IsAny <ISignedPackageReader>(), It.IsAny <bool>(), It.IsAny <CancellationToken>()))
                .ReturnsAsync(() => _fullVerifyResult);

                _signaturePartsExtractor = new Mock <ISignaturePartsExtractor>();
                _corePackageService      = new Mock <ICorePackageService>();
                var loggerFactory = new LoggerFactory().AddXunit(output);

                _logger = loggerFactory.CreateLogger <SignatureValidator>();

                _packageFileService = new Mock <IProcessorPackageFileService>();
                _nupkgUri           = new Uri("https://example-storage/TestProcessor/b777135f-1aac-4ec2-a3eb-1f64fe1880d5/nuget.versioning.4.3.0.nupkg");
                _packageFileService
                .Setup(x => x.GetReadAndDeleteUriAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Guid>()))
                .ReturnsAsync(() => _nupkgUri);

                _optionsSnapshot = new Mock <IOptionsSnapshot <ProcessSignatureConfiguration> >();
                _configuration   = new ProcessSignatureConfiguration
                {
                    AllowedRepositorySigningCertificates = new List <string> {
                        "fake-thumbprint"
                    },
                    V3ServiceIndexUrl = "http://example/v3/index.json",
                };
                _optionsSnapshot.Setup(x => x.Value).Returns(() => _configuration);

                _telemetryService = new Mock <ITelemetryService>();

                _target = new SignatureValidator(
                    _packageSigningStateService.Object,
                    _formatValidator.Object,
                    _signaturePartsExtractor.Object,
                    _packageFileService.Object,
                    _corePackageService.Object,
                    _optionsSnapshot.Object,
                    _telemetryService.Object,
                    _logger);
            }
Esempio n. 14
0
            public async Task RejectsPackagesWithFullVerificationErrors()
            {
                // Arrange
                _packageStream = TestResources.GetResourceStream(TestResources.SignedPackageLeaf1);
                TestUtility.RequireSignedPackage(
                    _corePackageService,
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    TestResources.Leaf1Thumbprint);
                _fullVerifyResult = new VerifySignaturesResult(
                    valid: false,
                    signed: true,
                    results: new[]
                {
                    new InvalidSignaturePackageVerificationResult(
                        SignatureVerificationStatus.Suspect,
                        new[]
                    {
                        SignatureLog.Issue(
                            fatal: true,
                            code: NuGetLogCode.NU3008,
                            message: "The package integrity check failed."),
                        SignatureLog.Issue(
                            fatal: false,
                            code: NuGetLogCode.NU3016,
                            message: "The package hash uses an unsupported hash algorithm."),
                        SignatureLog.Issue(
                            fatal: true,
                            code: NuGetLogCode.NU3000,
                            message: "Some other thing happened."),
                    })
                });
                _message = new SignatureValidationMessage(
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    new Uri($"https://unit.test/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                    Guid.NewGuid());

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);
                Assert.Equal(2, result.Issues.Count);
                var issue1 = Assert.IsType <ClientSigningVerificationFailure>(result.Issues[0]);

                Assert.Equal("NU3008", issue1.ClientCode);
                Assert.Equal("The package integrity check failed.", issue1.ClientMessage);
                var issue2 = Assert.IsType <ClientSigningVerificationFailure>(result.Issues[1]);

                Assert.Equal("NU3000", issue2.ClientCode);
                Assert.Equal("Some other thing happened.", issue2.ClientMessage);
            }
Esempio n. 15
0
            public async Task WhenStripsValidRepositorySignature_StripsAndAcceptsRepositorySignatureWhenRepositorySignatureIsNotRequired(
                string resourceName,
                string packageId,
                string packageVersion,
                PackageSigningStatus expectedSigningStatus)
            {
                // Arrange
                _configuration.StripValidRepositorySignatures       = true;
                _configuration.AllowedRepositorySigningCertificates = new List <string> {
                    TestResources.Leaf1Thumbprint, TestResources.Leaf2Thumbprint
                };

                _packageStream = TestResources.GetResourceStream(resourceName);

                if (resourceName == TestResources.RepoSignedPackageLeaf1)
                {
                    TestUtility.RequireUnsignedPackage(_corePackageService, TestResources.RepoSignedPackageLeafId, TestResources.RepoSignedPackageLeaf1Version);
                }

                if (resourceName == TestResources.AuthorAndRepoSignedPackageLeaf1)
                {
                    TestUtility.RequireSignedPackage(_corePackageService, TestResources.AuthorAndRepoSignedPackageLeafId, TestResources.AuthorAndRepoSignedPackageLeaf1Version, TestResources.Leaf1Thumbprint);
                }

                _message = new SignatureValidationMessage(
                    packageId,
                    packageVersion,
                    new Uri($"https://unit.test/{resourceName.ToLowerInvariant()}"),
                    Guid.NewGuid(),
                    requireRepositorySignature: false);

                Stream uploadedStream = null;

                _packageFileService
                .Setup(x => x.SaveAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Guid>(), It.IsAny <Stream>()))
                .Returns(Task.CompletedTask)
                .Callback <string, string, Guid, Stream>((_, __, ___, s) => uploadedStream = s);

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Succeeded, expectedSigningStatus, _nupkgUri);
                Assert.Empty(result.Issues);
                _packageFileService.Verify(
                    x => x.SaveAsync(_message.PackageId, _message.PackageVersion, _message.ValidationId, It.IsAny <Stream>()),
                    Times.Once);
                _packageFileService.Verify(
                    x => x.GetReadAndDeleteUriAsync(_message.PackageId, _message.PackageVersion, _message.ValidationId),
                    Times.Once);
                Assert.IsType <FileStream>(uploadedStream);
                Assert.Throws <ObjectDisposedException>(() => uploadedStream.Length);
            }
            public async Task WhenPackageSupportsButDoesNotRequireSigning_AcceptsUnsignedPackages()
            {
                // Arrange
                var user1 = new User()
                {
                    Key = 1
                };
                var user2 = new User()
                {
                    Key = 2
                };
                var packageRegistration = new PackageRegistration()
                {
                    Key = 3,
                    Id  = TestResources.UnsignedPackageId
                };
                var certificate = new Certificate()
                {
                    Key        = 4,
                    Thumbprint = TestResources.Leaf1Thumbprint
                };
                var userCertificate = new UserCertificate()
                {
                    Key            = 5,
                    CertificateKey = certificate.Key,
                    Certificate    = certificate,
                    UserKey        = user1.Key,
                    User           = user1
                };

                user1.UserCertificates.Add(userCertificate);
                certificate.UserCertificates.Add(userCertificate);

                packageRegistration.Owners.Add(user1);
                packageRegistration.Owners.Add(user2);

                _packageStream = TestResources.GetResourceStream(TestResources.UnsignedPackage);
                _corePackageService
                .Setup(x => x.FindPackageRegistrationById(It.Is <string>(id => id == _message.PackageId)))
                .Returns(packageRegistration);
                _message = new SignatureValidationMessage(
                    TestResources.UnsignedPackageId,
                    TestResources.UnsignedPackageVersion,
                    new Uri($"https://unit.test/{TestResources.UnsignedPackage.ToLowerInvariant()}"),
                    Guid.NewGuid());

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Succeeded, PackageSigningStatus.Unsigned);
                Assert.Empty(result.Issues);
            }
Esempio n. 17
0
        private async Task AcceptAsync(ValidatorStatus validation, SignatureValidationMessage message, PackageSigningStatus status)
        {
            await _packageSigningStateService.SetPackageSigningState(
                validation.PackageKey,
                message.PackageId,
                message.PackageVersion,
                status);

            validation.State = ValidationStatus.Succeeded;
        }
Esempio n. 18
0
        private async Task RejectAsync(ValidatorStatus validation, SignatureValidationMessage message)
        {
            await _packageSigningStateService.SetPackageSigningState(
                validation.PackageKey,
                message.PackageId,
                message.PackageVersion,
                status : PackageSigningStatus.Invalid);

            validation.State = ValidationStatus.Failed;
        }
Esempio n. 19
0
        public async Task RejectsUntrustedTimestampingCertificate()
        {
            // Arrange
            var testServer = await _fixture.GetTestServerAsync();

            var untrustedRootCa         = CertificateAuthority.Create(testServer.Url);
            var untrustedRootCertficate = new X509Certificate2(untrustedRootCa.Certificate.GetEncoded());
            var timestampService        = TimestampService.Create(untrustedRootCa);

            using (testServer.RegisterDefaultResponders(timestampService))
            {
                byte[] packageBytes;
                using (var temporaryTrust = new TrustedTestCert <X509Certificate2>(
                           untrustedRootCertficate,
                           x => x,
                           StoreName.Root,
                           StoreLocation.LocalMachine))
                {
                    packageBytes = await _fixture.GenerateSignedPackageBytesAsync(
                        TestResources.SignedPackageLeaf1,
                        await _fixture.GetSigningCertificateAsync(),
                        timestampService.Url,
                        _output);
                }

                TestUtility.RequireSignedPackage(_corePackageService,
                                                 TestResources.SignedPackageLeafId,
                                                 await _fixture.GetSigningCertificateThumbprintAsync());

                _packageStream = new MemoryStream(packageBytes);

                _message = new SignatureValidationMessage(
                    TestResources.SignedPackageLeafId,
                    TestResources.SignedPackageLeaf1Version,
                    new Uri($"https://unit.test/validation/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                    Guid.NewGuid());

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _token);

                // Assert
                VerifyPackageSigningStatus(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);
                var issue       = Assert.Single(result.Issues);
                var clientIssue = Assert.IsType <ClientSigningVerificationFailure>(issue);
                Assert.Equal("NU3028", clientIssue.ClientCode);
                Assert.Equal(
                    "A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.",
                    clientIssue.ClientMessage);
            }
        }
Esempio n. 20
0
        private async Task HandleUnsignedPackageAsync(ValidatorStatus validation, SignatureValidationMessage message)
        {
            _logger.LogInformation(
                "Package {PackageId} {PackageVersion} is unsigned, no additional validations necessary for {ValidationId}.",
                message.PackageId,
                message.PackageVersion,
                message.ValidationId);

            await AcceptAsync(validation, message, PackageSigningStatus.Unsigned);

            return;
        }
Esempio n. 21
0
 public Context(
     int packageKey,
     Stream packageStream,
     ISignedPackage packageReader,
     SignatureValidationMessage message,
     CancellationToken cancellationToken)
 {
     PackageKey        = packageKey;
     PackageStream     = packageStream ?? throw new ArgumentNullException(nameof(packageStream));
     PackageReader     = packageReader ?? throw new ArgumentNullException(nameof(packageReader));
     Message           = message ?? throw new ArgumentNullException(nameof(message));
     CancellationToken = cancellationToken;
 }
            public HandleAsync()
            {
                _message = new SignatureValidationMessage(
                    "NuGet.Versioning",
                    "4.3.0",
                    TestPackageUri,
                    new Guid("18e83aca-953a-4484-a698-a8fb8619e0bd"));
                _outputNupkgUri = new Uri("https://example/processor/18e83aca-953a-4484-a698-a8fb8619e0bd/nuget.versioning.4.3.0.nupkg");

                _validation = new ValidatorStatus
                {
                    PackageKey = 42,
                    State      = ValidationStatus.Incomplete,
                };
                _validationIssue = new Mock <IValidationIssue>();
                _validatorResult = new SignatureValidatorResult(ValidationStatus.Succeeded, nupkgUri: null);

                _packageDownloader     = new Mock <IFileDownloader>();
                _validatorStateService = new Mock <IValidatorStateService>();
                _signatureValidator    = new Mock <ISignatureValidator>();
                _validationEnqueuer    = new Mock <IPackageValidationEnqueuer>();
                _featureFlagService    = new Mock <IFeatureFlagService>();
                _logger = new Mock <ILogger <SignatureValidationMessageHandler> >();

                _packageDownloader
                .Setup(x => x.DownloadAsync(_message.NupkgUri, It.IsAny <CancellationToken>()))
                .ReturnsAsync(() => FileDownloadResult.Ok(TestResources.GetResourceStream(TestResources.UnsignedPackage)));
                _validatorStateService
                .Setup(x => x.GetStatusAsync(It.IsAny <Guid>()))
                .ReturnsAsync(() => _validation);

                _signatureValidator
                .Setup(x => x.ValidateAsync(
                           It.IsAny <int>(),
                           It.IsAny <Stream>(),
                           It.IsAny <SignatureValidationMessage>(),
                           It.IsAny <CancellationToken>()))
                .ReturnsAsync(() => _validatorResult);

                _featureFlagService.SetReturnsDefault(true);

                _target = new SignatureValidationMessageHandler(
                    _packageDownloader.Object,
                    _validatorStateService.Object,
                    _signatureValidator.Object,
                    _validationEnqueuer.Object,
                    _featureFlagService.Object,
                    _logger.Object);
            }
            public ValidateAsync(ITestOutputHelper output)
            {
                _packageStream = TestResources.GetResourceStream(TestResources.UnsignedPackage);
                _packageKey    = 42;
                _message       = new SignatureValidationMessage(
                    "NuGet.Versioning",
                    "4.3.0",
                    new Uri("https://example/nuget.versioning.4.3.0.nupkg"),
                    new Guid("b777135f-1aac-4ec2-a3eb-1f64fe1880d5"));
                _cancellationToken = CancellationToken.None;

                _packageSigningStateService = new Mock <IPackageSigningStateService>();

                _mimimalVerifyResult             = new VerifySignaturesResult(true);
                _mimimalPackageSignatureVerifier = new Mock <IPackageSignatureVerifier>();
                _mimimalPackageSignatureVerifier
                .Setup(x => x.VerifySignaturesAsync(It.IsAny <ISignedPackageReader>(), It.IsAny <CancellationToken>(), It.IsAny <Guid>()))
                .ReturnsAsync(() => _mimimalVerifyResult);

                _fullVerifyResult             = new VerifySignaturesResult(true);
                _fullPackageSignatureVerifier = new Mock <IPackageSignatureVerifier>();
                _fullPackageSignatureVerifier
                .Setup(x => x.VerifySignaturesAsync(It.IsAny <ISignedPackageReader>(), It.IsAny <CancellationToken>(), It.IsAny <Guid>()))
                .ReturnsAsync(() => _fullVerifyResult);

                _signaturePartsExtractor = new Mock <ISignaturePartsExtractor>();
                _corePackageService      = new Mock <ICorePackageService>();
                var loggerFactory = new LoggerFactory().AddXunit(output);

                _logger = loggerFactory.CreateLogger <SignatureValidator>();

                _packageFileService = new Mock <IProcessorPackageFileService>();
                _nupkgUri           = new Uri("https://example-storage/TestProcessor/b777135f-1aac-4ec2-a3eb-1f64fe1880d5/nuget.versioning.4.3.0.nupkg");
                _packageFileService
                .Setup(x => x.GetReadAndDeleteUriAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Guid>()))
                .ReturnsAsync(() => _nupkgUri);

                _telemetryService = new Mock <ITelemetryService>();

                _target = new SignatureValidator(
                    _packageSigningStateService.Object,
                    _mimimalPackageSignatureVerifier.Object,
                    _fullPackageSignatureVerifier.Object,
                    _signaturePartsExtractor.Object,
                    _packageFileService.Object,
                    _corePackageService.Object,
                    _telemetryService.Object,
                    _logger);
            }
            public async Task StripsAndAcceptsPackagesWithRepositorySignatures(
                string resourceName,
                string packageId,
                string packageVersion,
                PackageSigningStatus signingStatus,
                bool allowSignedPackage)
            {
                // Arrange
                _packageStream = TestResources.GetResourceStream(resourceName);
                if (allowSignedPackage)
                {
                    TestUtility.RequireSignedPackage(_corePackageService, packageId, TestResources.Leaf1Thumbprint);
                }
                else
                {
                    TestUtility.RequireUnsignedPackage(_corePackageService, packageId);
                }
                _message = new SignatureValidationMessage(
                    packageId,
                    packageVersion,
                    new Uri($"https://unit.test/{resourceName.ToLowerInvariant()}"),
                    Guid.NewGuid());

                Stream uploadedStream = null;

                _packageFileService
                .Setup(x => x.SaveAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <Guid>(), It.IsAny <Stream>()))
                .Returns(Task.CompletedTask)
                .Callback <string, string, Guid, Stream>((_, __, ___, s) => uploadedStream = s);

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Succeeded, signingStatus, _nupkgUri);
                Assert.Empty(result.Issues);
                _packageFileService.Verify(
                    x => x.SaveAsync(_message.PackageId, _message.PackageVersion, _message.ValidationId, It.IsAny <Stream>()),
                    Times.Once);
                _packageFileService.Verify(
                    x => x.GetReadAndDeleteUriAsync(_message.PackageId, _message.PackageVersion, _message.ValidationId),
                    Times.Once);
                Assert.IsType <FileStream>(uploadedStream);
                Assert.Throws <ObjectDisposedException>(() => uploadedStream.Length);
            }
        /// <summary>
        /// Kicks off the package verification process for the given request. Verification will begin when the
        /// <see cref="ValidationEntitiesContext"/> has a <see cref="ValidatorStatus"/> that matches the
        /// <see cref="IValidationRequest"/>'s validationId. Once verification completes, the <see cref="ValidatorStatus"/>'s
        /// State will be updated to "Succeeded" or "Failed".
        /// </summary>
        /// <param name="request">The request that details the package to be verified.</param>
        /// <returns>A task that will complete when the verification process has been queued.</returns>
        public Task EnqueueVerificationAsync(IValidationRequest request)
        {
            var message = new SignatureValidationMessage(
                request.PackageId,
                request.PackageVersion,
                new Uri(request.NupkgUrl),
                request.ValidationId);
            var brokeredMessage = _serializer.Serialize(message);

            var visibleAt = DateTimeOffset.UtcNow + (_configuration.Value.MessageDelay ?? TimeSpan.Zero);

            brokeredMessage.ScheduledEnqueueTimeUtc = visibleAt;

            return(_topicClient.SendAsync(brokeredMessage));
        }
Esempio n. 26
0
        [InlineData(null)]                   // No commitment type.
        public async Task AllowsNonAuthorAndRepositoryCounterSignatures(string commitmentTypeOidBase64)
        {
            // Arrange
            _message = new SignatureValidationMessage(
                TestResources.SignedPackageLeafId,
                TestResources.SignedPackageLeaf1Version,
                new Uri($"https://unit.test/validation/{TestResources.SignedPackageLeaf1.ToLowerInvariant()}"),
                Guid.NewGuid());
            var packageStream = await GetSignedPackageStream1Async();

            ModifySignatureContent(
                packageStream,
                configuredSignedCms: signedCms =>
            {
                using (var counterCertificate = SigningTestUtility.GenerateCertificate(subjectName: null, modifyGenerator: null))
                {
                    var cmsSigner = new CmsSigner(counterCertificate);

                    if (commitmentTypeOidBase64 != null)
                    {
                        var value = new AsnEncodedData(
                            Oids.CommitmentTypeIndication,
                            Convert.FromBase64String(commitmentTypeOidBase64));

                        var attribute = new CryptographicAttributeObject(
                            new Oid(Oids.CommitmentTypeIndication),
                            new AsnEncodedDataCollection(value));

                        cmsSigner.SignedAttributes.Add(attribute);
                    }

                    signedCms.SignerInfos[0].ComputeCounterSignature(cmsSigner);
                }
            });

            // Act
            var result = await _target.ValidateAsync(
                _packageKey,
                _packageStream,
                _message,
                _token);

            // Assert
            VerifyPackageSigningStatus(result, ValidationStatus.Failed, PackageSigningStatus.Invalid);

            // This failure type indicates the counter signature validation passed.
            VerifyNU3008(result);
        }
Esempio n. 27
0
            public HandleAsync()
            {
                _message = new SignatureValidationMessage(
                    "NuGet.Versioning",
                    "4.3.0",
                    TestPackageUri,
                    new Guid("18e83aca-953a-4484-a698-a8fb8619e0bd"));

                _validation = new ValidatorStatus
                {
                    PackageKey = 42,
                    State      = ValidationStatus.Incomplete,
                };
                _urlToResourceName = new Dictionary <Uri, string>
                {
                    { _message.NupkgUri, TestResources.UnsignedPackage },
                };

                _handler               = new EmbeddedResourceTestHandler(_urlToResourceName);
                _httpClient            = new HttpClient(_handler);
                _validatorStateService = new Mock <IValidatorStateService>();
                _signatureValidator    = new Mock <ISignatureValidator>();
                _logger = new Mock <ILogger <SignatureValidationMessageHandler> >();

                _validatorStateService
                .Setup(x => x.GetStatusAsync(It.IsAny <Guid>()))
                .ReturnsAsync(() => _validation);

                _signatureValidator
                .Setup(x => x.ValidateAsync(
                           It.IsAny <ISignedPackageReader>(),
                           It.IsAny <ValidatorStatus>(),
                           It.IsAny <SignatureValidationMessage>(),
                           It.IsAny <CancellationToken>()))
                .Returns(Task.CompletedTask)
                .Callback(() => _validation.State = ValidationStatus.Succeeded);

                _target = new SignatureValidationMessageHandler(
                    _httpClient,
                    _validatorStateService.Object,
                    _signatureValidator.Object,
                    _logger.Object);
            }
Esempio n. 28
0
        public async Task StripsRepositorySignatures()
        {
            // Arrange
            _message = new SignatureValidationMessage(
                TestResources.UnsignedPackageId,
                TestResources.UnsignedPackageVersion,
                new Uri($"https://unit.test/validation/{TestResources.UnsignedPackage.ToLowerInvariant()}"),
                Guid.NewGuid());
            var packageBytes = await _fixture.GenerateSignedPackageBytesAsync(
                TestResources.GetResourceStream(TestResources.UnsignedPackage),
                new RepositorySignPackageRequest(
                    await _fixture.GetSigningCertificateAsync(),
                    NuGetHashAlgorithmName.SHA256,
                    NuGetHashAlgorithmName.SHA256,
                    new Uri("https://example-source/v3/index.json"),
                    new[] { "nuget", "microsoft" }),
                await _fixture.GetTimestampServiceUrlAsync(),
                _output);

            var packageStream = new MemoryStream(packageBytes);

            TestUtility.RequireUnsignedPackage(_corePackageService, TestResources.UnsignedPackageId);

            // Act
            var result = await _target.ValidateAsync(
                _packageKey,
                packageStream,
                _message,
                _token);

            // Assert
            VerifyPackageSigningStatus(result, ValidationStatus.Succeeded, PackageSigningStatus.Unsigned);
            Assert.Empty(result.Issues);
            Assert.Equal(_nupkgUri, result.NupkgUri);
            Assert.NotNull(_savedPackageBytes);
            using (var savedPackageStream = new MemoryStream(_savedPackageBytes))
                using (var packageReader = new SignedPackageArchive(savedPackageStream, Stream.Null))
                {
                    Assert.Equal("TestUnsigned", packageReader.NuspecReader.GetId());
                    Assert.Equal("1.0.0", packageReader.NuspecReader.GetVersion().ToNormalizedString());
                    Assert.False(await packageReader.IsSignedAsync(CancellationToken.None), "The package should no longer be signed.");
                }
        }
Esempio n. 29
0
            public async Task WhenStripsValidRepositorySignature_AcceptsRepositorySignatureWhenRepositorySignatureIsRequired(
                string resourceName,
                string packageId,
                string packageVersion,
                PackageSigningStatus expectedSigningStatus)
            {
                // Arrange
                _configuration.StripValidRepositorySignatures       = true;
                _configuration.AllowedRepositorySigningCertificates = new List <string> {
                    TestResources.Leaf1Thumbprint, TestResources.Leaf2Thumbprint
                };

                _packageStream = TestResources.GetResourceStream(resourceName);

                if (resourceName == TestResources.RepoSignedPackageLeaf1)
                {
                    TestUtility.RequireUnsignedPackage(_corePackageService, TestResources.RepoSignedPackageLeafId, TestResources.RepoSignedPackageLeaf1Version);
                }

                if (resourceName == TestResources.AuthorAndRepoSignedPackageLeaf1)
                {
                    TestUtility.RequireSignedPackage(_corePackageService, TestResources.AuthorAndRepoSignedPackageLeafId, TestResources.AuthorAndRepoSignedPackageLeaf1Version, TestResources.Leaf1Thumbprint);
                }

                _message = new SignatureValidationMessage(
                    packageId,
                    packageVersion,
                    new Uri($"https://unit.test/{resourceName.ToLowerInvariant()}"),
                    Guid.NewGuid(),
                    requireRepositorySignature: true);

                // Act
                var result = await _target.ValidateAsync(
                    _packageKey,
                    _packageStream,
                    _message,
                    _cancellationToken);

                // Assert
                Validate(result, ValidationStatus.Succeeded, expectedSigningStatus);
                Assert.Empty(result.Issues);
            }
Esempio n. 30
0
        public async Task <SignatureValidatorResult> ValidateAsync(
            int packageKey,
            Stream packageStream,
            SignatureValidationMessage message,
            CancellationToken cancellationToken)
        {
            using (var packageReader = new SignedPackageArchive(packageStream, packageWriteStream: Stream.Null))
                using (var context = new Context(packageKey, packageStream, packageReader, message, cancellationToken))
                {
                    // Reject Zip64 package whether or not they are signed.
                    if (await context.PackageReader.IsZip64Async(context.CancellationToken))
                    {
                        return(await RejectAsync(context, ValidationIssue.PackageIsZip64));
                    }

                    SignatureValidatorResult result;

                    if (await context.PackageReader.IsSignedAsync(cancellationToken))
                    {
                        result = await HandleSignedPackageAsync(context);
                    }
                    else
                    {
                        result = await HandleUnsignedPackageAsync(context);
                    }

                    // Force the validation to fail if the repository signature is expected but missing. The signature
                    // and signing state that are stored in the database may be still valid.
                    if (context.Message.RequireRepositorySignature && !context.HasRepositorySignature)
                    {
                        _logger.LogCritical(
                            "Package {PackageId} {PackageVersion} for validation {ValidationId} is expected to be repository signed.",
                            context.Message.PackageId,
                            context.Message.PackageVersion,
                            context.Message.ValidationId);

                        return(new SignatureValidatorResult(ValidationStatus.Failed, result.Issues, nupkgUri: null));
                    }

                    return(result);
                }
        }