Skip to content

Commit

Permalink
Merge pull request #715 from skoruba/feature/533-add-support-for-azur…
Browse files Browse the repository at this point in the history
…e-key-vault

Add support for Azure Key Vault
  • Loading branch information
skoruba authored Oct 1, 2020
2 parents a3f8b6e + 2bd4c5b commit 5bbf599
Show file tree
Hide file tree
Showing 17 changed files with 331 additions and 25 deletions.
8 changes: 8 additions & 0 deletions src/Skoruba.IdentityServer4.Admin.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ private static IConfiguration GetConfiguration(string[] args)
configurationBuilder.AddUserSecrets<Startup>();
}

var configuration = configurationBuilder.Build();

configuration.AddAzureKeyVaultConfiguration(configurationBuilder);

configurationBuilder.AddCommandLine(args);
configurationBuilder.AddEnvironmentVariables();

Expand All @@ -60,6 +64,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostContext, configApp) =>
{
var configurationRoot = configApp.Build();

configApp.AddJsonFile("serilog.json", optional: true, reloadOnChange: true);

var env = hostContext.HostingEnvironment;
Expand All @@ -71,6 +77,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
configApp.AddUserSecrets<Startup>();
}

configurationRoot.AddAzureKeyVaultConfiguration(configApp);

configApp.AddEnvironmentVariables();
configApp.AddCommandLine(args);
})
Expand Down
4 changes: 1 addition & 3 deletions src/Skoruba.IdentityServer4.Admin.Api/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ public void ConfigureServices(IServiceCollection services)
// Add DbContexts
RegisterDbContexts(services);

services.AddDataProtection()
.SetApplicationName("Skoruba.IdentityServer4")
.PersistKeysToDbContext<IdentityServerDataProtectionDbContext>();
services.AddDataProtection<IdentityServerDataProtectionDbContext>(Configuration);

// Add email senders which is currently setup for SendGrid and SMTP
services.AddEmailSenders(Configuration);
Expand Down
17 changes: 14 additions & 3 deletions src/Skoruba.IdentityServer4.Admin.Api/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,24 @@
},
"IdentityOptions": {
"Password": {
"RequiredLength": 8
"RequiredLength": 8
},
"User": {
"RequireUniqueEmail": true
"RequireUniqueEmail": true
},
"SignIn": {
"RequireConfirmedAccount": false
"RequireConfirmedAccount": false
}
},
"DataProtectionConfiguration": {
"ProtectKeysWithAzureKeyVault": false
},
"AzureKeyVaultConfiguration": {
"AzureKeyVaultEndpoint": "",
"ClientId": "",
"ClientSecret": "",
"UseClientCredentials": true,
"DataProtectionKeyIdentifier": "",
"ReadConfigurationFromKeyVault": false
}
}
14 changes: 13 additions & 1 deletion src/Skoruba.IdentityServer4.Admin/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureKeyVault;
using Microsoft.Extensions.Hosting;
using Serilog;
using Skoruba.IdentityServer4.Admin.Configuration;
using Skoruba.IdentityServer4.Admin.EntityFramework.Shared.DbContexts;
using Skoruba.IdentityServer4.Admin.EntityFramework.Shared.Entities.Identity;
using Skoruba.IdentityServer4.Admin.Helpers;
using Skoruba.IdentityServer4.Shared.Configuration.Common;
using Skoruba.IdentityServer4.Shared.Helpers;

namespace Skoruba.IdentityServer4.Admin
Expand Down Expand Up @@ -49,7 +53,7 @@ public static async Task Main(string[] args)
private static async Task ApplyDbMigrationsWithDataSeedAsync(string[] args, IConfiguration configuration, IHost host)
{
var applyDbMigrationWithDataSeedFromProgramArguments = args.Any(x => x == SeedArgs);
if (applyDbMigrationWithDataSeedFromProgramArguments) args = args.Except(new[] {SeedArgs}).ToArray();
if (applyDbMigrationWithDataSeedFromProgramArguments) args = args.Except(new[] { SeedArgs }).ToArray();

var seedConfiguration = configuration.GetSection(nameof(SeedConfiguration)).Get<SeedConfiguration>();
var databaseMigrationsConfiguration = configuration.GetSection(nameof(DatabaseMigrationsConfiguration))
Expand Down Expand Up @@ -79,6 +83,10 @@ private static IConfiguration GetConfiguration(string[] args)
configurationBuilder.AddUserSecrets<Startup>();
}

var configuration = configurationBuilder.Build();

configuration.AddAzureKeyVaultConfiguration(configurationBuilder);

configurationBuilder.AddCommandLine(args);
configurationBuilder.AddEnvironmentVariables();

Expand All @@ -89,6 +97,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostContext, configApp) =>
{
var configurationRoot = configApp.Build();

configApp.AddJsonFile("serilog.json", optional: true, reloadOnChange: true);
configApp.AddJsonFile("identitydata.json", optional: true, reloadOnChange: true);
configApp.AddJsonFile("identityserverdata.json", optional: true, reloadOnChange: true);
Expand All @@ -104,6 +114,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
configApp.AddUserSecrets<Startup>();
}

configurationRoot.AddAzureKeyVaultConfiguration(configApp);

configApp.AddEnvironmentVariables();
configApp.AddCommandLine(args);
})
Expand Down
4 changes: 1 addition & 3 deletions src/Skoruba.IdentityServer4.Admin/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ public void ConfigureServices(IServiceCollection services)
RegisterDbContexts(services);

// Save data protection keys to db, using a common application name shared between Admin and STS
services.AddDataProtection()
.SetApplicationName("Skoruba.IdentityServer4")
.PersistKeysToDbContext<IdentityServerDataProtectionDbContext>();
services.AddDataProtection<IdentityServerDataProtectionDbContext>(Configuration);

// Add email senders which is currently setup for SendGrid and SMTP
services.AddEmailSenders(Configuration);
Expand Down
22 changes: 17 additions & 5 deletions src/Skoruba.IdentityServer4.Admin/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,25 @@
"BasePath": "",
"IdentityOptions": {
"Password": {
"RequiredLength": 8
"RequiredLength": 8
},
"User": {
"RequireUniqueEmail": true
"RequireUniqueEmail": true
},
"SignIn": {
"RequireConfirmedAccount": false
}
"SignIn": {
"RequireConfirmedAccount": false
}
},
"DataProtectionConfiguration": {
"ProtectKeysWithAzureKeyVault": false
},

"AzureKeyVaultConfiguration": {
"AzureKeyVaultEndpoint": "",
"ClientId": "",
"ClientSecret": "",
"UseClientCredentials": true,
"DataProtectionKeyIdentifier": "",
"ReadConfigurationFromKeyVault": false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Skoruba.IdentityServer4.Shared.Configuration.Common;
using Skoruba.IdentityServer4.Shared.Helpers;
using Skoruba.IdentityServer4.STS.Identity.Configuration;

namespace Skoruba.IdentityServer4.STS.Identity.Helpers
Expand All @@ -27,6 +29,7 @@ public static class IdentityServerBuilderExtensions
public static IIdentityServerBuilder AddCustomSigningCredential(this IIdentityServerBuilder builder, IConfiguration configuration)
{
var certificateConfiguration = configuration.GetSection(nameof(CertificateConfiguration)).Get<CertificateConfiguration>();
var azureKeyVaultConfiguration = configuration.GetSection(nameof(AzureKeyVaultConfiguration)).Get<AzureKeyVaultConfiguration>();

if (certificateConfiguration.UseSigningCertificateThumbprint)
{
Expand Down Expand Up @@ -66,6 +69,12 @@ public static IIdentityServerBuilder AddCustomSigningCredential(this IIdentitySe

builder.AddSigningCredential(certificate);
}
else if (certificateConfiguration.UseSigningCertificateForAzureKeyVault)
{
var x509Certificate2Certs = AzureKeyVaultHelpers.GetCertificates(azureKeyVaultConfiguration).GetAwaiter().GetResult();

builder.AddSigningCredential(x509Certificate2Certs.ActiveCertificate);
}
else if (certificateConfiguration.UseSigningCertificatePfxFile)
{
if (string.IsNullOrWhiteSpace(certificateConfiguration.SigningCertificatePfxFilePath))
Expand Down Expand Up @@ -112,6 +121,7 @@ public static IIdentityServerBuilder AddCustomSigningCredential(this IIdentitySe
public static IIdentityServerBuilder AddCustomValidationKey(this IIdentityServerBuilder builder, IConfiguration configuration)
{
var certificateConfiguration = configuration.GetSection(nameof(CertificateConfiguration)).Get<CertificateConfiguration>();
var azureKeyVaultConfiguration = configuration.GetSection(nameof(AzureKeyVaultConfiguration)).Get<AzureKeyVaultConfiguration>();

if (certificateConfiguration.UseValidationCertificateThumbprint)
{
Expand All @@ -134,6 +144,15 @@ public static IIdentityServerBuilder AddCustomValidationKey(this IIdentityServer
builder.AddValidationKey(certificate);

}
else if (certificateConfiguration.UseValidationCertificateForAzureKeyVault)
{
var x509Certificate2Certs = AzureKeyVaultHelpers.GetCertificates(azureKeyVaultConfiguration).GetAwaiter().GetResult();

if (x509Certificate2Certs.SecondaryCertificate != null)
{
builder.AddValidationKey(x509Certificate2Certs.SecondaryCertificate);
}
}
else if (certificateConfiguration.UseValidationCertificatePfxFile)
{
if (string.IsNullOrWhiteSpace(certificateConfiguration.ValidationCertificatePfxFilePath))
Expand All @@ -155,7 +174,7 @@ public static IIdentityServerBuilder AddCustomValidationKey(this IIdentityServer
}
else
{
throw new Exception($"Validation key file: {certificateConfiguration.SigningCertificatePfxFilePath} not found");
throw new Exception($"Validation key file: {certificateConfiguration.ValidationCertificatePfxFilePath} not found");
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/Skoruba.IdentityServer4.STS.Identity/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ private static IConfiguration GetConfiguration(string[] args)
configurationBuilder.AddUserSecrets<Startup>();
}

var configuration = configurationBuilder.Build();

configuration.AddAzureKeyVaultConfiguration(configurationBuilder);

configurationBuilder.AddCommandLine(args);
configurationBuilder.AddEnvironmentVariables();

Expand All @@ -60,6 +64,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostContext, configApp) =>
{
var configurationRoot = configApp.Build();

configApp.AddJsonFile("serilog.json", optional: true, reloadOnChange: true);

var env = hostContext.HostingEnvironment;
Expand All @@ -71,6 +77,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
configApp.AddUserSecrets<Startup>();
}

configurationRoot.AddAzureKeyVaultConfiguration(configApp);

configApp.AddEnvironmentVariables();
configApp.AddCommandLine(args);
})
Expand Down
4 changes: 1 addition & 3 deletions src/Skoruba.IdentityServer4.STS.Identity/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ public void ConfigureServices(IServiceCollection services)
RegisterDbContexts(services);

// Save data protection keys to db, using a common application name shared between Admin and STS
services.AddDataProtection()
.SetApplicationName("Skoruba.IdentityServer4")
.PersistKeysToDbContext<IdentityServerDataProtectionDbContext>();
services.AddDataProtection<IdentityServerDataProtectionDbContext>(Configuration);

// Add email senders which is currently setup for SendGrid and SMTP
services.AddEmailSenders(Configuration);
Expand Down
23 changes: 19 additions & 4 deletions src/Skoruba.IdentityServer4.STS.Identity/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
"ValidationCertificatePfxFilePassword": "",

"UseValidationCertificateThumbprint": false,
"ValidationCertificateThumbprint": ""
"ValidationCertificateThumbprint": "",

"UseSigningCertificateForAzureKeyVault": false,
"UseValidationCertificateForAzureKeyVault": false
},
"RegisterConfiguration": {
"Enabled": true
Expand Down Expand Up @@ -67,13 +70,25 @@
"BasePath": "",
"IdentityOptions": {
"Password": {
"RequiredLength": 8
"RequiredLength": 8
},
"User": {
"RequireUniqueEmail": true
"RequireUniqueEmail": true
},
"SignIn": {
"RequireConfirmedAccount": false
"RequireConfirmedAccount": false
}
},
"DataProtectionConfiguration": {
"ProtectKeysWithAzureKeyVault": false
},
"AzureKeyVaultConfiguration": {
"AzureKeyVaultEndpoint": "",
"ClientId": "",
"ClientSecret": "",
"UseClientCredentials": true,
"IdentityServerCertificateName": "",
"DataProtectionKeyIdentifier": "",
"ReadConfigurationFromKeyVault": false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Diagnostics;

namespace Skoruba.IdentityServer4.Shared.Configuration.Common
{
public class AzureKeyVaultConfiguration
{
public string AzureKeyVaultEndpoint { get; set; }

public string ClientId { get; set; }

public string ClientSecret { get; set; }

public bool UseClientCredentials { get; set; }

public string IdentityServerCertificateName { get; set; }

public string DataProtectionKeyIdentifier { get; set; }

public bool ReadConfigurationFromKeyVault { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Skoruba.IdentityServer4.STS.Identity.Configuration
namespace Skoruba.IdentityServer4.Shared.Configuration.Common
{
public class CertificateConfiguration
{
Expand Down Expand Up @@ -26,5 +26,9 @@ public class CertificateConfiguration
public string ValidationCertificatePfxFilePath { get; set; }

public string ValidationCertificatePfxFilePassword { get; set; }

public bool UseSigningCertificateForAzureKeyVault { get; set; }

public bool UseValidationCertificateForAzureKeyVault { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Skoruba.IdentityServer4.Shared.Configuration.Common
{
public class DataProtectionConfiguration
{
public bool ProtectKeysWithAzureKeyVault { get; set; }
}
}
27 changes: 27 additions & 0 deletions src/Skoruba.IdentityServer4.Shared/Helpers/AzureKeyVaultHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Original file comes from: https://github.com/damienbod/IdentityServer4AspNetCoreIdentityTemplate
// Modified by Jan Škoruba

using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Skoruba.IdentityServer4.Shared.Configuration.Common;
using Skoruba.IdentityServer4.Shared.Services;

namespace Skoruba.IdentityServer4.Shared.Helpers
{
public class AzureKeyVaultHelpers
{
public static async Task<(X509Certificate2 ActiveCertificate, X509Certificate2 SecondaryCertificate)> GetCertificates(AzureKeyVaultConfiguration certificateConfiguration)
{
(X509Certificate2 ActiveCertificate, X509Certificate2 SecondaryCertificate) certs = (null, null);

if (!string.IsNullOrEmpty(certificateConfiguration.AzureKeyVaultEndpoint))
{
var keyVaultCertificateService = new AzureKeyVaultService(certificateConfiguration);

certs = await keyVaultCertificateService.GetCertificatesFromKeyVault().ConfigureAwait(false);
}

return certs;
}
}
}
Loading

0 comments on commit 5bbf599

Please sign in to comment.