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); }
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); }
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); }
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)); }
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); }
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); }
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; }
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); }
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); }
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); }
private async Task AcceptAsync(ValidatorStatus validation, SignatureValidationMessage message, PackageSigningStatus status) { await _packageSigningStateService.SetPackageSigningState( validation.PackageKey, message.PackageId, message.PackageVersion, status); validation.State = ValidationStatus.Succeeded; }
private async Task RejectAsync(ValidatorStatus validation, SignatureValidationMessage message) { await _packageSigningStateService.SetPackageSigningState( validation.PackageKey, message.PackageId, message.PackageVersion, status : PackageSigningStatus.Invalid); validation.State = ValidationStatus.Failed; }
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); } }
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; }
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)); }
[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); }
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); }
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."); } }
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 <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); } }