Storing certificates in Azure Key Vault

Has anyone had any luck storing a certificate in Azure Key Vault?

I’m trying to use the ICertificateLoader to load a certificate from a Azure Key Vault rather than storing the certificate in a base64 encoded string. I’ve uploaded a .pfx file containing both the certificate and private key to my key vault. In the LocalServiceProviderConfiguration I’ve configured the local certificate with only the “Key” value that is the Azure Key Vault keys name. However when I call ICertificateLoader.LoadCertificateFromKeyAsync I get the exception below. “xxx-cert” is the name of the key vault key here.

ComponentSpace.Saml2.Exceptions.SamlCertificateException: The X.509 certificate could not be loaded from the configuration with key xxx-cert. —> ComponentSpace.Saml2.Exceptions.SamlCertificateException: The configuration key xxx-cert is invalid.

Do you need to upload the certificate in any particular way? The documentation only refers to the general Azure documentation.

The exception indicates that either the key vault access hasn’t been setup correctly or the key vault key is incorrect.
Please refer to our Certificate Guide for information on retrieving keys from the Azure key vault.
https://www.componentspace.com/Forums/8238/Certificate-Guide
The Certificate Guide includes some example code to include in your Program.cs for making the key vault values available through the IConfiguration interface.
I’ve included a section of it below.

config.AddAzureKeyVault(
$“https://{builtConfig[“KeyVault:Vault”]}.vault.azure.net/”,
builtConfig[“KeyVault:ClientId”],
builtConfig[“KeyVault:ClientSecret”]);


If everything is setup correctly, the base-64 encoded certificate string is available through the IConfiguration interface.
As an experiment, try accessing the certificate from your application.

// Retrieve the certificate string from the key vault.
var certificateString = configuration[“xxx-cert”];

if (string.IsNullOrEmpty(certificateString))
{
// Ensure AddAzureKeyVault has been called (see the Certificate Guide)
// and that the key is correct.
}


[quote]
ComponentSpace - 8/23/2018
The exception indicates that either the key vault access hasn't been setup correctly or the key vault key is incorrect.
Please refer to our Certificate Guide for information on retrieving keys from the Azure key vault.
https://www.componentspace.com/Forums/8238/Certificate-Guide
The Certificate Guide includes some example code to include in your Program.cs for making the key vault values available through the IConfiguration interface.
I've included a section of it below.

config.AddAzureKeyVault(
$"https://{builtConfig["KeyVault:Vault"]}.vault.azure.net/",
builtConfig["KeyVault:ClientId"],
builtConfig["KeyVault:ClientSecret"]);


If everything is setup correctly, the base-64 encoded certificate string is available through the IConfiguration interface.
As an experiment, try accessing the certificate from your application.

// Retrieve the certificate string from the key vault.
var certificateString = configuration["xxx-cert"];

if (string.IsNullOrEmpty(certificateString))
{
// Ensure AddAzureKeyVault has been called (see the Certificate Guide)
// and that the key is correct.
}


[/quote]

Hi,

I know Azure key vault is correctly setup because I have all other third party API keys stored in there and those integrations are working well. I'm suspecting though that we are talking apples and pears in the key vault.

From my prior experience what is being fetched from the key vault and available through the Configuration interface are not "keys", but "secrets" from the key vault. There is a great distinction between these in the Azure key vault.

From my prior experience with storing certificates in a secret in the key vault is that I've never managed to compose a base64 encoded string value with both certificate and private key that does not require a password. At least not with openssl, but any examples to accomplish this is most welcome. In your documentation you never mention the "Password" value of the configuration together with Azure key vault so my assumption is that the certificate loader would not use it when fetching the certificate from Azure key vault.

So based on your feedback I'm interpreting this as the way to go is to store the certificate as a base64 encoded string value in a "secret" in the Azure key vault.

The Azure Portal UI has changed since we documented Key Vault support in our Certificate Guide.
My apologies for the confusion. I’ll see that the Certificate Guide is updated.
There may also be some confusion with the overloaded term “key”.
Keys may be stored in the key vault.
We also refer to the configuration key which is used as the parameter to the IConfiguration.Item[String] property.
Originally certificates were added to the key vault as managed keys through the portal.
Now there’s a distinction between keys, secrets and certificates.
You should add certificates to the key vault as certificates rather than as keys or secrets.
You’ll need the certificate password to import the PFX file. You don’t need the certificate password to access the certificate from the key vault.
The portal interface for adding certificates to a key vault is shown below.




The Certificate Name corresponds to the certificate Key in the SAML configuration.
In our key vault I’ve imported the example idp.pfx and sp.pfx files and named these IdP and SP respectively.
The ExampleIdentityProvider’s configuration to access its IdP certificate is:

“LocalIdentityProviderConfiguration”: {
“Name”: “<a href=“https://ExampleIdentityProvider”,”>https://ExampleIdentityProvider",
“Description”: “Example Identity Provider”,
“SingleSignOnServiceUrl”: "<a href=“https://localhost:44313/SAML/SingleSignOnService",">https://localhost:44313/SAML/SingleSignOnService”,
“SingleLogoutServiceUrl”: "<a href=“https://localhost:44313/SAML/SingleLogoutService",">https://localhost:44313/SAML/SingleLogoutService”,
“ArtifactResolutionServiceUrl”: "<a href=“https://localhost:44313/SAML/ArtifactResolutionService",">https://localhost:44313/SAML/ArtifactResolutionService”,
“LocalCertificates”: [
{
“Key”: “IdP”
}
]
},


I’ve retested accessing certificates from the key vault and everything works as expected.
Hopefully that helps.

[quote]
ComponentSpace - 8/24/2018
The Azure Portal UI has changed since we documented Key Vault support in our Certificate Guide.
My apologies for the confusion. I'll see that the Certificate Guide is updated.
There may also be some confusion with the overloaded term "key".
Keys may be stored in the key vault.
We also refer to the configuration key which is used as the parameter to the IConfiguration.Item[String] property.
Originally certificates were added to the key vault as managed keys through the portal.
Now there's a distinction between keys, secrets and certificates.
You should add certificates to the key vault as certificates rather than as keys or secrets.
You'll need the certificate password to import the PFX file. You don't need the certificate password to access the certificate from the key vault.
The portal interface for adding certificates to a key vault is shown below.




The Certificate Name corresponds to the certificate Key in the SAML configuration.
In our key vault I've imported the example idp.pfx and sp.pfx files and named these IdP and SP respectively.
The ExampleIdentityProvider's configuration to access its IdP certificate is:

"LocalIdentityProviderConfiguration": {
"Name": "https://ExampleIdentityProvider",
"Description": "Example Identity Provider",
"SingleSignOnServiceUrl": "https://localhost:44313/SAML/SingleSignOnService",
"SingleLogoutServiceUrl": "https://localhost:44313/SAML/SingleLogoutService",
"ArtifactResolutionServiceUrl": "https://localhost:44313/SAML/ArtifactResolutionService",
"LocalCertificates": [
{
"Key": "IdP"
}
]
},


I've retested accessing certificates from the key vault and everything works as expected.
Hopefully that helps.
[/quote]


I have gone through the guides at https://www.componentspace.com/documentation/saml-for-asp-net/ComponentSpace%20SAML%20for%20ASP.NET%20Certificate%20Guide.pdf but made little headway even though I spent quite a bit of time on this issue today.

I've struggled with accessing certificates from the azure key vault.

I'm well versed with accessing certs from azure key vault since I do that with our Identity 4 IDP.

here's the snipped of the relevant code in appSettings.json


"LocalIdentityProviderConfiguration": {
"Name": "https://Some.SAML.Proxy",
"Description": "Some SAML Proxy",
"SingleSignOnServiceUrl": "https://localhost:7019/SAML/SingleSignOnService",
"SingleLogoutServiceUrl": "https://localhost:7019/SAML/SingleLogoutService",
"ArtifactResolutionServiceUrl": "https://localhost:7019/SAML/ArtifactResolutionService",
"LocalCertificates": [
//{
// "FileName": "certificates/SP.pfx",
// "Password": "Password"
//}
{
"Key": "IdP"
}
]
},


Here's how I access the secret from my key vault using managed identity.
I'm first testing this out locally and signed into the azure portal using the azure CLI

var azureCredential = new DefaultAzureCredential();

var secretClient = new SecretClient(new Uri(keyVaultConfiguration.RootUri), azureCredential);
var secretResponse = secretClient.GetSecret(keyVaultConfiguration.CertificateName);

// How should I assign the secret that component space's dll needs to sign the SAML responses???

ConfigurationManager.AppSettings["SAML:Configurations:0:LocalIdentityProviderConfiguration:LocalCertificates:0:Key"] = secretResponse.Value.Value;

ConfigurationManager.AppSettings["IdP"] = secretResponse.Value.Value;

builder.Services.AddSaml(builder.Configuration.GetSection("SAML"));

Please see my comment above, "How should I assign..."
I can't seem to understand where/what I should do once I have the secret from my pfx.

Any help would be greatly appreciated. I keep getting the same error as the original poster at https://www.componentspace.com/Forums/9147/Storing-certificates-in-Azure-Key-Vault

Loading the X.509 certificate from the configuration with key MIIJy..
2023-08-05 20:24:52.641 -04:00 [ERR] Sending an SSO response to the partner service provider has failed.
ComponentSpace.Saml2.Exceptions.SamlCertificateException: The X.509 certificate could not be loaded from the configuration with key MIIJy...

Please see my comment above, "How should I assign..."I can't seem to understand where/what I should do once I have the secret from my pfx.Any help would be greatly appreciated. I keep getting the same error as the original poster.

[quote]Certificate from the configuration with key MIIJy..2023-08-05 20:24:52.641 -04:00 [ERR] Sending an SSO response to the partner service provider has failed.ComponentSpace.Saml2.Exceptions.SamlCertificateException: The X.509 certificate could not be loaded from the configuration with key MIIJy...[/quote]

We don’t have any direct knowledge of the Azure key vault, its configuration or the client access. Instead, we access the private key retrieved from the key vault using the Microsoft.Extensions.Configuration.IConfiguration interface.

For example, if you’ve configured a local certificate with a Key of “idP” we access the private key string using IConfiguration[“IdP”].

Your application is responsible for the retrieval of the private key from the key vault and making it accessible through the IConfiguration interface.

To do this, we recommend using Microsoft’s AddAzureKeyVault extension.

https://github.com/Azure/azure-sdk-for-net/blob/Azure.Extensions.AspNetCore.Configuration.Secrets_1.2.2/sdk/extensions/Azure.Extensions.AspNetCore.Configuration.Secrets/README.md

However, you can use whatever method makes sense for your application.

As long as the private key string is accessible to your application through the IConfiguration interface then it will be accessible to the SAML library as well.

[quote]
ComponentSpace - 8/6/2023
We don’t have any direct knowledge of the Azure key vault, its configuration or the client access. Instead, we access the private key retrieved from the key vault using the Microsoft.Extensions.Configuration.IConfiguration interface.

For example, if you’ve configured a local certificate with a Key of "idP" we access the private key string using IConfiguration["IdP"].

Your application is responsible for the retrieval of the private key from the key vault and making it accessible through the IConfiguration interface.

To do this, we recommend using Microsoft’s AddAzureKeyVault extension.

https://github.com/Azure/azure-sdk-for-net/blob/Azure.Extensions.AspNetCore.Configuration.Secrets_1.2.2/sdk/extensions/Azure.Extensions.AspNetCore.Configuration.Secrets/README.md

However, you can use whatever method makes sense for your application.

As long as the private key string is accessible to your application through the IConfiguration interface then it will be accessible to the SAML library as well.
[/quote]

This worked perfectly, documenting it here in case someone else runs into this issue

builder.Configuration.AddAzureKeyVault(new Uri(keyVaultConfiguration.RootUri), new DefaultAzureCredential());

// Add SAML SSO services.
builder.Services.AddSaml(builder.Configuration.GetSection("SAML"));


Thanks for the update.