|
| 1 | +// Licensed to the .NET Foundation under one or more agreements. |
| 2 | +// The .NET Foundation licenses this file to you under the MIT license. |
| 3 | + |
| 4 | +using System; |
| 5 | +using System.IO; |
| 6 | +using System.Xml.Linq; |
| 7 | +using Microsoft.AspNetCore.DataProtection.KeyManagement; |
| 8 | +using Microsoft.AspNetCore.DataProtection.Repositories; |
| 9 | +using Microsoft.AspNetCore.DataProtection.XmlEncryption; |
| 10 | +using Microsoft.Extensions.Configuration; |
| 11 | +using Microsoft.Extensions.Logging; |
| 12 | +using Microsoft.Extensions.Options; |
| 13 | + |
| 14 | +namespace Microsoft.AspNetCore.DataProtection.Internal; |
| 15 | + |
| 16 | +/// <summary> |
| 17 | +/// Performs additional <see cref="KeyManagementOptions" /> configuration, after the user's configuration has been applied. |
| 18 | +/// </summary> |
| 19 | +/// <remarks> |
| 20 | +/// In practice, this type is used to set key management to readonly mode if an environment variable is set and the user |
| 21 | +/// has not explicitly configured data protection. |
| 22 | +/// </remarks> |
| 23 | +internal sealed class KeyManagementOptionsPostSetup : IPostConfigureOptions<KeyManagementOptions> |
| 24 | +{ |
| 25 | + /// <remarks> |
| 26 | + /// Settable as `ReadOnlyDataProtectionKeyDirectory`, `DOTNET_ReadOnlyDataProtectionKeyDirectory`, |
| 27 | + /// or `ASPNETCORE_ReadOnlyDataProtectionKeyDirectory`, in descending order of precedence. |
| 28 | + /// </remarks> |
| 29 | + internal const string ReadOnlyDataProtectionKeyDirectoryKey = "ReadOnlyDataProtectionKeyDirectory"; |
| 30 | + |
| 31 | + private readonly string? _keyDirectoryPath; |
| 32 | + private readonly ILoggerFactory? _loggerFactory; // Null iff _keyDirectoryPath is null |
| 33 | + |
| 34 | + public KeyManagementOptionsPostSetup() |
| 35 | + { |
| 36 | + // If there's no IConfiguration, there's no _keyDirectoryPath and this type will do nothing. |
| 37 | + // This is mostly a convenience for tests since ASP.NET Core apps will have an IConfiguration. |
| 38 | + } |
| 39 | + |
| 40 | + public KeyManagementOptionsPostSetup(IConfiguration configuration, ILoggerFactory loggerFactory) |
| 41 | + { |
| 42 | + _keyDirectoryPath = configuration[ReadOnlyDataProtectionKeyDirectoryKey]; |
| 43 | + _loggerFactory = loggerFactory; |
| 44 | + } |
| 45 | + |
| 46 | + void IPostConfigureOptions<KeyManagementOptions>.PostConfigure(string? name, KeyManagementOptions options) |
| 47 | + { |
| 48 | + if (_keyDirectoryPath is null || name != Options.DefaultName) |
| 49 | + { |
| 50 | + return; |
| 51 | + } |
| 52 | + |
| 53 | + // If Data Protection has not been configured, then set it up according to the environment variable |
| 54 | + if (options is { XmlRepository: null, XmlEncryptor: null }) |
| 55 | + { |
| 56 | + var keyDirectory = new DirectoryInfo(_keyDirectoryPath); |
| 57 | + |
| 58 | + options.AutoGenerateKeys = false; |
| 59 | + options.XmlEncryptor = InvalidEncryptor.Instance; |
| 60 | + options.XmlRepository = new ReadOnlyFileSystemXmlRepository(keyDirectory, _loggerFactory!); |
| 61 | + } |
| 62 | + } |
| 63 | + |
| 64 | + private sealed class InvalidEncryptor : IXmlEncryptor |
| 65 | + { |
| 66 | + public static readonly IXmlEncryptor Instance = new InvalidEncryptor(); |
| 67 | + |
| 68 | + private InvalidEncryptor() |
| 69 | + { |
| 70 | + } |
| 71 | + |
| 72 | + EncryptedXmlInfo IXmlEncryptor.Encrypt(XElement plaintextElement) |
| 73 | + { |
| 74 | + throw new InvalidOperationException("Keys access is set up as read-only, so nothing should be encrypting"); |
| 75 | + } |
| 76 | + } |
| 77 | + |
| 78 | + private sealed class ReadOnlyFileSystemXmlRepository : FileSystemXmlRepository |
| 79 | + { |
| 80 | + public ReadOnlyFileSystemXmlRepository(DirectoryInfo directory, ILoggerFactory loggerFactory) |
| 81 | + : base(directory, loggerFactory) |
| 82 | + { |
| 83 | + } |
| 84 | + |
| 85 | + public override void StoreElement(XElement element, string friendlyName) |
| 86 | + { |
| 87 | + throw new InvalidOperationException("Keys access is set up as read-only, so nothing should be storing keys"); |
| 88 | + } |
| 89 | + } |
| 90 | +} |
0 commit comments