コード例 #1
0
        public void GetTrustedSigner_WithEmptyTrustedSignersSection_ReturnsEmptyList()
        {
            // Arrange
            var config = @"
<configuration>
    <trustedSigners>
    </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 trustedSignerProvider = new TrustedSignersProvider(settings);

                var trustedSigners = trustedSignerProvider.GetTrustedSigners();
                trustedSigners.Should().NotBeNull();
                trustedSigners.Should().BeEmpty();
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        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>();
        }
コード例 #4
0
        public void AddOrUpdateTrustedSigner_WithNullItem_Throws()
        {
            var trustedSignersProvider = new TrustedSignersProvider(settings: NullSettings.Instance);

            // Act and Assert
            var ex = Record.Exception(() => trustedSignersProvider.AddOrUpdateTrustedSigner(trustedSigner: null));

            ex.Should().NotBeNull();
            ex.Should().BeOfType <ArgumentNullException>();
        }
コード例 #5
0
        public void Remove_WithEmptyListOFSignersToRemove_Throws()
        {
            var trustedSignersProvider = new TrustedSignersProvider(settings: NullSettings.Instance);

            // Act and Assert
            var ex = Record.Exception(() => trustedSignersProvider.Remove(trustedSigners: new List <TrustedSignerItem>()));

            ex.Should().NotBeNull();
            ex.Should().BeOfType <ArgumentException>();
        }
コード例 #6
0
        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);
            }
        }
コード例 #7
0
        public void AddOrUpdateTrustedSigner_WithNewTrustedSigner_AddsItSuccesfully()
        {
            // 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>
        <repository name=""repo1"" serviceIndex=""https://serviceIndex.test/v3/api.json"">
            <certificate fingerprint=""ghi"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </repository>
    </trustedSigners>
</configuration>";

            var nugetConfigPath = "NuGet.Config";

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

                var expectedTrustedSigners = new List <TrustedSignerItem>()
                {
                    new AuthorItem("author1", new CertificateItem("abc", HashAlgorithmName.SHA256)),
                    new AuthorItem("author2", new CertificateItem("def", HashAlgorithmName.SHA256)),
                    new RepositoryItem("repo1", "https://serviceIndex.test/v3/api.json", new CertificateItem("ghi", HashAlgorithmName.SHA256)),
                    new AuthorItem("author3", new CertificateItem("jkl", HashAlgorithmName.SHA256)),
                };

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

                var trustedSignerProvider = new TrustedSignersProvider(settings);

                trustedSignerProvider.AddOrUpdateTrustedSigner(new AuthorItem("author3", new CertificateItem("jkl", HashAlgorithmName.SHA256)));

                var trustedSigners = trustedSignerProvider.GetTrustedSigners();
                trustedSigners.Should().NotBeNull();
                trustedSigners.Count.Should().Be(4);
                trustedSigners.Should().BeEquivalentTo(
                    expectedTrustedSigners,
                    options => options
                    .Excluding(o => o.Path == "[0].Origin")
                    .Excluding(o => o.Path == "[1].Origin")
                    .Excluding(o => o.Path == "[2].Origin")
                    .Excluding(o => o.Path == "[3].Origin"));
            }
        }
コード例 #8
0
        public override async Task ExecuteCommandAsync()
        {
            var actionString = Arguments.FirstOrDefault();

            TrustedSignersAction action;

            if (string.IsNullOrEmpty(actionString))
            {
                action = TrustedSignersAction.List;
            }
            else if (!Enum.TryParse(actionString, ignoreCase: true, result: out action))
            {
                throw new CommandLineArgumentCombinationException(string.Format(CultureInfo.CurrentCulture, NuGetResources.Error_UnknownAction, actionString));
            }

            string packagePath = null;

            if (Arguments.Count() > 1)
            {
                packagePath = Arguments[1];
            }

            var trustedSignersProvider = new TrustedSignersProvider(Settings);

            var trustedSignersArgs = new TrustedSignersArgs()
            {
                Action                 = action,
                PackagePath            = packagePath,
                Name                   = Name,
                ServiceIndex           = ServiceIndex,
                CertificateFingerprint = CertificateFingerprint,
                FingerprintAlgorithm   = FingerprintAlgorithm,
                AllowUntrustedRoot     = AllowUntrustedRoot,
                Author                 = Author,
                Repository             = Repository,
                Owners                 = Owners,
                Logger                 = Console
            };

            if (TrustedSignersCommandRunner == null)
            {
                TrustedSignersCommandRunner = new TrustedSignersCommandRunner(trustedSignersProvider, SourceProvider);
            }

            var result = await TrustedSignersCommandRunner.ExecuteCommandAsync(trustedSignersArgs);

            if (result > 0)
            {
                throw new ExitCodeException(1);
            }
        }
コード例 #9
0
        public void GetTrustedSigner_WithItemsDifferentThanTrustedSigners_IgnoresThemAndOnlyReturnsTrustedSigners()
        {
            // Arrange
            var config = @"
<configuration>
    <trustedSigners>
        <add key=""oneKey"" value=""val"" />
        <author name=""author1"">
            <certificate fingerprint=""abc"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </author>
        <author name=""author2"">
            <certificate fingerprint=""def"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </author>
        <certificate fingerprint=""ghi"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        <repository name=""repo1"" serviceIndex=""https://serviceIndex.test/v3/api.json"">
            <certificate fingerprint=""ghi"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </repository>
        <add key=""otherKey"" value=""val"" />
    </trustedSigners>
</configuration>";

            var nugetConfigPath = "NuGet.Config";

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

                var expectedTrustedSigners = new List <TrustedSignerItem>()
                {
                    new AuthorItem("author1", new CertificateItem("abc", HashAlgorithmName.SHA256)),
                    new AuthorItem("author2", new CertificateItem("def", HashAlgorithmName.SHA256)),
                    new RepositoryItem("repo1", "https://serviceIndex.test/v3/api.json", new CertificateItem("ghi", HashAlgorithmName.SHA256))
                };

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

                var trustedSignerProvider = new TrustedSignersProvider(settings);

                var trustedSigners = trustedSignerProvider.GetTrustedSigners();
                trustedSigners.Should().NotBeNull();
                trustedSigners.Count.Should().Be(3);
                trustedSigners.Should().BeEquivalentTo(
                    expectedTrustedSigners,
                    options => options
                    .Excluding(o => o.SelectedMemberPath == "[0].Origin")
                    .Excluding(o => o.SelectedMemberPath == "[1].Origin")
                    .Excluding(o => o.SelectedMemberPath == "[2].Origin"));
            }
        }
コード例 #10
0
        public void Remove_IgnoresAnyUnexistantTrustedSigner()
        {
            // 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>
        <repository name=""repo1"" serviceIndex=""https://serviceIndex.test/v3/api.json"">
            <certificate fingerprint=""ghi"" hashAlgorithm=""SHA256"" allowUntrustedRoot=""false"" />
        </repository>
    </trustedSigners>
</configuration>";

            var nugetConfigPath = "NuGet.Config";

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

                var expectedTrustedSigners = new List <TrustedSignerItem>()
                {
                    new AuthorItem("author2", new CertificateItem("def", HashAlgorithmName.SHA256)),
                    new RepositoryItem("repo1", "https://serviceIndex.test/v3/api.json", new CertificateItem("ghi", HashAlgorithmName.SHA256))
                };

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

                var trustedSignerProvider = new TrustedSignersProvider(settings);

                var trustedSigners = trustedSignerProvider.GetTrustedSigners();
                trustedSignerProvider.Remove(new[] { trustedSigners.First(), new AuthorItem("DontExist", new CertificateItem("abc", HashAlgorithmName.SHA256)) });

                trustedSigners = trustedSignerProvider.GetTrustedSigners();
                trustedSigners.Should().NotBeNull();
                trustedSigners.Count.Should().Be(2);
                trustedSigners.Should().BeEquivalentTo(expectedTrustedSigners);
            }
        }
コード例 #11
0
        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);
            }
        }
コード例 #12
0
        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();
            }
        }
コード例 #13
0
        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);
            }
        }
コード例 #14
0
        private static async Task <int> ExecuteCommand(TrustCommand action,
                                                       CommandOption algorithm,
                                                       bool allowUntrustedRootOption,
                                                       CommandOption owners,
                                                       CommandOption verbosity,
                                                       CommandOption configFile,
                                                       Func <ILogger> getLogger,
                                                       Action <LogLevel> setLogLevel,
                                                       string name        = null,
                                                       string sourceUrl   = null,
                                                       string packagePath = null,
                                                       string fingerprint = null)
        {
            ILogger logger = getLogger();

            try
            {
                ISettings settings = XPlatUtility.ProcessConfigFile(configFile.Value());

                var trustedSignersArgs = new TrustedSignersArgs()
                {
                    Action                 = MapTrustEnumAction(action),
                    PackagePath            = packagePath,
                    Name                   = name,
                    ServiceIndex           = sourceUrl,
                    CertificateFingerprint = fingerprint,
                    FingerprintAlgorithm   = algorithm?.Value(),
                    AllowUntrustedRoot     = allowUntrustedRootOption,
                    Author                 = action == TrustCommand.Author,
                    Repository             = action == TrustCommand.Repository,
                    Owners                 = CommandLineUtility.SplitAndJoinAcrossMultipleValues(owners?.Values),
                    Logger                 = logger
                };

                setLogLevel(XPlatUtility.MSBuildVerbosityToNuGetLogLevel(verbosity.Value()));

                // Add is the only action which does certificate chain building.
                if (trustedSignersArgs.Action == TrustedSignersAction.Add)
                {
                    X509TrustStore.InitializeForDotNetSdk(logger);
                }

#pragma warning disable CS0618 // Type or member is obsolete
                var sourceProvider = new PackageSourceProvider(settings, enablePackageSourcesChangedEvent: false);
#pragma warning restore CS0618 // Type or member is obsolete
                var trustedSignersProvider = new TrustedSignersProvider(settings);

                var        runner          = new TrustedSignersCommandRunner(trustedSignersProvider, sourceProvider);
                Task <int> trustedSignTask = runner.ExecuteCommandAsync(trustedSignersArgs);
                return(await trustedSignTask);
            }
            catch (InvalidOperationException e)
            {
                // nuget trust command handled exceptions.
                if (!string.IsNullOrWhiteSpace(name))
                {
                    var error_TrustedSignerAlreadyExistsMessage = string.Format(CultureInfo.CurrentCulture, Strings.Error_TrustedSignerAlreadyExists, name);

                    if (e.Message == error_TrustedSignerAlreadyExistsMessage)
                    {
                        logger.LogError(error_TrustedSignerAlreadyExistsMessage);
                        return(1);
                    }
                }

                if (!string.IsNullOrWhiteSpace(sourceUrl))
                {
                    var error_TrustedRepoAlreadyExists = string.Format(CultureInfo.CurrentCulture, Strings.Error_TrustedRepoAlreadyExists, sourceUrl);

                    if (e.Message == error_TrustedRepoAlreadyExists)
                    {
                        logger.LogError(error_TrustedRepoAlreadyExists);
                        return(1);
                    }
                }

                throw;
            }
            catch (ArgumentException e)
            {
                if (e.Data is System.Collections.IDictionary)
                {
                    logger.LogError(string.Format(CultureInfo.CurrentCulture, Strings.Error_TrustFingerPrintAlreadyExist));
                    return(1);
                }

                throw;
            }
        }
コード例 #15
0
        internal static void Register(CommandLineApplication app,
                                      Func <ILogger> getLogger,
                                      Action <LogLevel> setLogLevel)
        {
            app.Command("trust", trustedSignersCmd =>
            {
                CommandArgument command = trustedSignersCmd.Argument(
                    "<command>",
                    Strings.TrustCommandActionDescription,
                    multipleValues: true);

                CommandOption algorithm = trustedSignersCmd.Option(
                    "--algorithm",
                    Strings.TrustCommandAlgorithm,
                    CommandOptionType.SingleValue);

                CommandOption allowUntrustedRootOption = trustedSignersCmd.Option(
                    "--allow-untrusted-root",
                    Strings.TrustCommandAllowUntrustedRoot,
                    CommandOptionType.NoValue);

                CommandOption owners = trustedSignersCmd.Option(
                    "--owners",
                    Strings.TrustCommandOwners,
                    CommandOptionType.MultipleValue);

                CommandOption verbosity = trustedSignersCmd.Option(
                    "-v|--verbosity",
                    Strings.Verbosity_Description,
                    CommandOptionType.SingleValue);

                CommandOption configFile = trustedSignersCmd.Option(
                    "--configfile",
                    Strings.Option_ConfigFile,
                    CommandOptionType.SingleValue);

                trustedSignersCmd.HelpOption(XPlatUtility.HelpOption);
                trustedSignersCmd.Description = Strings.TrustCommandDescription;

                trustedSignersCmd.OnExecute(async() =>
                {
                    TrustCommand action;

                    if (!command.Values.Any() || string.IsNullOrEmpty(command.Values[0]))
                    {
                        action = TrustCommand.List;
                    }
                    else if (!Enum.TryParse(command.Values[0], ignoreCase: true, result: out action))
                    {
                        throw new CommandLineArgumentCombinationException(string.Format(CultureInfo.CurrentCulture, Strings.Error_UnknownAction, command.Values[0]));
                    }

                    string name = null;

                    if (command.Values.Count > 1)
                    {
                        name = command.Values[1];
                    }

                    string packagePath = null;
                    string sourceUrl   = null;
                    string fingerprint = null;
                    if (command.Values.Count() > 2)
                    {
                        if (action == TrustCommand.Author || action == TrustCommand.Repository)
                        {
                            packagePath = command.Values[2];
                        }
                        else if (action == TrustCommand.Source)
                        {
                            sourceUrl = command.Values[2];
                        }
                        else if (action == TrustCommand.Certificate)
                        {
                            fingerprint = command.Values[2];
                        }
                    }

                    ISettings settings = ProcessConfigFile(configFile.Value());

                    var trustedSignersArgs = new TrustedSignersArgs()
                    {
                        Action                 = MapTrustEnumAction(action),
                        PackagePath            = packagePath,
                        Name                   = name,
                        ServiceIndex           = sourceUrl,
                        CertificateFingerprint = fingerprint,
                        FingerprintAlgorithm   = algorithm.Value(),
                        AllowUntrustedRoot     = allowUntrustedRootOption.HasValue(),
                        Author                 = action == TrustCommand.Author,
                        Repository             = action == TrustCommand.Repository,
                        Owners                 = CommandLineUtility.SplitAndJoinAcrossMultipleValues(owners.Values),
                        Logger                 = getLogger()
                    };

                    setLogLevel(XPlatUtility.MSBuildVerbosityToNuGetLogLevel(verbosity.Value()));

#pragma warning disable CS0618 // Type or member is obsolete
                    var sourceProvider = new PackageSourceProvider(settings, enablePackageSourcesChangedEvent: false);
#pragma warning restore CS0618 // Type or member is obsolete
                    var trustedSignersProvider = new TrustedSignersProvider(settings);

                    var runner = new TrustedSignersCommandRunner(trustedSignersProvider, sourceProvider);
                    Task <int> trustedSignTask = runner.ExecuteCommandAsync(trustedSignersArgs);
                    return(await trustedSignTask);
                });
            });
        }