diff --git a/Directory.Packages.props b/Directory.Packages.props
index b3825726499..6434cf91117 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -21,6 +21,8 @@
     
     
     
+    
+    
     
     
     
diff --git a/src/Components/Aspire.Azure.Security.KeyVault/AbstractAzureKeyVaultComponent.cs b/src/Components/Aspire.Azure.Security.KeyVault/AbstractAzureKeyVaultComponent.cs
new file mode 100644
index 00000000000..ffc8662641b
--- /dev/null
+++ b/src/Components/Aspire.Azure.Security.KeyVault/AbstractAzureKeyVaultComponent.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics.CodeAnalysis;
+using Aspire.Azure.Common;
+using Azure.Core;
+using Azure.Core.Extensions;
+using Microsoft.Extensions.Azure;
+
+namespace Aspire.Azure.Security.KeyVault;
+
+/// 
+/// Abstracts the common configuration binding required by  
+/// Deriving type implements KeyVaultClient specific item:
+/// 
+/// 
+/// The KeyVaultClient type for this component.
+/// The associated configuration for the 
+internal abstract class AbstractAzureKeyVaultComponent
+    : AzureComponent
+    where TClient : class
+    where TOptions : class
+{
+    internal abstract TClient CreateComponentClient(Uri vaultUri, TOptions options, TokenCredential cred);
+
+    protected override IAzureClientBuilder AddClient(AzureClientFactoryBuilder azureFactoryBuilder, AzureSecurityKeyVaultSettings settings, string connectionName, string configurationSectionName)
+    {
+        return azureFactoryBuilder.AddClient((options, cred, _) =>
+        {
+            if (settings.VaultUri is null)
+            {
+                throw new InvalidOperationException($"VaultUri is missing. It should be provided in 'ConnectionStrings:{connectionName}' or under the 'VaultUri' key in the '{configurationSectionName}' configuration section.");
+            }
+
+            return CreateComponentClient(settings.VaultUri, options, cred);
+        });
+    }
+
+    protected override bool GetHealthCheckEnabled(AzureSecurityKeyVaultSettings settings)
+        => !settings.DisableHealthChecks;
+
+    protected override TokenCredential? GetTokenCredential(AzureSecurityKeyVaultSettings settings)
+        => settings.Credential;
+
+    protected override bool GetMetricsEnabled(AzureSecurityKeyVaultSettings settings)
+        => false;
+
+    protected override bool GetTracingEnabled(AzureSecurityKeyVaultSettings settings)
+        => !settings.DisableTracing;
+}
diff --git a/src/Components/Aspire.Azure.Security.KeyVault/Aspire.Azure.Security.KeyVault.csproj b/src/Components/Aspire.Azure.Security.KeyVault/Aspire.Azure.Security.KeyVault.csproj
index 2a4dbb03da4..5f9ec339ce2 100644
--- a/src/Components/Aspire.Azure.Security.KeyVault/Aspire.Azure.Security.KeyVault.csproj
+++ b/src/Components/Aspire.Azure.Security.KeyVault/Aspire.Azure.Security.KeyVault.csproj
@@ -19,6 +19,8 @@
     
     
     
+    
+    
     
     
     
diff --git a/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs b/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs
index 1b2bffb2b80..7e87c0a2147 100644
--- a/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs
+++ b/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs
@@ -3,16 +3,14 @@
 
 using Aspire.Azure.Common;
 using Aspire.Azure.Security.KeyVault;
-using Azure.Core;
 using Azure.Core.Extensions;
 using Azure.Extensions.AspNetCore.Configuration.Secrets;
 using Azure.Identity;
+using Azure.Security.KeyVault.Certificates;
+using Azure.Security.KeyVault.Keys;
 using Azure.Security.KeyVault.Secrets;
-using HealthChecks.Azure.KeyVault.Secrets;
-using Microsoft.Extensions.Azure;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Diagnostics.HealthChecks;
 
 namespace Microsoft.Extensions.Hosting;
 
@@ -42,7 +40,8 @@ public static void AddAzureKeyVaultClient(
         ArgumentNullException.ThrowIfNull(builder);
         ArgumentException.ThrowIfNullOrEmpty(connectionName);
 
-        new KeyVaultComponent().AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName, serviceKey: null);
+        new AzureKeyVaultSecretsComponent()
+            .AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName, serviceKey: null);
     }
 
     /// 
@@ -64,7 +63,96 @@ public static void AddKeyedAzureKeyVaultClient(
         ArgumentNullException.ThrowIfNull(builder);
         ArgumentException.ThrowIfNullOrEmpty(name);
 
-        new KeyVaultComponent().AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName: name, serviceKey: name);
+        new AzureKeyVaultSecretsComponent()
+            .AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName: name, serviceKey: name);
+    }
+
+    /// 
+    /// Registers  as a singleton in the services provided by the .
+    /// 
+    /// The  to read config from and add services to.
+    /// A name used to retrieve the connection string from the ConnectionStrings configuration section.
+    /// An optional method that can be used for customizing the . It's invoked after the settings are read from the configuration.
+    /// An optional method that can be used for customizing the .
+    /// Reads the configuration from "Aspire:Azure:Security:KeyVault:{name}" section.
+    /// Thrown when mandatory  is not provided.
+    public static void AddAzureKeyVaultCertificateClient(
+        this IHostApplicationBuilder builder,
+        string connectionName,
+        Action? configureSettings = null,
+        Action>? configureClientBuilder = null)
+    {
+        ArgumentNullException.ThrowIfNull(builder);
+        ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
+        new AzureKeyVaultCertificatesComponent()
+            .AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName, serviceKey: null);
+    }
+
+    /// 
+    /// Registers  as a singleton for given  in the services provided by the .
+    /// 
+    /// The  to read config from and add services to.
+    /// The name of the component, which is used as the  of the service and also to retrieve the connection information from the ConnectionStrings configuration section.
+    /// An optional method that can be used for customizing the . It's invoked after the settings are read from the configuration.
+    /// An optional method that can be used for customizing the .
+    /// Reads the configuration from "Aspire:Azure:Security:KeyVault:{name}" section.
+    /// Thrown when mandatory  is not provided.
+    public static void AddKeyedAzureKeyVaultCertificateClient(
+        this IHostApplicationBuilder builder,
+        string name,
+        Action? configureSettings = null,
+        Action>? configureClientBuilder = null)
+    {
+        ArgumentNullException.ThrowIfNull(builder);
+        ArgumentException.ThrowIfNullOrEmpty(name);
+
+        new AzureKeyVaultCertificatesComponent()
+            .AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName: name, serviceKey: name);
+    }
+
+    /// 
+    /// Registers  as a singleton in the services provided by the .
+    /// 
+    /// The  to read config from and add services to.
+    /// A name used to retrieve the connection string from the ConnectionStrings configuration section.
+    /// An optional method that can be used for customizing the . It's invoked after the settings are read from the configuration.
+    /// An optional method that can be used for customizing the .
+    /// Reads the configuration from "Aspire:Azure:Security:KeyVault:{name}" section.
+    /// Thrown when mandatory  is not provided.
+    public static void AddAzureKeyVaultKeyClient(
+        this IHostApplicationBuilder builder,
+        string connectionName,
+        Action? configureSettings = null,
+        Action>? configureClientBuilder = null)
+    {
+        ArgumentNullException.ThrowIfNull(builder);
+        ArgumentException.ThrowIfNullOrEmpty(connectionName);
+
+        new AzureKeyVaultKeysComponent()
+            .AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName, serviceKey: null);
+    }
+
+    /// 
+    /// Registers  as a singleton for given  in the services provided by the .
+    /// 
+    /// The  to read config from and add services to.
+    /// The name of the component, which is used as the  of the service and also to retrieve the connection information from the ConnectionStrings configuration section.
+    /// An optional method that can be used for customizing the . It's invoked after the settings are read from the configuration.
+    /// An optional method that can be used for customizing the .
+    /// Reads the configuration from "Aspire:Azure:Security:KeyVault:{name}" section.
+    /// Thrown when mandatory  is not provided.
+    public static void AddKeyedAzureKeyVaultKeyClient(
+        this IHostApplicationBuilder builder,
+        string name,
+        Action? configureSettings = null,
+        Action>? configureClientBuilder = null)
+    {
+        ArgumentNullException.ThrowIfNull(builder);
+        ArgumentException.ThrowIfNullOrEmpty(name);
+
+        new AzureKeyVaultKeysComponent()
+            .AddClient(builder, DefaultConfigSectionName, configureSettings, configureClientBuilder, connectionName: name, serviceKey: name);
     }
 
     /// 
@@ -118,49 +206,4 @@ private static SecretClient GetSecretClient(
 
         return new SecretClient(settings.VaultUri, settings.Credential ?? new DefaultAzureCredential(), clientOptions);
     }
-
-    private sealed class KeyVaultComponent : AzureComponent
-    {
-        protected override IAzureClientBuilder AddClient(
-            AzureClientFactoryBuilder azureFactoryBuilder, AzureSecurityKeyVaultSettings settings,
-            string connectionName, string configurationSectionName)
-        {
-            return azureFactoryBuilder.AddClient((options, cred, _) =>
-            {
-                if (settings.VaultUri is null)
-                {
-                    throw new InvalidOperationException($"VaultUri is missing. It should be provided in 'ConnectionStrings:{connectionName}' or under the 'VaultUri' key in the '{configurationSectionName}' configuration section.");
-                }
-
-                return new SecretClient(settings.VaultUri, cred, options);
-            });
-        }
-
-        protected override IHealthCheck CreateHealthCheck(SecretClient client, AzureSecurityKeyVaultSettings settings)
-            => new AzureKeyVaultSecretsHealthCheck(client, new AzureKeyVaultSecretsHealthCheckOptions());
-
-        protected override void BindClientOptionsToConfiguration(IAzureClientBuilder clientBuilder, IConfiguration configuration)
-        {
-#pragma warning disable IDE0200 // Remove unnecessary lambda expression - needed so the ConfigBinder Source Generator works
-            clientBuilder.ConfigureOptions(options => configuration.Bind(options));
-#pragma warning restore IDE0200
-        }
-
-        protected override void BindSettingsToConfiguration(AzureSecurityKeyVaultSettings settings, IConfiguration configuration)
-        {
-            configuration.Bind(settings);
-        }
-
-        protected override bool GetHealthCheckEnabled(AzureSecurityKeyVaultSettings settings)
-            => !settings.DisableHealthChecks;
-
-        protected override TokenCredential? GetTokenCredential(AzureSecurityKeyVaultSettings settings)
-            => settings.Credential;
-
-        protected override bool GetMetricsEnabled(AzureSecurityKeyVaultSettings settings)
-            => false;
-
-        protected override bool GetTracingEnabled(AzureSecurityKeyVaultSettings settings)
-            => !settings.DisableTracing;
-    }
 }
diff --git a/src/Components/Aspire.Azure.Security.KeyVault/AzureKeyVaultCertificatesComponent.cs b/src/Components/Aspire.Azure.Security.KeyVault/AzureKeyVaultCertificatesComponent.cs
new file mode 100644
index 00000000000..33e85dc84c8
--- /dev/null
+++ b/src/Components/Aspire.Azure.Security.KeyVault/AzureKeyVaultCertificatesComponent.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Azure.Common;
+using Aspire.Azure.Security.KeyVault;
+using Azure.Core;
+using Azure.Core.Extensions;
+using Azure.Security.KeyVault.Certificates;
+using Microsoft.Extensions.Azure;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+
+namespace Microsoft.Extensions.Hosting;
+
+/// 
+/// Representation of an  configured as a 
+/// 
+internal sealed class AzureKeyVaultCertificatesComponent : AbstractAzureKeyVaultComponent
+{
+    internal override CertificateClient CreateComponentClient(Uri vaultUri, CertificateClientOptions options, TokenCredential cred)
+        => new(vaultUri, cred, options);
+
+    protected override bool GetHealthCheckEnabled(AzureSecurityKeyVaultSettings settings)
+        => false;
+
+    protected override IHealthCheck CreateHealthCheck(CertificateClient client, AzureSecurityKeyVaultSettings settings)
+        => throw new NotImplementedException();
+
+    protected override void BindClientOptionsToConfiguration(IAzureClientBuilder clientBuilder, IConfiguration configuration)
+#pragma warning disable IDE0200 // Remove unnecessary lambda expression - needed so the ConfigBinder Source Generator works
+        => clientBuilder.ConfigureOptions(options => configuration.Bind(options));
+#pragma warning restore IDE0200 // Remove unnecessary lambda expression
+
+    protected override void BindSettingsToConfiguration(AzureSecurityKeyVaultSettings settings, IConfiguration configuration)
+        => configuration.Bind(settings);
+}
diff --git a/src/Components/Aspire.Azure.Security.KeyVault/AzureKeyVaultKeysComponent.cs b/src/Components/Aspire.Azure.Security.KeyVault/AzureKeyVaultKeysComponent.cs
new file mode 100644
index 00000000000..2688f890b11
--- /dev/null
+++ b/src/Components/Aspire.Azure.Security.KeyVault/AzureKeyVaultKeysComponent.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Azure.Security.KeyVault;
+using Azure.Core;
+using Azure.Core.Extensions;
+using Azure.Security.KeyVault.Keys;
+using Microsoft.Extensions.Azure;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+
+namespace Microsoft.Extensions.Hosting;
+
+internal sealed class AzureKeyVaultKeysComponent : AbstractAzureKeyVaultComponent
+{
+    protected override bool GetHealthCheckEnabled(AzureSecurityKeyVaultSettings settings)
+        => false;
+
+    protected override IHealthCheck CreateHealthCheck(KeyClient client, AzureSecurityKeyVaultSettings settings)
+        => throw new NotImplementedException();
+
+    internal override KeyClient CreateComponentClient(Uri vaultUri, KeyClientOptions options, TokenCredential cred)
+        => new(vaultUri, cred, options);
+
+    protected override void BindClientOptionsToConfiguration(IAzureClientBuilder clientBuilder, IConfiguration configuration)
+#pragma warning disable IDE0200 // Remove unnecessary lambda expression - needed so the ConfigBinder Source Generator works
+        => clientBuilder.ConfigureOptions(options => configuration.Bind(options));
+#pragma warning restore IDE0200 // Remove unnecessary lambda expression
+
+    protected override void BindSettingsToConfiguration(AzureSecurityKeyVaultSettings settings, IConfiguration configuration)
+        => configuration.Bind(settings);
+}
diff --git a/src/Components/Aspire.Azure.Security.KeyVault/AzureKeyVaultSecretsComponent.cs b/src/Components/Aspire.Azure.Security.KeyVault/AzureKeyVaultSecretsComponent.cs
new file mode 100644
index 00000000000..9e56132a53c
--- /dev/null
+++ b/src/Components/Aspire.Azure.Security.KeyVault/AzureKeyVaultSecretsComponent.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Azure.Security.KeyVault;
+using Azure.Core;
+using Azure.Core.Extensions;
+using Azure.Security.KeyVault.Secrets;
+using HealthChecks.Azure.KeyVault.Secrets;
+using Microsoft.Extensions.Azure;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Diagnostics.HealthChecks;
+
+namespace Microsoft.Extensions.Hosting;
+
+internal sealed class AzureKeyVaultSecretsComponent : AbstractAzureKeyVaultComponent
+{
+    protected override void BindClientOptionsToConfiguration(IAzureClientBuilder clientBuilder, IConfiguration configuration)
+#pragma warning disable IDE0200 // Remove unnecessary lambda expression - needed so the ConfigBinder Source Generator works
+        => clientBuilder.ConfigureOptions(options => configuration.Bind(options));
+#pragma warning restore IDE0200 // Remove unnecessary lambda expression
+
+    protected override void BindSettingsToConfiguration(AzureSecurityKeyVaultSettings settings, IConfiguration configuration)
+        => configuration.Bind(settings);
+
+    protected override IHealthCheck CreateHealthCheck(SecretClient client, AzureSecurityKeyVaultSettings settings)
+        => new AzureKeyVaultSecretsHealthCheck(client, new AzureKeyVaultSecretsHealthCheckOptions());
+
+    internal override SecretClient CreateComponentClient(Uri vaultUri, SecretClientOptions options, TokenCredential cred)
+        => new(vaultUri, cred, options);
+}
diff --git a/src/Components/Aspire.Azure.Security.KeyVault/README.md b/src/Components/Aspire.Azure.Security.KeyVault/README.md
index b657c927941..5cafd647cdb 100644
--- a/src/Components/Aspire.Azure.Security.KeyVault/README.md
+++ b/src/Components/Aspire.Azure.Security.KeyVault/README.md
@@ -57,6 +57,41 @@ public ProductsController(SecretClient client)
 
 See the [Azure.Security.KeyVault.Secrets documentation](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/keyvault/Azure.Security.KeyVault.Secrets/README.md) for examples on using the `SecretClient`.
 
+### Optionally include KeyClient and CertificateClient
+
+You can also dependency inject a `KeyClient` and/or `CertificateClient` too:
+
+```csharp
+builder.AddAzureKeyVaultKeyClient("keys");
+builder.AddAzureKeyVaultCertificateClient("certificates");
+```
+
+Which can then be retrieved in the same way the `SecretClient` is. For example , to retrieve a `KeyClient` from a Web API controller:
+
+```csharp
+private readonly KeyClient _client;
+
+public ProductsController(KeyClient client)
+{
+    _client = client;
+}
+```
+
+Or to retrieve a `CertificateClient` from a Web API controller:
+
+```csharp
+private readonly CertificateClient _client;
+
+public ProductsController(CertificateClient client)
+{
+    _client = client;
+}
+```
+
+See the [Azure.Security.KeyVault.Keys documentation](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/keyvault/Azure.Security.KeyVault.Keys/README.md) for examples on using the `KeyClient`.
+
+See the [Azure.Security.KeyVault.Certificates documentation](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/keyvault/Azure.Security.KeyVault.Certificates/README.md) for examples on using the `CertificateClient`.
+
 ## Configuration
 
 The .NET Aspire Azure Key Vault library provides multiple options to configure the Azure Key Vault connection based on the requirements and conventions of your project. Note that the `VaultUri` is required to be supplied.
diff --git a/tests/Aspire.Azure.Security.KeyVault.Tests/AspireKeyVaultExtensionsTests.cs b/tests/Aspire.Azure.Security.KeyVault.Tests/AspireKeyVaultExtensionsTests.cs
index e9cf7d23eb2..682386d3fc9 100644
--- a/tests/Aspire.Azure.Security.KeyVault.Tests/AspireKeyVaultExtensionsTests.cs
+++ b/tests/Aspire.Azure.Security.KeyVault.Tests/AspireKeyVaultExtensionsTests.cs
@@ -4,6 +4,8 @@
 using System.Globalization;
 using System.Text;
 using Azure.Core;
+using Azure.Security.KeyVault.Certificates;
+using Azure.Security.KeyVault.Keys;
 using Azure.Security.KeyVault.Secrets;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
@@ -19,7 +21,7 @@ public class AspireKeyVaultExtensionsTests
     [InlineData(false)]
     public void VaultUriCanBeSetInCode(bool useKeyed)
     {
-        var vaultUri = new Uri(ConformanceTests.VaultUri);
+        var vaultUri = new Uri(ConformanceConstants.VaultUri);
 
         var builder = Host.CreateEmptyApplicationBuilder(null);
         builder.Configuration.AddInMemoryCollection([
@@ -52,8 +54,8 @@ public void ConnectionNameWinsOverConfigSection(bool useKeyed)
 
         var key = useKeyed ? "secrets" : null;
         builder.Configuration.AddInMemoryCollection([
-            new KeyValuePair(ConformanceTests.CreateConfigKey("Aspire:Azure:Security:KeyVault", key, "VaultUri"), "unused"),
-            new KeyValuePair("ConnectionStrings:secrets", ConformanceTests.VaultUri)
+            new KeyValuePair("Aspire:Azure:Security:KeyVault:{key}:VaultUri", "unused"),
+            new KeyValuePair("ConnectionStrings:secrets", ConformanceConstants.VaultUri)
         ]);
 
         if (useKeyed)
@@ -70,7 +72,7 @@ public void ConnectionNameWinsOverConfigSection(bool useKeyed)
             host.Services.GetRequiredKeyedService("secrets") :
             host.Services.GetRequiredService();
 
-        Assert.Equal(new Uri(ConformanceTests.VaultUri), client.VaultUri);
+        Assert.Equal(new Uri(ConformanceConstants.VaultUri), client.VaultUri);
     }
 
     [Fact]
@@ -78,7 +80,7 @@ public void AddsKeyVaultSecretsToConfig()
     {
         var builder = Host.CreateEmptyApplicationBuilder(null);
         builder.Configuration.AddInMemoryCollection([
-            new KeyValuePair("ConnectionStrings:secrets", ConformanceTests.VaultUri)
+            new KeyValuePair("ConnectionStrings:secrets", ConformanceConstants.VaultUri)
         ]);
 
         builder.Configuration.AddAzureKeyVaultSecrets("secrets", configureClientOptions: o =>
@@ -177,7 +179,7 @@ public void CanAddMultipleKeyedServices()
     {
         var builder = Host.CreateEmptyApplicationBuilder(null);
         builder.Configuration.AddInMemoryCollection([
-            new KeyValuePair("ConnectionStrings:secrets1", ConformanceTests.VaultUri),
+            new KeyValuePair("ConnectionStrings:secrets1", ConformanceConstants.VaultUri),
             new KeyValuePair("ConnectionStrings:secrets2", "https://aspiretests2.vault.azure.net/"),
             new KeyValuePair("ConnectionStrings:secrets3", "https://aspiretests3.vault.azure.net/")
         ]);
@@ -201,4 +203,124 @@ public void CanAddMultipleKeyedServices()
         Assert.Equal(new Uri("https://aspiretests2.vault.azure.net/"), client2.VaultUri);
         Assert.Equal(new Uri("https://aspiretests3.vault.azure.net/"), client3.VaultUri);
     }
+
+    [Fact]
+    public void CanAddMultipleClientTypes()
+    {
+        var builder = Host.CreateEmptyApplicationBuilder(null);
+
+        var connectionName = "keyVaultMultipleClients";
+
+        builder.Configuration.AddInMemoryCollection([
+            new KeyValuePair($"ConnectionStrings:{connectionName}", ConformanceConstants.VaultUri)
+        ]);
+
+        builder.AddAzureKeyVaultClient(connectionName);
+        builder.AddAzureKeyVaultKeyClient(connectionName);
+        builder.AddAzureKeyVaultCertificateClient(connectionName);
+
+        using var host = builder.Build();
+
+        var secretClient = host.Services.GetRequiredService();
+        var keyClient = host.Services.GetRequiredService();
+        var certClient = host.Services.GetRequiredService();
+
+        var vaultUri = new Uri(ConformanceConstants.VaultUri);
+
+        Assert.Equal(vaultUri, secretClient.VaultUri);
+        Assert.Equal(vaultUri, keyClient.VaultUri);
+        Assert.Equal(vaultUri, certClient.VaultUri);
+    }
+
+    [Fact]
+    public void CanAddMultipleKeyedClients()
+    {
+        var builder = Host.CreateEmptyApplicationBuilder(null);
+
+        var secretClientName = "secret-client";
+        var secretClientUri = "https://aspiretests1.vault.azure.net/";
+
+        var keyClientName = "key-client";
+        var keyClientUri = "https://aspiretests2.vault.azure.net/";
+
+        var certClientName = "cert-client";
+        var certClientUri = "https://aspiretests3.vault.azure.net/";
+
+        builder.Configuration.AddInMemoryCollection([
+            new KeyValuePair($"ConnectionStrings:{secretClientName}", secretClientUri),
+            new KeyValuePair($"ConnectionStrings:{keyClientName}", keyClientUri),
+            new KeyValuePair($"ConnectionStrings:{certClientName}", certClientUri)
+        ]);
+
+        builder.AddKeyedAzureKeyVaultClient(secretClientName);
+        builder.AddKeyedAzureKeyVaultKeyClient(keyClientName);
+        builder.AddKeyedAzureKeyVaultCertificateClient(certClientName);
+
+        using var host = builder.Build();
+
+        var secretClient = host.Services.GetRequiredKeyedService(secretClientName);
+        var keyClient = host.Services.GetRequiredKeyedService(keyClientName);
+        var certClient = host.Services.GetRequiredKeyedService(certClientName);
+
+        Assert.NotEqual(secretClient.VaultUri, keyClient.VaultUri);
+        Assert.NotEqual(keyClient.VaultUri, certClient.VaultUri);
+
+        Assert.Equal(secretClient.VaultUri, new Uri(secretClientUri));
+        Assert.Equal(keyClient.VaultUri, new Uri(keyClientUri));
+        Assert.Equal(certClient.VaultUri, new Uri(certClientUri));
+    }
+
+    [Theory]
+    [InlineData(true)]
+    [InlineData(false)]
+    public void AddingUnnamedKeyedSecretClientShouldThrow(bool isNull)
+    {
+        var builder = Host.CreateEmptyApplicationBuilder(null);
+
+        var name = isNull ? null! : string.Empty;
+
+        var action = () => builder.AddKeyedAzureKeyVaultClient(name);
+
+        var exception = isNull
+                    ? Assert.Throws(action)
+                    : Assert.Throws(action);
+
+        Assert.Equal(nameof(name), exception.ParamName);
+    }
+
+    [Theory]
+    [InlineData(true)]
+    [InlineData(false)]
+    public void AddingUnnamedKeyedKeyClientShouldThrow(bool isNull)
+    {
+        var builder = Host.CreateEmptyApplicationBuilder(null);
+
+        var name = isNull ? null! : string.Empty;
+
+        var action = () => builder.AddKeyedAzureKeyVaultKeyClient(name);
+
+        var exception = isNull
+                    ? Assert.Throws(action)
+                    : Assert.Throws(action);
+
+        Assert.Equal(nameof(name), exception.ParamName);
+    }
+
+    [Theory]
+    [InlineData(true)]
+    [InlineData(false)]
+    public void AddingUnnamedKeyedCertificateClientShouldThrow(bool isNull)
+    {
+        var builder = Host.CreateEmptyApplicationBuilder(null);
+
+        var name = isNull ? null! : string.Empty;
+
+        var action = () => builder.AddKeyedAzureKeyVaultCertificateClient(name);
+
+        var exception = isNull
+                    ? Assert.Throws(action)
+                    : Assert.Throws(action);
+
+        Assert.Equal(nameof(name), exception.ParamName);
+    }
 }
diff --git a/tests/Aspire.Azure.Security.KeyVault.Tests/CertificateClientConformanceTests.cs b/tests/Aspire.Azure.Security.KeyVault.Tests/CertificateClientConformanceTests.cs
new file mode 100644
index 00000000000..eb9029e8255
--- /dev/null
+++ b/tests/Aspire.Azure.Security.KeyVault.Tests/CertificateClientConformanceTests.cs
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Components.ConformanceTests;
+using Azure.Identity;
+using Azure.Security.KeyVault.Certificates;
+using Microsoft.DotNet.RemoteExecutor;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Azure.Security.KeyVault.Tests;
+public class CertificateClientConformanceTests : ConformanceTests
+{
+    // Roles: Key Vault Certificate User (pending)
+    private const string VaultUri = ConformanceConstants.VaultUri;
+
+    private static readonly Lazy s_canConnectToServer = new(GetCanConnect);
+
+    protected override ServiceLifetime ServiceLifetime => ServiceLifetime.Singleton;
+
+    protected override string ActivitySourceName => "Azure.Security.KeyVault.Certificates.CertificateClient";
+
+    protected override string[] RequiredLogCategories => new string[] { "Azure.Core" };
+
+    protected override bool SupportsKeyedRegistrations => true;
+
+    protected override bool CanConnectToServer => s_canConnectToServer.Value;
+
+    protected override string ValidJsonConfig => """
+        {
+          "Aspire": {
+            "Azure": {
+              "Security": {
+                "KeyVault": {
+                  "VaultUri": "http://YOUR_URI",
+                  "DisableHealthChecks": true,
+                  "DisableTracing": false,
+                  "ClientOptions": {
+                    "DisableChallengeResourceVerification": true,
+                    "Retry": {
+                      "Mode": "Exponential",
+                      "Delay": "00:03"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        """;
+
+    protected override (string json, string error)[] InvalidJsonToErrorMessage => new[]
+        {
+            ("""{"Aspire": { "Azure": { "Security":{ "KeyVault": { "VaultUri": "YOUR_URI"}}}}}""", "Value does not match format \"uri\""),
+            ("""{"Aspire": { "Azure": { "Security":{ "KeyVault": { "VaultUri": "http://YOUR_URI", "DisableHealthChecks": "true"}}}}}""", "Value is \"string\" but should be \"boolean\""),
+            ("""{"Aspire": { "Azure": { "Security":{ "KeyVault": { "VaultUri": "http://YOUR_URI", "ClientOptions": {"Retry": {"Mode": "Fast"}}}}}}}""", "Value should match one of the values specified by the enum"),
+            ("""{"Aspire": { "Azure": { "Security":{ "KeyVault": { "VaultUri": "http://YOUR_URI", "ClientOptions": {"Retry": {"NetworkTimeout": "3S"}}}}}}}""", "The string value is not a match for the indicated regular expression")
+        };
+
+    protected override void PopulateConfiguration(ConfigurationManager configuration, string? key = null)
+        => configuration.AddInMemoryCollection(new KeyValuePair[]
+        {
+            new(CreateConfigKey("Aspire:Azure:Security:KeyVault", key, "VaultUri"), VaultUri),
+            new(CreateConfigKey("Aspire:Azure:Security:KeyVault", key, "ClientOptions:Retry:MaxRetries"), "0")
+        });
+
+    protected override void RegisterComponent(HostApplicationBuilder builder, Action? configure = null, string? key = null)
+    {
+        if (key is null)
+        {
+            builder.AddAzureKeyVaultCertificateClient("certificates", ConfigureCredentials);
+        }
+        else
+        {
+            builder.AddKeyedAzureKeyVaultCertificateClient(key, ConfigureCredentials);
+        }
+
+        void ConfigureCredentials(AzureSecurityKeyVaultSettings settings)
+        {
+            if (CanConnectToServer)
+            {
+                settings.Credential = new DefaultAzureCredential();
+            }
+            configure?.Invoke(settings);
+        }
+    }
+
+    protected override void SetHealthCheck(AzureSecurityKeyVaultSettings options, bool enabled)
+    // Disable Key Vault health check tests until https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/2279 is fixed
+    //    => options.DisableHealthChecks = !enabled;
+        => throw new NotImplementedException();
+
+    protected override void SetMetrics(AzureSecurityKeyVaultSettings options, bool enabled)
+        => throw new NotImplementedException();
+
+    protected override void SetTracing(AzureSecurityKeyVaultSettings options, bool enabled)
+        => options.DisableTracing = !enabled;
+
+    protected override void TriggerActivity(CertificateClient service)
+        => service.GetCertificate("IsAlive");
+
+    [Fact]
+    public void TracingEnablesTheRightActivitySource()
+        => RemoteExecutor.Invoke(() => ActivitySourceTest(key: null)).Dispose();
+
+    [Fact]
+    public void TracingEnablesTheRightActivitySource_Keyed()
+        => RemoteExecutor.Invoke(() => ActivitySourceTest(key: "key")).Dispose();
+
+    private static bool GetCanConnect()
+    {
+        CertificateClientOptions clientOptions = new();
+        clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster)
+        CertificateClient certClient = new(new Uri(VaultUri), new DefaultAzureCredential(), clientOptions);
+
+        try
+        {
+            return certClient.GetCertificate("IsAlive").Value.Name.Equals("IsAlive", StringComparison.CurrentCultureIgnoreCase);
+        }
+        catch (Exception)
+        {
+            return false;
+        }
+    }
+}
diff --git a/tests/Aspire.Azure.Security.KeyVault.Tests/ConformanceConstants.cs b/tests/Aspire.Azure.Security.KeyVault.Tests/ConformanceConstants.cs
new file mode 100644
index 00000000000..8720fa5efdf
--- /dev/null
+++ b/tests/Aspire.Azure.Security.KeyVault.Tests/ConformanceConstants.cs
@@ -0,0 +1,9 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Aspire.Azure.Security.KeyVault.Tests;
+
+public sealed class ConformanceConstants
+{
+    public const string VaultUri = "https://aspiretests.vault.azure.net/";
+}
diff --git a/tests/Aspire.Azure.Security.KeyVault.Tests/KeyClientConformanceTests.cs b/tests/Aspire.Azure.Security.KeyVault.Tests/KeyClientConformanceTests.cs
new file mode 100644
index 00000000000..141604c562b
--- /dev/null
+++ b/tests/Aspire.Azure.Security.KeyVault.Tests/KeyClientConformanceTests.cs
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Components.ConformanceTests;
+using Azure.Identity;
+using Azure.Security.KeyVault.Keys;
+using Microsoft.DotNet.RemoteExecutor;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Xunit;
+
+namespace Aspire.Azure.Security.KeyVault.Tests;
+
+public class KeyClientConformanceTests : ConformanceTests
+{
+
+    // Roles: Key Vault Certificate User (pending)
+    private const string VaultUri = ConformanceConstants.VaultUri;
+
+    private static readonly Lazy s_canConnectToServer = new(GetCanConnect);
+
+    protected override ServiceLifetime ServiceLifetime => ServiceLifetime.Singleton;
+
+    protected override string ActivitySourceName => "Azure.Security.KeyVault.Keys.KeyClient";
+
+    protected override string[] RequiredLogCategories => new string[] { "Azure.Core" };
+
+    protected override bool SupportsKeyedRegistrations => true;
+
+    protected override bool CanConnectToServer => s_canConnectToServer.Value;
+
+    protected override string ValidJsonConfig => """
+        {
+          "Aspire": {
+            "Azure": {
+              "Security": {
+                "KeyVault": {
+                  "VaultUri": "http://YOUR_URI",
+                  "DisableHealthChecks": true,
+                  "DisableTracing": false,
+                  "ClientOptions": {
+                    "DisableChallengeResourceVerification": true,
+                    "Retry": {
+                      "Mode": "Exponential",
+                      "Delay": "00:03"
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        """;
+
+    protected override (string json, string error)[] InvalidJsonToErrorMessage => new[]
+        {
+            ("""{"Aspire": { "Azure": { "Security":{ "KeyVault": { "VaultUri": "YOUR_URI"}}}}}""", "Value does not match format \"uri\""),
+            ("""{"Aspire": { "Azure": { "Security":{ "KeyVault": { "VaultUri": "http://YOUR_URI", "DisableHealthChecks": "true"}}}}}""", "Value is \"string\" but should be \"boolean\""),
+            ("""{"Aspire": { "Azure": { "Security":{ "KeyVault": { "VaultUri": "http://YOUR_URI", "ClientOptions": {"Retry": {"Mode": "Fast"}}}}}}}""", "Value should match one of the values specified by the enum"),
+            ("""{"Aspire": { "Azure": { "Security":{ "KeyVault": { "VaultUri": "http://YOUR_URI", "ClientOptions": {"Retry": {"NetworkTimeout": "3S"}}}}}}}""", "The string value is not a match for the indicated regular expression")
+        };
+
+    protected override void PopulateConfiguration(ConfigurationManager configuration, string? key = null)
+        => configuration.AddInMemoryCollection(new KeyValuePair[]
+        {
+            new(CreateConfigKey("Aspire:Azure:Security:KeyVault", key, "VaultUri"), VaultUri),
+            new(CreateConfigKey("Aspire:Azure:Security:KeyVault", key, "ClientOptions:Retry:MaxRetries"), "0")
+        });
+
+    protected override void RegisterComponent(HostApplicationBuilder builder, Action? configure = null, string? key = null)
+    {
+        if (key is null)
+        {
+            builder.AddAzureKeyVaultKeyClient("keys", ConfigureCredentials);
+        }
+        else
+        {
+            builder.AddKeyedAzureKeyVaultKeyClient(key, ConfigureCredentials);
+        }
+
+        void ConfigureCredentials(AzureSecurityKeyVaultSettings settings)
+        {
+            if (CanConnectToServer)
+            {
+                settings.Credential = new DefaultAzureCredential();
+            }
+            configure?.Invoke(settings);
+        }
+    }
+
+    protected override void SetHealthCheck(AzureSecurityKeyVaultSettings options, bool enabled)
+    // Disable Key Vault health check tests until https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/2279 is fixed
+    //    => options.DisableHealthChecks = !enabled;
+        => throw new NotImplementedException();
+
+    protected override void SetMetrics(AzureSecurityKeyVaultSettings options, bool enabled)
+        => throw new NotImplementedException();
+
+    protected override void SetTracing(AzureSecurityKeyVaultSettings options, bool enabled)
+        => options.DisableTracing = !enabled;
+
+    protected override void TriggerActivity(KeyClient service)
+        => service.GetKey("IsAlive");
+
+    [Fact]
+    public void TracingEnablesTheRightActivitySource()
+        => RemoteExecutor.Invoke(() => ActivitySourceTest(key: null)).Dispose();
+
+    [Fact]
+    public void TracingEnablesTheRightActivitySource_Keyed()
+        => RemoteExecutor.Invoke(() => ActivitySourceTest(key: "key")).Dispose();
+
+    private static bool GetCanConnect()
+    {
+        KeyClientOptions clientOptions = new();
+        clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster)
+        KeyClient keyClient = new(new Uri(VaultUri), new DefaultAzureCredential(), clientOptions);
+
+        try
+        {
+            return keyClient.GetKey("IsAlive").Value.Name.Equals("IsAlive", StringComparison.CurrentCultureIgnoreCase);
+        }
+        catch (Exception)
+        {
+            return false;
+        }
+    }
+}
diff --git a/tests/Aspire.Azure.Security.KeyVault.Tests/ConformanceTests.cs b/tests/Aspire.Azure.Security.KeyVault.Tests/SecretClientConformanceTests.cs
similarity index 96%
rename from tests/Aspire.Azure.Security.KeyVault.Tests/ConformanceTests.cs
rename to tests/Aspire.Azure.Security.KeyVault.Tests/SecretClientConformanceTests.cs
index 24cf646b333..0fb9c51150e 100644
--- a/tests/Aspire.Azure.Security.KeyVault.Tests/ConformanceTests.cs
+++ b/tests/Aspire.Azure.Security.KeyVault.Tests/SecretClientConformanceTests.cs
@@ -12,10 +12,10 @@
 
 namespace Aspire.Azure.Security.KeyVault.Tests;
 
-public class ConformanceTests : ConformanceTests
+public class SecretClientConformanceTests : ConformanceTests
 {
     // Roles: Key Vault Secrets User
-    public const string VaultUri = "https://aspiretests.vault.azure.net/";
+    private const string VaultUri = ConformanceConstants.VaultUri;
 
     private static readonly Lazy s_canConnectToServer = new(GetCanConnect);