diff --git a/src/Sign.Cli/AzureCredentialOptions.cs b/src/Sign.Cli/AzureCredentialOptions.cs index c6380457..c85fb7b4 100644 --- a/src/Sign.Cli/AzureCredentialOptions.cs +++ b/src/Sign.Cli/AzureCredentialOptions.cs @@ -5,6 +5,7 @@ using System.CommandLine; using System.CommandLine.Invocation; using System.CommandLine.IO; +using System.CommandLine.Parsing; using Azure.Core; using Azure.Identity; @@ -12,19 +13,41 @@ namespace Sign.Cli { internal sealed class AzureCredentialOptions { - internal Option ManagedIdentityOption { get; } = new(["-kvm", "--azure-key-vault-managed-identity"], Resources.ManagedIdentityOptionDescription); + internal Option CredentialTypeOption { get; } = new Option(["-act", "--azure-credential-type"], Resources.CredentialTypeOptionDescription).FromAmong( + AzureCredentialType.Environment); + internal Option ManagedIdentityOption { get; } = new(["-kvm", "--azure-key-vault-managed-identity"], Resources.ManagedIdentityOptionDescription) { IsHidden = true }; internal Option TenantIdOption { get; } = new(["-kvt", "--azure-key-vault-tenant-id"], Resources.TenantIdOptionDescription); internal Option ClientIdOption { get; } = new(["-kvi", "--azure-key-vault-client-id"], Resources.ClientIdOptionDescription); internal Option ClientSecretOption { get; } = new(["-kvs", "--azure-key-vault-client-secret"], Resources.ClientSecretOptionDescription); internal void AddOptionsToCommand(Command command) { + command.AddOption(CredentialTypeOption); command.AddOption(ManagedIdentityOption); command.AddOption(TenantIdOption); command.AddOption(ClientIdOption); command.AddOption(ClientSecretOption); } + internal DefaultAzureCredentialOptions CreateDefaultAzureCredentialOptions(ParseResult parseResult) + { + DefaultAzureCredentialOptions options = new(); + + string? credentialType = parseResult.GetValueForOption(CredentialTypeOption); + if (credentialType is not null) + { + options.ExcludeAzureCliCredential = true; + options.ExcludeAzureDeveloperCliCredential = true; + options.ExcludeAzurePowerShellCredential = true; + options.ExcludeEnvironmentCredential = credentialType != AzureCredentialType.Environment; + options.ExcludeManagedIdentityCredential = true; + options.ExcludeVisualStudioCredential = true; + options.ExcludeWorkloadIdentityCredential = true; + } + + return options; + } + internal TokenCredential? CreateTokenCredential(InvocationContext context) { bool? useManagedIdentity = context.ParseResult.GetValueForOption(ManagedIdentityOption); @@ -45,7 +68,8 @@ internal void AddOptionsToCommand(Command command) return new ClientSecretCredential(tenantId, clientId, secret); } - return new DefaultAzureCredential(); + DefaultAzureCredentialOptions options = CreateDefaultAzureCredentialOptions(context.ParseResult); + return new DefaultAzureCredential(options); } } } diff --git a/src/Sign.Cli/AzureCredentialType.cs b/src/Sign.Cli/AzureCredentialType.cs new file mode 100644 index 00000000..d9da1200 --- /dev/null +++ b/src/Sign.Cli/AzureCredentialType.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE.txt file in the project root for more information. + +namespace Sign.Cli +{ + internal static class AzureCredentialType + { + public const string Environment = "environment"; + } +} diff --git a/src/Sign.Cli/Resources.Designer.cs b/src/Sign.Cli/Resources.Designer.cs index f58b91f0..dc686498 100644 --- a/src/Sign.Cli/Resources.Designer.cs +++ b/src/Sign.Cli/Resources.Designer.cs @@ -114,6 +114,15 @@ internal static string CodeCommandDescription { } } + /// + /// Looks up a localized string similar to Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code.. + /// + internal static string CredentialTypeOptionDescription { + get { + return ResourceManager.GetString("CredentialTypeOptionDescription", resourceCulture); + } + } + /// /// Looks up a localized string similar to Description of the signing certificate.. /// diff --git a/src/Sign.Cli/Resources.resx b/src/Sign.Cli/Resources.resx index daf1555d..65dd43e5 100644 --- a/src/Sign.Cli/Resources.resx +++ b/src/Sign.Cli/Resources.resx @@ -135,6 +135,9 @@ Sign binaries and containers. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Description of the signing certificate. diff --git a/src/Sign.Cli/xlf/Resources.cs.xlf b/src/Sign.Cli/xlf/Resources.cs.xlf index db722b16..1cf3427b 100644 --- a/src/Sign.Cli/xlf/Resources.cs.xlf +++ b/src/Sign.Cli/xlf/Resources.cs.xlf @@ -32,6 +32,11 @@ Podepisovat binární soubory a kontejnery. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. Popis podpisového certifikátu. diff --git a/src/Sign.Cli/xlf/Resources.de.xlf b/src/Sign.Cli/xlf/Resources.de.xlf index b00461c5..23cae140 100644 --- a/src/Sign.Cli/xlf/Resources.de.xlf +++ b/src/Sign.Cli/xlf/Resources.de.xlf @@ -32,6 +32,11 @@ Signieren Sie Binärdateien und Container. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. Beschreibung des Signaturzertifikats. diff --git a/src/Sign.Cli/xlf/Resources.es.xlf b/src/Sign.Cli/xlf/Resources.es.xlf index 8035034b..f163508c 100644 --- a/src/Sign.Cli/xlf/Resources.es.xlf +++ b/src/Sign.Cli/xlf/Resources.es.xlf @@ -32,6 +32,11 @@ Firmar archivos binarios y contenedores. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. Descripción del certificado de firma. diff --git a/src/Sign.Cli/xlf/Resources.fr.xlf b/src/Sign.Cli/xlf/Resources.fr.xlf index e23944ea..47a0309f 100644 --- a/src/Sign.Cli/xlf/Resources.fr.xlf +++ b/src/Sign.Cli/xlf/Resources.fr.xlf @@ -32,6 +32,11 @@ Signer les fichiers binaires et les conteneurs. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. Description du certificat de signature. diff --git a/src/Sign.Cli/xlf/Resources.it.xlf b/src/Sign.Cli/xlf/Resources.it.xlf index dc084deb..9d2847d6 100644 --- a/src/Sign.Cli/xlf/Resources.it.xlf +++ b/src/Sign.Cli/xlf/Resources.it.xlf @@ -32,6 +32,11 @@ Consente di firmare file binari e contenitori. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. Descrizione del certificato di firma. diff --git a/src/Sign.Cli/xlf/Resources.ja.xlf b/src/Sign.Cli/xlf/Resources.ja.xlf index 575b64b7..78e2be68 100644 --- a/src/Sign.Cli/xlf/Resources.ja.xlf +++ b/src/Sign.Cli/xlf/Resources.ja.xlf @@ -32,6 +32,11 @@ バイナリとコンテナーに署名します。 + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. 署名証明書の説明。 diff --git a/src/Sign.Cli/xlf/Resources.ko.xlf b/src/Sign.Cli/xlf/Resources.ko.xlf index a0e3d012..a69168ff 100644 --- a/src/Sign.Cli/xlf/Resources.ko.xlf +++ b/src/Sign.Cli/xlf/Resources.ko.xlf @@ -32,6 +32,11 @@ 이진 파일 및 컨테이너에 서명합니다. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. 서명 인증서에 대한 설명입니다. diff --git a/src/Sign.Cli/xlf/Resources.pl.xlf b/src/Sign.Cli/xlf/Resources.pl.xlf index f172e0a4..f589edb8 100644 --- a/src/Sign.Cli/xlf/Resources.pl.xlf +++ b/src/Sign.Cli/xlf/Resources.pl.xlf @@ -32,6 +32,11 @@ Podpisz pliki binarne i kontenery. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. Opis certyfikatu podpisywania. diff --git a/src/Sign.Cli/xlf/Resources.pt-BR.xlf b/src/Sign.Cli/xlf/Resources.pt-BR.xlf index 2d8996d8..138c68a0 100644 --- a/src/Sign.Cli/xlf/Resources.pt-BR.xlf +++ b/src/Sign.Cli/xlf/Resources.pt-BR.xlf @@ -32,6 +32,11 @@ Autenticar contêineres e binários. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. Descrição do certificado de autenticação. diff --git a/src/Sign.Cli/xlf/Resources.ru.xlf b/src/Sign.Cli/xlf/Resources.ru.xlf index aa52487a..0b590542 100644 --- a/src/Sign.Cli/xlf/Resources.ru.xlf +++ b/src/Sign.Cli/xlf/Resources.ru.xlf @@ -32,6 +32,11 @@ Подписывание двоичных файлов и контейнеров. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. Описание сертификата для подписи diff --git a/src/Sign.Cli/xlf/Resources.tr.xlf b/src/Sign.Cli/xlf/Resources.tr.xlf index 2016ae4b..203776f2 100644 --- a/src/Sign.Cli/xlf/Resources.tr.xlf +++ b/src/Sign.Cli/xlf/Resources.tr.xlf @@ -32,6 +32,11 @@ İkili dosyaları ve kapsayıcıları imzalayın. + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. İmzalama sertifikasının açıklaması. diff --git a/src/Sign.Cli/xlf/Resources.zh-Hans.xlf b/src/Sign.Cli/xlf/Resources.zh-Hans.xlf index 3a62e4f7..5d1f5323 100644 --- a/src/Sign.Cli/xlf/Resources.zh-Hans.xlf +++ b/src/Sign.Cli/xlf/Resources.zh-Hans.xlf @@ -32,6 +32,11 @@ 对二进制文件和容器进行签名。 + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. 签名证书的说明。 diff --git a/src/Sign.Cli/xlf/Resources.zh-Hant.xlf b/src/Sign.Cli/xlf/Resources.zh-Hant.xlf index a6145466..4e87305a 100644 --- a/src/Sign.Cli/xlf/Resources.zh-Hant.xlf +++ b/src/Sign.Cli/xlf/Resources.zh-Hant.xlf @@ -32,6 +32,11 @@ 簽署二進位檔和容器。 + + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + Azure credential type that will be used. This defaults to all types except interactive browser, shared token and Visual Studio Code. + + Description of the signing certificate. 簽署憑證的描述。 diff --git a/test/Sign.Cli.Test/AzureCredentialOptionsTests.cs b/test/Sign.Cli.Test/AzureCredentialOptionsTests.cs index c267d2e7..46d0327c 100644 --- a/test/Sign.Cli.Test/AzureCredentialOptionsTests.cs +++ b/test/Sign.Cli.Test/AzureCredentialOptionsTests.cs @@ -3,12 +3,38 @@ // See the LICENSE.txt file in the project root for more information. using System.CommandLine; +using System.CommandLine.Builder; +using System.CommandLine.Parsing; +using Azure.Identity; +using Moq; +using Sign.Core; namespace Sign.Cli.Test { public class AzureCredentialOptionsTests { - private readonly AzureCredentialOptions _options = new(); + private readonly AzureCredentialOptions _options; + private readonly AzureKeyVaultCommand _command; + private readonly Parser _parser; + + public AzureCredentialOptionsTests() + { + _command = new(new CodeCommand(), Mock.Of()); + _parser = new CommandLineBuilder(_command).Build(); + _options = _command.AzureCredentialOptions; + } + + [Fact] + public void CredentialTypeOption_Always_HasArityOfExactlyOne() + { + Assert.Equal(ArgumentArity.ExactlyOne, _options.CredentialTypeOption.Arity); + } + + [Fact] + public void CredentialTypeOption_Always_IsNotRequired() + { + Assert.False(_options.CredentialTypeOption.IsRequired); + } [Fact] public void ManagedIdentityOption_Always_HasArityOfZeroOrOne() @@ -22,6 +48,12 @@ public void ManagedIdentityOption_Always_IsNotRequired() Assert.False(_options.ManagedIdentityOption.IsRequired); } + [Fact] + public void ManagedIdentityOption_Always_IsHidden() + { + Assert.True(_options.ManagedIdentityOption.IsHidden); + } + [Fact] public void TenantIdOption_Always_HasArityOfExactlyOne() { @@ -57,5 +89,57 @@ public void ClientSecretOption_Always_IsNotRequired() { Assert.False(_options.ClientSecretOption.IsRequired); } + + [Fact] + public void AddOptionsToCommand_Always_AddsAllOptionsToCommand() + { + var command = new Command("test"); + + _options.AddOptionsToCommand(command); + + Assert.Contains(_options.CredentialTypeOption, command.Options); + Assert.Contains(_options.ManagedIdentityOption, command.Options); + Assert.Contains(_options.TenantIdOption, command.Options); + Assert.Contains(_options.ClientIdOption, command.Options); + Assert.Contains(_options.ClientSecretOption, command.Options); + } + + [Fact] + public void CreateDefaultAzureCredentialOptions_WhenNoOptionsAreSpecified_ExcludeOptionsHaveTheCorrectDefaultValues() + { + ParseResult result = _parser.Parse("azure-key-vault -kvu https://keyvault.test -kvc a b"); + + DefaultAzureCredentialOptions credentialOptions = _options.CreateDefaultAzureCredentialOptions(result); + + Assert.True(credentialOptions.ExcludeInteractiveBrowserCredential); + Assert.True(credentialOptions.ExcludeSharedTokenCacheCredential); + Assert.True(credentialOptions.ExcludeVisualStudioCodeCredential); + Assert.False(credentialOptions.ExcludeAzureCliCredential); + Assert.False(credentialOptions.ExcludeAzureDeveloperCliCredential); + Assert.False(credentialOptions.ExcludeAzurePowerShellCredential); + Assert.False(credentialOptions.ExcludeEnvironmentCredential); + Assert.False(credentialOptions.ExcludeManagedIdentityCredential); + Assert.False(credentialOptions.ExcludeVisualStudioCredential); + Assert.False(credentialOptions.ExcludeWorkloadIdentityCredential); + } + + [Fact] + public void CreateDefaultAzureCredentialOptions_WhenEnvironmentIsSpecified_ExcludeOptionsHaveTheCorrectValues() + { + ParseResult result = _parser.Parse(@"azure-key-vault -kvu https://keyvault.test -kvc a -act environment b"); + + DefaultAzureCredentialOptions credentialOptions = _options.CreateDefaultAzureCredentialOptions(result); + + Assert.True(credentialOptions.ExcludeAzureCliCredential); + Assert.True(credentialOptions.ExcludeAzureDeveloperCliCredential); + Assert.True(credentialOptions.ExcludeAzurePowerShellCredential); + Assert.False(credentialOptions.ExcludeEnvironmentCredential); + Assert.True(credentialOptions.ExcludeInteractiveBrowserCredential); + Assert.True(credentialOptions.ExcludeManagedIdentityCredential); + Assert.True(credentialOptions.ExcludeSharedTokenCacheCredential); + Assert.True(credentialOptions.ExcludeVisualStudioCodeCredential); + Assert.True(credentialOptions.ExcludeVisualStudioCredential); + Assert.True(credentialOptions.ExcludeWorkloadIdentityCredential); + } } }