public void GetAllowListEntries_WithDuplicateEntries_ConflictingAllowUntrustedRoot_WarnsAndSetsToFalse()
        {
            // Arrange
            var config = @"
<configuration>
    <trustedSigners>
        <repository name=""repository1"" serviceIndex=""api.v3ServiceIndex.test/json"">
            <certificate fingerprint=""abc"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
            <certificate fingerprint=""def"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
            <certificate fingerprint=""abc"" hashAlgorithm=""SHA512"" allowUntrustedRoot=""false"" />
            <owners>nuget;randomOwner</owners>
        </repository>
        <author name=""author1"">
            <certificate fingerprint=""jkl"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
            <certificate fingerprint=""abc"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""true"" />
        </author>
    </trustedSigners>
</configuration>";

            var nugetConfigPath = "NuGet.Config";

            using (var mockBaseDirectory = TestDirectory.Create())
            {
                SettingsTestUtils.CreateConfigurationFile(nugetConfigPath, mockBaseDirectory, config);

                // Act and Assert
                var settings = new Settings(mockBaseDirectory);
                settings.Should().NotBeNull();

                var logger = new Mock <ILogger>();

                var entries = TrustedSignersProvider.GetAllowListEntries(settings, logger.Object);
                entries.Should().NotBeNull();
                entries.Count.Should().Be(4);

                logger.Verify(l =>
                              l.Log(It.Is <ILogMessage>(m =>
                                                        m.Level == LogLevel.Warning &&
                                                        m.Code == NuGetLogCode.NU3040)));

                var expectedEntries = new List <VerificationAllowListEntry>()
                {
                    new TrustedSignerAllowListEntry(VerificationTarget.Repository, SignaturePlacement.Any, "abc", HashAlgorithmName.SHA512, owners: new List <string>()
                    {
                        "nuget", "randomOwner"
                    }),
                    new TrustedSignerAllowListEntry(VerificationTarget.Author | VerificationTarget.Repository, SignaturePlacement.Any, "abc", HashAlgorithmName.SHA256, owners: new List <string>()
                    {
                        "nuget", "randomOwner"
                    }),
                    new TrustedSignerAllowListEntry(VerificationTarget.Repository, SignaturePlacement.Any, "def", HashAlgorithmName.SHA256, owners: new List <string>()
                    {
                        "nuget", "randomOwner"
                    }),
                    new TrustedSignerAllowListEntry(VerificationTarget.Author, SignaturePlacement.PrimarySignature, "jkl", HashAlgorithmName.SHA256),
                };

                entries.Should().BeEquivalentTo(expectedEntries);
            }
        }
        public void GetAllowListEntries_WithNullLogger_Throws()
        {
            // Act and Assert
            var ex = Record.Exception(() => TrustedSignersProvider.GetAllowListEntries(settings: NullSettings.Instance, logger: null));

            ex.Should().NotBeNull();
            ex.Should().BeOfType <ArgumentNullException>();
        }
        public void GetAllowListEntries_WithDuplicateFingerprints_DifferentHashAlgorithm_TakesThemAsDifferentEntries()
        {
            // Arrange
            var config = @"
<configuration>
    <trustedSigners>
        <repository name=""repository1"" serviceIndex=""api.v3ServiceIndex.test/json"">
            <certificate fingerprint=""abc"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
            <certificate fingerprint=""def"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
            <certificate fingerprint=""abc"" hashAlgorithm=""SHA512"" allowUntrustedRoot=""false"" />
            <owners>nuget;randomOwner</owners>
        </repository>
        <author name=""author1"">
            <certificate fingerprint=""jkl"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
            <certificate fingerprint=""abc"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </author>
    </trustedSigners>
</configuration>";

            var nugetConfigPath = "NuGet.Config";

            using (var mockBaseDirectory = TestDirectory.Create())
            {
                SettingsTestUtils.CreateConfigurationFile(nugetConfigPath, mockBaseDirectory, config);

                // Act and Assert
                var settings = new Settings(mockBaseDirectory);
                settings.Should().NotBeNull();

                var entries = TrustedSignersProvider.GetAllowListEntries(settings, NullLogger.Instance);
                entries.Should().NotBeNull();
                entries.Count.Should().Be(4);

                var expectedEntries = new List <VerificationAllowListEntry>()
                {
                    new TrustedSignerAllowListEntry(VerificationTarget.Repository, SignaturePlacement.Any, "abc", HashAlgorithmName.SHA512, owners: new List <string>()
                    {
                        "nuget", "randomOwner"
                    }),
                    new TrustedSignerAllowListEntry(VerificationTarget.Author | VerificationTarget.Repository, SignaturePlacement.Any, "abc", HashAlgorithmName.SHA256, owners: new List <string>()
                    {
                        "nuget", "randomOwner"
                    }),
                    new TrustedSignerAllowListEntry(VerificationTarget.Repository, SignaturePlacement.Any, "def", HashAlgorithmName.SHA256, owners: new List <string>()
                    {
                        "nuget", "randomOwner"
                    }),
                    new TrustedSignerAllowListEntry(VerificationTarget.Author, SignaturePlacement.PrimarySignature, "jkl", HashAlgorithmName.SHA256),
                };

                entries.Should().BeEquivalentTo(expectedEntries);
            }
        }
        public void GetAllowListEntries_TrustedRepository_WithMultipleCertificates_ParsedCorrectly()
        {
            // Arrange
            var config = @"
<configuration>
    <trustedSigners>
        <repository name=""repository1"" serviceIndex=""api.v3ServiceIndex.test/json"">
            <certificate fingerprint=""abc"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
            <certificate fingerprint=""def"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
            <certificate fingerprint=""ghi"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </repository>
        <repository name=""repository2"" serviceIndex=""api.v3ServiceIndex.test/json"">
            <certificate fingerprint=""jkl"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
            <certificate fingerprint=""mno"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </repository>
    </trustedSigners>
</configuration>";

            var nugetConfigPath = "NuGet.Config";

            using (var mockBaseDirectory = TestDirectory.Create())
            {
                SettingsTestUtils.CreateConfigurationFile(nugetConfigPath, mockBaseDirectory, config);

                // Act and Assert
                var settings = new Settings(mockBaseDirectory);
                settings.Should().NotBeNull();

                var entries = TrustedSignersProvider.GetAllowListEntries(settings, NullLogger.Instance);
                entries.Should().NotBeNull();
                entries.Count.Should().Be(5);

                var expectedEntries = new List <VerificationAllowListEntry>()
                {
                    new TrustedSignerAllowListEntry(VerificationTarget.Repository, SignaturePlacement.Any, "abc", HashAlgorithmName.SHA256),
                    new TrustedSignerAllowListEntry(VerificationTarget.Repository, SignaturePlacement.Any, "def", HashAlgorithmName.SHA256),
                    new TrustedSignerAllowListEntry(VerificationTarget.Repository, SignaturePlacement.Any, "ghi", HashAlgorithmName.SHA256),
                    new TrustedSignerAllowListEntry(VerificationTarget.Repository, SignaturePlacement.Any, "jkl", HashAlgorithmName.SHA256),
                    new TrustedSignerAllowListEntry(VerificationTarget.Repository, SignaturePlacement.Any, "mno", HashAlgorithmName.SHA256)
                };

                entries.Should().BeEquivalentTo(expectedEntries);
            }
        }
        public void GetAllowListEntries_WithoutTrustedSignersSection_ReturnsEmptyList()
        {
            // Arrange
            var config = @"
<configuration>
</configuration>";

            var nugetConfigPath = "NuGet.Config";

            using (var mockBaseDirectory = TestDirectory.Create())
            {
                SettingsTestUtils.CreateConfigurationFile(nugetConfigPath, mockBaseDirectory, config);

                // Act and Assert
                var settings = new Settings(mockBaseDirectory);
                settings.Should().NotBeNull();

                var entries = TrustedSignersProvider.GetAllowListEntries(settings, NullLogger.Instance);
                entries.Should().NotBeNull();
                entries.Should().BeEmpty();
            }
        }
        public void GetAllowListEntries_TrustedAuthor_WithOneCertificate_ParsedCorrectly()
        {
            // Arrange
            var config = @"
<configuration>
    <trustedSigners>
        <author name=""author1"">
            <certificate fingerprint=""abc"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </author>
        <author name=""author2"">
            <certificate fingerprint=""def"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </author>
    </trustedSigners>
</configuration>";

            var nugetConfigPath = "NuGet.Config";

            using (var mockBaseDirectory = TestDirectory.Create())
            {
                SettingsTestUtils.CreateConfigurationFile(nugetConfigPath, mockBaseDirectory, config);

                // Act and Assert
                var settings = new Settings(mockBaseDirectory);
                settings.Should().NotBeNull();

                var entries = TrustedSignersProvider.GetAllowListEntries(settings, NullLogger.Instance);
                entries.Should().NotBeNull();
                entries.Count.Should().Be(2);

                var expectedEntries = new List <VerificationAllowListEntry>()
                {
                    new TrustedSignerAllowListEntry(VerificationTarget.Author, SignaturePlacement.PrimarySignature, "abc", HashAlgorithmName.SHA256),
                    new TrustedSignerAllowListEntry(VerificationTarget.Author, SignaturePlacement.PrimarySignature, "def", HashAlgorithmName.SHA256)
                };

                entries.Should().BeEquivalentTo(expectedEntries);
            }
        }