Пример #1
0
        private async Task <SignatureValidatorResult> AcceptAsync(
            Context context,
            PackageSigningStatus status)
        {
            await _packageSigningStateService.SetPackageSigningState(
                context.PackageKey,
                context.Message.PackageId,
                context.Message.PackageVersion,
                status);

            // Upload the package stream to storage if the package content has changed.
            Uri nupkgUri = null;

            if (context.Changed)
            {
                await _packageFileService.SaveAsync(
                    context.Message.PackageId,
                    context.Message.PackageVersion,
                    context.Message.ValidationId,
                    context.PackageStream);

                nupkgUri = await _packageFileService.GetReadAndDeleteUriAsync(
                    context.Message.PackageId,
                    context.Message.PackageVersion,
                    context.Message.ValidationId);
            }

            return(new SignatureValidatorResult(ValidationStatus.Succeeded, nupkgUri));
        }
        public async Task SetPackageSigningState(
            int packageKey,
            string packageId,
            string packageVersion,
            PackageSigningStatus status)
        {
            if (string.IsNullOrEmpty(packageId))
            {
                throw new ArgumentException(nameof(packageId));
            }
            if (string.IsNullOrEmpty(packageVersion))
            {
                throw new ArgumentException(nameof(packageVersion));
            }

            // Update the signing state if it already exists, otherwise, create a new record.
            var signatureState = await _validationContext.PackageSigningStates.FirstOrDefaultAsync(s => s.PackageKey == packageKey);

            if (signatureState != null)
            {
                signatureState.SigningStatus = status;
            }
            else
            {
                _validationContext.PackageSigningStates.Add(new PackageSigningState
                {
                    PackageId  = packageId,
                    PackageKey = packageKey,
                    PackageNormalizedVersion = NuGetVersion.Parse(packageVersion).ToNormalizedString(),
                    SigningStatus            = status
                });
            }
        }
Пример #3
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);
            }
Пример #4
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);
            }
Пример #5
0
            public async Task DropsAllPackageSignaturesWhenPackageStateTransitionsToUnsigned()
            {
                // Arrange
                const int    packageKey              = 1;
                const string packageId               = "packageId";
                const string packageVersion          = "1.0.0";
                const PackageSigningStatus newStatus = PackageSigningStatus.Unsigned;

                var signature1 = new PackageSignature();
                var signature2 = new PackageSignature();

                var packageSigningState = new PackageSigningState
                {
                    PackageId                = packageId,
                    PackageKey               = packageKey,
                    SigningStatus            = PackageSigningStatus.Valid,
                    PackageNormalizedVersion = packageVersion,

                    PackageSignatures = new List <PackageSignature> {
                        signature1, signature2
                    }
                };

                var logger = _loggerFactory.CreateLogger <PackageSigningStateService>();
                var packageSigningStatesDbSetMock = DbSetMockFactory.CreateMock(packageSigningState);
                var packageSignaturesDbSetMock    = DbSetMockFactory.CreateMock(signature1, signature2);
                var validationContextMock         = new Mock <IValidationEntitiesContext>(MockBehavior.Strict);

                validationContextMock.Setup(m => m.PackageSigningStates).Returns(packageSigningStatesDbSetMock.Object);
                validationContextMock.Setup(m => m.PackageSignatures).Returns(packageSignaturesDbSetMock.Object);

                // Act
                var packageSigningStateService = new PackageSigningStateService(validationContextMock.Object, logger);

                // Assert
                await packageSigningStateService.SetPackageSigningState(
                    packageKey,
                    packageId,
                    packageVersion,
                    status : newStatus);

                // Assert
                Assert.Equal(newStatus, packageSigningState.SigningStatus);

                packageSignaturesDbSetMock.Verify(m => m.Remove(signature1), Times.Once);
                packageSignaturesDbSetMock.Verify(m => m.Remove(signature2), Times.Once);

                validationContextMock.Verify(
                    m => m.SaveChangesAsync(),
                    Times.Never,
                    "Saving the context here is incorrect as updating the validator's status also saves the context. Doing so would cause both queries not to be executed in the same transaction.");
            }
Пример #6
0
            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);
            }
        public async Task SetPackageSigningState(
            int packageKey,
            string packageId,
            string packageVersion,
            PackageSigningStatus status)
        {
            if (string.IsNullOrEmpty(packageId))
            {
                throw new ArgumentException(nameof(packageId));
            }
            if (string.IsNullOrEmpty(packageVersion))
            {
                throw new ArgumentException(nameof(packageVersion));
            }

            // Update the signing state if it already exists, otherwise, create a new record.
            var signatureState = await _validationContext
                                 .PackageSigningStates
                                 .Include(s => s.PackageSignatures)
                                 .FirstOrDefaultAsync(s => s.PackageKey == packageKey);

            if (signatureState != null)
            {
                signatureState.SigningStatus = status;

                // Remove all stored signatures if the package is transitioning to an unsigned state.
                if (status == PackageSigningStatus.Unsigned)
                {
                    foreach (var signature in signatureState.PackageSignatures.ToList())
                    {
                        _validationContext.PackageSignatures.Remove(signature);
                    }
                }
            }
            else
            {
                _validationContext.PackageSigningStates.Add(new PackageSigningState
                {
                    PackageId  = packageId,
                    PackageKey = packageKey,
                    PackageNormalizedVersion = NuGetVersion.Parse(packageVersion).ToNormalizedString(),
                    SigningStatus            = status
                });
            }
        }
Пример #8
0
 private void Validate(ValidationStatus validationStatus, PackageSigningStatus packageSigningStatus)
 {
     Assert.Equal(validationStatus, _validation.State);
     _packageSigningStateService.Verify(
         x => x.SetPackageSigningState(
             _validation.PackageKey,
             _message.PackageId,
             _message.PackageVersion,
             packageSigningStatus),
         Times.Once);
     _packageSigningStateService.Verify(
         x => x.SetPackageSigningState(
             It.IsAny <int>(),
             It.IsAny <string>(),
             It.IsAny <string>(),
             It.IsAny <PackageSigningStatus>()),
         Times.Once);
 }
Пример #9
0
            private void Validate(
                SignatureValidatorResult result,
                ValidationStatus validationStatus,
                PackageSigningStatus packageSigningStatus,
                Uri nupkgUri       = null,
                bool?shouldExtract = null)
            {
                Assert.Equal(validationStatus, result.State);
                Assert.Equal(nupkgUri, result.NupkgUri);
                _packageSigningStateService.Verify(
                    x => x.SetPackageSigningState(
                        _packageKey,
                        _message.PackageId,
                        _message.PackageVersion,
                        packageSigningStatus),
                    Times.Once);
                _packageSigningStateService.Verify(
                    x => x.SetPackageSigningState(
                        It.IsAny <int>(),
                        It.IsAny <string>(),
                        It.IsAny <string>(),
                        It.IsAny <PackageSigningStatus>()),
                    Times.Once);

                if ((shouldExtract.HasValue && shouldExtract.Value) ||
                    (validationStatus == ValidationStatus.Succeeded && packageSigningStatus == PackageSigningStatus.Valid))
                {
                    _signaturePartsExtractor.Verify(
                        x => x.ExtractAsync(_packageKey, It.Is <PrimarySignature>(y => y != null), It.IsAny <CancellationToken>()),
                        Times.Once);
                    _signaturePartsExtractor.Verify(
                        x => x.ExtractAsync(It.IsAny <int>(), It.IsAny <PrimarySignature>(), It.IsAny <CancellationToken>()),
                        Times.Once);
                }
                else
                {
                    _signaturePartsExtractor.Verify(
                        x => x.ExtractAsync(It.IsAny <int>(), It.IsAny <PrimarySignature>(), It.IsAny <CancellationToken>()),
                        Times.Never);
                }

                _corePackageService.VerifyAll();
            }
Пример #10
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);
            }
            public async Task AddsNewStateWhenSignatureStateIsNull()
            {
                // Arrange
                const int    packageKey              = 1;
                const string packageId               = "packageId";
                const string packageVersion          = "1.0.0";
                const PackageSigningStatus newStatus = PackageSigningStatus.Invalid;

                var logger = _loggerFactory.CreateLogger <PackageSigningStateService>();
                var packageSigningStatesDbSetMock = DbSetMockFactory.Create <PackageSigningState>();
                var validationContextMock         = new Mock <IValidationEntitiesContext>(MockBehavior.Strict);

                validationContextMock.Setup(m => m.PackageSigningStates).Returns(packageSigningStatesDbSetMock);

                // Act
                var packageSigningStateService = new PackageSigningStateService(validationContextMock.Object, logger);

                // Assert
                await packageSigningStateService.SetPackageSigningState(
                    packageKey,
                    packageId,
                    packageVersion,
                    status : newStatus);

                // Assert
                var newState = validationContextMock.Object.PackageSigningStates.FirstOrDefault();

                Assert.NotNull(newState);
                Assert.Equal(packageKey, newState.PackageKey);
                Assert.Equal(packageId, newState.PackageId);
                Assert.Equal(packageVersion, newState.PackageNormalizedVersion);
                Assert.Equal(newStatus, newState.SigningStatus);
                validationContextMock.Verify(
                    m => m.SaveChangesAsync(),
                    Times.Never,
                    "Saving the context here is incorrect as updating the validator's status also saves the context. Doing so would cause both queries not to be executed in the same transaction.");
            }
Пример #12
0
        public async Task SetPackageSigningState(
            int packageKey,
            string packageId,
            string packageVersion,
            PackageSigningStatus status)
        {
            if (string.IsNullOrEmpty(packageId))
            {
                throw new ArgumentException(nameof(packageId));
            }
            if (string.IsNullOrEmpty(packageVersion))
            {
                throw new ArgumentException(nameof(packageVersion));
            }

            // It is possible this package has already been validated. If so, the package's state will already exist
            // in the database. Updates to this state should only be requested on explicit revalidation gestures. However,
            // this invariant may be broken due to message duplication.
            var signatureState = await _validationContext.PackageSigningStates.FirstOrDefaultAsync(s => s.PackageKey == packageKey);

            if (signatureState != null)
            {
                signatureState.SigningStatus = status;
            }
            else
            {
                // This package does not have a persisted record for its state. Create a new one.
                _validationContext.PackageSigningStates.Add(new PackageSigningState
                {
                    PackageId  = packageId,
                    PackageKey = packageKey,
                    PackageNormalizedVersion = NuGetVersion.Parse(packageVersion).ToNormalizedString(),
                    SigningStatus            = status
                });
            }
        }
Пример #13
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;
        }
Пример #14
0
        private void VerifyPackageSigningStatus(SignatureValidatorResult result, ValidationStatus validationStatus, PackageSigningStatus packageSigningStatus)
        {
            Assert.Equal(validationStatus, result.State);
            var state = _validationEntitiesContext
                        .Object
                        .PackageSigningStates
                        .Where(x => x.PackageKey == _packageKey)
                        .SingleOrDefault();

            Assert.Equal(state.PackageId, _message.PackageId);
            Assert.Equal(state.PackageNormalizedVersion, _message.PackageVersion);
            Assert.Equal(state.SigningStatus, packageSigningStatus);
        }