From 1a92632e1e2668f73bf380e20e3703556eb60efb Mon Sep 17 00:00:00 2001 From: JoshL Date: Sun, 14 Jun 2020 13:29:40 -0400 Subject: [PATCH] Add new module for OrchardCore.KeyVault.Azure --- OrchardCore.sln | 7 ++++ src/OrchardCore.Build/Dependencies.props | 1 + src/OrchardCore.Cms.Web/appsettings.json | 7 ++++ .../AzureKeyVaultWebHostBuilderExtension.cs | 40 +++++++++++++++++++ .../OrchardCore.KeyVault.Azure.csproj | 20 ++++++++++ .../Services/CustomKeyVaultSecretManager.cs | 23 +++++++++++ 6 files changed, 98 insertions(+) create mode 100644 src/OrchardCore/OrchardCore.KeyVault.Azure/Extensions/AzureKeyVaultWebHostBuilderExtension.cs create mode 100644 src/OrchardCore/OrchardCore.KeyVault.Azure/OrchardCore.KeyVault.Azure.csproj create mode 100644 src/OrchardCore/OrchardCore.KeyVault.Azure/Services/CustomKeyVaultSecretManager.cs diff --git a/OrchardCore.sln b/OrchardCore.sln index c30bd4a1893..cabad1c6f02 100644 --- a/OrchardCore.sln +++ b/OrchardCore.sln @@ -380,6 +380,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.ShortCodes", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.ShortCodes.Abstractions", "src\OrchardCore\OrchardCore.ShortCodes.Abstractions\OrchardCore.ShortCodes.Abstractions.csproj", "{901DA1A3-E5C7-4965-80EA-A1780BE1B820}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.KeyVault.Azure", "src\OrchardCore\OrchardCore.KeyVault.Azure\OrchardCore.KeyVault.Azure.csproj", "{13A89FAE-EDEA-4ED1-8C8E-13AB78F1FD03}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1010,6 +1012,10 @@ Global {901DA1A3-E5C7-4965-80EA-A1780BE1B820}.Debug|Any CPU.Build.0 = Debug|Any CPU {901DA1A3-E5C7-4965-80EA-A1780BE1B820}.Release|Any CPU.ActiveCfg = Release|Any CPU {901DA1A3-E5C7-4965-80EA-A1780BE1B820}.Release|Any CPU.Build.0 = Release|Any CPU + {13A89FAE-EDEA-4ED1-8C8E-13AB78F1FD03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13A89FAE-EDEA-4ED1-8C8E-13AB78F1FD03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13A89FAE-EDEA-4ED1-8C8E-13AB78F1FD03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13A89FAE-EDEA-4ED1-8C8E-13AB78F1FD03}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1186,6 +1192,7 @@ Global {38EE0258-F010-425B-949F-9ECCE886584B} = {F23AC6C2-DE44-4699-999D-3C478EF3D691} {9EEEB83D-85C5-4025-8367-CD7D1ACBBB1A} = {90030E85-0C4F-456F-B879-443E8A3F220D} {901DA1A3-E5C7-4965-80EA-A1780BE1B820} = {F23AC6C2-DE44-4699-999D-3C478EF3D691} + {13A89FAE-EDEA-4ED1-8C8E-13AB78F1FD03} = {F23AC6C2-DE44-4699-999D-3C478EF3D691} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {46A1D25A-78D1-4476-9CBF-25B75E296341} diff --git a/src/OrchardCore.Build/Dependencies.props b/src/OrchardCore.Build/Dependencies.props index e8b58a4c1f1..8c1f9c47ea5 100644 --- a/src/OrchardCore.Build/Dependencies.props +++ b/src/OrchardCore.Build/Dependencies.props @@ -22,6 +22,7 @@ + diff --git a/src/OrchardCore.Cms.Web/appsettings.json b/src/OrchardCore.Cms.Web/appsettings.json index ab497fb322a..db080d7211e 100644 --- a/src/OrchardCore.Cms.Web/appsettings.json +++ b/src/OrchardCore.Cms.Web/appsettings.json @@ -39,5 +39,12 @@ // "BlobName": "", // Optional, defaults to Sites/tenant_name/DataProtectionKeys.xml. Templatable, refer docs. // "CreateContainer": true // Creates the container during app startup if it does not already exist. //}, + // Uncomment to load app configuration values from Azure Key Vault. + // Add '.UseOrchardCoreAzureKeyVault()' to the Generic Host in CreateHostBuilder() + //"OrchardCore_Azure_KeyVault": { + // "KeyVaultName": "", // Set the name of your Azure Key Vault. + // "AzureADApplicationId": "", // Set the Azure AD Application Id + // "AzureADApplicationSecret": "" //The Azure AD Application Secret should never be checked into source control. Instead use an environment variable. + // } } } diff --git a/src/OrchardCore/OrchardCore.KeyVault.Azure/Extensions/AzureKeyVaultWebHostBuilderExtension.cs b/src/OrchardCore/OrchardCore.KeyVault.Azure/Extensions/AzureKeyVaultWebHostBuilderExtension.cs new file mode 100644 index 00000000000..895b665e22f --- /dev/null +++ b/src/OrchardCore/OrchardCore.KeyVault.Azure/Extensions/AzureKeyVaultWebHostBuilderExtension.cs @@ -0,0 +1,40 @@ +using System; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using OrchardCore.Azure.KeyVault.Services; + +namespace OrchardCore.Azure.KeyVault.Extensions +{ + public static class AzureKeyVaultWebHostBuilderExtension + { + /// + /// Adds Azure Key Vault as a Configuration Source. + /// + /// The web host builder to configure. + /// The web host builder. + public static IHostBuilder UseOrchardCoreAzureKeyVault(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 CustomKeyVaultSecretManager() + ); + }); + + return builder; + } + + + } +} diff --git a/src/OrchardCore/OrchardCore.KeyVault.Azure/OrchardCore.KeyVault.Azure.csproj b/src/OrchardCore/OrchardCore.KeyVault.Azure/OrchardCore.KeyVault.Azure.csproj new file mode 100644 index 00000000000..9c80256674b --- /dev/null +++ b/src/OrchardCore/OrchardCore.KeyVault.Azure/OrchardCore.KeyVault.Azure.csproj @@ -0,0 +1,20 @@ + + + + $(AspNetCoreTargetFramework) + + + + + + + + + + + + + + + + diff --git a/src/OrchardCore/OrchardCore.KeyVault.Azure/Services/CustomKeyVaultSecretManager.cs b/src/OrchardCore/OrchardCore.KeyVault.Azure/Services/CustomKeyVaultSecretManager.cs new file mode 100644 index 00000000000..589c5a499e9 --- /dev/null +++ b/src/OrchardCore/OrchardCore.KeyVault.Azure/Services/CustomKeyVaultSecretManager.cs @@ -0,0 +1,23 @@ +using Microsoft.Azure.KeyVault.Models; +using Microsoft.Extensions.Configuration.AzureKeyVault; + +namespace OrchardCore.Azure.KeyVault.Services +{ + /// + /// A custom override of the DefaultKeyVaultManger class that retrieves secrets from azure keyvault and translates --- + /// to the OC format using single underscore (illegal character in Azure KeyVault) and -- to : to define a section + /// Examples: + /// Key Vault Input: "OrchardCore--OrchardCore---Shells---Database--ConnectionString". + /// Output: "OrchardCore:OrchardCore_Shells_Database:ConnectionString". + /// See https://github.com/OrchardCMS/OrchardCore/issues/6359. + /// + public class CustomKeyVaultSecretManager : DefaultKeyVaultSecretManager + { + public override string GetKey(SecretBundle secret) + { + var key = secret.SecretIdentifier.Name.Replace("---", "_").Replace("--", ":"); + return key; + } + + } +}