diff --git a/Directory.Packages.props b/Directory.Packages.props index 84fa4b7f..865516c9 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,6 +4,8 @@ true + + @@ -31,4 +33,4 @@ - \ No newline at end of file + diff --git a/sign.sln b/sign.sln index a66db519..bcd6c440 100644 --- a/sign.sln +++ b/sign.sln @@ -42,6 +42,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sign.SignatureProviders.Cer EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sign.SignatureProviders.CertificateStore.Test", "test\Sign.SignatureProviders.CertificateStore.Test\Sign.SignatureProviders.CertificateStore.Test.csproj", "{3AE48DC2-8422-4E3A-AFBC-12551D50DBCA}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sign.SignatureProviders.TrustedSigning", "src\Sign.SignatureProviders.TrustedSigning\Sign.SignatureProviders.TrustedSigning.csproj", "{060800AF-42FC-493C-AD99-9C87212BA969}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sign.SignatureProviders.TrustedSigning.Test", "test\Sign.SignatureProviders.TrustedSigning.Test\Sign.SignatureProviders.TrustedSigning.Test.csproj", "{A81695AF-088A-436A-9A38-4D0B0DB2D826}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -84,6 +88,14 @@ Global {3AE48DC2-8422-4E3A-AFBC-12551D50DBCA}.Debug|Any CPU.Build.0 = Debug|Any CPU {3AE48DC2-8422-4E3A-AFBC-12551D50DBCA}.Release|Any CPU.ActiveCfg = Release|Any CPU {3AE48DC2-8422-4E3A-AFBC-12551D50DBCA}.Release|Any CPU.Build.0 = Release|Any CPU + {060800AF-42FC-493C-AD99-9C87212BA969}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {060800AF-42FC-493C-AD99-9C87212BA969}.Debug|Any CPU.Build.0 = Debug|Any CPU + {060800AF-42FC-493C-AD99-9C87212BA969}.Release|Any CPU.ActiveCfg = Release|Any CPU + {060800AF-42FC-493C-AD99-9C87212BA969}.Release|Any CPU.Build.0 = Release|Any CPU + {A81695AF-088A-436A-9A38-4D0B0DB2D826}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A81695AF-088A-436A-9A38-4D0B0DB2D826}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A81695AF-088A-436A-9A38-4D0B0DB2D826}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A81695AF-088A-436A-9A38-4D0B0DB2D826}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -98,6 +110,8 @@ Global {47F03ADD-A646-44C8-92FA-9594CD4506E6} = {780818DD-6B52-47C8-AC54-71448DF822BD} {68104303-9832-4841-89AB-B98712C4E618} = {92C73EE1-4EF3-4721-B6A9-9F458A673CA3} {3AE48DC2-8422-4E3A-AFBC-12551D50DBCA} = {780818DD-6B52-47C8-AC54-71448DF822BD} + {060800AF-42FC-493C-AD99-9C87212BA969} = {92C73EE1-4EF3-4721-B6A9-9F458A673CA3} + {A81695AF-088A-436A-9A38-4D0B0DB2D826} = {780818DD-6B52-47C8-AC54-71448DF822BD} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7AA1043F-37A2-404F-8EC3-34C747C1CEB7} diff --git a/src/Sign.Cli/AzureCredentialOptions.cs b/src/Sign.Cli/AzureCredentialOptions.cs new file mode 100644 index 00000000..c6380457 --- /dev/null +++ b/src/Sign.Cli/AzureCredentialOptions.cs @@ -0,0 +1,51 @@ +// 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. + +using System.CommandLine; +using System.CommandLine.Invocation; +using System.CommandLine.IO; +using Azure.Core; +using Azure.Identity; + +namespace Sign.Cli +{ + internal sealed class AzureCredentialOptions + { + internal Option ManagedIdentityOption { get; } = new(["-kvm", "--azure-key-vault-managed-identity"], Resources.ManagedIdentityOptionDescription); + 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(ManagedIdentityOption); + command.AddOption(TenantIdOption); + command.AddOption(ClientIdOption); + command.AddOption(ClientSecretOption); + } + + internal TokenCredential? CreateTokenCredential(InvocationContext context) + { + bool? useManagedIdentity = context.ParseResult.GetValueForOption(ManagedIdentityOption); + + if (useManagedIdentity is not null) + { + context.Console.Out.WriteLine(Resources.ManagedIdentityOptionObsolete); + } + + string? tenantId = context.ParseResult.GetValueForOption(TenantIdOption); + string? clientId = context.ParseResult.GetValueForOption(ClientIdOption); + string? secret = context.ParseResult.GetValueForOption(ClientSecretOption); + + if (!string.IsNullOrEmpty(tenantId) && + !string.IsNullOrEmpty(clientId) && + !string.IsNullOrEmpty(secret)) + { + return new ClientSecretCredential(tenantId, clientId, secret); + } + + return new DefaultAzureCredential(); + } + } +} diff --git a/src/Sign.Cli/AzureKeyVaultCommand.cs b/src/Sign.Cli/AzureKeyVaultCommand.cs index 046080a6..ef423635 100644 --- a/src/Sign.Cli/AzureKeyVaultCommand.cs +++ b/src/Sign.Cli/AzureKeyVaultCommand.cs @@ -6,7 +6,6 @@ using System.CommandLine.Invocation; using System.CommandLine.IO; using Azure.Core; -using Azure.Identity; using Sign.Core; using Sign.SignatureProviders.KeyVault; @@ -14,14 +13,9 @@ namespace Sign.Cli { internal sealed class AzureKeyVaultCommand : Command { - private readonly CodeCommand _codeCommand; - - internal Option CertificateOption { get; } = new(["-kvc", "--azure-key-vault-certificate"], AzureKeyVaultResources.CertificateOptionDescription); - internal Option ClientIdOption { get; } = new(["-kvi", "--azure-key-vault-client-id"], AzureKeyVaultResources.ClientIdOptionDescription); - internal Option ClientSecretOption { get; } = new(["-kvs", "--azure-key-vault-client-secret"], AzureKeyVaultResources.ClientSecretOptionDescription); - internal Option ManagedIdentityOption { get; } = new(["-kvm", "--azure-key-vault-managed-identity"], getDefaultValue: () => false, AzureKeyVaultResources.ManagedIdentityOptionDescription); - internal Option TenantIdOption { get; } = new(["-kvt", "--azure-key-vault-tenant-id"], AzureKeyVaultResources.TenantIdOptionDescription); internal Option UrlOption { get; } = new(["-kvu", "--azure-key-vault-url"], AzureKeyVaultResources.UrlOptionDescription); + internal Option CertificateOption { get; } = new(["-kvc", "--azure-key-vault-certificate"], AzureKeyVaultResources.CertificateOptionDescription); + internal AzureCredentialOptions AzureCredentialOptions { get; } = new(); internal Argument FileArgument { get; } = new("file(s)", Resources.FilesArgumentDescription); @@ -31,19 +25,12 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s ArgumentNullException.ThrowIfNull(codeCommand, nameof(codeCommand)); ArgumentNullException.ThrowIfNull(serviceProviderFactory, nameof(serviceProviderFactory)); - _codeCommand = codeCommand; - CertificateOption.IsRequired = true; UrlOption.IsRequired = true; - ManagedIdentityOption.SetDefaultValue(false); - AddOption(UrlOption); - AddOption(TenantIdOption); - AddOption(ClientIdOption); - AddOption(ClientSecretOption); AddOption(CertificateOption); - AddOption(ManagedIdentityOption); + AzureCredentialOptions.AddOptionsToCommand(this); AddArgument(FileArgument); @@ -67,41 +54,19 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s return; } + TokenCredential? credential = AzureCredentialOptions.CreateTokenCredential(context); + if (credential is null) + { + return; + } + // Some of the options are required and that is why we can safely use // the null-forgiving operator (!) to simplify the code. Uri url = context.ParseResult.GetValueForOption(UrlOption)!; - string? tenantId = context.ParseResult.GetValueForOption(TenantIdOption); - string? clientId = context.ParseResult.GetValueForOption(ClientIdOption); - string? secret = context.ParseResult.GetValueForOption(ClientSecretOption); string certificateId = context.ParseResult.GetValueForOption(CertificateOption)!; - bool useManagedIdentity = context.ParseResult.GetValueForOption(ManagedIdentityOption); - - TokenCredential? credential = null; - - if (useManagedIdentity) - { - credential = new DefaultAzureCredential(); - } - else - { - if (string.IsNullOrEmpty(tenantId) || - string.IsNullOrEmpty(clientId) || - string.IsNullOrEmpty(secret)) - { - context.Console.Error.WriteFormattedLine( - AzureKeyVaultResources.InvalidClientSecretCredential, - TenantIdOption, - ClientIdOption, - ClientSecretOption); - context.ExitCode = ExitCode.NoInputsFound; - return; - } - - credential = new ClientSecretCredential(tenantId, clientId, secret); - } KeyVaultServiceProvider keyVaultServiceProvider = new(credential, url, certificateId); - await _codeCommand.HandleAsync(context, serviceProviderFactory, keyVaultServiceProvider, fileArgument); + await codeCommand.HandleAsync(context, serviceProviderFactory, keyVaultServiceProvider, fileArgument); }); } } diff --git a/src/Sign.Cli/AzureKeyVaultResources.Designer.cs b/src/Sign.Cli/AzureKeyVaultResources.Designer.cs index 6717fe00..ae840eba 100644 --- a/src/Sign.Cli/AzureKeyVaultResources.Designer.cs +++ b/src/Sign.Cli/AzureKeyVaultResources.Designer.cs @@ -78,24 +78,6 @@ internal static string ClickOnceExtensionNotSupported { } } - /// - /// Looks up a localized string similar to Client ID to authenticate to Azure Key Vault.. - /// - internal static string ClientIdOptionDescription { - get { - return ResourceManager.GetString("ClientIdOptionDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Client secret to authenticate to Azure Key Vault.. - /// - internal static string ClientSecretOptionDescription { - get { - return ResourceManager.GetString("ClientSecretOptionDescription", resourceCulture); - } - } - /// /// Looks up a localized string similar to Use Azure Key Vault.. /// @@ -105,33 +87,6 @@ internal static string CommandDescription { } } - /// - /// Looks up a localized string similar to If not using a managed identity, all of these options are required: {0}, {1}, and {2}.. - /// - internal static string InvalidClientSecretCredential { - get { - return ResourceManager.GetString("InvalidClientSecretCredential", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Managed identity to authenticate to Azure Key Vault.. - /// - internal static string ManagedIdentityOptionDescription { - get { - return ResourceManager.GetString("ManagedIdentityOptionDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Tenant ID to authenticate to Azure Key Vault.. - /// - internal static string TenantIdOptionDescription { - get { - return ResourceManager.GetString("TenantIdOptionDescription", resourceCulture); - } - } - /// /// Looks up a localized string similar to URL to an Azure Key Vault.. /// diff --git a/src/Sign.Cli/AzureKeyVaultResources.resx b/src/Sign.Cli/AzureKeyVaultResources.resx index 773e45dc..97762b0d 100644 --- a/src/Sign.Cli/AzureKeyVaultResources.resx +++ b/src/Sign.Cli/AzureKeyVaultResources.resx @@ -123,25 +123,9 @@ ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation. - - Client ID to authenticate to Azure Key Vault. - - - Client secret to authenticate to Azure Key Vault. - Use Azure Key Vault. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - - - Tenant ID to authenticate to Azure Key Vault. - URL to an Azure Key Vault. diff --git a/src/Sign.Cli/CertificateStoreCommand.cs b/src/Sign.Cli/CertificateStoreCommand.cs index 64605355..adefdc9f 100644 --- a/src/Sign.Cli/CertificateStoreCommand.cs +++ b/src/Sign.Cli/CertificateStoreCommand.cs @@ -15,8 +15,6 @@ namespace Sign.Cli { internal sealed class CertificateStoreCommand : Command { - private readonly CodeCommand _codeCommand; - internal Option CertificateFingerprintOption { get; } = new(["-cfp", "--certificate-fingerprint"], ParseCertificateFingerprint, description: CertificateStoreResources.CertificateFingerprintOptionDescription); internal Option CertificateFileOption { get; } = new(["-cf", "--certificate-file"], CertificateStoreResources.CertificateFileOptionDescription); internal Option CertificatePasswordOption { get; } = new(["-p", "--password"], CertificateStoreResources.CertificatePasswordOptionDescription); @@ -32,8 +30,6 @@ internal CertificateStoreCommand(CodeCommand codeCommand, IServiceProviderFactor ArgumentNullException.ThrowIfNull(codeCommand, nameof(codeCommand)); ArgumentNullException.ThrowIfNull(serviceProviderFactory, nameof(serviceProviderFactory)); - _codeCommand = codeCommand; - CertificateFingerprintOption.IsRequired = true; AddOption(CertificateFingerprintOption); @@ -111,7 +107,7 @@ internal CertificateStoreCommand(CodeCommand codeCommand, IServiceProviderFactor certificatePassword, useMachineKeyContainer); - await _codeCommand.HandleAsync(context, serviceProviderFactory, certificateStoreServiceProvider, fileArgument); + await codeCommand.HandleAsync(context, serviceProviderFactory, certificateStoreServiceProvider, fileArgument); }); } diff --git a/src/Sign.Cli/Resources.Designer.cs b/src/Sign.Cli/Resources.Designer.cs index 08783b2b..f58b91f0 100644 --- a/src/Sign.Cli/Resources.Designer.cs +++ b/src/Sign.Cli/Resources.Designer.cs @@ -87,6 +87,24 @@ internal static string CertificateStoreCommandDescription { } } + /// + /// Looks up a localized string similar to Client ID to authenticate to Azure.. + /// + internal static string ClientIdOptionDescription { + get { + return ResourceManager.GetString("ClientIdOptionDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Client secret to authenticate to Azure.. + /// + internal static string ClientSecretOptionDescription { + get { + return ResourceManager.GetString("ClientSecretOptionDescription", resourceCulture); + } + } + /// /// Looks up a localized string similar to Sign binaries and containers.. /// @@ -195,6 +213,24 @@ internal static string InvalidUrlValue { } } + /// + /// Looks up a localized string similar to Managed identity to authenticate to Azure Key. (obsolete). + /// + internal static string ManagedIdentityOptionDescription { + get { + return ResourceManager.GetString("ManagedIdentityOptionDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.. + /// + internal static string ManagedIdentityOptionObsolete { + get { + return ResourceManager.GetString("ManagedIdentityOptionObsolete", resourceCulture); + } + } + /// /// Looks up a localized string similar to Maximum concurrency.. /// @@ -258,6 +294,15 @@ internal static string SomeFilesDoNotExist { } } + /// + /// Looks up a localized string similar to Tenant ID to authenticate to Azure.. + /// + internal static string TenantIdOptionDescription { + get { + return ResourceManager.GetString("TenantIdOptionDescription", resourceCulture); + } + } + /// /// Looks up a localized string similar to Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512.. /// diff --git a/src/Sign.Cli/Resources.resx b/src/Sign.Cli/Resources.resx index 631c1d92..daf1555d 100644 --- a/src/Sign.Cli/Resources.resx +++ b/src/Sign.Cli/Resources.resx @@ -126,6 +126,12 @@ Use Windows Certificate Store or a local certificate file. + + Client ID to authenticate to Azure. + + + Client secret to authenticate to Azure. + Sign binaries and containers. @@ -168,6 +174,12 @@ Invalid value for {0}. The value must be an absolute HTTP or HTTPS URL. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + Maximum concurrency. @@ -191,6 +203,9 @@ Some files do not exist. Try using a different {0} value or a fully qualified file path. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. {Locked="RFC 3161"} is an Internet standard (https://www.rfc-editor.org/info/rfc3161), and {Locked="sha256", "sha384", "sha512"} are cryptographic hash algorithm names should not be localized. diff --git a/src/Sign.Cli/Sign.Cli.csproj b/src/Sign.Cli/Sign.Cli.csproj index d5b1a9f1..8c34c446 100644 --- a/src/Sign.Cli/Sign.Cli.csproj +++ b/src/Sign.Cli/Sign.Cli.csproj @@ -22,6 +22,7 @@ + @@ -68,6 +69,11 @@ True Resources.resx + + True + True + TrustedSigningResources.resx + @@ -83,5 +89,9 @@ ResXFileCodeGenerator Resources.Designer.cs + + ResXFileCodeGenerator + TrustedSigningResources.Designer.cs + - \ No newline at end of file + diff --git a/src/Sign.Cli/SignCommand.cs b/src/Sign.Cli/SignCommand.cs index ab7d8706..dc54a0a7 100644 --- a/src/Sign.Cli/SignCommand.cs +++ b/src/Sign.Cli/SignCommand.cs @@ -23,11 +23,17 @@ internal SignCommand(IServiceProviderFactory? serviceProviderFactory = null) codeCommand.AddCommand(azureKeyVaultCommand); - CertificateStoreCommand certManagerCommand = new( + CertificateStoreCommand certificateStoreCommand = new( codeCommand, serviceProviderFactory); - codeCommand.AddCommand(certManagerCommand); + codeCommand.AddCommand(certificateStoreCommand); + + TrustedSigningCommand trustedSigningCommand = new( + codeCommand, + serviceProviderFactory); + + codeCommand.AddCommand(trustedSigningCommand); } } -} \ No newline at end of file +} diff --git a/src/Sign.Cli/TrustedSigningCommand.cs b/src/Sign.Cli/TrustedSigningCommand.cs new file mode 100644 index 00000000..0c2809d8 --- /dev/null +++ b/src/Sign.Cli/TrustedSigningCommand.cs @@ -0,0 +1,69 @@ +// 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. + +using System.CommandLine; +using System.CommandLine.Invocation; +using System.CommandLine.IO; +using Azure.Core; +using Sign.Core; +using Sign.SignatureProviders.TrustedSigning; + +namespace Sign.Cli +{ + internal sealed class TrustedSigningCommand : Command + { + internal Option EndpointOption { get; } = new(["-tse", "--trusted-signing-endpoint"], TrustedSigningResources.EndpointOptionDescription); + internal Option AccountOption { get; } = new(["-tsa", "--trusted-signing-account"], TrustedSigningResources.AccountOptionDescription); + internal Option CertificateProfileOption { get; } = new(["-tscp", "--trusted-signing-certificate-profile"], TrustedSigningResources.CertificateProfileOptionDescription); + internal AzureCredentialOptions AzureCredentialOptions { get; } = new(); + + internal Argument FileArgument { get; } = new("file(s)", Resources.FilesArgumentDescription); + + internal TrustedSigningCommand(CodeCommand codeCommand, IServiceProviderFactory serviceProviderFactory) + : base("trusted-signing", TrustedSigningResources.CommandDescription) + { + ArgumentNullException.ThrowIfNull(codeCommand, nameof(codeCommand)); + ArgumentNullException.ThrowIfNull(serviceProviderFactory, nameof(serviceProviderFactory)); + + EndpointOption.IsRequired = true; + AccountOption.IsRequired = true; + CertificateProfileOption.IsRequired = true; + + AddOption(EndpointOption); + AddOption(AccountOption); + AddOption(CertificateProfileOption); + AzureCredentialOptions.AddOptionsToCommand(this); + + AddArgument(FileArgument); + + this.SetHandler(async (InvocationContext context) => + { + string? fileArgument = context.ParseResult.GetValueForArgument(FileArgument); + + if (string.IsNullOrEmpty(fileArgument)) + { + context.Console.Error.WriteLine(Resources.MissingFileValue); + context.ExitCode = ExitCode.InvalidOptions; + return; + } + + TokenCredential? credential = AzureCredentialOptions.CreateTokenCredential(context); + if (credential is null) + { + return; + } + + // Some of the options are required and that is why we can safely use + // the null-forgiving operator (!) to simplify the code. + Uri endpointUrl = context.ParseResult.GetValueForOption(EndpointOption)!; + string accountName = context.ParseResult.GetValueForOption(AccountOption)!; + string certificateProfileName = context.ParseResult.GetValueForOption(CertificateProfileOption)!; + + TrustedSigningServiceProvider trustedSigningServiceProvider = new(credential, endpointUrl, accountName, certificateProfileName); + + await codeCommand.HandleAsync(context, serviceProviderFactory, trustedSigningServiceProvider, fileArgument); + }); + } + } +} diff --git a/src/Sign.Cli/TrustedSigningResources.Designer.cs b/src/Sign.Cli/TrustedSigningResources.Designer.cs new file mode 100644 index 00000000..cd73ba54 --- /dev/null +++ b/src/Sign.Cli/TrustedSigningResources.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sign.Cli { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class TrustedSigningResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal TrustedSigningResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sign.Cli.TrustedSigningResources", typeof(TrustedSigningResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to The Trusted Signing Account name.. + /// + internal static string AccountOptionDescription { + get { + return ResourceManager.GetString("AccountOptionDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Certificate Profile name.. + /// + internal static string CertificateProfileOptionDescription { + get { + return ResourceManager.GetString("CertificateProfileOptionDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use Trusted Signing.. + /// + internal static string CommandDescription { + get { + return ResourceManager.GetString("CommandDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in.. + /// + internal static string EndpointOptionDescription { + get { + return ResourceManager.GetString("EndpointOptionDescription", resourceCulture); + } + } + } +} diff --git a/src/Sign.Cli/TrustedSigningResources.resx b/src/Sign.Cli/TrustedSigningResources.resx new file mode 100644 index 00000000..e899487e --- /dev/null +++ b/src/Sign.Cli/TrustedSigningResources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The Trusted Signing Account name. + + + The Certificate Profile name. + + + Use Trusted Signing. + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.cs.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.cs.xlf index 49bf8943..0c35af0d 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.cs.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.cs.xlf @@ -12,36 +12,11 @@ Podepisování ClickOnce prostřednictvím starší verze alternativního řešení .clickonce ZIP se už nepodporuje. Projděte si dokumentaci. - - Client ID to authenticate to Azure Key Vault. - ID klienta, které se má ověřit pro Azure Key Vault. - - - - Client secret to authenticate to Azure Key Vault. - Tajný kód klienta, který se má ověřit pro Azure Key Vault. - - Use Azure Key Vault. Použijte Azure Key Vault. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - Pokud se nepoužívá spravovaná identita, vyžadují se všechny tyto možnosti: {0}, {1}a {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Spravovaná identita pro ověření pro Azure Key Vault. - - - - Tenant ID to authenticate to Azure Key Vault. - ID tenanta, které se má ověřit pro Azure Key Vault. - - URL to an Azure Key Vault. Adresa URL Azure Key Vault. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.de.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.de.xlf index 17e60980..be16e6c8 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.de.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.de.xlf @@ -12,36 +12,11 @@ Die ClickOnce-Signierung über die Legacy-.clickonce-ZIP-Problemumgehung wird nicht mehr unterstützt. Siehe Dokumentation. - - Client ID to authenticate to Azure Key Vault. - Client-ID für die Authentifizierung bei Azure Key Vault. - - - - Client secret to authenticate to Azure Key Vault. - Geheimer Clientschlüssel für die Authentifizierung bei Azure Key Vault. - - Use Azure Key Vault. Verwenden Sie Azure Key Vault. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - Wenn Sie keine verwaltete Identität verwenden, sind alle diese Optionen erforderlich: {0}, {1} und {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Verwaltete Identität für die Authentifizierung bei Azure Key Vault. - - - - Tenant ID to authenticate to Azure Key Vault. - Mandanten-ID für die Authentifizierung bei Azure Key Vault. - - URL to an Azure Key Vault. URL zu einem Azure Key Vault. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.es.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.es.xlf index e3068538..05cc2178 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.es.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.es.xlf @@ -12,36 +12,11 @@ Ya no se admite la firma ClickOnce a través de la solución zip heredada .clickonce. Consulte la documentación. - - Client ID to authenticate to Azure Key Vault. - Id. de cliente para autenticarse en Azure Key Vault. - - - - Client secret to authenticate to Azure Key Vault. - Secreto de cliente para autenticarse en Azure Key Vault. - - Use Azure Key Vault. Use Azure Key Vault. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - Si no usa una identidad administrada, se requieren todas estas opciones: {0}, {1} y {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Identidad administrada para autenticarse en Azure Key Vault. - - - - Tenant ID to authenticate to Azure Key Vault. - Identificador de inquilino para autenticarse en Azure Key Vault. - - URL to an Azure Key Vault. Dirección URL a un Azure Key Vault. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.fr.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.fr.xlf index 9500cca3..0944b34e 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.fr.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.fr.xlf @@ -12,36 +12,11 @@ La signature ClickOnce via la solution de contournement zip .clickonce héritée n’est plus prise en charge. Consulter la documentation. - - Client ID to authenticate to Azure Key Vault. - ID client à authentifier auprès d’Azure Key Vault. - - - - Client secret to authenticate to Azure Key Vault. - Clé secrète client pour s’authentifier auprès d’Azure Key Vault. - - Use Azure Key Vault. Utilisez Azure Key Vault. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - Si vous n’utilisez pas d’identité managée, toutes ces options sont requises : {0}, {1} et {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Identité managée à authentifier auprès d’Azure Key Vault. - - - - Tenant ID to authenticate to Azure Key Vault. - ID client pour s’authentifier auprès d’Azure Key Vault. - - URL to an Azure Key Vault. URL d’un Azure Key Vault. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.it.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.it.xlf index 3751cdc4..41c944c4 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.it.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.it.xlf @@ -12,36 +12,11 @@ La firma ClickOnce tramite la soluzione alternativa legacy .clickonce ZIP non è più supportata. Vedere la documentazione. - - Client ID to authenticate to Azure Key Vault. - ID client da autenticare in Azure Key Vault. - - - - Client secret to authenticate to Azure Key Vault. - Segreto client da autenticare in Azure Key Vault. - - Use Azure Key Vault. Usare Azure Key Vault. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - Se non si usa un'identità gestita, saranno necessarie tutte le opzioni seguenti: {0}, {1} e {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Identità gestita da autenticare in Azure Key Vault. - - - - Tenant ID to authenticate to Azure Key Vault. - ID tenant da autenticare in Azure Key Vault. - - URL to an Azure Key Vault. URL a un Azure Key Vault. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.ja.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.ja.xlf index 4532f67a..ea8b1e01 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.ja.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.ja.xlf @@ -12,36 +12,11 @@ 従来の .clickonce ZIP 回避策による ClickOnce 署名はサポートされなくなりました。ドキュメントを参照してください。 - - Client ID to authenticate to Azure Key Vault. - Azure Key Vault に対して認証するクライアント ID。 - - - - Client secret to authenticate to Azure Key Vault. - Azure Key Vault に対して認証するクライアント シークレット。 - - Use Azure Key Vault. Azure Key Vault を使用してください。 - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - マネージド ID を使用しない場合は、{0}、{1}、{2} のオプションがすべて必要です。 - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Azure Key Vault に対して認証するマネージド ID。 - - - - Tenant ID to authenticate to Azure Key Vault. - Azure Key Vault に対して認証するテナント ID。 - - URL to an Azure Key Vault. Azure Key Vault への URL。 diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.ko.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.ko.xlf index 7aaf4955..bf448e15 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.ko.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.ko.xlf @@ -12,36 +12,11 @@ 레거시 .clickonce ZIP 해결 방법을 통한 ClickOnce 서명은 더 이상 지원되지 않습니다. 설명서를 참조하세요. - - Client ID to authenticate to Azure Key Vault. - Azure Key Vault에 인증하기 위한 클라이언트 ID입니다. - - - - Client secret to authenticate to Azure Key Vault. - Azure Key Vault에 인증하기 위한 클라이언트 암호입니다. - - Use Azure Key Vault. Azure Key Vault를 사용합니다. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - 관리 ID를 사용하고 있지 않은 경우 {0}, {1} 및 {2} 옵션이 모두 필요합니다. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Azure Key Vault에 인증하기 위한 관리 ID입니다. - - - - Tenant ID to authenticate to Azure Key Vault. - Azure Key Vault에 인증하기 위한 테넌트 ID입니다. - - URL to an Azure Key Vault. Azure Key Vault에 대한 URL입니다. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.pl.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.pl.xlf index f846f13c..ec2a609b 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.pl.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.pl.xlf @@ -12,36 +12,11 @@ Podpisywanie clickOnce za pośrednictwem starszego obejścia .clickonce ZIP nie jest już obsługiwane. Zobacz dokumentację. - - Client ID to authenticate to Azure Key Vault. - Identyfikator klienta do uwierzytelnienia w usłudze Azure Key Vault. - - - - Client secret to authenticate to Azure Key Vault. - Klucz tajny klienta do uwierzytelnienia w usłudze Azure Key Vault. - - Use Azure Key Vault. Użyj usługi Azure Key Vault. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - Jeśli tożsamość zarządzana nie jest używana, wymagane są wszystkie następujące opcje: {0}, {1} i {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Tożsamość zarządzana do uwierzytelnienia w usłudze Azure Key Vault. - - - - Tenant ID to authenticate to Azure Key Vault. - Identyfikator dzierżawy do uwierzytelnienia w usłudze Azure Key Vault. - - URL to an Azure Key Vault. Adres URL do usługi Azure Key Vault. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.pt-BR.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.pt-BR.xlf index bfac1e07..46c29ed6 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.pt-BR.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.pt-BR.xlf @@ -12,36 +12,11 @@ Não há mais suporte para a assinatura do ClickOnce por meio da solução alternativa .clickonce ZIP herdada. Consulte a documentação. - - Client ID to authenticate to Azure Key Vault. - ID do cliente a ser autenticada no Azure Key Vault. - - - - Client secret to authenticate to Azure Key Vault. - Segredo do cliente a ser autenticado no Azure Key Vault. - - Use Azure Key Vault. Use o Azure Key Vault. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - Se não estiver usando uma identidade gerenciada, todas essas opções serão necessárias: {0}, {1} e {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Identidade gerenciada a ser autenticada no Azure Key Vault. - - - - Tenant ID to authenticate to Azure Key Vault. - ID do locatário a ser autenticada no Azure Key Vault. - - URL to an Azure Key Vault. URL para um Azure Key Vault. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.ru.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.ru.xlf index 7fa74c88..e1cc1b47 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.ru.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.ru.xlf @@ -12,36 +12,11 @@ Подписание ClickOnce с помощью устаревшего обходного пути .clickonce ZIP больше не поддерживается. См. документацию. - - Client ID to authenticate to Azure Key Vault. - ИД клиента для проверки подлинности в Azure Key Vault. - - - - Client secret to authenticate to Azure Key Vault. - Секрет клиента для проверки подлинности в Azure Key Vault. - - Use Azure Key Vault. Использование Azure Key Vault. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - Если управляемое удостоверение не используется, требуются все следующие параметры: {0}, {1} и {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Управляемое удостоверение для проверки подлинности в Azure Key Vault. - - - - Tenant ID to authenticate to Azure Key Vault. - ИД клиента для проверки подлинности в Azure Key Vault. - - URL to an Azure Key Vault. URL-адрес для Azure Key Vault. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.tr.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.tr.xlf index f4bf097b..60a93955 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.tr.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.tr.xlf @@ -12,36 +12,11 @@ Eski .clickonce ZIP geçici çözümü aracılığıyla ClickOnce imzalama işlemi artık desteklenmiyor. Belgelere bakın. - - Client ID to authenticate to Azure Key Vault. - Azure Key Vault için kimlik doğrulamak amacıyla kullanılan istemci kimliği. - - - - Client secret to authenticate to Azure Key Vault. - Azure Key Vault için kimlik doğrulamak amacıyla kullanılan gizli anahtar. - - Use Azure Key Vault. Azure Key Vault’u kullanın. - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - Bir yönetilen kimlik kullanılmıyorsa bu seçeneklerin tümü gereklidir: {0}, {1} ve {2}. - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - Azure Key Vault için kimlik doğrulamak amacıyla kullanılan yönetilen kimlik. - - - - Tenant ID to authenticate to Azure Key Vault. - Azure Key Vault için kimlik doğrulamak amacıyla kullanılan kiracı kimliği. - - URL to an Azure Key Vault. Azure Key Vault URL’si. diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hans.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hans.xlf index 05e0b438..d6ec9934 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hans.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hans.xlf @@ -12,36 +12,11 @@ 不再支持通过旧版 .clickonce ZIP 解决方法进行 ClickOnce 签名。参阅文档。 - - Client ID to authenticate to Azure Key Vault. - 要向 Azure Key Vault 进行身份验证的客户端 ID。 - - - - Client secret to authenticate to Azure Key Vault. - 要向 Azure Key Vault 进行身份验证的客户端密码。 - - Use Azure Key Vault. 使用 Azure Key Vault。 - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - 如果不使用托管标识,则需要以下所有选项: {0}、{1} 和 {2}。 - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - 要向 Azure Key Vault 进行身份验证的托管标识。 - - - - Tenant ID to authenticate to Azure Key Vault. - 要向 Azure Key Vault 进行身份验证的租户 ID。 - - URL to an Azure Key Vault. 指向 Azure Key Vault 的 URL。 diff --git a/src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hant.xlf b/src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hant.xlf index 25b41727..4d51be73 100644 --- a/src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hant.xlf +++ b/src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hant.xlf @@ -12,36 +12,11 @@ 已不再支援透過舊版 .clickonce ZIP 因應措施進行 ClickOnce 簽署。請參閱文件。 - - Client ID to authenticate to Azure Key Vault. - 要向 Azure Key Vault 進行驗證的用戶端識別碼。 - - - - Client secret to authenticate to Azure Key Vault. - 要向 Azure Key Vault 進行驗證的用戶端密碼。 - - Use Azure Key Vault. 使用 Azure Key Vault。 - - If not using a managed identity, all of these options are required: {0}, {1}, and {2}. - 如果未使用受控識別,則需要下列所有選項: {0}、{1} 和 {2}。 - {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized. - - - Managed identity to authenticate to Azure Key Vault. - 要向 Azure Key Vault 進行驗證的受控識別。 - - - - Tenant ID to authenticate to Azure Key Vault. - 要向 Azure Key Vault 進行驗證的租用戶識別碼。 - - URL to an Azure Key Vault. Azure Key Vault 的 URL。 diff --git a/src/Sign.Cli/xlf/Resources.cs.xlf b/src/Sign.Cli/xlf/Resources.cs.xlf index 1bc95143..db722b16 100644 --- a/src/Sign.Cli/xlf/Resources.cs.xlf +++ b/src/Sign.Cli/xlf/Resources.cs.xlf @@ -17,6 +17,16 @@ Použijte úložiště certifikátů systému Windows nebo místní soubor certifikátu. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. Podepisovat binární soubory a kontejnery. @@ -77,6 +87,16 @@ Neplatná hodnota pro {0}. Hodnota musí být absolutní adresa URL protokolu HTTP nebo HTTPS. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. Maximální souběžnost. @@ -112,6 +132,11 @@ Některé soubory neexistují. Zkuste použít jinou hodnotu {0} nebo plně kvalifikovanou cestu k souboru. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. Algoritmus hodnoty hash pro server časového razítka RFC 3161. Povolené hodnoty jsou sha256, sha384 a sha512. diff --git a/src/Sign.Cli/xlf/Resources.de.xlf b/src/Sign.Cli/xlf/Resources.de.xlf index 2d624b57..b00461c5 100644 --- a/src/Sign.Cli/xlf/Resources.de.xlf +++ b/src/Sign.Cli/xlf/Resources.de.xlf @@ -17,6 +17,16 @@ Verwenden Sie den Windows-Zertifikatspeicher oder eine lokale Zertifikatdatei. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. Signieren Sie Binärdateien und Container. @@ -77,6 +87,16 @@ Ungültiger Wert für {0}. Der Wert muss eine absolute HTTP- oder HTTPS-URL sein. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. Maximale Parallelität. @@ -112,6 +132,11 @@ Einige Dateien sind nicht vorhanden. Versuchen Sie, einen anderen {0}-Wert oder einen vollqualifizierten Dateipfad zu verwenden. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. Digest-Algorithmus für den RFC 3161-Zeitstempelserver. Zulässige Werte sind sha256, sha384 und sha512. diff --git a/src/Sign.Cli/xlf/Resources.es.xlf b/src/Sign.Cli/xlf/Resources.es.xlf index 435a67d1..8035034b 100644 --- a/src/Sign.Cli/xlf/Resources.es.xlf +++ b/src/Sign.Cli/xlf/Resources.es.xlf @@ -17,6 +17,16 @@ Use el Almacén de certificados de Windows o un archivo de certificados local. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. Firmar archivos binarios y contenedores. @@ -77,6 +87,16 @@ Valor no válido para {0}. El valor debe ser una dirección URL HTTP o HTTPS absoluta. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. Simultaneidad máxima. @@ -112,6 +132,11 @@ Algunos archivos no existen. Pruebe a usar otro valor {0} o una ruta de acceso de archivo completa. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. Algoritmo de resumen para el servidor de marca de tiempo RFC 3161. Los valores permitidos son sha256, sha384 y sha512. diff --git a/src/Sign.Cli/xlf/Resources.fr.xlf b/src/Sign.Cli/xlf/Resources.fr.xlf index ca13a794..e23944ea 100644 --- a/src/Sign.Cli/xlf/Resources.fr.xlf +++ b/src/Sign.Cli/xlf/Resources.fr.xlf @@ -17,6 +17,16 @@ Utilisez le magasin de certificats Windows ou un fichier local du certificat. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. Signer les fichiers binaires et les conteneurs. @@ -77,6 +87,16 @@ Valeur non valide pour {0}. La valeur doit être une URL HTTP ou HTTPS absolue. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. Concurrence maximale. @@ -112,6 +132,11 @@ Certains fichiers n’existent pas. Essayez d’utiliser une autre valeur {0} ou un chemin de fichier complet. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. Algorithme de hachage pour le serveur d’horodatage RFC 3161. Les valeurs autorisées sont sha256, sha384 et sha512. diff --git a/src/Sign.Cli/xlf/Resources.it.xlf b/src/Sign.Cli/xlf/Resources.it.xlf index 18594555..dc084deb 100644 --- a/src/Sign.Cli/xlf/Resources.it.xlf +++ b/src/Sign.Cli/xlf/Resources.it.xlf @@ -17,6 +17,16 @@ Utilizzare l'archivio certificati di Windows o un file di certificato locale. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. Consente di firmare file binari e contenitori. @@ -77,6 +87,16 @@ Valore non valido per {0}. Il valore deve essere un URL HTTP o HTTPS assoluto. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. Concorrenza massima. @@ -112,6 +132,11 @@ Alcuni file non esistono. Provare a usare un valore di {0} diverso o un percorso di file completo. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. Algoritmo di digest per il server di timestamp RFC 3161. I valori consentiti sono sha256, sha384 e sha512. diff --git a/src/Sign.Cli/xlf/Resources.ja.xlf b/src/Sign.Cli/xlf/Resources.ja.xlf index 204a8dab..575b64b7 100644 --- a/src/Sign.Cli/xlf/Resources.ja.xlf +++ b/src/Sign.Cli/xlf/Resources.ja.xlf @@ -17,6 +17,16 @@ Windows 証明書ストアまたはローカル証明書ファイルを使用します。 + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. バイナリとコンテナーに署名します。 @@ -77,6 +87,16 @@ {0}の値が無効です。値は HTTP または HTTPS の絶対 URL である必要があります。 {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. 最大コンカレンシー。 @@ -112,6 +132,11 @@ 一部のファイルが存在しません。別の {0} 値または完全修飾ファイル パスを使用してみてください。 {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. RFC 3161 タイムスタンプ サーバーのダイジェスト アルゴリズム。使用できる値は、sha256、sha384、および sha512 です。 diff --git a/src/Sign.Cli/xlf/Resources.ko.xlf b/src/Sign.Cli/xlf/Resources.ko.xlf index 3be29715..a0e3d012 100644 --- a/src/Sign.Cli/xlf/Resources.ko.xlf +++ b/src/Sign.Cli/xlf/Resources.ko.xlf @@ -17,6 +17,16 @@ Windows 인증서 저장소 또는 로컬 인증서 파일을 사용합니다. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. 이진 파일 및 컨테이너에 서명합니다. @@ -77,6 +87,16 @@ {0}에 대한 값이 잘못되었습니다. 값은 절대 HTTP 또는 HTTPS URL이어야 합니다. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. 최대 동시성입니다. @@ -112,6 +132,11 @@ 일부 파일이 존재하지 않습니다. 다른 {0} 값 또는 정규화된 파일 경로를 사용해 보세요. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. RFC 3161 타임스탬프 서버용 다이제스트 알고리즘입니다. 허용되는 값은 sha256, sha384 및 sha512입니다. diff --git a/src/Sign.Cli/xlf/Resources.pl.xlf b/src/Sign.Cli/xlf/Resources.pl.xlf index c123396a..f172e0a4 100644 --- a/src/Sign.Cli/xlf/Resources.pl.xlf +++ b/src/Sign.Cli/xlf/Resources.pl.xlf @@ -17,6 +17,16 @@ Użyj magazynu certyfikatów systemu Windows lub lokalnego pliku certyfikatów. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. Podpisz pliki binarne i kontenery. @@ -77,6 +87,16 @@ Nieprawidłowa wartość dla {0}. Wartość musi być bezwzględnym adresem URL protokołu HTTP lub HTTPS. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. Maksymalna współbieżność. @@ -112,6 +132,11 @@ Niektóre pliki nie istnieją. Spróbuj użyć innej wartości {0} lub w pełni kwalifikowanej ścieżki pliku. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. Algorytm skrótu dla serwera znacznika czasu RFC 3161. Dozwolonymi wartościami są: sha256, sha384 i sha512. diff --git a/src/Sign.Cli/xlf/Resources.pt-BR.xlf b/src/Sign.Cli/xlf/Resources.pt-BR.xlf index c55b5f83..2d8996d8 100644 --- a/src/Sign.Cli/xlf/Resources.pt-BR.xlf +++ b/src/Sign.Cli/xlf/Resources.pt-BR.xlf @@ -17,6 +17,16 @@ Use o Repositório de Certificados do Windows ou um arquivo de certificado local. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. Autenticar contêineres e binários. @@ -77,6 +87,16 @@ Valor inválido para {0}. O valor deve ser uma URL HTTP ou HTTPS absoluta. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. Simultaneidade máxima. @@ -112,6 +132,11 @@ Alguns arquivos não existem. Tente usar um valor diferente de {0} ou um caminho de arquivo totalmente qualificado. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. Resumo do algoritmo para o servidor de carimbo de data/hora RFC 3161. Os valores permitidos são sha256, sha384 e sha512. diff --git a/src/Sign.Cli/xlf/Resources.ru.xlf b/src/Sign.Cli/xlf/Resources.ru.xlf index a37483ac..aa52487a 100644 --- a/src/Sign.Cli/xlf/Resources.ru.xlf +++ b/src/Sign.Cli/xlf/Resources.ru.xlf @@ -17,6 +17,16 @@ Используйте хранилище сертификатов Windows или локальный файл сертификата. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. Подписывание двоичных файлов и контейнеров. @@ -77,6 +87,16 @@ Недопустимое значение для {0}. Значение должно быть абсолютным URL-адресом HTTP или HTTPS. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. Максимальный параллелизм. @@ -112,6 +132,11 @@ Некоторые файлы не существуют. Попробуйте использовать другое значение {0} или полный путь к файлу. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. Алгоритм дайджеста для сервера меток времени RFC 3161. Допустимые значения: sha256, sha384 и sha512. diff --git a/src/Sign.Cli/xlf/Resources.tr.xlf b/src/Sign.Cli/xlf/Resources.tr.xlf index 79cbcf74..2016ae4b 100644 --- a/src/Sign.Cli/xlf/Resources.tr.xlf +++ b/src/Sign.Cli/xlf/Resources.tr.xlf @@ -17,6 +17,16 @@ Windows Sertifika Deposu veya yerel bir sertifika dosyası kullanın. + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. İkili dosyaları ve kapsayıcıları imzalayın. @@ -77,6 +87,16 @@ {0} için geçersiz değer. Değer mutlak bir HTTP veya HTTPS URL’si olmalıdır. {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. Maksimum eşzamanlılık. @@ -112,6 +132,11 @@ Bazı dosyalar mevcut değil. Farklı bir {0} değeri veya tam bir dosya yolu kullanmayı deneyin. {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. RFC 3161 zaman damgası sunucusu için karma algoritması. İzin verilen değerler şunlardır. sha256, sha384 ve sha512. diff --git a/src/Sign.Cli/xlf/Resources.zh-Hans.xlf b/src/Sign.Cli/xlf/Resources.zh-Hans.xlf index cfecc57f..3a62e4f7 100644 --- a/src/Sign.Cli/xlf/Resources.zh-Hans.xlf +++ b/src/Sign.Cli/xlf/Resources.zh-Hans.xlf @@ -17,6 +17,16 @@ 使用 Windows 证书存储或本地证书文件。 + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. 对二进制文件和容器进行签名。 @@ -77,6 +87,16 @@ {0} 的值无效。值必须是绝对 HTTP 或 HTTPS URL。 {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. 最大并发。 @@ -112,6 +132,11 @@ 某些文件不存在。请尝试使用其他 {0} 值或完全限定的文件路径。 {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. RFC 3161 时间戳服务器的摘要算法。允许的值为 sha256、sha384 和 sha512。 diff --git a/src/Sign.Cli/xlf/Resources.zh-Hant.xlf b/src/Sign.Cli/xlf/Resources.zh-Hant.xlf index d21006c4..a6145466 100644 --- a/src/Sign.Cli/xlf/Resources.zh-Hant.xlf +++ b/src/Sign.Cli/xlf/Resources.zh-Hant.xlf @@ -17,6 +17,16 @@ 使用 Windows 憑證存放區或本機憑證檔案。 + + Client ID to authenticate to Azure. + Client ID to authenticate to Azure. + + + + Client secret to authenticate to Azure. + Client secret to authenticate to Azure. + + Sign binaries and containers. 簽署二進位檔和容器。 @@ -77,6 +87,16 @@ {0} 的值無效。值必須是絕對 HTTP 或 HTTPS URL。 {NumberedPlaceholder="{0}"} is an option name (e.g.: --timestamp-url) and should not be localized. + + Managed identity to authenticate to Azure Key. (obsolete) + Managed identity to authenticate to Azure Key. (obsolete) + + + + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified. + + Maximum concurrency. 並行最大值。 @@ -112,6 +132,11 @@ 某些檔案不存在。請嘗試使用不同的 {0} 值或完整檔案路徑。 {NumberedPlaceholder="{0}"} is an option name (e.g.: --base-directory) and should not be localized. + + Tenant ID to authenticate to Azure. + Tenant ID to authenticate to Azure. + + Digest algorithm for the RFC 3161 timestamp server. Allowed values are sha256, sha384, and sha512. RFC 3161 時間戳記伺服器的摘要演算法。允許的值為 sha256、sha384 和 sha512。 diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.cs.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.cs.xlf new file mode 100644 index 00000000..d0a3847e --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.cs.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.de.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.de.xlf new file mode 100644 index 00000000..4439175b --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.de.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.es.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.es.xlf new file mode 100644 index 00000000..1f919d4f --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.es.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.fr.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.fr.xlf new file mode 100644 index 00000000..0862ceb8 --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.fr.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.it.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.it.xlf new file mode 100644 index 00000000..3918f419 --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.it.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.ja.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.ja.xlf new file mode 100644 index 00000000..acd4bfb0 --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.ja.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.ko.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.ko.xlf new file mode 100644 index 00000000..7ea9fab3 --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.ko.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.pl.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.pl.xlf new file mode 100644 index 00000000..8c408c4c --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.pl.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.pt-BR.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.pt-BR.xlf new file mode 100644 index 00000000..a6cfbb08 --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.pt-BR.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.ru.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.ru.xlf new file mode 100644 index 00000000..624f84c9 --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.ru.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.tr.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.tr.xlf new file mode 100644 index 00000000..82ff9092 --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.tr.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.zh-Hans.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.zh-Hans.xlf new file mode 100644 index 00000000..1fc298d2 --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.zh-Hans.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Cli/xlf/TrustedSigningResources.zh-Hant.xlf b/src/Sign.Cli/xlf/TrustedSigningResources.zh-Hant.xlf new file mode 100644 index 00000000..697c4168 --- /dev/null +++ b/src/Sign.Cli/xlf/TrustedSigningResources.zh-Hant.xlf @@ -0,0 +1,27 @@ + + + + + + The Trusted Signing Account name. + The Trusted Signing Account name. + + + + The Certificate Profile name. + The Certificate Profile name. + + + + Use Trusted Signing. + Use Trusted Signing. + + + + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + The Trusted Signing Account endpoint. The value must be a URI that aligns to the region that your Trusted Signing Account and Certificate Profile were created in. + + + + + \ No newline at end of file diff --git a/src/Sign.Core/Sign.Core.csproj b/src/Sign.Core/Sign.Core.csproj index adaeba0a..3eee397d 100644 --- a/src/Sign.Core/Sign.Core.csproj +++ b/src/Sign.Core/Sign.Core.csproj @@ -29,6 +29,8 @@ + + diff --git a/src/Sign.SignatureProviders.TrustedSigning/RSATrustedSigning.cs b/src/Sign.SignatureProviders.TrustedSigning/RSATrustedSigning.cs new file mode 100644 index 00000000..d6fdebaa --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/RSATrustedSigning.cs @@ -0,0 +1,84 @@ +// 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. + +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using Azure; +using Azure.CodeSigning; +using Azure.CodeSigning.Models; + +namespace Sign.SignatureProviders.TrustedSigning +{ + internal sealed class RSATrustedSigning : RSA + { + private readonly CertificateProfileClient _client; + private readonly string _accountName; + private readonly string _certificateProfileName; + private readonly X509Certificate2 _certificate; + + public RSATrustedSigning( + CertificateProfileClient client, + string accountName, + string certificateProfileName, + X509Certificate2 certificate) + { + _client = client; + _accountName = accountName; + _certificateProfileName = certificateProfileName; + _certificate = certificate; + } + + private RSA PublicKey + => _certificate.GetRSAPublicKey()!; + + public override RSAParameters ExportParameters(bool includePrivateParameters) + { + if (includePrivateParameters) + { + throw new NotSupportedException(); + } + + return PublicKey.ExportParameters(false); + } + + public override void ImportParameters(RSAParameters parameters) + => throw new NotImplementedException(); + + public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) + { + SignatureAlgorithm signatureAlgorithm = GetSignatureAlgorithm(hash, padding); + SignRequest request = new(signatureAlgorithm, hash); + CertificateProfileSignOperation operation = _client.StartSign(_accountName, _certificateProfileName, request); + Response response = operation.WaitForCompletion(); + return response.Value.Signature; + } + + public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) + => PublicKey.VerifyHash(hash, signature, hashAlgorithm, padding); + + protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) + { + using HashAlgorithm hasher = CreateHasher(hashAlgorithm); + return hasher.ComputeHash(data, offset, count); + } + + private static SignatureAlgorithm GetSignatureAlgorithm(byte[] digest, RSASignaturePadding padding) + => digest.Length switch + { + 32 => padding == RSASignaturePadding.Pss ? Azure.CodeSigning.Models.SignatureAlgorithm.PS256 : Azure.CodeSigning.Models.SignatureAlgorithm.RS256, + 48 => padding == RSASignaturePadding.Pss ? Azure.CodeSigning.Models.SignatureAlgorithm.PS384 : Azure.CodeSigning.Models.SignatureAlgorithm.RS384, + 64 => padding == RSASignaturePadding.Pss ? Azure.CodeSigning.Models.SignatureAlgorithm.PS512 : Azure.CodeSigning.Models.SignatureAlgorithm.RS512, + _ => throw new NotSupportedException(), + }; + + private static HashAlgorithm CreateHasher(HashAlgorithmName hashAlgorithm) + => hashAlgorithm.Name switch + { + nameof(SHA256) => SHA256.Create(), + nameof(SHA384) => SHA384.Create(), + nameof(SHA512) => SHA512.Create(), + _ => throw new NotSupportedException(), + }; + } +} diff --git a/src/Sign.SignatureProviders.TrustedSigning/Resources.Designer.cs b/src/Sign.SignatureProviders.TrustedSigning/Resources.Designer.cs new file mode 100644 index 00000000..a7210e20 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/Resources.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Sign.SignatureProviders.TrustedSigning { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Sign.SignatureProviders.TrustedSigning.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Fetched certificate. [{milliseconds} ms]. + /// + internal static string FetchedCertificate { + get { + return ResourceManager.GetString("FetchedCertificate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fetching certificate from Trusted Signing certificate profile.. + /// + internal static string FetchingCertificate { + get { + return ResourceManager.GetString("FetchingCertificate", resourceCulture); + } + } + } +} diff --git a/src/Sign.SignatureProviders.TrustedSigning/Resources.resx b/src/Sign.SignatureProviders.TrustedSigning/Resources.resx new file mode 100644 index 00000000..821cb271 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/Resources.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/Sign.SignatureProviders.TrustedSigning.csproj b/src/Sign.SignatureProviders.TrustedSigning/Sign.SignatureProviders.TrustedSigning.csproj new file mode 100644 index 00000000..f83b9212 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/Sign.SignatureProviders.TrustedSigning.csproj @@ -0,0 +1,40 @@ + + + + true + + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/TrustedSigningService.cs b/src/Sign.SignatureProviders.TrustedSigning/TrustedSigningService.cs new file mode 100644 index 00000000..da9761aa --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/TrustedSigningService.cs @@ -0,0 +1,99 @@ +// 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. + +using System.Diagnostics; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using Azure; +using Azure.CodeSigning; +using Azure.CodeSigning.Models; +using Azure.Core; +using Microsoft.Extensions.Logging; +using Sign.Core; + +namespace Sign.SignatureProviders.TrustedSigning +{ + internal sealed class TrustedSigningService : ISignatureAlgorithmProvider, ICertificateProvider, IDisposable + { + private static readonly SignRequest _emptyRequest = new(SignatureAlgorithm.RS256, new byte[32]); + + private readonly CertificateProfileClient _client; + private readonly string _accountName; + private readonly string _certificateProfileName; + private readonly ILogger _logger; + private readonly SemaphoreSlim _mutex = new(1); + private X509Certificate2? _certificate; + + public TrustedSigningService( + TokenCredential tokenCredential, + Uri endpointUrl, + string accountName, + string certificateProfileName, + ILogger logger) + { + ArgumentNullException.ThrowIfNull(tokenCredential, nameof(tokenCredential)); + ArgumentNullException.ThrowIfNull(endpointUrl, nameof(endpointUrl)); + ArgumentException.ThrowIfNullOrEmpty(accountName, nameof(accountName)); + ArgumentException.ThrowIfNullOrEmpty(certificateProfileName, nameof(certificateProfileName)); + ArgumentNullException.ThrowIfNull(logger, nameof(logger)); + + _accountName = accountName; + _certificateProfileName = certificateProfileName; + _logger = logger; + + _client = new CertificateProfileClient(tokenCredential, endpointUrl); + } + + public void Dispose() + { + _mutex.Dispose(); + _certificate?.Dispose(); + GC.SuppressFinalize(this); + } + + public async Task GetCertificateAsync(CancellationToken cancellationToken) + { + if (_certificate is not null) + { + return new X509Certificate2(_certificate); + } + + await _mutex.WaitAsync(cancellationToken); + try + { + if (_certificate is null) + { + Stopwatch stopwatch = Stopwatch.StartNew(); + + _logger.LogTrace(Resources.FetchingCertificate); + + CertificateProfileSignOperation operation = await _client.StartSignAsync(_accountName, _certificateProfileName, _emptyRequest, cancellationToken: cancellationToken); + Response response = await operation.WaitForCompletionAsync(cancellationToken); + + byte[] rawData = Convert.FromBase64String(Encoding.UTF8.GetString(response.Value.SigningCertificate)); + X509Certificate2Collection collection = []; + collection.Import(rawData); + + // This should contain the certificate chain in root->leaf order. + _certificate = collection[collection.Count - 1]; + + _logger.LogTrace(Resources.FetchedCertificate, stopwatch.Elapsed.TotalMilliseconds); + } + } + finally + { + _mutex.Release(); + } + + return new X509Certificate2(_certificate); + } + + public async Task GetRsaAsync(CancellationToken cancellationToken) + { + X509Certificate2 certificate = await GetCertificateAsync(cancellationToken); + return new RSATrustedSigning(_client, _accountName, _certificateProfileName, certificate); + } + } +} diff --git a/src/Sign.SignatureProviders.TrustedSigning/TrustedSigningServiceProvider.cs b/src/Sign.SignatureProviders.TrustedSigning/TrustedSigningServiceProvider.cs new file mode 100644 index 00000000..aca0bd90 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/TrustedSigningServiceProvider.cs @@ -0,0 +1,73 @@ +// 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. + +using Azure.Core; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Sign.Core; + +namespace Sign.SignatureProviders.TrustedSigning +{ + internal sealed class TrustedSigningServiceProvider : ISignatureProvider + { + private readonly TokenCredential _tokenCredential; + private readonly Uri _endpointUrl; + private readonly string _accountName; + private readonly string _certificateProfileName; + private readonly object _lockObject = new(); + private TrustedSigningService? _trustedSigningService; + + public TrustedSigningServiceProvider( + TokenCredential tokenCredential, + Uri endpointUrl, + string accountName, + string certificateProfileName) + { + ArgumentNullException.ThrowIfNull(tokenCredential, nameof(tokenCredential)); + ArgumentNullException.ThrowIfNull(endpointUrl, nameof(endpointUrl)); + ArgumentException.ThrowIfNullOrEmpty(accountName, nameof(accountName)); + ArgumentException.ThrowIfNullOrEmpty(certificateProfileName, nameof(certificateProfileName)); + + _tokenCredential = tokenCredential; + _endpointUrl = endpointUrl; + _accountName = accountName; + _certificateProfileName = certificateProfileName; + } + + public ISignatureAlgorithmProvider GetSignatureAlgorithmProvider(IServiceProvider serviceProvider) + { + ArgumentNullException.ThrowIfNull(serviceProvider, nameof(serviceProvider)); + + return GetService(serviceProvider); + } + + public ICertificateProvider GetCertificateProvider(IServiceProvider serviceProvider) + { + ArgumentNullException.ThrowIfNull(serviceProvider, nameof(serviceProvider)); + + return GetService(serviceProvider); + } + + private TrustedSigningService GetService(IServiceProvider serviceProvider) + { + if (_trustedSigningService is not null) + { + return _trustedSigningService; + } + + lock (_lockObject) + { + if (_trustedSigningService is not null) + { + return _trustedSigningService; + } + + ILogger logger = serviceProvider.GetRequiredService>(); + _trustedSigningService = new TrustedSigningService(_tokenCredential, _endpointUrl, _accountName, _certificateProfileName, logger); + } + + return _trustedSigningService; + } + } +} diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.cs.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.cs.xlf new file mode 100644 index 00000000..555039b1 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.cs.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.de.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.de.xlf new file mode 100644 index 00000000..ae313658 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.de.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.es.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.es.xlf new file mode 100644 index 00000000..447121e7 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.es.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.fr.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.fr.xlf new file mode 100644 index 00000000..c67d7ea0 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.fr.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.it.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.it.xlf new file mode 100644 index 00000000..2025d598 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.it.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.ja.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.ja.xlf new file mode 100644 index 00000000..a0e3a21c --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.ja.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.ko.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.ko.xlf new file mode 100644 index 00000000..5e435f06 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.ko.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.pl.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.pl.xlf new file mode 100644 index 00000000..fcbe4a67 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.pl.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.pt-BR.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.pt-BR.xlf new file mode 100644 index 00000000..ee948091 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.pt-BR.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.ru.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.ru.xlf new file mode 100644 index 00000000..c751fa2b --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.ru.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.tr.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.tr.xlf new file mode 100644 index 00000000..5663ea3e --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.tr.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.zh-Hans.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.zh-Hans.xlf new file mode 100644 index 00000000..02f43e30 --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.zh-Hans.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.zh-Hant.xlf b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.zh-Hant.xlf new file mode 100644 index 00000000..89b64b0d --- /dev/null +++ b/src/Sign.SignatureProviders.TrustedSigning/xlf/Resources.zh-Hant.xlf @@ -0,0 +1,17 @@ + + + + + + Fetched certificate. [{milliseconds} ms] + Fetched certificate. [{milliseconds} ms] + {Placeholder="{milliseconds}"} is a decimal number representing the number of milliseconds elapsed, and "ms" is the unit abbreviation for milliseconds. + + + Fetching certificate from Trusted Signing certificate profile. + Fetching certificate from Trusted Signing certificate profile. + + + + + \ No newline at end of file diff --git a/test/Sign.Cli.Test/AzureCredentialOptionsTests.cs b/test/Sign.Cli.Test/AzureCredentialOptionsTests.cs new file mode 100644 index 00000000..c267d2e7 --- /dev/null +++ b/test/Sign.Cli.Test/AzureCredentialOptionsTests.cs @@ -0,0 +1,61 @@ +// 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. + +using System.CommandLine; + +namespace Sign.Cli.Test +{ + public class AzureCredentialOptionsTests + { + private readonly AzureCredentialOptions _options = new(); + + [Fact] + public void ManagedIdentityOption_Always_HasArityOfZeroOrOne() + { + Assert.Equal(ArgumentArity.ZeroOrOne, _options.ManagedIdentityOption.Arity); + } + + [Fact] + public void ManagedIdentityOption_Always_IsNotRequired() + { + Assert.False(_options.ManagedIdentityOption.IsRequired); + } + + [Fact] + public void TenantIdOption_Always_HasArityOfExactlyOne() + { + Assert.Equal(ArgumentArity.ExactlyOne, _options.TenantIdOption.Arity); + } + + [Fact] + public void TenantIdOption_Always_IsNotRequired() + { + Assert.False(_options.TenantIdOption.IsRequired); + } + + [Fact] + public void ClientIdOption_Always_HasArityOfExactlyOne() + { + Assert.Equal(ArgumentArity.ExactlyOne, _options.ClientIdOption.Arity); + } + + [Fact] + public void ClientIdOption_Always_IsNotRequired() + { + Assert.False(_options.ClientIdOption.IsRequired); + } + + [Fact] + public void ClientSecretOption_Always_HasArityOfExactlyOne() + { + Assert.Equal(ArgumentArity.ExactlyOne, _options.ClientSecretOption.Arity); + } + + [Fact] + public void ClientSecretOption_Always_IsNotRequired() + { + Assert.False(_options.ClientSecretOption.IsRequired); + } + } +} diff --git a/test/Sign.Cli.Test/AzureKeyVaultCommandTests.cs b/test/Sign.Cli.Test/AzureKeyVaultCommandTests.cs index 8dd507d4..eb3190e4 100644 --- a/test/Sign.Cli.Test/AzureKeyVaultCommandTests.cs +++ b/test/Sign.Cli.Test/AzureKeyVaultCommandTests.cs @@ -44,54 +44,6 @@ public void CertificateOption_Always_IsRequired() Assert.True(_command.CertificateOption.IsRequired); } - [Fact] - public void ClientIdOption_Always_HasArityOfExactlyOne() - { - Assert.Equal(ArgumentArity.ExactlyOne, _command.ClientIdOption.Arity); - } - - [Fact] - public void ClientIdOption_Always_IsNotRequired() - { - Assert.False(_command.ClientIdOption.IsRequired); - } - - [Fact] - public void ClientSecretOption_Always_HasArityOfExactlyOne() - { - Assert.Equal(ArgumentArity.ExactlyOne, _command.ClientSecretOption.Arity); - } - - [Fact] - public void ClientSecretOption_Always_IsNotRequired() - { - Assert.False(_command.ClientSecretOption.IsRequired); - } - - [Fact] - public void ManagedIdentityOption_Always_HasArityOfZeroOrOne() - { - Assert.Equal(ArgumentArity.ZeroOrOne, _command.ManagedIdentityOption.Arity); - } - - [Fact] - public void ManagedIdentityOption_Always_IsNotRequired() - { - Assert.False(_command.ManagedIdentityOption.IsRequired); - } - - [Fact] - public void TenantIdOption_Always_HasArityOfExactlyOne() - { - Assert.Equal(ArgumentArity.ExactlyOne, _command.TenantIdOption.Arity); - } - - [Fact] - public void TenantIdOption_Always_IsNotRequired() - { - Assert.False(_command.TenantIdOption.IsRequired); - } - [Fact] public void UrlOption_Always_HasArityOfExactlyOne() { @@ -137,7 +89,7 @@ public void Command_WhenRequiredArgumentOrOptionsAreMissing_HasError(string comm } [Theory] - [InlineData("azure-key-vault -kvu https://keyvault.test -kvc a -kvm b")] + [InlineData("azure-key-vault -kvu https://keyvault.test -kvc a b")] [InlineData("azure-key-vault -kvu https://keyvault.test -kvc a -kvt b -kvi c -kvs d e")] public void Command_WhenRequiredArgumentsArePresent_HasNoError(string command) { @@ -147,4 +99,4 @@ public void Command_WhenRequiredArgumentsArePresent_HasNoError(string command) } } } -} \ No newline at end of file +} diff --git a/test/Sign.Cli.Test/SignCommandTests.Globbing.cs b/test/Sign.Cli.Test/SignCommandTests.Globbing.cs index 74c4a65b..248d8de9 100644 --- a/test/Sign.Cli.Test/SignCommandTests.Globbing.cs +++ b/test/Sign.Cli.Test/SignCommandTests.Globbing.cs @@ -60,7 +60,7 @@ public void Dispose() public async Task Command_WhenFileIsGlobPattern_SignsOnlyMatches() { string commandText = $"code azure-key-vault --description {Description} --description-url {DescriptionUrl} " - + $"-kvu {KeyVaultUrl} -kvc {CertificateName} -kvm --timestamp-url {TimestampUrl} " + + $"-kvu {KeyVaultUrl} -kvc {CertificateName} --timestamp-url {TimestampUrl} " + $"-b \"{_temporaryDirectory.Directory.FullName}\" **/*.dll"; int exitCode = await _parser.InvokeAsync(commandText); @@ -78,7 +78,7 @@ public async Task Command_WhenFileIsGlobPattern_SignsOnlyMatches() public async Task Command_WhenFileIsGlobPatternWithSubdirectory_SignsOnlyMatches() { string commandText = $"code azure-key-vault --description {Description} --description-url {DescriptionUrl} " - + $"-kvu {KeyVaultUrl} -kvc {CertificateName} -kvm --timestamp-url {TimestampUrl} " + + $"-kvu {KeyVaultUrl} -kvc {CertificateName} --timestamp-url {TimestampUrl} " + $"-b \"{_temporaryDirectory.Directory.FullName}\" **/e/*.dll"; int exitCode = await _parser.InvokeAsync(commandText); @@ -94,7 +94,7 @@ public async Task Command_WhenFileIsGlobPatternWithSubdirectory_SignsOnlyMatches public async Task Command_WhenFileIsGlobPatternWithBracedExpansion_SignsOnlyMatches() { string commandText = $"code azure-key-vault --description {Description} --description-url {DescriptionUrl} " - + $"-kvu {KeyVaultUrl} -kvc {CertificateName} -kvm --timestamp-url {TimestampUrl} " + + $"-kvu {KeyVaultUrl} -kvc {CertificateName} --timestamp-url {TimestampUrl} " + $"-b \"{_temporaryDirectory.Directory.FullName}\" **/*.{{dll,exe}}"; int exitCode = await _parser.InvokeAsync(commandText); @@ -181,4 +181,4 @@ private static void EnsureParentDirectoriesExist(DirectoryInfo directory) } } } -} \ No newline at end of file +} diff --git a/test/Sign.Cli.Test/SignCommandTests.cs b/test/Sign.Cli.Test/SignCommandTests.cs index d13467fa..88808b7c 100644 --- a/test/Sign.Cli.Test/SignCommandTests.cs +++ b/test/Sign.Cli.Test/SignCommandTests.cs @@ -73,7 +73,7 @@ public void Command_WhenArgumentAndOptionsAreMissing_HasError(string command) public void Command_WhenRequiredArgumentIsMissing_HasError() { string command = $"code azure-key-vault --description {Description} --description-url {DescriptionUrl} " - + $"-kvu {KeyVaultUrl} -kvc {CertificateName} -kvm --timestamp-url {TimestampUrl}"; + + $"-kvu {KeyVaultUrl} -kvc {CertificateName} --timestamp-url {TimestampUrl}"; ParseResult result = _parser.Parse(command); Assert.NotEmpty(result.Errors); @@ -83,7 +83,7 @@ public void Command_WhenRequiredArgumentIsMissing_HasError() public void Command_WhenAllOptionsAndArgumentAreValid_HasNoError() { string command = $"code azure-key-vault --description {Description} --description-url {DescriptionUrl} " - + $"-kvu {KeyVaultUrl} -kvc {CertificateName} -kvm --timestamp-url {TimestampUrl} {File}"; + + $"-kvu {KeyVaultUrl} -kvc {CertificateName} --timestamp-url {TimestampUrl} {File}"; ParseResult result = _parser.Parse(command); Assert.Empty(result.Errors); @@ -96,4 +96,4 @@ public void Command_WhenAllOptionsAndArgumentAreValid_HasNoError() Assert.Equal(File, result.GetValueForArgument(_azureKeyVaultCommand.FileArgument)); } } -} \ No newline at end of file +} diff --git a/test/Sign.Cli.Test/TrustedSigningCommandTests.cs b/test/Sign.Cli.Test/TrustedSigningCommandTests.cs new file mode 100644 index 00000000..26928217 --- /dev/null +++ b/test/Sign.Cli.Test/TrustedSigningCommandTests.cs @@ -0,0 +1,114 @@ +// 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. + +using System.CommandLine; +using System.CommandLine.Builder; +using System.CommandLine.Parsing; +using Moq; +using Sign.Core; + +namespace Sign.Cli.Test +{ + public class TrustedSigningCommandTests + { + private readonly TrustedSigningCommand _command = new(new CodeCommand(), Mock.Of()); + + [Fact] + public void Constructor_WhenCodeCommandIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningCommand(codeCommand: null!, Mock.Of())); + + Assert.Equal("codeCommand", exception.ParamName); + } + + [Fact] + public void Constructor_WhenServiceProviderFactoryIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningCommand(new CodeCommand(), serviceProviderFactory: null!)); + + Assert.Equal("serviceProviderFactory", exception.ParamName); + } + + [Fact] + public void EndpointOption_Always_HasArityOfExactlyOne() + { + Assert.Equal(ArgumentArity.ExactlyOne, _command.EndpointOption.Arity); + } + + [Fact] + public void EndpointOption_Always_IsRequired() + { + Assert.True(_command.EndpointOption.IsRequired); + } + + [Fact] + public void AccountOption_Always_HasArityOfExactlyOne() + { + Assert.Equal(ArgumentArity.ExactlyOne, _command.AccountOption.Arity); + } + + [Fact] + public void AccountOption_Always_IsRequired() + { + Assert.True(_command.AccountOption.IsRequired); + } + + [Fact] + public void CertificateProfileOption_Always_HasArityOfExactlyOne() + { + Assert.Equal(ArgumentArity.ExactlyOne, _command.CertificateProfileOption.Arity); + } + + [Fact] + public void CertificateProfileOption_Always_IsRequired() + { + Assert.True(_command.CertificateProfileOption.IsRequired); + } + + public class ParserTests + { + private readonly TrustedSigningCommand _command; + private readonly Parser _parser; + + public ParserTests() + { + _command = new(new CodeCommand(), Mock.Of()); + _parser = new CommandLineBuilder(_command).Build(); + } + + [Theory] + [InlineData("trusted-signing")] + [InlineData("trusted-signing a")] + [InlineData("trusted-signing -tse")] + [InlineData("trusted-signing -tse https://trustedsigning.test")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a -tscp b")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a -tscp b -kvt")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a -tscp b -kvt c")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a -tscp b -kvt c -kvi")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a -tscp b -kvt c -kvi d")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a -tscp b -kvt c -kvi d -kvs")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a -tscp b -kvt c -kvi d -kvs e")] + public void Command_WhenRequiredArgumentOrOptionsAreMissing_HasError(string command) + { + ParseResult result = _parser.Parse(command); + + Assert.NotEmpty(result.Errors); + } + + [Theory] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a -tscp b c")] + [InlineData("trusted-signing -tse https://trustedsigning.test -tsa a -tscp b -kvt c -kvi d -kvs e f")] + public void Command_WhenRequiredArgumentsArePresent_HasNoError(string command) + { + ParseResult result = _parser.Parse(command); + + Assert.Empty(result.Errors); + } + } + } +} diff --git a/test/Sign.SignatureProviders.TrustedSigning.Test/Sign.SignatureProviders.TrustedSigning.Test.csproj b/test/Sign.SignatureProviders.TrustedSigning.Test/Sign.SignatureProviders.TrustedSigning.Test.csproj new file mode 100644 index 00000000..9fe902db --- /dev/null +++ b/test/Sign.SignatureProviders.TrustedSigning.Test/Sign.SignatureProviders.TrustedSigning.Test.csproj @@ -0,0 +1,22 @@ + + + + + false + true + true + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + \ No newline at end of file diff --git a/test/Sign.SignatureProviders.TrustedSigning.Test/TrustedSigningServiceProviderTests.cs b/test/Sign.SignatureProviders.TrustedSigning.Test/TrustedSigningServiceProviderTests.cs new file mode 100644 index 00000000..5918d019 --- /dev/null +++ b/test/Sign.SignatureProviders.TrustedSigning.Test/TrustedSigningServiceProviderTests.cs @@ -0,0 +1,136 @@ +// 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. + +using System.Collections.Concurrent; +using Azure.Core; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Moq; +using Sign.Core; +using Sign.TestInfrastructure; + +namespace Sign.SignatureProviders.TrustedSigning.Test +{ + public class TrustedSigningServiceProviderTests + { + private readonly static TokenCredential TokenCredential = Mock.Of(); + private readonly static Uri EndpointUrl = new("https://trustedsigning.test"); + private const string AccountName = "a"; + private const string CertificateProfileName = "b"; + private readonly IServiceProvider serviceProvider; + + public TrustedSigningServiceProviderTests() + { + ServiceCollection services = new(); + services.AddSingleton>(new TestLogger()); + serviceProvider = services.BuildServiceProvider(); + } + + [Fact] + public void Constructor_WhenTokenCredentialIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningServiceProvider(tokenCredential: null!, EndpointUrl, AccountName, CertificateProfileName)); + + Assert.Equal("tokenCredential", exception.ParamName); + } + + [Fact] + public void Constructor_WhenEndpointUrlIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningServiceProvider(TokenCredential, endpointUrl: null!, AccountName, CertificateProfileName)); + + Assert.Equal("endpointUrl", exception.ParamName); + } + + [Fact] + public void Constructor_WhenAccountNameIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningServiceProvider(TokenCredential, EndpointUrl, accountName: null!, CertificateProfileName)); + + Assert.Equal("accountName", exception.ParamName); + } + + [Fact] + public void Constructor_WhenAccountNameIsEmpty_Throws() + { + ArgumentException exception = Assert.Throws( + () => new TrustedSigningServiceProvider(TokenCredential, EndpointUrl, accountName: string.Empty, CertificateProfileName)); + + Assert.Equal("accountName", exception.ParamName); + } + + [Fact] + public void Constructor_WhenCertificateProfileNameIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningServiceProvider(TokenCredential, EndpointUrl, AccountName, certificateProfileName: null!)); + + Assert.Equal("certificateProfileName", exception.ParamName); + } + + [Fact] + public void Constructor_WhenCertificateProfileNameIsEmpty_Throws() + { + ArgumentException exception = Assert.Throws( + () => new TrustedSigningServiceProvider(TokenCredential, EndpointUrl, AccountName, certificateProfileName: string.Empty)); + + Assert.Equal("certificateProfileName", exception.ParamName); + } + + [Fact] + public void GetSignatureAlgorithmProvider_WhenServiceProviderIsNull_Throws() + { + TrustedSigningServiceProvider provider = new(TokenCredential, EndpointUrl, AccountName, CertificateProfileName); + + ArgumentNullException exception = Assert.Throws( + () => provider.GetSignatureAlgorithmProvider(serviceProvider: null!)); + + Assert.Equal("serviceProvider", exception.ParamName); + } + + [Fact] + public void GetSignatureAlgorithmProvider_ReturnsSameInstance() + { + TrustedSigningServiceProvider provider = new(TokenCredential, EndpointUrl, AccountName, CertificateProfileName); + + ConcurrentBag signatureAlgorithmProviders = []; + Parallel.For(0, 2, (_, _) => + { + signatureAlgorithmProviders.Add(provider.GetSignatureAlgorithmProvider(serviceProvider)); + }); + + Assert.Equal(2, signatureAlgorithmProviders.Count); + Assert.Same(signatureAlgorithmProviders.First(), signatureAlgorithmProviders.Last()); + } + + [Fact] + public void GetCertificateProvider_WhenServiceProviderIsNull_Throws() + { + TrustedSigningServiceProvider provider = new(TokenCredential, EndpointUrl, AccountName, CertificateProfileName); + + ArgumentNullException exception = Assert.Throws( + () => provider.GetSignatureAlgorithmProvider(serviceProvider: null!)); + + Assert.Equal("serviceProvider", exception.ParamName); + } + + [Fact] + public void GetCertificateProvider_ReturnsSameInstance() + { + TrustedSigningServiceProvider provider = new(TokenCredential, EndpointUrl, AccountName, CertificateProfileName); + + ConcurrentBag certificateProviders = []; + Parallel.For(0, 2, (_, _) => + { + certificateProviders.Add(provider.GetCertificateProvider(serviceProvider)); + }); + + Assert.Equal(2, certificateProviders.Count); + Assert.Same(certificateProviders.First(), certificateProviders.Last()); + } + } +} diff --git a/test/Sign.SignatureProviders.TrustedSigning.Test/TrustedSigningServiceTests.cs b/test/Sign.SignatureProviders.TrustedSigning.Test/TrustedSigningServiceTests.cs new file mode 100644 index 00000000..e78d4215 --- /dev/null +++ b/test/Sign.SignatureProviders.TrustedSigning.Test/TrustedSigningServiceTests.cs @@ -0,0 +1,82 @@ +// 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. + +using Azure.Core; +using Microsoft.Extensions.Logging; +using Moq; + +namespace Sign.SignatureProviders.TrustedSigning.Test +{ + public class TrustedSigningServiceTests + { + private readonly static TokenCredential TokenCredential = Mock.Of(); + private readonly static Uri EndpointUrl = new("https://trustedsigning.test"); + private const string AccountName = "a"; + private const string CertificateProfileName = "b"; + private readonly static ILogger Logger = Mock.Of>(); + + [Fact] + public void Constructor_WhenTokenCredentialIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningService(tokenCredential: null!, EndpointUrl, AccountName, CertificateProfileName, Logger)); + + Assert.Equal("tokenCredential", exception.ParamName); + } + + [Fact] + public void Constructor_WhenEndpointUrlIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningService(TokenCredential, endpointUrl: null!, AccountName, CertificateProfileName, Logger)); + + Assert.Equal("endpointUrl", exception.ParamName); + } + + [Fact] + public void Constructor_WhenAccountNameIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningService(TokenCredential, EndpointUrl, accountName: null!, CertificateProfileName, Logger)); + + Assert.Equal("accountName", exception.ParamName); + } + + [Fact] + public void Constructor_WhenAccountNameIsEmpty_Throws() + { + ArgumentException exception = Assert.Throws( + () => new TrustedSigningService(TokenCredential, EndpointUrl, accountName: string.Empty, CertificateProfileName, Logger)); + + Assert.Equal("accountName", exception.ParamName); + } + + [Fact] + public void Constructor_WhenCertificateProfileNameIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningService(TokenCredential, EndpointUrl, AccountName, certificateProfileName: null!, Logger)); + + Assert.Equal("certificateProfileName", exception.ParamName); + } + + [Fact] + public void Constructor_WhenCertificateProfileNameIsEmpty_Throws() + { + ArgumentException exception = Assert.Throws( + () => new TrustedSigningService(TokenCredential, EndpointUrl, AccountName, certificateProfileName: string.Empty, Logger)); + + Assert.Equal("certificateProfileName", exception.ParamName); + } + + [Fact] + public void Constructor_WhenLoggerIsNull_Throws() + { + ArgumentNullException exception = Assert.Throws( + () => new TrustedSigningService(TokenCredential, EndpointUrl, AccountName, CertificateProfileName, logger: null!)); + + Assert.Equal("logger", exception.ParamName); + } + } +} diff --git a/test/Sign.SignatureProviders.TrustedSigning.Test/Usings.cs b/test/Sign.SignatureProviders.TrustedSigning.Test/Usings.cs new file mode 100644 index 00000000..bf1085a9 --- /dev/null +++ b/test/Sign.SignatureProviders.TrustedSigning.Test/Usings.cs @@ -0,0 +1,5 @@ +// 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. + +global using Xunit; \ No newline at end of file