@@ -39,6 +39,8 @@ public class ValidateAsync
3939 private readonly Mock < ISignatureFormatValidator > _formatValidator ;
4040 private VerifySignaturesResult _minimalVerifyResult ;
4141 private VerifySignaturesResult _fullVerifyResult ;
42+ private VerifySignaturesResult _authorSignatureVerifyResult ;
43+ private VerifySignaturesResult _repositorySignatureVerifyResult ;
4244 private readonly Mock < ISignaturePartsExtractor > _signaturePartsExtractor ;
4345 private readonly Mock < ICorePackageService > _corePackageService ;
4446 private readonly ILogger < SignatureValidator > _logger ;
@@ -73,6 +75,16 @@ public ValidateAsync(ITestOutputHelper output)
7375 . Setup ( x => x . ValidateAllSignaturesAsync ( It . IsAny < ISignedPackageReader > ( ) , It . IsAny < bool > ( ) , It . IsAny < CancellationToken > ( ) ) )
7476 . ReturnsAsync ( ( ) => _fullVerifyResult ) ;
7577
78+ _authorSignatureVerifyResult = new VerifySignaturesResult ( isValid : true , isSigned : true ) ;
79+ _formatValidator
80+ . Setup ( x => x . ValidateAuthorSignatureAsync ( It . IsAny < ISignedPackageReader > ( ) , It . IsAny < CancellationToken > ( ) ) )
81+ . ReturnsAsync ( ( ) => _authorSignatureVerifyResult ) ;
82+
83+ _repositorySignatureVerifyResult = new VerifySignaturesResult ( isValid : true , isSigned : true ) ;
84+ _formatValidator
85+ . Setup ( x => x . ValidateRepositorySignatureAsync ( It . IsAny < ISignedPackageReader > ( ) , It . IsAny < CancellationToken > ( ) ) )
86+ . ReturnsAsync ( ( ) => _repositorySignatureVerifyResult ) ;
87+
7688 _signaturePartsExtractor = new Mock < ISignaturePartsExtractor > ( ) ;
7789 _corePackageService = new Mock < ICorePackageService > ( ) ;
7890 var loggerFactory = new LoggerFactory ( ) . AddXunit ( output ) ;
@@ -88,7 +100,8 @@ public ValidateAsync(ITestOutputHelper output)
88100 _configuration = new ProcessSignatureConfiguration
89101 {
90102 AllowedRepositorySigningCertificates = new List < string > { "fake-thumbprint" } ,
91- V3ServiceIndexUrl = "http://example/v3/index.json" ,
103+ V3ServiceIndexUrl = TestResources . V3ServiceIndexUrl ,
104+ StripValidRepositorySignatures = false ,
92105 } ;
93106 _optionsSnapshot . Setup ( x => x . Value ) . Returns ( ( ) => _configuration ) ;
94107
@@ -490,6 +503,33 @@ public async Task AcceptsSignedPackagesWithUnknownCertificatesOnRevalidation()
490503 Assert . Empty ( result . Issues ) ;
491504 }
492505
506+ [ Fact ]
507+ public async Task AcceptsRepositorySignedPackage ( )
508+ {
509+ // Arrange
510+ _configuration . AllowedRepositorySigningCertificates = new List < string > { TestResources . Leaf1Thumbprint } ;
511+ _packageStream = TestResources . GetResourceStream ( TestResources . RepoSignedPackageLeaf1 ) ;
512+
513+ TestUtility . RequireUnsignedPackage ( _corePackageService , TestResources . RepoSignedPackageLeafId , TestResources . RepoSignedPackageLeaf1Version ) ;
514+
515+ _message = new SignatureValidationMessage (
516+ TestResources . RepoSignedPackageLeafId ,
517+ TestResources . RepoSignedPackageLeaf1Version ,
518+ new Uri ( $ "https://unit.test/{ TestResources . RepoSignedPackageLeaf1 . ToLowerInvariant ( ) } ") ,
519+ Guid . NewGuid ( ) ) ;
520+
521+ // Act
522+ var result = await _target . ValidateAsync (
523+ _packageKey ,
524+ _packageStream ,
525+ _message ,
526+ _cancellationToken ) ;
527+
528+ // Assert
529+ Validate ( result , ValidationStatus . Succeeded , PackageSigningStatus . Valid ) ;
530+ Assert . Empty ( result . Issues ) ;
531+ }
532+
493533 [ Fact ]
494534 public async Task WhenRepositorySigningIsRequired_FailsValidationOfSignedPackagesWithNoRepositorySignature ( )
495535 {
@@ -663,6 +703,124 @@ public async Task StripsAndAcceptsPackagesWithRepositorySignatures(
663703 }
664704 }
665705
706+ [ Theory ]
707+ [ InlineData (
708+ TestResources . RepoSignedPackageLeaf1 ,
709+ TestResources . RepoSignedPackageLeafId ,
710+ TestResources . RepoSignedPackageLeaf1Version ,
711+ PackageSigningStatus . Unsigned ) ]
712+ [ InlineData (
713+ TestResources . AuthorAndRepoSignedPackageLeaf1 ,
714+ TestResources . AuthorAndRepoSignedPackageLeafId ,
715+ TestResources . AuthorAndRepoSignedPackageLeaf1Version ,
716+ PackageSigningStatus . Valid ) ]
717+ public async Task WhenStripsValidRepositorySignature_StripsAndAcceptsRepositorySignatureWhenRepositorySignatureIsNotRequired (
718+ string resourceName ,
719+ string packageId ,
720+ string packageVersion ,
721+ PackageSigningStatus expectedSigningStatus )
722+ {
723+ // Arrange
724+ _configuration . StripValidRepositorySignatures = true ;
725+ _configuration . AllowedRepositorySigningCertificates = new List < string > { TestResources . Leaf1Thumbprint , TestResources . Leaf2Thumbprint } ;
726+
727+ _packageStream = TestResources . GetResourceStream ( resourceName ) ;
728+
729+ if ( resourceName == TestResources . RepoSignedPackageLeaf1 )
730+ {
731+ TestUtility . RequireUnsignedPackage ( _corePackageService , TestResources . RepoSignedPackageLeafId , TestResources . RepoSignedPackageLeaf1Version ) ;
732+ }
733+
734+ if ( resourceName == TestResources . AuthorAndRepoSignedPackageLeaf1 )
735+ {
736+ TestUtility . RequireSignedPackage ( _corePackageService , TestResources . AuthorAndRepoSignedPackageLeafId , TestResources . AuthorAndRepoSignedPackageLeaf1Version , TestResources . Leaf1Thumbprint ) ;
737+ }
738+
739+ _message = new SignatureValidationMessage (
740+ packageId ,
741+ packageVersion ,
742+ new Uri ( $ "https://unit.test/{ resourceName . ToLowerInvariant ( ) } ") ,
743+ Guid . NewGuid ( ) ,
744+ requireRepositorySignature : false ) ;
745+
746+ Stream uploadedStream = null ;
747+ _packageFileService
748+ . Setup ( x => x . SaveAsync ( It . IsAny < string > ( ) , It . IsAny < string > ( ) , It . IsAny < Guid > ( ) , It . IsAny < Stream > ( ) ) )
749+ . Returns ( Task . CompletedTask )
750+ . Callback < string , string , Guid , Stream > ( ( _ , __ , ___ , s ) => uploadedStream = s ) ;
751+
752+ // Act
753+ var result = await _target . ValidateAsync (
754+ _packageKey ,
755+ _packageStream ,
756+ _message ,
757+ _cancellationToken ) ;
758+
759+ // Assert
760+ Validate ( result , ValidationStatus . Succeeded , expectedSigningStatus , _nupkgUri ) ;
761+ Assert . Empty ( result . Issues ) ;
762+ _packageFileService . Verify (
763+ x => x . SaveAsync ( _message . PackageId , _message . PackageVersion , _message . ValidationId , It . IsAny < Stream > ( ) ) ,
764+ Times . Once ) ;
765+ _packageFileService . Verify (
766+ x => x . GetReadAndDeleteUriAsync ( _message . PackageId , _message . PackageVersion , _message . ValidationId ) ,
767+ Times . Once ) ;
768+ Assert . IsType < FileStream > ( uploadedStream ) ;
769+ Assert . Throws < ObjectDisposedException > ( ( ) => uploadedStream . Length ) ;
770+ }
771+
772+ [ Theory ]
773+ [ InlineData (
774+ TestResources . RepoSignedPackageLeaf1 ,
775+ TestResources . RepoSignedPackageLeafId ,
776+ TestResources . RepoSignedPackageLeaf1Version ,
777+ PackageSigningStatus . Valid ) ]
778+ [ InlineData (
779+ TestResources . AuthorAndRepoSignedPackageLeaf1 ,
780+ TestResources . AuthorAndRepoSignedPackageLeafId ,
781+ TestResources . AuthorAndRepoSignedPackageLeaf1Version ,
782+ PackageSigningStatus . Valid ) ]
783+ public async Task WhenStripsValidRepositorySignature_AcceptsRepositorySignatureWhenRepositorySignatureIsRequired (
784+ string resourceName ,
785+ string packageId ,
786+ string packageVersion ,
787+ PackageSigningStatus expectedSigningStatus )
788+ {
789+ // Arrange
790+ _configuration . StripValidRepositorySignatures = true ;
791+ _configuration . AllowedRepositorySigningCertificates = new List < string > { TestResources . Leaf1Thumbprint , TestResources . Leaf2Thumbprint } ;
792+
793+ _packageStream = TestResources . GetResourceStream ( resourceName ) ;
794+
795+ if ( resourceName == TestResources . RepoSignedPackageLeaf1 )
796+ {
797+ TestUtility . RequireUnsignedPackage ( _corePackageService , TestResources . RepoSignedPackageLeafId , TestResources . RepoSignedPackageLeaf1Version ) ;
798+ }
799+
800+ if ( resourceName == TestResources . AuthorAndRepoSignedPackageLeaf1 )
801+ {
802+ TestUtility . RequireSignedPackage ( _corePackageService , TestResources . AuthorAndRepoSignedPackageLeafId , TestResources . AuthorAndRepoSignedPackageLeaf1Version , TestResources . Leaf1Thumbprint ) ;
803+ }
804+
805+ _message = new SignatureValidationMessage (
806+ packageId ,
807+ packageVersion ,
808+ new Uri ( $ "https://unit.test/{ resourceName . ToLowerInvariant ( ) } ") ,
809+ Guid . NewGuid ( ) ,
810+ requireRepositorySignature : true ) ;
811+
812+ // Act
813+ var result = await _target . ValidateAsync (
814+ _packageKey ,
815+ _packageStream ,
816+ _message ,
817+ _cancellationToken ) ;
818+
819+ // Assert
820+ Validate ( result , ValidationStatus . Succeeded , expectedSigningStatus ) ;
821+ Assert . Empty ( result . Issues ) ;
822+ }
823+
666824 [ Fact ]
667825 public async Task StripsAndRejectsPackagesWithRepositorySignatureWhenPackageMustBeAuthorSigned ( )
668826 {
0 commit comments