Skip to content

Commit

Permalink
Moved certificates to Azure Storage
Browse files Browse the repository at this point in the history
  • Loading branch information
jelledruyts committed Aug 24, 2022
1 parent cd2cc8d commit b6e2459
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ ClientBin/
*.dbmdl
*.dbproj.schemaview
*.jfm
#*.pfx
*.pfx
*.publishsettings
orleans.codegen.cs

Expand Down
Binary file removed Authr.WebApp/App_Data/AuthrEncryptionCertificate.pfx
Binary file not shown.
Binary file removed Authr.WebApp/App_Data/AuthrSigningCertificate.pfx
Binary file not shown.
40 changes: 40 additions & 0 deletions Authr.WebApp/Services/AzureStorageCertificateProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Azure.Storage.Blobs;
using Microsoft.Extensions.Configuration;

namespace Authr.WebApp.Services
{
public class AzureStorageCertificateProvider : ICertificateProvider
{
private static IDictionary<string, X509Certificate2> certificates = new Dictionary<string, X509Certificate2>();
private readonly IConfiguration configuration;
private readonly BlobServiceClient client;

public AzureStorageCertificateProvider(IConfiguration configuration, string connectionString)
{
this.configuration = configuration;
this.client = new BlobServiceClient(connectionString);
}

public async Task<X509Certificate2> GetCertificateAsync(string name)
{
if (!certificates.ContainsKey(name))
{
var path = this.configuration.GetValue<string>($"App:Certificates:{name}:Path");
var password = this.configuration.GetValue<string>($"App:Certificates:{name}:Password");
var containerClient = this.client.GetBlobContainerClient("certificates");
var blob = containerClient.GetBlobClient(path);
var certificateBlob = await blob.DownloadAsync();
using (var streamReader = new BinaryReader(certificateBlob.Value.Content))
{
var certificateBytes = streamReader.ReadBytes((int)certificateBlob.Value.Details.ContentLength);
certificates[name] = new X509Certificate2(certificateBytes, password);
}
}
return certificates[name];
}
}
}
26 changes: 13 additions & 13 deletions Authr.WebApp/Services/FileSystemCertificateProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,39 @@
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;

namespace Authr.WebApp.Services
{
public class FileSystemCertificateProvider : ICertificateProvider
{
private static IDictionary<string, X509Certificate2> certificates = new Dictionary<string, X509Certificate2>();
private readonly IConfiguration configuration;
private readonly IFileProvider fileProvider;
private readonly string relativeBasePath;

public FileSystemCertificateProvider(IFileProvider fileProvider)
public FileSystemCertificateProvider(IConfiguration configuration, IFileProvider fileProvider, string relativeBasePath)
{
this.configuration = configuration;
this.fileProvider = fileProvider;
this.relativeBasePath = relativeBasePath;
}

public void LoadCertificate(string name, string path, string password)
public Task<X509Certificate2> GetCertificateAsync(string name)
{
if (!string.IsNullOrWhiteSpace(name) && !string.IsNullOrWhiteSpace(path) && !string.IsNullOrWhiteSpace(password))
if (!certificates.ContainsKey(name))
{
var path = this.configuration.GetValue<string>($"App:Certificates:{name}:Path");
var password = this.configuration.GetValue<string>($"App:Certificates:{name}:Password");
if (!Path.IsPathRooted(path))
{
path = this.fileProvider.GetFileInfo(path).PhysicalPath;
var relativePath = Path.Combine(this.relativeBasePath, path);
path = this.fileProvider.GetFileInfo(relativePath).PhysicalPath;
}
certificates[name] = new X509Certificate2(path, password);
}
}

public Task<X509Certificate2> GetCertificateAsync(string name)
{
if (certificates.ContainsKey(name))
{
return Task.FromResult(certificates[name]);
}
return Task.FromResult<X509Certificate2>(null);
return Task.FromResult(certificates[name]);
}
}
}
13 changes: 9 additions & 4 deletions Authr.WebApp/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,15 @@ public void ConfigureServices(IServiceCollection services)
services.AddApplicationInsightsTelemetry();

// Set up a certificate provider.
var certificateProvider = new FileSystemCertificateProvider(WebHostEnvironment.ContentRootFileProvider);
certificateProvider.LoadCertificate(Constants.CertificateNames.SigningCertificate, Configuration.GetValue<string>("App:SigningCertificate:Path"), Configuration.GetValue<string>("App:SigningCertificate:Password"));
certificateProvider.LoadCertificate(Constants.CertificateNames.EncryptionCertificate, Configuration.GetValue<string>("App:EncryptionCertificate:Path"), Configuration.GetValue<string>("App:EncryptionCertificate:Password"));
services.AddSingleton<ICertificateProvider>(certificateProvider);
var certificatesConnectionString = Configuration.GetValue<string>("App:Certificates:ConnectionString");
if (string.IsNullOrWhiteSpace(certificatesConnectionString))
{
services.AddSingleton<ICertificateProvider>(new FileSystemCertificateProvider(Configuration, WebHostEnvironment.ContentRootFileProvider, "App_Data"));
}
else
{
services.AddSingleton<ICertificateProvider>(new AzureStorageCertificateProvider(Configuration, certificatesConnectionString));
}

// Configure external Data Protection so that cookies and other secrets can be decoded
// from different hosting environments (e.g. Web App Slots).
Expand Down
17 changes: 10 additions & 7 deletions Authr.WebApp/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@
"DataProtection": {
"ConnectionString": ""
},
"SigningCertificate": {
"Path": "App_Data/AuthrSigningCertificate.pfx",
"Password": ""
},
"EncryptionCertificate": {
"Path": "App_Data/AuthrEncryptionCertificate.pfx",
"Password": ""
"Certificates": {
"ConnectionString": "",
"SigningCertificate": {
"Path": "AuthrSigningCertificate.pfx",
"Password": ""
},
"EncryptionCertificate": {
"Path": "AuthrEncryptionCertificate.pfx",
"Password": ""
}
},
"UserConfiguration": {
"ConnectionString": ""
Expand Down

0 comments on commit b6e2459

Please sign in to comment.