Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/Sign.Cli/AzureKeyVaultCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace Sign.Cli
internal sealed class AzureKeyVaultCommand : Command
{
internal Option<Uri> UrlOption { get; }
internal Option<string> CertificateVersionOption { get; }
internal Option<string> CertificateOption { get; }
internal AzureCredentialOptions AzureCredentialOptions { get; } = new();

Expand All @@ -40,6 +41,10 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s
Description = AzureKeyVaultResources.CertificateOptionDescription,
Required = true
};
CertificateVersionOption = new Option<string>("--azure-key-vault-certificate-version", "-kvcv")
{
Description = AzureKeyVaultResources.CertificateVersionOptionDescription
};
FilesArgument = new Argument<List<string>?>("file(s)")
{
Description = Resources.FilesArgumentDescription,
Expand All @@ -48,6 +53,7 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s

Options.Add(UrlOption);
Options.Add(CertificateOption);
Options.Add(CertificateVersionOption);
AzureCredentialOptions.AddOptionsToCommand(this);

Arguments.Add(FilesArgument);
Expand Down Expand Up @@ -82,9 +88,11 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s
// the null-forgiving operator (!) to simplify the code.
Uri url = parseResult.GetValue(UrlOption)!;
string certificateId = parseResult.GetValue(CertificateOption)!;
string? certificateVersion = parseResult.GetValue(CertificateVersionOption);
string certificateVersionPath = string.IsNullOrEmpty(certificateVersion) ? string.Empty : $"/{certificateVersion}";

// Construct the URI for the certificate and the key from user parameters. We'll validate those with the SDK
var certUri = new Uri($"{url.Scheme}://{url.Authority}/certificates/{certificateId}");
var certUri = new Uri($"{url.Scheme}://{url.Authority}/certificates/{certificateId}{certificateVersionPath}");

if (!KeyVaultCertificateIdentifier.TryCreate(certUri, out var certId))
{
Expand All @@ -94,7 +102,7 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s
}

// The key uri is similar and the key name matches the certificate name
var keyUri = new Uri($"{url.Scheme}://{url.Authority}/keys/{certificateId}");
var keyUri = new Uri($"{url.Scheme}://{url.Authority}/keys/{certificateId}{certificateVersionPath}");

serviceProviderFactory.AddServices(services =>
{
Expand All @@ -112,6 +120,7 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s
serviceProvider.GetRequiredService<CertificateClient>(),
serviceProvider.GetRequiredService<CryptographyClient>(),
certId.Name,
certId.Version,
serviceProvider.GetRequiredService<ILogger<KeyVaultService>>());
});
});
Expand Down
6 changes: 6 additions & 0 deletions src/Sign.Cli/AzureKeyVaultResources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Sign.Cli/AzureKeyVaultResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
<data name="CertificateOptionDescription" xml:space="preserve">
<value>Name of the certificate in Azure Key Vault.</value>
</data>
<data name="CertificateVersionOptionDescription" xml:space="preserve">
<value>Optional version of the Azure Key Vault certificate.</value>
</data>
<data name="ClickOnceExtensionNotSupported" xml:space="preserve">
<value>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</value>
</data>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.cs.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Název certifikátu v Azure Key Vault.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">Podepisování ClickOnce prostřednictvím starší verze alternativního řešení .clickonce ZIP se už nepodporuje. Projděte si dokumentaci.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.de.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Name des Zertifikats in Azure Key Vault.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">Die ClickOnce-Signierung über die Legacy-.clickonce-ZIP-Problemumgehung wird nicht mehr unterstützt. Siehe Dokumentation.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.es.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Nombre del certificado en Azure Key Vault.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">Ya no se admite la firma ClickOnce a través de la solución zip heredada .clickonce. Consulte la documentación.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Nom du certificat dans Azure Key Vault.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">La signature ClickOnce via la solution de contournement zip .clickonce héritée n’est plus prise en charge. Consulter la documentation.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.it.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Nome del certificato in Azure Key Vault.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">La firma ClickOnce tramite la soluzione alternativa legacy .clickonce ZIP non è più supportata. Vedere la documentazione.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.ja.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Azure Key Vault 内の証明書の名前。</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">従来の .clickonce ZIP 回避策による ClickOnce 署名はサポートされなくなりました。ドキュメントを参照してください。</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.ko.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Azure Key Vault의 인증서 이름입니다.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">레거시 .clickonce ZIP 해결 방법을 통한 ClickOnce 서명은 더 이상 지원되지 않습니다. 설명서를 참조하세요.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.pl.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Nazwa certyfikatu w usłudze Azure Key Vault.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">Podpisywanie clickOnce za pośrednictwem starszego obejścia .clickonce ZIP nie jest już obsługiwane. Zobacz dokumentację.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.pt-BR.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Nome do certificado no Azure Key Vault.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">Não há mais suporte para a assinatura do ClickOnce por meio da solução alternativa .clickonce ZIP herdada. Consulte a documentação.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.ru.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Имя сертификата в Azure Key Vault.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">Подписание ClickOnce с помощью устаревшего обходного пути .clickonce ZIP больше не поддерживается. См. документацию.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.tr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Azure Key Vault’taki sertifikanın adı.</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">Eski .clickonce ZIP geçici çözümü aracılığıyla ClickOnce imzalama işlemi artık desteklenmiyor. Belgelere bakın.</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hans.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Azure Key Vault 中的证书名称。</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">不再支持通过旧版 .clickonce ZIP 解决方法进行 ClickOnce 签名。参阅文档。</target>
Expand Down
5 changes: 5 additions & 0 deletions src/Sign.Cli/xlf/AzureKeyVaultResources.zh-Hant.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<target state="translated">Azure Key Vault 中的憑證名稱。</target>
<note />
</trans-unit>
<trans-unit id="CertificateVersionOptionDescription">
<source>Optional version of the Azure Key Vault certificate.</source>
<target state="new">Optional version of the Azure Key Vault certificate.</target>
<note />
</trans-unit>
<trans-unit id="ClickOnceExtensionNotSupported">
<source>ClickOnce signing via the legacy .clickonce ZIP workaround is no longer supported. See documentation.</source>
<target state="translated">已不再支援透過舊版 .clickonce ZIP 因應措施進行 ClickOnce 簽署。請參閱文件。</target>
Expand Down
18 changes: 16 additions & 2 deletions src/Sign.SignatureProviders.KeyVault/KeyVaultService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal sealed class KeyVaultService : ISignatureAlgorithmProvider, ICertificat
{
private readonly CertificateClient _certificateClient;
private readonly CryptographyClient _cryptographyClient;
private readonly string? _certificateVersion;
private readonly string _certificateName;
private readonly ILogger<KeyVaultService> _logger;
private readonly SemaphoreSlim _mutex = new(1);
Expand All @@ -26,6 +27,7 @@ internal KeyVaultService(
CertificateClient certificateClient,
CryptographyClient cryptographyClient,
string certificateName,
string? certificateVersion,
ILogger<KeyVaultService> logger)
{
ArgumentNullException.ThrowIfNull(certificateClient, nameof(certificateClient));
Expand All @@ -34,6 +36,7 @@ internal KeyVaultService(
ArgumentNullException.ThrowIfNull(logger, nameof(logger));

_certificateName = certificateName;
_certificateVersion = certificateVersion;
_certificateClient = certificateClient;
_cryptographyClient = cryptographyClient;
_logger = logger;
Expand Down Expand Up @@ -63,11 +66,22 @@ public async Task<X509Certificate2> GetCertificateAsync(CancellationToken cancel

_logger.LogTrace(Resources.FetchingCertificate);

Response<KeyVaultCertificateWithPolicy> response = await _certificateClient.GetCertificateAsync(_certificateName, cancellationToken);
byte[] certificateBytes;
if (string.IsNullOrEmpty(_certificateVersion))
{
Response<KeyVaultCertificateWithPolicy> response = await _certificateClient.GetCertificateAsync(_certificateName, cancellationToken);
certificateBytes = response.Value.Cer;
}
else
{
Response<KeyVaultCertificate> response =
await _certificateClient.GetCertificateVersionAsync(_certificateName, _certificateVersion, cancellationToken);
certificateBytes = response.Value.Cer;
}

_logger.LogTrace(Resources.FetchedCertificate, stopwatch.Elapsed.TotalMilliseconds);

_certificate = new X509Certificate2(response.Value.Cer);
_certificate = new X509Certificate2(certificateBytes);

//print the certificate info
_logger.LogTrace($"{Resources.CertificateDetails}{Environment.NewLine}{_certificate.ToString(verbose: true)}");
Expand Down
25 changes: 25 additions & 0 deletions test/Sign.Cli.Test/AzureKeyVaultCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ public void CertificateOption_Always_IsRequired()
Assert.True(_command.CertificateOption.Required);
}

[Fact]
public void CertificateVersionOption_Always_HasArityOfExactlyOne()
{
Assert.Equal(ArgumentArity.ExactlyOne, _command.CertificateVersionOption.Arity);
}

[Fact]
public void CertificateVersionOption_Always_IsOptional()
{
Assert.False(_command.CertificateVersionOption.Required);
}

[Fact]
public void UrlOption_Always_HasArityOfExactlyOne()
{
Expand Down Expand Up @@ -92,13 +104,26 @@ public void Command_WhenRequiredArgumentOrOptionsAreMissing_HasError(string comm
[Theory]
[InlineData("code azure-key-vault -kvu https://keyvault.test -kvc a b")]
[InlineData("code azure-key-vault -kvu https://keyvault.test -kvc a -kvt b -kvi c -kvs d e")]
[InlineData("code azure-key-vault -kvu https://keyvault.test -kvc a -kvcv b c")]
[InlineData("code azure-key-vault -kvu https://keyvault.test -kvc a --azure-key-vault-certificate-version b c")]
public void Command_WhenRequiredArgumentsArePresent_HasNoError(string command)
{
ParseResult result = _rootCommand.Parse(command);

Assert.Empty(result.Errors);
}

[Theory]
[InlineData("-kvcv")]
[InlineData("--azure-key-vault-certificate-version")]
public void Command_WhenCertificateVersionIsSpecified_ParsesCorrectly(string option)
{
ParseResult result = _rootCommand.Parse($"code azure-key-vault -kvu https://keyvault.test -kvc a {option} b c");

Assert.Empty(result.Errors);
Assert.Equal("b", result.GetValue(_command.CertificateVersionOption));
}

[Theory]
[InlineData("code azure-key-vault -kvu \"\" -kvc a b")]
[InlineData("code azure-key-vault -kvu //keyvault.test -kvc a b")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ public KeyVaultServiceProviderTests()
return new KeyVaultService(
Mock.Of<CertificateClient>(),
Mock.Of<CryptographyClient>(),
"a", sp.GetRequiredService<ILogger<KeyVaultService>>());
"a",
null,
sp.GetRequiredService<ILogger<KeyVaultService>>());
});
serviceProvider = services.BuildServiceProvider();
}
Expand Down
Loading