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
6 changes: 3 additions & 3 deletions OpenVsixSignTool.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26403.7
# Visual Studio Version 17
VisualStudioVersion = 17.11.34909.67
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenVsixSignTool.Core", "src\OpenVsixSignTool.Core\OpenVsixSignTool.Core.csproj", "{351BD833-DE64-4042-9ADE-343825443A36}"
EndProject
Expand All @@ -13,8 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenVsixSignTool.Tests", "t
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{49F130E1-BD5B-43AD-98C6-4CDE1AA10B2A}"
ProjectSection(SolutionItems) = preProject
azure-pipelines.yml = azure-pipelines.yml
Directory.Build.props = Directory.Build.props
.github\workflows\pr.yml = .github\workflows\pr.yml
EndProjectSection
EndProject
Global
Expand Down
17 changes: 10 additions & 7 deletions src/OpenVsixSignTool/AzureKeyVaultMaterializedConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
using Microsoft.Azure.KeyVault;
using System;
using System.Security.Cryptography.X509Certificates;

using Azure.Identity;
using Azure.Security.KeyVault.Keys.Cryptography;

namespace OpenVsixSignTool
{
public class AzureKeyVaultMaterializedConfiguration
{
public AzureKeyVaultMaterializedConfiguration(KeyVaultClient client, X509Certificate2 publicCertificate, KeyIdentifier keyId)
public AzureKeyVaultMaterializedConfiguration(ClientSecretCredential creds, Uri keyId, X509Certificate2 x509Certificate)
{
Client = client;
KeyId = keyId;
PublicCertificate = publicCertificate;
this.Credentials = creds;
this.KeyId = keyId;
this.PublicCertificate = x509Certificate;
}

public X509Certificate2 PublicCertificate { get; }
public KeyVaultClient Client { get; }
public KeyIdentifier KeyId { get; }
public ClientSecretCredential Credentials { get; }
public Uri KeyId { get; }
}
}
1 change: 1 addition & 0 deletions src/OpenVsixSignTool/AzureKeyVaultSignConfigurationSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ public sealed class AzureKeyVaultSignConfigurationSet
public string AzureKeyVaultUrl { get; set; }
public string AzureKeyVaultCertificateName { get; set; }
public string AzureAccessToken { get; set; }
public string AzureTenantId { get; set; }
}
}
40 changes: 10 additions & 30 deletions src/OpenVsixSignTool/KeyVaultConfigurationDiscoverer.cs
Original file line number Diff line number Diff line change
@@ -1,42 +1,22 @@
using Microsoft.Azure.KeyVault;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

using Azure.Identity;
using Azure.Security.KeyVault.Certificates;
using Azure.Security.KeyVault.Keys.Cryptography;

namespace OpenVsixSignTool
{
internal class KeyVaultConfigurationDiscoverer
{
public async Task<ErrorOr<AzureKeyVaultMaterializedConfiguration>> Materialize(AzureKeyVaultSignConfigurationSet configuration)
{
async Task<string> Authenticate(string authority, string resource, string scope)
{
if (!string.IsNullOrWhiteSpace(configuration.AzureAccessToken))
{
return configuration.AzureAccessToken;
}

var context = new AuthenticationContext(authority);
ClientCredential credential = new ClientCredential(configuration.AzureClientId, configuration.AzureClientSecret);

try
{
var result = await context.AcquireTokenAsync(resource, credential);
return result.AccessToken;
}
catch (AdalServiceException e) when (e.StatusCode >= 400 && e.StatusCode < 500)
{
return null;
}
}

var vault = new KeyVaultClient(Authenticate);
var azureCertificate = await vault.GetCertificateAsync(configuration.AzureKeyVaultUrl, configuration.AzureKeyVaultCertificateName);

var certificate = new X509Certificate2(azureCertificate.Cer);
var keyId = azureCertificate.KeyIdentifier;
return new AzureKeyVaultMaterializedConfiguration(vault, certificate, keyId);
var creds = new ClientSecretCredential(configuration.AzureTenantId, configuration.AzureClientId, configuration.AzureClientSecret);

var certClient = new CertificateClient(new System.Uri(configuration.AzureKeyVaultUrl), creds);
KeyVaultCertificateWithPolicy azureCertificate = await certClient.GetCertificateAsync(configuration.AzureKeyVaultCertificateName);
var x509Certificate = new X509Certificate2(azureCertificate.Cer);
return new AzureKeyVaultMaterializedConfiguration(creds, azureCertificate.KeyId, x509Certificate);
}
}
}
5 changes: 4 additions & 1 deletion src/OpenVsixSignTool/OpenVsixSignTool.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.11.4" />
<PackageReference Include="Azure.Security.KeyVault.Certificates" Version="4.6.0" />
<PackageReference Include="Azure.Security.KeyVault.Keys" Version="4.6.0" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.0" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.4" />
<PackageReference Include="Microsoft.Azure.KeyVault.Cryptography" Version="3.0.4" />
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.0" />
<PackageReference Include="RSAKeyVaultProvider" Version="1.1.22" />
<PackageReference Include="RSAKeyVaultProvider" Version="2.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenVsixSignTool.Core\OpenVsixSignTool.Core.csproj" />
Expand Down
3 changes: 2 additions & 1 deletion src/OpenVsixSignTool/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal static int Main(string[] args)
var file = signConfiguration.Argument("file", "A to the VSIX file.");

var azureKeyVaultUrl = signConfiguration.Option("-kvu | --azure-key-vault-url", "The URL to an Azure Key Vault.", CommandOptionType.SingleValue);
var azureKeyVaultTenantId = signConfiguration.Option("-kvt | --azure-key-vault-tenant-id", "The Tenant ID to authenticate to the Azure Key Vault.", CommandOptionType.SingleValue);
var azureKeyVaultClientId = signConfiguration.Option("-kvi | --azure-key-vault-client-id", "The Client ID to authenticate to the Azure Key Vault.", CommandOptionType.SingleValue);
var azureKeyVaultClientSecret = signConfiguration.Option("-kvs | --azure-key-vault-client-secret", "The Client Secret to authenticate to the Azure Key Vault.", CommandOptionType.SingleValue);
var azureKeyVaultCertificateName = signConfiguration.Option("-kvc | --azure-key-vault-certificate", "The name of the certificate in Azure Key Vault.", CommandOptionType.SingleValue);
Expand All @@ -35,7 +36,7 @@ internal static int Main(string[] args)
}
else
{
return sign.SignAzure(azureKeyVaultUrl, azureKeyVaultClientId, azureKeyVaultClientSecret,
return sign.SignAzure(azureKeyVaultUrl, azureKeyVaultTenantId, azureKeyVaultClientId, azureKeyVaultClientSecret,
azureKeyVaultCertificateName, azureKeyVaultAccessToken, force, fileDigest, timestamp, timestampAlgorithm, file);
}
});
Expand Down
15 changes: 12 additions & 3 deletions src/OpenVsixSignTool/SignCommand.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Microsoft.Azure.KeyVault;
using Microsoft.Extensions.CommandLineUtils;

using OpenVsixSignTool.Core;

using System;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -115,7 +117,7 @@ internal Task<int> SignAsync
certificate, GetSigningKeyFromCertificate(certificate));
}

internal async Task<int> SignAzure(CommandOption azureKeyVaultUrl, CommandOption azureKeyVaultClientId,
internal async Task<int> SignAzure(CommandOption azureKeyVaultUrl, CommandOption azureKeyVaultTenantId, CommandOption azureKeyVaultClientId,
CommandOption azureKeyVaultClientSecret, CommandOption azureKeyVaultCertificateName, CommandOption azureKeyVaultAccessToken, CommandOption force,
CommandOption fileDigest, CommandOption timestampUrl, CommandOption timestampAlgorithm, CommandArgument vsixPath)
{
Expand All @@ -129,6 +131,12 @@ internal async Task<int> SignAzure(CommandOption azureKeyVaultUrl, CommandOption
// we only need the client id/secret if we don't have an access token
if (!azureKeyVaultAccessToken.HasValue())
{
if (!azureKeyVaultTenantId.HasValue())
{
_signCommandApplication.Out.WriteLine("The Azure Key Vault Tenant ID or Access Token must be specified for Azure signing.");
return EXIT_CODES.INVALID_OPTIONS;
}

if (!azureKeyVaultClientId.HasValue())
{
_signCommandApplication.Out.WriteLine("The Azure Key Vault Client ID or Access Token must be specified for Azure signing.");
Expand Down Expand Up @@ -192,6 +200,7 @@ internal async Task<int> SignAzure(CommandOption azureKeyVaultUrl, CommandOption
{
AzureKeyVaultUrl = azureKeyVaultUrl.Value(),
AzureKeyVaultCertificateName = azureKeyVaultCertificateName.Value(),
AzureTenantId = azureKeyVaultTenantId.Value(),
AzureClientId = azureKeyVaultClientId.Value(),
AzureAccessToken = azureKeyVaultAccessToken.Value(),
AzureClientSecret = azureKeyVaultClientSecret.Value(),
Expand All @@ -209,8 +218,8 @@ internal async Task<int> SignAzure(CommandOption azureKeyVaultUrl, CommandOption
_signCommandApplication.Out.WriteLine("Failed to get configuration from Azure Key Vault.");
return EXIT_CODES.FAILED;
}
var context = new KeyVaultContext(materialized.Client, materialized.KeyId, materialized.PublicCertificate);
using (var keyVault = new RSAKeyVault(context))

using (var keyVault = new RSAKeyVaultProvider.RSAKeyVault(new RSAKeyVaultProvider.KeyVaultContext(materialized.Credentials, materialized.KeyId, materialized.PublicCertificate)))
{
return await PerformSignOnVsixAsync(
vsixPathValue,
Expand Down