-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add new module for OrchardCore.KeyVault.Azure #6422
Changes from 7 commits
1a92632
584b72b
5a3e559
7efcebc
6518ee2
4e35481
f226041
238f099
babcabb
56b282d
837691f
8538dc3
079b62d
ba37db1
56abadf
9e1b20f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
using System; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Hosting; | ||
using OrchardCore.Azure.KeyVault.Services; | ||
|
||
namespace OrchardCore.Azure.KeyVault.Extensions | ||
{ | ||
public static class AzureKeyVaultWebHostBuilderExtension | ||
{ | ||
/// <summary> | ||
/// Adds Azure Key Vault as a Configuration Source. | ||
/// </summary> | ||
/// <param name="builder">The web host builder to configure.</param> | ||
/// <returns>The web host builder.</returns> | ||
public static IHostBuilder AddOrchardCoreAzureKeyVault(this IHostBuilder builder) | ||
{ | ||
if (builder == null) throw new ArgumentNullException(nameof(builder)); | ||
|
||
builder.ConfigureAppConfiguration((context, configuration) => | ||
{ | ||
var builtConfig = configuration.Build(); | ||
var keyVaultName = builtConfig["OrchardCore:OrchardCore_Azure_KeyVault:KeyVaultName"]; | ||
var clientId = builtConfig["OrchardCore:OrchardCore_Azure_KeyVault:AzureADApplicationId"]; | ||
var clientSecret = builtConfig["OrchardCore:OrchardCore_Azure_KeyVault:AzureADApplicationSecret"]; | ||
|
||
var keyVaultEndpoint = "https://" + keyVaultName + ".vault.azure.net"; | ||
configuration.AddAzureKeyVault( | ||
keyVaultEndpoint, | ||
clientId, | ||
clientSecret, | ||
new AzureKeyVaultSecretManager() | ||
); | ||
}); | ||
|
||
return builder; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>$(AspNetCoreTargetFramework)</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<FrameworkReference Include="Microsoft.AspNetCore.App" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\OrchardCore.Abstractions\OrchardCore.Abstractions.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using Microsoft.Azure.KeyVault.Models; | ||
using Microsoft.Extensions.Configuration.AzureKeyVault; | ||
|
||
namespace OrchardCore.Azure.KeyVault.Services | ||
{ | ||
public class AzureKeyVaultSecretManager : DefaultKeyVaultSecretManager | ||
{ | ||
public override string GetKey(SecretBundle secret) => | ||
secret.SecretIdentifier.Name.Replace("---", "_").Replace("--", ":"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Azure Key Vault (`OrchardCore.Azure.KeyVault`) | ||
|
||
The Azure Key Vault configuration provider adds app configuration values from the Azure Key Vault in order to safeguard your cryptographic keys and secrets used by your app. It also contains custom override of the DefaultKeyVaultManager class that retrieves secrets from Azure Key Vault and translates --- | ||
to an underscore (_) and -- to a colon (:). Both underscores and colons are illegal characters in Azure KeyVault. | ||
|
||
Example: | ||
Key Vault Input: "OrchardCore--OrchardCore---Shells---Database--ConnectionString". | ||
Output: "OrchardCore:OrchardCore_Shells_Database:ConnectionString". | ||
See https://github.com/OrchardCMS/OrchardCore/issues/6359. | ||
|
||
## Configuration | ||
You will need to specify the name of your Azure Key Vault and [register a service principal](https://docs.microsoft.com/en-us/azure/key-vault/general/group-permissions-for-apps) in Active Directory for accessing your key vault using an access control policy. | ||
|
||
```json | ||
"OrchardCore_Azure_KeyVault": { | ||
"KeyVaultName": "", // Set the name of your Azure Key Vault. | ||
"AzureADApplicationId": "", // Set the Azure AD Application Id | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is that required when using managed identity in Azure? I believe we can also associated an Azure Web App for instance to be allowed to access a KV account without anything to setup. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not required. We can use the AzureServiceTokenProvider. I got it working on my OrchardCore project. |
||
"AzureADApplicationSecret": "" //Set the Azure AD Application Secret | ||
} | ||
``` | ||
|
||
!!! note | ||
You should **never check in your client secret into source control** as this defeats the purpose of using a key vault in the first place. Instead, set your client secret as an environment variable on your machine, create a separate azurekeyvault.json file and add it to your `.gitignore`, or use user secrets. | ||
|
||
In the `Program.cs`, add `AddOrchardCoreAzureKeyVault()` to the Generic Host in `CreateHostBuilder()`. | ||
|
||
```csharp | ||
using OrchardCore.KeyVault.Azure; | ||
public class Program | ||
{ | ||
public static Task Main(string[] args) | ||
=> BuildHost(args).RunAsync(); | ||
|
||
public static IHost BuildHost(string[] args) => | ||
Host.CreateDefaultBuilder(args) | ||
.AddOrchardCoreAzureKeyVault() | ||
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>()) | ||
.Build(); | ||
} | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a small example that uses directly
AzureKeyVaultSecretManager
such that standard ASP.NET tutorials can be followrd?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean an example of IConfiguration? I have been using it to retrieve my media and database connection strings. For example in DatabaseShellConfigurationSources.cs:
Using the following Keys:
OrchardCore--OrchardCore---Shells---Database--ConnectionString
OrchardCore--OrchardCore---Shells---Database--DatabaseProvider (Not actually a secret, but required to get the section)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What Seb was asking for is something that matches the getting started guides from the ASP.NET docs here https://docs.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-3.1
Where they are using the
AzureServiceTokenProvider
callbacks and such.Which makes me also wonder if we should not be using the callback technique, rather than having our own configuration secrets for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@deanmarcussen
Here @JoshLefebvre just override the
DefaultKeyVaultSecretManager
with a newAzureKeyVaultSecretManager
and provide anAddOrchardCoreAzureKeyVault()
extension that uses it and other config values.But people can just follow the aspnet documentation and then use
new AzureKeyVaultSecretManager()
in place ofnew DefaultKeyVaultSecretManager()
So maybe just remove the
AddOrchardCoreAzureKeyVault()
that is just an example on how to use the newAzureKeyVaultSecretManager
and let people follow the doc and do their own extension if they want.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do I understand your implementation right that you have added replacement of
---
to_
along with default--
to:
behavior?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xperiandri Exactly, this is what @JoshLefebvre did ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that something that is common? Either in OC or ASP.NET with Keyvault?