Make ILoggerFactory an optional service on any DI-injected services

This commit is contained in:
Nate McMaster 2017-06-13 00:00:47 -07:00
parent abf05e2856
commit 5d1a523682
33 changed files with 238 additions and 236 deletions

View File

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<OutputType>exe</OutputType>
</PropertyGroup>
<ItemGroup>

View File

@ -6,6 +6,7 @@ using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
namespace AzureBlob
{
@ -24,21 +25,19 @@ namespace AzureBlob
container.CreateIfNotExistsAsync().GetAwaiter().GetResult();
// Configure
using (var services = new ServiceCollection()
.AddLogging(o => o.AddConsole().SetMinimumLevel(LogLevel.Debug))
.AddDataProtection()
.PersistKeysToAzureBlobStorage(container, "keys.xml")
.Services
.BuildServiceProvider())
{
// Run a sample payload
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging();
serviceCollection.AddDataProtection()
.PersistKeysToAzureBlobStorage(container, "keys.xml");
var services = serviceCollection.BuildServiceProvider();
var loggerFactory = services.GetService<LoggerFactory>();
loggerFactory.AddConsole();
// Run a sample payload
var protector = services.GetDataProtector("sample-purpose");
var protectedData = protector.Protect("Hello world!");
Console.WriteLine(protectedData);
var protector = services.GetDataProtector("sample-purpose");
var protectedData = protector.Protect("Hello world!");
Console.WriteLine(protectedData);
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:2041/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"AzureBlob": {
"commandName": "Project"
}
}
}

View File

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<OutputType>exe</OutputType>
</PropertyGroup>
<ItemGroup>

View File

@ -14,25 +14,23 @@ namespace CustomEncryptorSample
public static void Main(string[] args)
{
var keysFolder = Path.Combine(Directory.GetCurrentDirectory(), "temp-keys");
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging();
serviceCollection.AddDataProtection()
using (var services = new ServiceCollection()
.AddLogging(o => o.AddConsole().SetMinimumLevel(LogLevel.Debug))
.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(keysFolder))
.UseXmlEncryptor(s => new CustomXmlEncryptor(s));
.UseXmlEncryptor(s => new CustomXmlEncryptor(s))
.Services.BuildServiceProvider())
{
var protector = services.GetDataProtector("SamplePurpose");
var services = serviceCollection.BuildServiceProvider();
var loggerFactory = services.GetRequiredService<LoggerFactory>();
loggerFactory.AddConsole();
// protect the payload
var protectedPayload = protector.Protect("Hello World!");
Console.WriteLine($"Protect returned: {protectedPayload}");
var protector = services.GetDataProtector("SamplePurpose");
// protect the payload
var protectedPayload = protector.Protect("Hello World!");
Console.WriteLine($"Protect returned: {protectedPayload}");
// unprotect the payload
var unprotectedPayload = protector.Unprotect(protectedPayload);
Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
// unprotect the payload
var unprotectedPayload = protector.Unprotect(protectedPayload);
Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:1398/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"CustomEncryptorSample": {
"commandName": "Project"
}
}
}

View File

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<OutputType>exe</OutputType>
</PropertyGroup>
<ItemGroup>

View File

@ -16,7 +16,8 @@ namespace KeyManagementSample
{
var keysFolder = Path.Combine(Directory.GetCurrentDirectory(), "temp-keys");
var serviceCollection = new ServiceCollection();
var builder = serviceCollection.AddDataProtection()
var builder = serviceCollection
.AddDataProtection()
// point at a specific folder and use DPAPI to encrypt keys
.PersistKeysToFileSystem(new DirectoryInfo(keysFolder));
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@ -24,40 +25,41 @@ namespace KeyManagementSample
builder.ProtectKeysWithDpapi();
}
var services = serviceCollection.BuildServiceProvider();
// perform a protect operation to force the system to put at least
// one key in the key ring
services.GetDataProtector("Sample.KeyManager.v1").Protect("payload");
Console.WriteLine("Performed a protect operation.");
// get a reference to the key manager
var keyManager = services.GetService<IKeyManager>();
// list all keys in the key ring
var allKeys = keyManager.GetAllKeys();
Console.WriteLine($"The key ring contains {allKeys.Count} key(s).");
foreach (var key in allKeys)
using (var services = serviceCollection.BuildServiceProvider())
{
Console.WriteLine($"Key {key.KeyId:B}: Created = {key.CreationDate:u}, IsRevoked = {key.IsRevoked}");
}
// perform a protect operation to force the system to put at least
// one key in the key ring
services.GetDataProtector("Sample.KeyManager.v1").Protect("payload");
Console.WriteLine("Performed a protect operation.");
// revoke all keys in the key ring
keyManager.RevokeAllKeys(DateTimeOffset.Now, reason: "Revocation reason here.");
Console.WriteLine("Revoked all existing keys.");
// get a reference to the key manager
var keyManager = services.GetService<IKeyManager>();
// add a new key to the key ring with immediate activation and a 1-month expiration
keyManager.CreateNewKey(
activationDate: DateTimeOffset.Now,
expirationDate: DateTimeOffset.Now.AddMonths(1));
Console.WriteLine("Added a new key.");
// list all keys in the key ring
var allKeys = keyManager.GetAllKeys();
Console.WriteLine($"The key ring contains {allKeys.Count} key(s).");
foreach (var key in allKeys)
{
Console.WriteLine($"Key {key.KeyId:B}: Created = {key.CreationDate:u}, IsRevoked = {key.IsRevoked}");
}
// list all keys in the key ring
allKeys = keyManager.GetAllKeys();
Console.WriteLine($"The key ring contains {allKeys.Count} key(s).");
foreach (var key in allKeys)
{
Console.WriteLine($"Key {key.KeyId:B}: Created = {key.CreationDate:u}, IsRevoked = {key.IsRevoked}");
// revoke all keys in the key ring
keyManager.RevokeAllKeys(DateTimeOffset.Now, reason: "Revocation reason here.");
Console.WriteLine("Revoked all existing keys.");
// add a new key to the key ring with immediate activation and a 1-month expiration
keyManager.CreateNewKey(
activationDate: DateTimeOffset.Now,
expirationDate: DateTimeOffset.Now.AddMonths(1));
Console.WriteLine("Added a new key.");
// list all keys in the key ring
allKeys = keyManager.GetAllKeys();
Console.WriteLine($"The key ring contains {allKeys.Count} key(s).");
foreach (var key in allKeys)
{
Console.WriteLine($"Key {key.KeyId:B}: Created = {key.CreationDate:u}, IsRevoked = {key.IsRevoked}");
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:1396/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"KeyManagementSample": {
"commandName": "Project"
}
}
}

View File

@ -17,19 +17,18 @@ namespace Redis
var redis = ConnectionMultiplexer.Connect("localhost:6379");
// Configure
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging();
serviceCollection.AddDataProtection()
.PersistKeysToRedis(redis, "DataProtection-Keys");
var services = serviceCollection.BuildServiceProvider();
var loggerFactory = services.GetService<LoggerFactory>();
loggerFactory.AddConsole();
// Run a sample payload
var protector = services.GetDataProtector("sample-purpose");
var protectedData = protector.Protect("Hello world!");
Console.WriteLine(protectedData);
using (var services = new ServiceCollection()
.AddLogging(o => o.AddConsole().SetMinimumLevel(LogLevel.Debug))
.AddDataProtection()
.PersistKeysToRedis(redis, "DataProtection-Keys")
.Services
.BuildServiceProvider())
{
// Run a sample payload
var protector = services.GetDataProtector("sample-purpose");
var protectedData = protector.Protect("Hello world!");
Console.WriteLine(protectedData);
}
}
}
}

View File

@ -1,22 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:2042/",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Redis": {
"commandName": "Project"
}
}
}

View File

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\build\dependencies.props" />
<PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
<OutputType>exe</OutputType>
</PropertyGroup>
<ItemGroup>

View File

@ -4,6 +4,7 @@
using System;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel
{
@ -42,7 +43,7 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat
void IInternalAlgorithmConfiguration.Validate()
{
var factory = new AuthenticatedEncryptorFactory(DataProtectionProviderFactory.GetDefaultLoggerFactory());
var factory = new AuthenticatedEncryptorFactory(NullLoggerFactory.Instance);
// Run a sample payload through an encrypt -> decrypt operation to make sure data round-trips properly.
var encryptor = factory.CreateAuthenticatedEncryptorInstance(Secret.Random(512 / 8), this);
try

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Cryptography;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel
{
@ -88,7 +89,7 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat
/// </summary>
void IInternalAlgorithmConfiguration.Validate()
{
var factory = new CngCbcAuthenticatedEncryptorFactory(DataProtectionProviderFactory.GetDefaultLoggerFactory());
var factory = new CngCbcAuthenticatedEncryptorFactory(NullLoggerFactory.Instance);
// Run a sample payload through an encrypt -> decrypt operation to make sure data round-trips properly.
using (var encryptor = factory.CreateAuthenticatedEncryptorInstance(Secret.Random(512 / 8), this))
{

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Cryptography;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel
{
@ -64,7 +65,7 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat
/// </summary>
void IInternalAlgorithmConfiguration.Validate()
{
var factory = new CngGcmAuthenticatedEncryptorFactory(DataProtectionProviderFactory.GetDefaultLoggerFactory());
var factory = new CngGcmAuthenticatedEncryptorFactory(NullLoggerFactory.Instance);
// Run a sample payload through an encrypt -> decrypt operation to make sure data round-trips properly.
using (var encryptor = factory.CreateAuthenticatedEncryptorInstance(Secret.Random(512 / 8), this))
{

View File

@ -3,6 +3,7 @@
using System;
using System.Security.Cryptography;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel
{
@ -66,7 +67,7 @@ namespace Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.Configurat
/// </summary>
void IInternalAlgorithmConfiguration.Validate()
{
var factory = new ManagedAuthenticatedEncryptorFactory(DataProtectionProviderFactory.GetDefaultLoggerFactory());
var factory = new ManagedAuthenticatedEncryptorFactory(NullLoggerFactory.Instance);
// Run a sample payload through an encrypt -> decrypt operation to make sure data round-trips properly.
using (var encryptor = factory.CreateAuthenticatedEncryptorInstance(Secret.Random(512 / 8), this))
{

View File

@ -14,6 +14,7 @@ using Microsoft.AspNetCore.DataProtection.XmlEncryption;
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;
@ -206,7 +207,7 @@ namespace Microsoft.AspNetCore.DataProtection
builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(services =>
{
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
var loggerFactory = services.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
return new ConfigureOptions<KeyManagementOptions>(options =>
{
options.XmlRepository = new FileSystemXmlRepository(directory, loggerFactory);
@ -236,7 +237,7 @@ namespace Microsoft.AspNetCore.DataProtection
builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(services =>
{
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
var loggerFactory = services.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
return new ConfigureOptions<KeyManagementOptions>(options =>
{
options.XmlRepository = new RegistryXmlRepository(registryKey, loggerFactory);
@ -266,7 +267,7 @@ namespace Microsoft.AspNetCore.DataProtection
builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(services =>
{
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
var loggerFactory = services.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
return new ConfigureOptions<KeyManagementOptions>(options =>
{
options.XmlEncryptor = new CertificateXmlEncryptor(certificate, loggerFactory);
@ -306,7 +307,7 @@ namespace Microsoft.AspNetCore.DataProtection
builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(services =>
{
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
var loggerFactory = services.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
var certificateResolver = services.GetRequiredService<ICertificateResolver>();
return new ConfigureOptions<KeyManagementOptions>(options =>
{
@ -357,7 +358,7 @@ namespace Microsoft.AspNetCore.DataProtection
builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(services =>
{
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
var loggerFactory = services.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
return new ConfigureOptions<KeyManagementOptions>(options =>
{
CryptoUtil.AssertPlatformIsWindows();
@ -419,7 +420,7 @@ namespace Microsoft.AspNetCore.DataProtection
builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(services =>
{
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
var loggerFactory = services.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
return new ConfigureOptions<KeyManagementOptions>(options =>
{
CryptoUtil.AssertPlatformIsWindows8OrLater();

View File

@ -1,16 +0,0 @@
// 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 Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.DataProtection
{
internal static class DataProtectionProviderFactory
{
public static ILoggerFactory GetDefaultLoggerFactory()
{
return NullLoggerFactory.Instance;
}
}
}

View File

@ -12,6 +12,7 @@ using Microsoft.AspNetCore.DataProtection.XmlEncryption;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
@ -64,8 +65,6 @@ namespace Microsoft.Extensions.DependencyInjection
private static void AddDataProtectionServices(IServiceCollection services)
{
services.TryAddSingleton<ILoggerFactory>(DataProtectionProviderFactory.GetDefaultLoggerFactory());
if (OSVersionUtil.IsWindows())
{
services.TryAddSingleton<RegistryPolicyResolver>();
@ -88,10 +87,9 @@ namespace Microsoft.Extensions.DependencyInjection
{
var dpOptions = s.GetRequiredService<IOptions<DataProtectionOptions>>();
var keyRingProvider = s.GetRequiredService<IKeyRingProvider>();
var loggerFactory = s.GetRequiredService<ILoggerFactory>();
var loggerFactory = s.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
IDataProtectionProvider dataProtectionProvider = null;
dataProtectionProvider = new KeyRingBasedDataProtectionProvider(keyRingProvider, loggerFactory);
IDataProtectionProvider dataProtectionProvider = new KeyRingBasedDataProtectionProvider(keyRingProvider, loggerFactory);
// Link the provider to the supplied discriminator
if (!string.IsNullOrEmpty(dpOptions.Value.ApplicationDiscriminator))

View File

@ -8,6 +8,7 @@ using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationM
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.DataProtection
{
@ -24,11 +25,23 @@ namespace Microsoft.AspNetCore.DataProtection
private readonly KeyRingBasedDataProtectionProvider _dataProtectionProvider;
/// <summary>
/// Creates an ephemeral <see cref="IDataProtectionProvider"/>, optionally providing
/// services (such as logging) for consumption by the provider.
/// Creates an ephemeral <see cref="IDataProtectionProvider"/>.
/// </summary>
public EphemeralDataProtectionProvider()
: this (NullLoggerFactory.Instance)
{ }
/// <summary>
/// Creates an ephemeral <see cref="IDataProtectionProvider"/> with logging.
/// </summary>
/// <param name="loggerFactory">The <see cref="ILoggerFactory" />.</param>
public EphemeralDataProtectionProvider(ILoggerFactory loggerFactory)
{
if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
IKeyRingProvider keyringProvider;
if (OSVersionUtil.IsWindows())
{

View File

@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.DataProtection.Internal
{
@ -14,6 +15,10 @@ namespace Microsoft.AspNetCore.DataProtection.Internal
private readonly IKeyRingProvider _keyRingProvider;
private readonly ILogger<DataProtectionStartupFilter> _logger;
public DataProtectionStartupFilter(IKeyRingProvider keyRingProvider)
: this(keyRingProvider, NullLoggerFactory.Instance)
{ }
public DataProtectionStartupFilter(IKeyRingProvider keyRingProvider, ILoggerFactory loggerFactory)
{
_keyRingProvider = keyRingProvider;

View File

@ -6,6 +6,7 @@ using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.DataProtection.Internal
@ -15,7 +16,18 @@ namespace Microsoft.AspNetCore.DataProtection.Internal
private readonly RegistryPolicyResolver _registryPolicyResolver;
private readonly ILoggerFactory _loggerFactory;
public KeyManagementOptionsSetup(ILoggerFactory loggerFactory) : this(loggerFactory, registryPolicyResolver: null)
public KeyManagementOptionsSetup()
: this(NullLoggerFactory.Instance, registryPolicyResolver: null)
{
}
public KeyManagementOptionsSetup(ILoggerFactory loggerFactory)
: this(loggerFactory, registryPolicyResolver: null)
{
}
public KeyManagementOptionsSetup(RegistryPolicyResolver registryPolicyResolver)
: this(NullLoggerFactory.Instance, registryPolicyResolver)
{
}

View File

@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Cryptography;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.DataProtection.KeyManagement
@ -40,6 +41,10 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
/// </remarks>
private readonly TimeSpan _maxServerToServerClockSkew;
public DefaultKeyResolver(IOptions<KeyManagementOptions> keyManagementOptions)
: this(keyManagementOptions, NullLoggerFactory.Instance)
{ }
public DefaultKeyResolver(IOptions<KeyManagementOptions> keyManagementOptions, ILoggerFactory loggerFactory)
{
_keyPropagationWindow = keyManagementOptions.Value.KeyPropagationWindow;

View File

@ -8,6 +8,7 @@ using System.Threading;
using Microsoft.AspNetCore.Cryptography;
using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.DataProtection.KeyManagement
@ -16,7 +17,6 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
{
private CacheableKeyRing _cacheableKeyRing;
private readonly object _cacheableKeyRingLockObj = new object();
private readonly ICacheableKeyRingProvider _cacheableKeyRingProvider;
private readonly IDefaultKeyResolver _defaultKeyResolver;
private readonly KeyManagementOptions _keyManagementOptions;
private readonly IKeyManager _keyManager;
@ -25,31 +25,31 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
public KeyRingProvider(
IKeyManager keyManager,
IOptions<KeyManagementOptions> keyManagementOptions,
IDefaultKeyResolver defaultKeyResolver,
ILoggerFactory loggerFactory)
IDefaultKeyResolver defaultKeyResolver)
: this(
keyManager,
keyManagementOptions,
cacheableKeyRingProvider: null,
defaultKeyResolver: defaultKeyResolver,
loggerFactory: loggerFactory)
defaultKeyResolver,
NullLoggerFactory.Instance)
{
}
public KeyRingProvider(
IKeyManager keyManager,
IOptions<KeyManagementOptions> keyManagementOptions,
ICacheableKeyRingProvider cacheableKeyRingProvider,
IDefaultKeyResolver defaultKeyResolver,
ILoggerFactory loggerFactory)
{
_keyManagementOptions = new KeyManagementOptions(keyManagementOptions.Value); // clone so new instance is immutable
_keyManager = keyManager;
_cacheableKeyRingProvider = cacheableKeyRingProvider ?? this;
CacheableKeyRingProvider = this;
_defaultKeyResolver = defaultKeyResolver;
_logger = loggerFactory.CreateLogger<KeyRingProvider>();
}
// for testing
internal ICacheableKeyRingProvider CacheableKeyRingProvider { get; set; }
private CacheableKeyRing CreateCacheableKeyRingCore(DateTimeOffset now, IKey keyJustAdded)
{
// Refresh the list of all keys
@ -183,7 +183,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
try
{
newCacheableKeyRing = _cacheableKeyRingProvider.GetCacheableKeyRing(utcNow);
newCacheableKeyRing = CacheableKeyRingProvider.GetCacheableKeyRing(utcNow);
}
catch (Exception ex)
{

View File

@ -20,6 +20,7 @@ using Microsoft.AspNetCore.DataProtection.KeyManagement.Internal;
using Microsoft.AspNetCore.DataProtection.Repositories;
using Microsoft.AspNetCore.DataProtection.XmlEncryption;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Microsoft.Win32;
@ -55,6 +56,15 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
private CancellationTokenSource _cacheExpirationTokenSource;
/// <summary>
/// Creates an <see cref="XmlKeyManager"/>.
/// </summary>
/// <param name="keyManagementOptions">The <see cref="IOptions{KeyManagementOptions}"/> instance that provides the configuration.</param>
/// <param name="activator">The <see cref="IActivator"/>.</param>
public XmlKeyManager(IOptions<KeyManagementOptions> keyManagementOptions, IActivator activator)
: this (keyManagementOptions, activator, NullLoggerFactory.Instance)
{ }
/// <summary>
/// Creates an <see cref="XmlKeyManager"/>.
/// </summary>
@ -63,7 +73,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
public XmlKeyManager(IOptions<KeyManagementOptions> keyManagementOptions, IActivator activator, ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
_loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
_logger = _loggerFactory.CreateLogger<XmlKeyManager>();
KeyRepository = keyManagementOptions.Value.XmlRepository;

View File

@ -10,7 +10,6 @@ using Microsoft.AspNetCore.Cryptography;
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel;
using Microsoft.AspNetCore.DataProtection.Internal;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.Extensions.Logging;
using Microsoft.Win32;
namespace Microsoft.AspNetCore.DataProtection
@ -22,20 +21,17 @@ namespace Microsoft.AspNetCore.DataProtection
{
private readonly Func<RegistryKey> _getPolicyRegKey;
private readonly IActivator _activator;
private readonly ILoggerFactory _loggerFactory;
public RegistryPolicyResolver(IActivator activator, ILoggerFactory loggerFactory)
public RegistryPolicyResolver(IActivator activator)
{
_getPolicyRegKey = () => Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\DotNetPackages\Microsoft.AspNetCore.DataProtection");
_activator = activator;
_loggerFactory = loggerFactory;
}
internal RegistryPolicyResolver(RegistryKey policyRegKey, IActivator activator, ILoggerFactory loggerFactory)
internal RegistryPolicyResolver(RegistryKey policyRegKey, IActivator activator)
{
_getPolicyRegKey = () => policyRegKey;
_activator = activator;
_loggerFactory = loggerFactory;
}
// populates an options object from values stored in the registry
@ -95,10 +91,8 @@ namespace Microsoft.AspNetCore.DataProtection
/// <summary>
/// Returns a <see cref="RegistryPolicy"/> from the default registry location.
/// </summary>
public static RegistryPolicy ResolveDefaultPolicy(IActivator activator, ILoggerFactory loggerFactory)
{
return new RegistryPolicyResolver(activator, loggerFactory).ResolvePolicy();
}
public static RegistryPolicy ResolveDefaultPolicy(IActivator activator)
=> new RegistryPolicyResolver(activator).ResolvePolicy();
internal RegistryPolicy ResolvePolicy()
{

View File

@ -4,6 +4,7 @@
using System;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
namespace Microsoft.AspNetCore.DataProtection
{
@ -15,7 +16,7 @@ namespace Microsoft.AspNetCore.DataProtection
private static readonly Regex _versionPattern = new Regex(@",\s?Version=[0-9]+(\.[0-9]+){0,3}", RegexOptions.Compiled, TimeSpan.FromSeconds(2));
public TypeForwardingActivator(IServiceProvider services)
: this(services, DataProtectionProviderFactory.GetDefaultLoggerFactory())
: this(services, NullLoggerFactory.Instance)
{
}

View File

@ -79,11 +79,6 @@
"MemberId": "public .ctor(Microsoft.Win32.RegistryKey registryKey, System.IServiceProvider services)",
"Kind": "Removal"
},
{
"TypeId": "public sealed class Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider : Microsoft.AspNetCore.DataProtection.IDataProtectionProvider",
"MemberId": "public .ctor()",
"Kind": "Removal"
},
{
"TypeId": "public sealed class Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider : Microsoft.AspNetCore.DataProtection.IDataProtectionProvider",
"MemberId": "public .ctor(System.IServiceProvider services)",
@ -244,4 +239,4 @@
"MemberId": "Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor CreateEncryptor()",
"Kind": "Addition"
}
]
]

View File

@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.DataProtection
public void DifferentProvider_SamePurpose_DoesNotRoundTripData()
{
// Arrange
var dataProtector1 = new EphemeralDataProtectionProvider(NullLoggerFactory.Instance).CreateProtector("purpose");
var dataProtector1 = new EphemeralDataProtectionProvider().CreateProtector("purpose");
var dataProtector2 = new EphemeralDataProtectionProvider(NullLoggerFactory.Instance).CreateProtector("purpose");
byte[] bytes = Encoding.UTF8.GetBytes("Hello there!");

View File

@ -89,8 +89,7 @@ namespace Microsoft.AspNetCore.DataProtection.Internal
var policyResolver = new RegistryPolicyResolver(
registryKey,
activator: SimpleActivator.DefaultWithoutServices,
loggerFactory: NullLoggerFactory.Instance);
activator: SimpleActivator.DefaultWithoutServices);
var setup = new KeyManagementOptionsSetup(NullLoggerFactory.Instance, policyResolver);

View File

@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
ShouldGenerateNewKey = false
})
});
// Act
var cacheableKeyRing = keyRingProvider.GetCacheableKeyRing(now);
@ -597,9 +597,11 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
return new KeyRingProvider(
keyManager: null,
keyManagementOptions: Options.Create(options),
cacheableKeyRingProvider: cacheableKeyRingProvider,
defaultKeyResolver: null,
loggerFactory: NullLoggerFactory.Instance);
loggerFactory: NullLoggerFactory.Instance)
{
CacheableKeyRingProvider = cacheableKeyRingProvider
};
}
private static ICacheableKeyRingProvider CreateKeyRingProvider(IKeyManager keyManager, IDefaultKeyResolver defaultKeyResolver, KeyManagementOptions keyManagementOptions= null)
@ -612,7 +614,6 @@ namespace Microsoft.AspNetCore.DataProtection.KeyManagement
return new KeyRingProvider(
keyManager: keyManager,
keyManagementOptions: Options.Create(keyManagementOptions),
cacheableKeyRingProvider: null,
defaultKeyResolver: defaultKeyResolver,
loggerFactory: NullLoggerFactory.Instance);
}

View File

@ -251,8 +251,7 @@ namespace Microsoft.AspNetCore.DataProtection
var policyResolver = new RegistryPolicyResolver(
registryKey,
activator: SimpleActivator.DefaultWithoutServices,
loggerFactory: NullLoggerFactory.Instance);
activator: SimpleActivator.DefaultWithoutServices);
return policyResolver.ResolvePolicy();
});

View File

@ -0,0 +1,67 @@
// 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 Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Xunit;
namespace Microsoft.AspNetCore.DataProtection
{
public class ServiceCollectionTests
{
[Fact]
public void AddsOptions()
{
var services = new ServiceCollection()
.AddDataProtection()
.Services
.BuildServiceProvider();
Assert.NotNull(services.GetService<IOptions<DataProtectionOptions>>());
}
[Fact]
public void DoesNotOverrideLogging()
{
var services1 = new ServiceCollection()
.AddLogging()
.AddDataProtection()
.Services
.BuildServiceProvider();
var services2 = new ServiceCollection()
.AddDataProtection()
.Services
.AddLogging()
.BuildServiceProvider();
Assert.Equal(
services1.GetRequiredService<ILoggerFactory>().GetType(),
services2.GetRequiredService<ILoggerFactory>().GetType());
}
[Fact]
public void CanResolveAllRegisteredServices()
{
var serviceCollection = new ServiceCollection()
.AddDataProtection()
.Services;
var services = serviceCollection.BuildServiceProvider(validateScopes: true);
Assert.Null(services.GetService<ILoggerFactory>());
foreach (var descriptor in serviceCollection)
{
if (descriptor.ServiceType.Assembly.GetName().Name == "Microsoft.Extensions.Options")
{
// ignore any descriptors added by the call to .AddOptions()
continue;
}
Assert.NotNull(services.GetService(descriptor.ServiceType));
}
}
}
}