-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Shell configuration for Smtp, Https & Reverse proxy settings (#287)
- Loading branch information
Jean-Philippe Tissot
authored
Jun 22, 2021
1 parent
3ca48f1
commit 70820ac
Showing
12 changed files
with
730 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
# Deployment configuration | ||
|
||
The `StatCan.OrchardCore.Configuration` library adds support for configuring persistent modules, smtp settings, reverse proxy setting and https settings with orchard's [configuration](https://docs.orchardcore.net/en/dev/docs/reference/core/Configuration/). | ||
|
||
## Example appsettings.json | ||
|
||
```json | ||
{ | ||
"OrchardCore": { | ||
"Features": [ | ||
"StatCan.OrchardCore.Configuration", | ||
"OrchardCore.Email", | ||
"OrchardCore.ReverseProxy", | ||
"OrchardCore.Https" | ||
], | ||
"StatCan_Configuration": { | ||
"OverwriteSmtpSettings": true, | ||
"OverwriteReverseProxySettings": true, | ||
"OverwriteHttpsSettings": true | ||
}, | ||
"StatCan_Smtp": { | ||
"DefaultSender": "no-reply@cloud.statcan.ca", | ||
"DeliveryMethod": 0, | ||
"Host": "smtp.cloud.statcan.ca", | ||
"PickupDirectoryLocation": null, | ||
"AutoSelectEncryption": false, | ||
"EncryptionMethod": 2, | ||
"Port": 25, | ||
"RequireCredentials": true, | ||
"UseDefaultCredentials": false, | ||
"UserName": "test", | ||
"Password": "mysmtppassword" | ||
}, | ||
"StatCan_Https": { | ||
"RequireHttps": true, | ||
"EnableStrictTransportSecurity": false, | ||
"RequireHttpsPermanent": false, | ||
"SslPort": null | ||
}, | ||
"StatCan_ReverseProxy": { | ||
"EnableXForwardedFor": true, | ||
"EnableXForwardedHost": true, | ||
"EnableXForwardedProto": true | ||
}, | ||
} | ||
} | ||
``` | ||
|
||
## Sections | ||
|
||
### StatCan_Configuration | ||
|
||
The variables in this section define if the related settings will be overwritten when the tenant activates. For example, if someone modifies the smtp settings from the Admin interface and the `OverwriteSmtpSettings` is set to true, the settings will be reset to those specified via configuration the next time the tenant activates. | ||
|
||
### StatCan_Smtp | ||
This section will update Orchard's [email module configuration](https://docs.orchardcore.net/en/dev/docs/reference/modules/Email). | ||
|
||
### StatCan_Https | ||
This section will update Orchard's [https module configuration](https://docs.orchardcore.net/en/dev/docs/reference/modules/Https). | ||
|
||
### StatCan_ReverseProxy | ||
This section will update Orchard's [reverse proxy module configuration](https://docs.orchardcore.net/en/dev/docs/reference/modules/ReverseProxy). | ||
|
||
|
||
## Environment variables | ||
|
||
It is recommended to use [environment variables](https://docs.orchardcore.net/en/dev/docs/reference/core/Configuration/index.html#ishellconfiguration-via-environment-variables) to configure these settings in a production environment. | ||
|
||
```shell | ||
# Configuration | ||
OrchardCore__StatCan_Configuration__OverwriteSmtpSettings: bool | ||
OrchardCore__StatCan_Configuration__OverwriteReverseProxySettings: bool | ||
OrchardCore__StatCan_Configuration__OverwriteHttpsSettings: bool | ||
|
||
# Smtp | ||
OrchardCore__StatCan_Smtp__DefaultSender: string | ||
OrchardCore__StatCan_Smtp__DeliveryMethod: 0=Network;1=SpecifiedPickupDirectory | ||
OrchardCore__StatCan_Smtp__Host: string | ||
OrchardCore__StatCan_Smtp__PickupDirectoryLocation: string | ||
OrchardCore__StatCan_Smtp__AutoSelectEncryption: bool | ||
OrchardCore__StatCan_Smtp__EncryptionMethod: 0=none;1=SSLTLS;2=STARTTLS | ||
OrchardCore__StatCan_Smtp__Port: int | ||
OrchardCore__StatCan_Smtp__RequireCredentials: bool | ||
OrchardCore__StatCan_Smtp__UseDefaultCredentials: bool | ||
OrchardCore__StatCan_Smtp__UserName: string | ||
OrchardCore__StatCan_Smtp__Password: string (unencrypted) | ||
|
||
# Https | ||
OrchardCore__StatCan_Https__RequireHttps: bool | ||
OrchardCore__StatCan_Https__EnableStrictTransportSecurity: bool | ||
OrchardCore__StatCan_Https__RequireHttpsPermanent: bool | ||
OrchardCore__StatCan_Https__SslPort: int | ||
|
||
# ReverseProxy | ||
OrchardCore__StatCan_ReverseProxy__EnableXForwardedFor: bool | ||
OrchardCore__StatCan_ReverseProxy__EnableXForwardedHost: bool | ||
OrchardCore__StatCan_ReverseProxy__EnableXForwardedProto: bool | ||
|
||
# Features | ||
OrchardCore__Features__0: string | ||
OrchardCore__Features__1: string | ||
|
||
``` | ||
|
||
Here is an example on how to set these environment variables with powershell | ||
```powershell | ||
$env:OrchardCore__Features__0="StatCan.OrchardCore.Configuration" | ||
$env:OrchardCore__Features__1="OrchardCore.ReverseProxy" | ||
$env:OrchardCore__Features__2="OrchardCore.Https" | ||
$env:OrchardCore__StatCan_Configuration__OverwriteReverseProxySettings="true" | ||
$env:OrchardCore__StatCan_ReverseProxy__EnableXForwardedFor="true" | ||
$env:OrchardCore__StatCan_ReverseProxy__EnableXForwardedHost="true" | ||
$env:OrchardCore__StatCan_ReverseProxy__EnableXForwardedProto="true" | ||
$env:OrchardCore__StatCan_Configuration__OverwriteHttpsSettings="true" | ||
$env:OrchardCore__StatCan_Https__RequireHttps="true" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
src/Modules/StatCan.OrchardCore.Configuration/ConfigurationSettings.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace StatCan.OrchardCore.Configuration | ||
{ | ||
public class ConfigurationSettings | ||
{ | ||
public string HttpsSettingsHash { get; set; } | ||
public string ReverseProxySettingsHash { get; set; } | ||
public string SmtpSettingsHash { get; set; } | ||
} | ||
} |
130 changes: 130 additions & 0 deletions
130
src/Modules/StatCan.OrchardCore.Configuration/HttpsSettingsUpdater.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
using System.Threading.Tasks; | ||
using OrchardCore.Entities; | ||
using OrchardCore.Environment.Extensions.Features; | ||
using OrchardCore.Environment.Shell; | ||
using OrchardCore.Settings; | ||
using OrchardCore.Environment.Shell.Configuration; | ||
using Microsoft.Extensions.Configuration; | ||
using OrchardCore.Modules; | ||
using OrchardCore.Https.Settings; | ||
using System.Security.Cryptography; | ||
using System.Text; | ||
using Microsoft.AspNetCore.WebUtilities; | ||
|
||
namespace StatCan.OrchardCore.Configuration | ||
{ | ||
/// <summary> | ||
/// Updates the Https settings based on a configuration | ||
/// </summary> | ||
public class HttpsSettingsUpdater : ModularTenantEvents, IFeatureEventHandler | ||
{ | ||
private readonly ShellSettings _shellSettings; | ||
private readonly IShellHost _shellHost; | ||
private readonly ISiteService _siteService; | ||
private readonly IShellConfiguration _shellConfiguration; | ||
|
||
public HttpsSettingsUpdater( | ||
ISiteService siteService, | ||
IShellConfiguration shellConfiguration, | ||
IShellHost shellHost, | ||
ShellSettings shellSettings) | ||
{ | ||
_siteService = siteService; | ||
_shellConfiguration = shellConfiguration; | ||
_shellHost = shellHost; | ||
_shellSettings = shellSettings; | ||
} | ||
|
||
// for existing sites, update settings from configuration when tenant activates | ||
public async override Task ActivatedAsync() | ||
{ | ||
var section = _shellConfiguration.GetSection("StatCan_Configuration"); | ||
|
||
if(section.GetValue<bool>("OverwriteHttpsSettings")) | ||
{ | ||
await UpdateConfiguration(); | ||
} | ||
} | ||
|
||
Task IFeatureEventHandler.InstallingAsync(IFeatureInfo feature) => Task.CompletedTask; | ||
|
||
Task IFeatureEventHandler.InstalledAsync(IFeatureInfo feature) => Task.CompletedTask; | ||
|
||
Task IFeatureEventHandler.EnablingAsync(IFeatureInfo feature) => Task.CompletedTask; | ||
|
||
Task IFeatureEventHandler.EnabledAsync(IFeatureInfo feature) => SetConfiguredHttpsSettings(feature); | ||
|
||
Task IFeatureEventHandler.DisablingAsync(IFeatureInfo feature) => Task.CompletedTask; | ||
|
||
Task IFeatureEventHandler.DisabledAsync(IFeatureInfo feature) => Task.CompletedTask; | ||
|
||
Task IFeatureEventHandler.UninstallingAsync(IFeatureInfo feature) => Task.CompletedTask; | ||
|
||
Task IFeatureEventHandler.UninstalledAsync(IFeatureInfo feature) => Task.CompletedTask; | ||
|
||
private async Task SetConfiguredHttpsSettings(IFeatureInfo feature) | ||
{ | ||
if (feature.Id != "OrchardCore.Https") | ||
{ | ||
return; | ||
} | ||
await UpdateConfiguration(); | ||
} | ||
|
||
private async Task UpdateConfiguration() | ||
{ | ||
var siteSettings = await _siteService.LoadSiteSettingsAsync(); | ||
if(NeedsUpdate(siteSettings)) | ||
{ | ||
SetConfiguration(siteSettings); | ||
SetHash(siteSettings); | ||
await _siteService.UpdateSiteSettingsAsync(siteSettings); | ||
await _shellHost.ReleaseShellContextAsync(_shellSettings); | ||
} | ||
} | ||
|
||
private void SetConfiguration(ISite siteSettings) | ||
{ | ||
var httpsSettings = siteSettings.As<HttpsSettings>(); | ||
var section = _shellConfiguration.GetSection("StatCan_Https"); | ||
|
||
httpsSettings.RequireHttps = section.GetValue("RequireHttps", false); | ||
httpsSettings.EnableStrictTransportSecurity = section.GetValue("EnableStrictTransportSecurity", false); | ||
httpsSettings.RequireHttpsPermanent = section.GetValue("RequireHttpsPermanent", false); | ||
httpsSettings.SslPort = section.GetValue<int?>("SslPort", null); | ||
|
||
siteSettings.Put(httpsSettings); | ||
} | ||
|
||
private static bool NeedsUpdate(ISite settings) | ||
{ | ||
var configSettings = settings.As<ConfigurationSettings>(); | ||
if(!string.IsNullOrEmpty(configSettings.HttpsSettingsHash)) | ||
{ | ||
var encValue = EncryptSettings(settings); | ||
if(configSettings.HttpsSettingsHash == encValue) | ||
{ | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
private static void SetHash(ISite settings) | ||
{ | ||
var configSettings = settings.As<ConfigurationSettings>(); | ||
configSettings.HttpsSettingsHash = EncryptSettings(settings); | ||
settings.Put(configSettings); | ||
} | ||
|
||
private static string EncryptSettings(ISite settings) | ||
{ | ||
using var sha256 = SHA256.Create(); | ||
if (settings.Properties.TryGetValue(nameof(HttpsSettings), out var value)) | ||
{ | ||
return WebEncoders.Base64UrlEncode(sha256.ComputeHash(Encoding.UTF8.GetBytes(value.ToString()))); | ||
} | ||
return string.Empty; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using OrchardCore.Modules.Manifest; | ||
using static StatCan.OrchardCore.Manifest.StatCanManifestConstants; | ||
|
||
[assembly: Module( | ||
Name = "StatCan Configuration", | ||
Author = DigitalInnovationTeam, | ||
Website = DigitalInnovationWebsite, | ||
Version = Version, | ||
Description = "Deployment configuration", | ||
Category = "Configuration" | ||
)] | ||
|
||
[assembly: Feature( | ||
Id = "StatCan.OrchardCore.Configuration", | ||
Name = "StatCan Configuration", | ||
Description = "Deployment configuration", | ||
Category = "Configuration", | ||
Dependencies = new[] | ||
{ | ||
"OrchardCore.Features", | ||
"OrchardCore.Settings", | ||
} | ||
)] |
Oops, something went wrong.