Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/libraries/Common/tests/Extensions/ConfigurationRootTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace Microsoft.Extensions.Configuration.Test
{
public class ConfigurationRootTest
{
private const string SecretCover = "*****";

[Fact]
public void RootDisposesProviders()
{
Expand Down Expand Up @@ -76,12 +78,56 @@ public void ChainedConfigurationIsDisposed(bool shouldDispose)
Assert.Equal(shouldDispose, provider.IsDisposed);
}

[Fact]
public void SecretsAreConcealed()
{
var provider = new SecretConfigurationProvider("secret", "secret-value");

var config = new ConfigurationRoot(new IConfigurationProvider[] {
provider
});

var debugView = config.GetDebugView(ProcessValue);

Assert.Contains(SecretCover, debugView);
}

[Fact]
public void NonSecretsAreNotConcealed()
{
var provider = new TestConfigurationProvider("foo", "foo-value");

var config = new ConfigurationRoot(new IConfigurationProvider[] {
provider
});

var debugView = config.GetDebugView(ProcessValue);

Assert.DoesNotContain(SecretCover, debugView);
}

private string ProcessValue(ConfigurationDebugViewContext context)
{
if (context.ConfigurationProvider.ToString() == nameof(SecretConfigurationProvider))
{
return SecretCover;
}

return context.Value;
}

private class TestConfigurationProvider : ConfigurationProvider
{
public TestConfigurationProvider(string key, string value)
=> Data.Add(key, value);
}

private class SecretConfigurationProvider : ConfigurationProvider
{
public SecretConfigurationProvider(string key, string value)
=> Data.Add(key, value);
}

private class DisposableTestConfigurationProvider : ConfigurationProvider, IDisposable
{
public bool IsDisposed { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ public static partial class ConfigurationPath
public static partial class ConfigurationRootExtensions
{
public static string GetDebugView(this Microsoft.Extensions.Configuration.IConfigurationRoot root) { throw null; }
public static string GetDebugView(this IConfigurationRoot root, System.Func<ConfigurationDebugViewContext, string>? processValue) { throw null; }
}
public readonly partial struct ConfigurationDebugViewContext
{
public ConfigurationDebugViewContext(string path, string key, string? value, IConfigurationProvider configurationProvider) { throw null; }
public string Path { get; }
public string Key { get; }
public string? Value { get; }
public IConfigurationProvider ConfigurationProvider { get; }
}
public partial interface IConfiguration
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.Extensions.Configuration
{
/// <summary>
/// Provides the data about current item of the configuration.
/// </summary>
public readonly struct ConfigurationDebugViewContext
{
public ConfigurationDebugViewContext(string path, string key, string? value, IConfigurationProvider configurationProvider)
{
Path = path;
Key = key;
Value = value;
ConfigurationProvider = configurationProvider;
}

/// <summary>
/// Gets the path of the current item.
/// </summary>
public string Path { get; }

/// <summary>
/// Gets the key of the current item.
/// </summary>
public string Key { get; }

/// <summary>
/// Gets the value of the current item.
/// </summary>
public string? Value { get; }

/// <summary>
/// Gets the <see cref="IConfigurationProvider" /> that was used to get the value of the current item.
/// </summary>
public IConfigurationProvider ConfigurationProvider { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand All @@ -17,6 +18,22 @@ public static class ConfigurationRootExtensions
/// </summary>
/// <returns> The debug view. </returns>
public static string GetDebugView(this IConfigurationRoot root)
{
return GetDebugView(root, processValue: null);
}

/// <summary>
/// Generates a human-readable view of the configuration showing where each value came from.
/// </summary>
/// <param name="root">Configuration root</param>
/// <param name="processValue">
/// Function for processing the value e.g. hiding secrets
/// Parameters:
/// ConfigurationDebugViewContext: Context of the current configuration item
/// returns: A string value is used to assign as the Value of the configuration section
/// </param>
/// <returns> The debug view. </returns>
public static string GetDebugView(this IConfigurationRoot root, Func<ConfigurationDebugViewContext, string>? processValue)
{
void RecurseChildren(
StringBuilder stringBuilder,
Expand All @@ -29,11 +46,15 @@ void RecurseChildren(

if (valueAndProvider.Provider != null)
{
string? value = processValue != null
? processValue(new ConfigurationDebugViewContext(child.Key, child.Path, valueAndProvider.Value, valueAndProvider.Provider))
: valueAndProvider.Value;

stringBuilder
.Append(indent)
.Append(child.Key)
.Append('=')
.Append(valueAndProvider.Value)
.Append(value)
.Append(" (")
.Append(valueAndProvider.Provider)
.AppendLine(")");
Expand Down