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 @@
TrueResources.resx
+
+ True
+ True
+ TrustedSigningResources.resx
+
@@ -83,5 +89,9 @@
ResXFileCodeGeneratorResources.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.
-
-
- ID klienta, které se má ověřit pro Azure Key Vault.
-
-
-
-
- Tajný kód klienta, který se má ověřit pro Azure Key Vault.
-
- Použijte Azure Key Vault.
-
-
- 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.
-
-
-
- Spravovaná identita pro ověření pro Azure Key Vault.
-
-
-
-
- ID tenanta, které se má ověřit pro 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 für die Authentifizierung bei Azure Key Vault.
-
-
-
-
- Geheimer Clientschlüssel für die Authentifizierung bei Azure Key Vault.
-
- Verwenden Sie Azure Key Vault.
-
-
- 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.
-
-
-
- Verwaltete Identität für die Authentifizierung bei Azure Key Vault.
-
-
-
-
- Mandanten-ID für die Authentifizierung bei 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.
-
-
- Id. de cliente para autenticarse en Azure Key Vault.
-
-
-
-
- Secreto de cliente para autenticarse en Azure Key Vault.
-
- Use Azure Key Vault.
-
-
- 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.
-
-
-
- Identidad administrada para autenticarse en Azure Key Vault.
-
-
-
-
- Identificador de inquilino para autenticarse en 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.
-
-
- ID client à authentifier auprès d’Azure Key Vault.
-
-
-
-
- Clé secrète client pour s’authentifier auprès d’Azure Key Vault.
-
- Utilisez Azure Key Vault.
-
-
- 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.
-
-
-
- Identité managée à authentifier auprès d’Azure Key Vault.
-
-
-
-
- ID client pour s’authentifier auprès d’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.
-
-
- ID client da autenticare in Azure Key Vault.
-
-
-
-
- Segreto client da autenticare in Azure Key Vault.
-
- Usare Azure Key Vault.
-
-
- 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.
-
-
-
- Identità gestita da autenticare in Azure Key Vault.
-
-
-
-
- ID tenant da autenticare in 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 署名はサポートされなくなりました。ドキュメントを参照してください。
-
-
- Azure Key Vault に対して認証するクライアント ID。
-
-
-
-
- Azure Key Vault に対して認証するクライアント シークレット。
-
- Azure Key Vault を使用してください。
-
-
- マネージド ID を使用しない場合は、{0}、{1}、{2} のオプションがすべて必要です。
- {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized.
-
-
-
- Azure Key Vault に対して認証するマネージド ID。
-
-
-
-
- Azure Key Vault に対して認証するテナント ID。
-
- 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 서명은 더 이상 지원되지 않습니다. 설명서를 참조하세요.
-
-
- Azure Key Vault에 인증하기 위한 클라이언트 ID입니다.
-
-
-
-
- Azure Key Vault에 인증하기 위한 클라이언트 암호입니다.
-
- Azure Key Vault를 사용합니다.
-
-
- 관리 ID를 사용하고 있지 않은 경우 {0}, {1} 및 {2} 옵션이 모두 필요합니다.
- {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized.
-
-
-
- Azure Key Vault에 인증하기 위한 관리 ID입니다.
-
-
-
-
- Azure Key Vault에 인증하기 위한 테넌트 ID입니다.
-
- 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ę.
-
-
- Identyfikator klienta do uwierzytelnienia w usłudze Azure Key Vault.
-
-
-
-
- Klucz tajny klienta do uwierzytelnienia w usłudze Azure Key Vault.
-
- Użyj usługi Azure Key Vault.
-
-
- 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.
-
-
-
- Tożsamość zarządzana do uwierzytelnienia w usłudze Azure Key Vault.
-
-
-
-
- Identyfikator dzierżawy do uwierzytelnienia w usłudze 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.
-
-
- ID do cliente a ser autenticada no Azure Key Vault.
-
-
-
-
- Segredo do cliente a ser autenticado no Azure Key Vault.
-
- Use o Azure Key Vault.
-
-
- 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.
-
-
-
- Identidade gerenciada a ser autenticada no Azure Key Vault.
-
-
-
-
- ID do locatário a ser autenticada no 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 больше не поддерживается. См. документацию.
-
-
- ИД клиента для проверки подлинности в Azure Key Vault.
-
-
-
-
- Секрет клиента для проверки подлинности в Azure Key Vault.
-
- Использование Azure Key Vault.
-
-
- Если управляемое удостоверение не используется, требуются все следующие параметры: {0}, {1} и {2}.
- {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized.
-
-
-
- Управляемое удостоверение для проверки подлинности в Azure Key Vault.
-
-
-
-
- ИД клиента для проверки подлинности в 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.
-
-
- Azure Key Vault için kimlik doğrulamak amacıyla kullanılan istemci kimliği.
-
-
-
-
- Azure Key Vault için kimlik doğrulamak amacıyla kullanılan gizli anahtar.
-
- Azure Key Vault’u kullanın.
-
-
- 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.
-
-
-
- Azure Key Vault için kimlik doğrulamak amacıyla kullanılan yönetilen kimlik.
-
-
-
-
- Azure Key Vault için kimlik doğrulamak amacıyla kullanılan kiracı kimliği.
-
- 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 签名。参阅文档。
-
-
- 要向 Azure Key Vault 进行身份验证的客户端 ID。
-
-
-
-
- 要向 Azure Key Vault 进行身份验证的客户端密码。
-
- 使用 Azure Key Vault。
-
-
- 如果不使用托管标识,则需要以下所有选项: {0}、{1} 和 {2}。
- {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized.
-
-
-
- 要向 Azure Key Vault 进行身份验证的托管标识。
-
-
-
-
- 要向 Azure Key Vault 进行身份验证的租户 ID。
-
- 指向 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 簽署。請參閱文件。
-
-
- 要向 Azure Key Vault 進行驗證的用戶端識別碼。
-
-
-
-
- 要向 Azure Key Vault 進行驗證的用戶端密碼。
-
- 使用 Azure Key Vault。
-
-
- 如果未使用受控識別,則需要下列所有選項: {0}、{1} 和 {2}。
- {NumberedPlaceholder="{0}", "{1}", "{2}"} are option names and should not be localized.
-
-
-
- 要向 Azure Key Vault 進行驗證的受控識別。
-
-
-
-
- 要向 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 secret to authenticate to Azure.
+
+ 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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 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.
+
+ 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 secret to authenticate to Azure.
+
+ 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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 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.
+
+ 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 secret to authenticate to Azure.
+
+ 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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 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.
+
+ 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 secret to authenticate to Azure.
+
+ 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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 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.
+
+ 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 secret to authenticate to Azure.
+
+ 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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 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.
+
+ 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 secret to authenticate to Azure.
+
+ バイナリとコンテナーに署名します。
@@ -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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 最大コンカレンシー。
@@ -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.
+
+ 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 secret to authenticate to Azure.
+
+ 이진 파일 및 컨테이너에 서명합니다.
@@ -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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 최대 동시성입니다.
@@ -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.
+
+ 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 secret to authenticate to Azure.
+
+ 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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 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.
+
+ 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 secret to authenticate to Azure.
+
+ 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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 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.
+
+ 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 secret to authenticate to Azure.
+
+ Подписывание двоичных файлов и контейнеров.
@@ -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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ Максимальный параллелизм.
@@ -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.
+
+ Алгоритм дайджеста для сервера меток времени 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 secret to authenticate to Azure.
+
+ İ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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 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.
+
+ 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 secret to authenticate to Azure.
+
+ 对二进制文件和容器进行签名。
@@ -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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 最大并发。
@@ -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.
+
+ 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 secret to authenticate to Azure.
+
+ 簽署二進位檔和容器。
@@ -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)
+
+
+
+
+ The -kvm and --azure-key-vault-managed-identity options are obsolete and should no longer be specified.
+
+ 並行最大值。
@@ -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.
+
+ 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 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/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 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/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 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/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 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/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 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/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 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/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 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/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 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/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 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/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 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/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 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/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 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/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 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.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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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]
+ {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/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