adding back the functionality to install a machine key during installation
This commit is contained in:
86
src/Umbraco.Core/Security/MachineKeyGenerator.cs
Normal file
86
src/Umbraco.Core/Security/MachineKeyGenerator.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to generate a machine key
|
||||
/// </summary>
|
||||
internal class MachineKeyGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates the string to be stored in the web.config
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Machine key details are here: https://msdn.microsoft.com/en-us/library/vstudio/w8h3skw9%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
|
||||
/// </remarks>
|
||||
public string GenerateConfigurationBlock()
|
||||
{
|
||||
var c = @"<machineKey validationKey=""{0}""
|
||||
decryptionKey=""{1}""
|
||||
validation=""HMACSHA256"" decryption=""AES""
|
||||
/>";
|
||||
|
||||
var Xxx = 3;
|
||||
|
||||
return string.Format(c, GenerateAESDecryptionKey(), GenerateHMACSHA256ValidationKey());
|
||||
}
|
||||
|
||||
public string GenerateHMACSHA256ValidationKey()
|
||||
{
|
||||
//See: https://msdn.microsoft.com/en-us/library/vstudio/w8h3skw9%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
|
||||
//See: https://msdn.microsoft.com/en-us/library/ff649308.aspx?f=255&MSPPError=-2147217396
|
||||
/*
|
||||
key value Specifies a manually assigned key.
|
||||
The validationKey value must be manually set to a string of hexadecimal
|
||||
characters to ensure consistent configuration across all servers in a Web farm.
|
||||
The length of the key depends on the hash algorithm that is used:
|
||||
|
||||
AES requires a 256-bit key (64 hexadecimal characters).
|
||||
MD5 requires a 128-bit key (32 hexadecimal characters).
|
||||
SHA1 requires a 160-bit key (40 hexadecimal characters).
|
||||
3DES requires a 192-bit key (48 hexadecimal characters).
|
||||
HMACSHA256 requires a 256-bit key (64 hexadecimal characters) == DEFAULT
|
||||
HMACSHA384 requires a 384-bit key (96 hexadecimal characters).
|
||||
HMACSHA512 requires a 512-bit key (128 hexadecimal characters).
|
||||
*/
|
||||
|
||||
//64 in length = 256 bits
|
||||
return GenerateKey(64);
|
||||
}
|
||||
|
||||
public string GenerateAESDecryptionKey()
|
||||
{
|
||||
//See: //See: https://msdn.microsoft.com/en-us/library/vstudio/w8h3skw9%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
|
||||
/*
|
||||
key value Specifies a manually assigned key.
|
||||
The decryptionKey value must be manually set to a string of
|
||||
hexadecimal characters to ensure consistent configuration across all servers in a Web farm.
|
||||
The key should be 64 bits (16 hexadecimal characters) long for DES encryption, or 192 bits
|
||||
(48 hexadecimal characters) long for 3DES. For AES, the key can be 128 bits (32 characters),
|
||||
192 bits (48 characters), or 256 bits (64 characters) long.
|
||||
*/
|
||||
|
||||
//64 in length = 256 bits
|
||||
return GenerateKey(64);
|
||||
}
|
||||
|
||||
private string GenerateKey(int len = 64)
|
||||
{
|
||||
var buff = new byte[len / 2];
|
||||
var rng = new RNGCryptoServiceProvider();
|
||||
rng.GetBytes(buff);
|
||||
var sb = new StringBuilder(len);
|
||||
|
||||
for (int i = 0; i < buff.Length; i++)
|
||||
sb.Append(string.Format("{0:X2}", buff[i]));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -666,6 +666,7 @@
|
||||
<Compile Include="Security\IBackOfficeUserPasswordChecker.cs" />
|
||||
<Compile Include="Security\IMembershipProviderPasswordHasher.cs" />
|
||||
<Compile Include="Security\IUserAwarePasswordHasher.cs" />
|
||||
<Compile Include="Security\MachineKeyGenerator.cs" />
|
||||
<Compile Include="Security\MembershipProviderPasswordHasher.cs" />
|
||||
<Compile Include="Security\EmailService.cs" />
|
||||
<Compile Include="Security\MembershipProviderPasswordValidator.cs" />
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
angular.module("umbraco.install").controller("Umbraco.Installer.MachineKeyController", function ($scope, installerService) {
|
||||
|
||||
|
||||
$scope.continue = function () {
|
||||
installerService.status.current.model = true;
|
||||
installerService.forward();
|
||||
};
|
||||
|
||||
$scope.ignoreKey = function () {
|
||||
installerService.status.current.model = false;
|
||||
installerService.forward();
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
<div ng-controller="Umbraco.Installer.MachineKeyController">
|
||||
<h1>Configure an ASP.Net Machine Key</h1>
|
||||
<p>
|
||||
By default the installer will generate a custom ASP.Net Machine Key for your site and install it into your web.config file.
|
||||
A Machine Key is used for hashing and encryption and it is recommended that you install a custom one into your site.
|
||||
This ensures that your site is fully portable between environments that might have different Machine Key settings and that
|
||||
your site by default will work with load balancing when installed between various server environments.
|
||||
</p>
|
||||
|
||||
<form name="myForm" class="form-horizontal" novalidate ng-submit="continue();">
|
||||
|
||||
<div class="row">
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<input type="submit" value="Continue" class="btn btn-success" />
|
||||
|
||||
<button class="btn" ng-click="ignoreKey()">I don't want a custom Machine Key</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
@@ -48,6 +48,7 @@ namespace Umbraco.Web.Install
|
||||
new MajorVersion7UpgradeReport(_umbContext.Application),
|
||||
new Version73FileCleanup(_umbContext.HttpContext, _umbContext.Application.ProfilingLogger.Logger),
|
||||
new DatabaseConfigureStep(_umbContext.Application),
|
||||
new ConfigureMachineKey(_umbContext.Application),
|
||||
new DatabaseInstallStep(_umbContext.Application),
|
||||
new DatabaseUpgradeStep(_umbContext.Application),
|
||||
new StarterKitDownloadStep(_umbContext.Application, _umbContext.Security, _umbContext.HttpContext),
|
||||
|
||||
75
src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs
Normal file
75
src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Web.Configuration;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Web.Install.Models;
|
||||
|
||||
namespace Umbraco.Web.Install.InstallSteps
|
||||
{
|
||||
[InstallSetupStep(InstallationType.NewInstall,
|
||||
"ConfigureMachineKey", "machinekey", 2,
|
||||
"Updating some security settings...",
|
||||
PerformsAppRestart = true)]
|
||||
internal class ConfigureMachineKey : InstallSetupStep<bool?>
|
||||
{
|
||||
private readonly ApplicationContext _appContext;
|
||||
|
||||
public ConfigureMachineKey(ApplicationContext appContext)
|
||||
{
|
||||
if (appContext == null) throw new ArgumentNullException("appContext");
|
||||
_appContext = appContext;
|
||||
}
|
||||
|
||||
public override string View
|
||||
{
|
||||
get { return HasMachineKey() == false ? base.View : ""; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Don't display the view or execute if a machine key already exists
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool HasMachineKey()
|
||||
{
|
||||
var section = (MachineKeySection)WebConfigurationManager.GetSection("system.web/machineKey");
|
||||
return section.ElementInformation.Source != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The step execution method
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns></returns>
|
||||
public override InstallSetupResult Execute(bool? model)
|
||||
{
|
||||
if (model.HasValue && model.Value == false) return null;
|
||||
|
||||
//install the machine key
|
||||
var fileName = IOHelper.MapPath(string.Format("{0}/web.config", SystemDirectories.Root));
|
||||
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
|
||||
var systemWeb = xml.Root.DescendantsAndSelf("system.web").Single();
|
||||
|
||||
// Update appSetting if it exists, or else create a new appSetting for the given key and value
|
||||
var machineKey = systemWeb.Descendants("machineKey").FirstOrDefault();
|
||||
if (machineKey != null) return null;
|
||||
|
||||
var generator = new MachineKeyGenerator();
|
||||
var generatedSection = generator.GenerateConfigurationBlock();
|
||||
systemWeb.Add(XElement.Parse(generatedSection));
|
||||
|
||||
xml.Save(fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool RequiresExecution(bool? model)
|
||||
{
|
||||
return HasMachineKey() == false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Web.Install.Models;
|
||||
|
||||
@@ -94,8 +95,9 @@ namespace Umbraco.Web.Install.InstallSteps
|
||||
result.DetermineInstalledVersion();
|
||||
return false;
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
_applicationContext.ProfilingLogger.Logger.Error<DatabaseConfigureStep>("An error occurred, reconfiguring...", ex);
|
||||
//something went wrong, could not connect so probably need to reconfigure
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -359,6 +359,7 @@
|
||||
<Compile Include="HealthCheck\StatusResultType.cs" />
|
||||
<Compile Include="HealthCheck\Checks\DataIntegrity\XmlDataIntegrityHealthCheck.cs" />
|
||||
<Compile Include="IHttpContextAccessor.cs" />
|
||||
<Compile Include="Install\InstallSteps\ConfigureMachineKey.cs" />
|
||||
<Compile Include="Models\ContentEditing\AssignedContentPermissions.cs" />
|
||||
<Compile Include="Models\ContentEditing\AssignedUserGroupPermissions.cs" />
|
||||
<Compile Include="Models\ContentEditing\ContentRedirectUrl.cs" />
|
||||
|
||||
Reference in New Issue
Block a user