aspnetcore/test/Microsoft.AspNetCore.DataPr.../RegistryPolicyResolverTests.cs

315 lines
13 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Xml.Linq;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
using Microsoft.AspNetCore.DataProtection.Internal;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Microsoft.Win32;
using Xunit;
namespace Microsoft.AspNetCore.DataProtection
{
public class RegistryPolicyResolverTests
{
[ConditionalFact]
[ConditionalRunTestOnlyIfHkcuRegistryAvailable]
public void ResolvePolicy_NoEntries_ResultsInNoPolicies()
{
// Arrange
var registryEntries = new Dictionary<string, object>();
// Act
var context = RunTestWithRegValues(registryEntries);
// Assert
Assert.Null(context.EncryptorConfiguration);
Assert.Null(context.DefaultKeyLifetime);
Assert.Empty(context.KeyEscrowSinks);
}
[ConditionalFact]
[ConditionalRunTestOnlyIfHkcuRegistryAvailable]
public void ResolvePolicy_KeyEscrowSinks()
{
// Arrange
var registryEntries = new Dictionary<string, object>()
{
["KeyEscrowSinks"] = String.Join(" ;; ; ", new Type[] { typeof(MyKeyEscrowSink1), typeof(MyKeyEscrowSink2) }.Select(t => t.AssemblyQualifiedName))
};
// Act
var context = RunTestWithRegValues(registryEntries);
// Assert
var actualKeyEscrowSinks = context.KeyEscrowSinks.ToArray();
Assert.Equal(2, actualKeyEscrowSinks.Length);
Assert.IsType<MyKeyEscrowSink1>(actualKeyEscrowSinks[0]);
Assert.IsType<MyKeyEscrowSink2>(actualKeyEscrowSinks[1]);
}
[ConditionalFact]
[ConditionalRunTestOnlyIfHkcuRegistryAvailable]
public void ResolvePolicy_DefaultKeyLifetime()
{
// Arrange
var registryEntries = new Dictionary<string, object>()
{
["DefaultKeyLifetime"] = 1024 // days
};
// Act
var context = RunTestWithRegValues(registryEntries);
// Assert
Assert.Equal(1024, context.DefaultKeyLifetime);
}
[ConditionalFact]
[ConditionalRunTestOnlyIfHkcuRegistryAvailable]
public void ResolvePolicy_CngCbcEncryption_WithoutExplicitSettings()
{
// Arrange
var registryEntries = new Dictionary<string, object>()
{
["EncryptionType"] = "cng-cbc"
};
var expectedConfiguration = new CngCbcAuthenticatedEncryptorConfiguration();
// Act
var context = RunTestWithRegValues(registryEntries);
// Assert
var actualConfiguration = (CngCbcAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration;
Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider);
Assert.Equal(expectedConfiguration.HashAlgorithm, actualConfiguration.HashAlgorithm);
Assert.Equal(expectedConfiguration.HashAlgorithmProvider, actualConfiguration.HashAlgorithmProvider);
}
[ConditionalFact]
[ConditionalRunTestOnlyIfHkcuRegistryAvailable]
public void ResolvePolicy_CngCbcEncryption_WithExplicitSettings()
{
// Arrange
var registryEntries = new Dictionary<string, object>()
{
["EncryptionType"] = "cng-cbc",
["EncryptionAlgorithm"] = "enc-alg",
["EncryptionAlgorithmKeySize"] = 2048,
["EncryptionAlgorithmProvider"] = "my-enc-alg-provider",
["HashAlgorithm"] = "hash-alg",
["HashAlgorithmProvider"] = "my-hash-alg-provider"
};
var expectedConfiguration = new CngCbcAuthenticatedEncryptorConfiguration()
{
EncryptionAlgorithm = "enc-alg",
EncryptionAlgorithmKeySize = 2048,
EncryptionAlgorithmProvider = "my-enc-alg-provider",
HashAlgorithm = "hash-alg",
HashAlgorithmProvider = "my-hash-alg-provider"
};
// Act
var context = RunTestWithRegValues(registryEntries);
// Assert
var actualConfiguration = (CngCbcAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration;
Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider);
Assert.Equal(expectedConfiguration.HashAlgorithm, actualConfiguration.HashAlgorithm);
Assert.Equal(expectedConfiguration.HashAlgorithmProvider, actualConfiguration.HashAlgorithmProvider);
}
[ConditionalFact]
[ConditionalRunTestOnlyIfHkcuRegistryAvailable]
public void ResolvePolicy_CngGcmEncryption_WithoutExplicitSettings()
{
// Arrange
var registryEntries = new Dictionary<string, object>()
{
["EncryptionType"] = "cng-gcm"
};
var expectedConfiguration = new CngGcmAuthenticatedEncryptorConfiguration();
// Act
var context = RunTestWithRegValues(registryEntries);
// Assert
var actualConfiguration = (CngGcmAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration;
Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider);
}
[ConditionalFact]
[ConditionalRunTestOnlyIfHkcuRegistryAvailable]
public void ResolvePolicy_CngGcmEncryption_WithExplicitSettings()
{
// Arrange
var registryEntries = new Dictionary<string, object>()
{
["EncryptionType"] = "cng-gcm",
["EncryptionAlgorithm"] = "enc-alg",
["EncryptionAlgorithmKeySize"] = 2048,
["EncryptionAlgorithmProvider"] = "my-enc-alg-provider"
};
var expectedConfiguration = new CngGcmAuthenticatedEncryptorConfiguration()
{
EncryptionAlgorithm = "enc-alg",
EncryptionAlgorithmKeySize = 2048,
EncryptionAlgorithmProvider = "my-enc-alg-provider"
};
// Act
var context = RunTestWithRegValues(registryEntries);
// Assert
var actualConfiguration = (CngGcmAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration;
Assert.Equal(expectedConfiguration.EncryptionAlgorithm, actualConfiguration.EncryptionAlgorithm);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmProvider, actualConfiguration.EncryptionAlgorithmProvider);
}
[ConditionalFact]
[ConditionalRunTestOnlyIfHkcuRegistryAvailable]
public void ResolvePolicy_ManagedEncryption_WithoutExplicitSettings()
{
// Arrange
var registryEntries = new Dictionary<string, object>()
{
["EncryptionType"] = "managed"
};
var expectedConfiguration = new ManagedAuthenticatedEncryptorConfiguration();
// Act
var context = RunTestWithRegValues(registryEntries);
// Assert
var actualConfiguration = (ManagedAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration;
Assert.Equal(expectedConfiguration.EncryptionAlgorithmType, actualConfiguration.EncryptionAlgorithmType);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize);
Assert.Equal(expectedConfiguration.ValidationAlgorithmType, actualConfiguration.ValidationAlgorithmType);
}
[ConditionalFact]
[ConditionalRunTestOnlyIfHkcuRegistryAvailable]
public void ResolvePolicy_ManagedEncryption_WithExplicitSettings()
{
// Arrange
var registryEntries = new Dictionary<string, object>()
{
["EncryptionType"] = "managed",
["EncryptionAlgorithmType"] = typeof(TripleDES).AssemblyQualifiedName,
["EncryptionAlgorithmKeySize"] = 2048,
["ValidationAlgorithmType"] = typeof(HMACSHA1).AssemblyQualifiedName
};
var expectedConfiguration = new ManagedAuthenticatedEncryptorConfiguration()
{
EncryptionAlgorithmType = typeof(TripleDES),
EncryptionAlgorithmKeySize = 2048,
ValidationAlgorithmType = typeof(HMACSHA1)
};
// Act
var context = RunTestWithRegValues(registryEntries);
// Assert
var actualConfiguration = (ManagedAuthenticatedEncryptorConfiguration)context.EncryptorConfiguration;
Assert.Equal(expectedConfiguration.EncryptionAlgorithmType, actualConfiguration.EncryptionAlgorithmType);
Assert.Equal(expectedConfiguration.EncryptionAlgorithmKeySize, actualConfiguration.EncryptionAlgorithmKeySize);
Assert.Equal(expectedConfiguration.ValidationAlgorithmType, actualConfiguration.ValidationAlgorithmType);
}
private static RegistryPolicy RunTestWithRegValues(Dictionary<string, object> regValues)
{
return WithUniqueTempRegKey(registryKey =>
{
foreach (var entry in regValues)
{
registryKey.SetValue(entry.Key, entry.Value);
}
var policyResolver = new RegistryPolicyResolver(
registryKey,
activator: SimpleActivator.DefaultWithoutServices);
return policyResolver.ResolvePolicy();
});
}
/// <summary>
/// Runs a test and cleans up the registry key afterward.
/// </summary>
private static RegistryPolicy WithUniqueTempRegKey(Func<RegistryKey, RegistryPolicy> testCode)
{
string uniqueName = Guid.NewGuid().ToString();
var uniqueSubkey = LazyHkcuTempKey.Value.CreateSubKey(uniqueName);
try
{
return testCode(uniqueSubkey);
}
finally
{
// clean up when test is done
LazyHkcuTempKey.Value.DeleteSubKeyTree(uniqueName, throwOnMissingSubKey: false);
}
}
private static readonly Lazy<RegistryKey> LazyHkcuTempKey = new Lazy<RegistryKey>(() =>
{
try
{
return Registry.CurrentUser.CreateSubKey(@"SOFTWARE\Microsoft\ASP.NET\temp");
}
catch
{
// swallow all failures
return null;
}
});
private class ConditionalRunTestOnlyIfHkcuRegistryAvailable : Attribute, ITestCondition
{
public bool IsMet => (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && LazyHkcuTempKey.Value != null);
public string SkipReason { get; } = "HKCU registry couldn't be opened.";
}
private class MyKeyEscrowSink1 : IKeyEscrowSink
{
public void Store(Guid keyId, XElement element)
{
throw new NotImplementedException();
}
}
private class MyKeyEscrowSink2 : IKeyEscrowSink
{
public void Store(Guid keyId, XElement element)
{
throw new NotImplementedException();
}
}
}
}