Skip to content

Commit

Permalink
add additionalCharactersForConfigurationPath option (#14)
Browse files Browse the repository at this point in the history
Co-authored-by: tsvetko <[email protected]>
  • Loading branch information
cparandiev and tsvetko authored Mar 30, 2021
1 parent 6535fe0 commit 5c59317
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 2 deletions.
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,39 @@ Later in your services you can track changes in app configuration using `IOption
Keep in mind that your service should be registered as scoped or transient to receive updates.
Also `IOptionsSnapshot` can return empty value in some cases ([it's .net core bug](https://github.com/dotnet/runtime/issues/37860))

## Configuration using additional characters for a configuration path
This will be helpful when you want to flatten the structure of the secrets.
For example the following two secret objects will evaluate to the same configuration if for the second object the `additionalCharactersForConfigurationPath` option is used with `new []{'.'}` value:
```json
{
"secrets":
{
"DB":
{
"ConnectionString": "secret value"
}
}
}
```
```json
{
"secrets":
{
"DB.ConnectionString": "secret value"
}
}
```

```csharp
config.AddVaultConfiguration(
() => new VaultOptions(
"htpp://localhost:8200",
"root",
additionalCharactersForConfigurationPath: new []{'.'}),),
"sampleapp",
"secret");
```
new VaultOptions("http://localhost:8200", "root", null, null, false, 300, false, new []{'.'}),
## Configuration using environmnt variables

Alternatively, you can configure Vault connection using next environmnt variables:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ namespace VaultSharp.Extensions.Configuration
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -94,6 +96,7 @@ private async Task LoadVaultDataAsync(IVaultClient vaultClient)
var key = secretData.Key;
key = key.Replace(this._source.BasePath, string.Empty, StringComparison.InvariantCultureIgnoreCase).TrimStart('/')
.Replace('/', ':');
key = this.ReplaceTheAdditionalCharactersForConfigurationPath(key);
var data = secretData.SecretData.Data;

var shouldSetValue = true;
Expand All @@ -118,6 +121,8 @@ private void SetData<TValue>(IEnumerable<KeyValuePair<string, TValue>> data, str
foreach (var pair in data)
{
var nestedKey = string.IsNullOrEmpty(key) ? pair.Key : $"{key}:{pair.Key}";
nestedKey = this.ReplaceTheAdditionalCharactersForConfigurationPath(nestedKey);

var nestedValue = pair.Value;
switch (nestedValue)
{
Expand Down Expand Up @@ -235,6 +240,23 @@ private async IAsyncEnumerable<KeyedSecretData> ReadKeysAsync(IVaultClient vault
}
}

private string ReplaceTheAdditionalCharactersForConfigurationPath(string inputKey)
{
if (!this._source.Options.AdditionalCharactersForConfigurationPath.Any())
{
return inputKey;
}

var outputKey = new StringBuilder(inputKey);

foreach (var c in this._source.Options.AdditionalCharactersForConfigurationPath)
{
outputKey.Replace(c, ':');
}

return outputKey.ToString();
}

private class KeyedSecretData
{
public KeyedSecretData(string key, SecretData secretData)
Expand Down
13 changes: 12 additions & 1 deletion Source/VaultSharp.Extensions.Configuration/VaultOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace VaultSharp.Extensions.Configuration
{
using System;
using System.Collections.Generic;

/// <summary>
/// Vault options class.
/// </summary>
Expand All @@ -15,14 +18,16 @@ public class VaultOptions
/// <param name="reloadOnChange">Reload secrets if changed in Vault.</param>
/// <param name="reloadCheckIntervalSeconds">Interval in seconds to check Vault for any changes.</param>
/// <param name="omitVaultKeyName">Omit Vault Key Name in Configuration Keys.</param>
/// <param name="additionalCharactersForConfigurationPath">Additional characters for the Configuration path.</param>
public VaultOptions(
string vaultAddress,
string? vaultToken,
string? vaultSecret = null,
string? vaultRoleId = null,
bool reloadOnChange = false,
int reloadCheckIntervalSeconds = 300,
bool omitVaultKeyName = false)
bool omitVaultKeyName = false,
IEnumerable<char>? additionalCharactersForConfigurationPath = null)
{
this.VaultAddress = vaultAddress;
this.VaultToken = vaultToken;
Expand All @@ -31,6 +36,7 @@ public VaultOptions(
this.ReloadOnChange = reloadOnChange;
this.ReloadCheckIntervalSeconds = reloadCheckIntervalSeconds;
this.OmitVaultKeyName = omitVaultKeyName;
this.AdditionalCharactersForConfigurationPath = additionalCharactersForConfigurationPath ?? Array.Empty<char>();
}

/// <summary>
Expand Down Expand Up @@ -68,5 +74,10 @@ public VaultOptions(
/// Gets a value indicating whether the Vault key should be ommited when generation Configuration key names.
/// </summary>
public bool OmitVaultKeyName { get; }

/// <summary>
/// Gets an array of characters that will be used as a path to form the Configuration.
/// </summary>
public IEnumerable<char> AdditionalCharactersForConfigurationPath { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ public async Task Success_SimpleTest_TokenAuth()
new KeyValuePair<string, object>("option2", "value2"),
}
},
{
"test/otherSubsection.otherSubsection2/otherSubsection3.otherSubsection4.otherSubsection5", new[]
{
new KeyValuePair<string, object>("option7", "value7"),
}
},
};

var container = this.PrepareVaultContainer();
Expand All @@ -115,7 +121,7 @@ public async Task Success_SimpleTest_TokenAuth()
// act
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddVaultConfiguration(
() => new VaultOptions("http://localhost:8200", "root"),
() => new VaultOptions("http://localhost:8200", "root", additionalCharactersForConfigurationPath: new []{'.'}),
"test",
"secret",
this._logger);
Expand All @@ -137,6 +143,12 @@ public async Task Success_SimpleTest_TokenAuth()
t2.OptionA.Should().Be("a2");
t2.OptionB.Should().Be("b2");
configurationRoot.GetSection("subsection").GetValue<string>("option2").Should().Be("value2");
configurationRoot.GetSection("otherSubsection")
.GetSection("otherSubsection2")
.GetSection("otherSubsection3")
.GetSection("otherSubsection4")
.GetSection("otherSubsection5")
.GetValue<string>("option7").Should().Be("value7");
}
finally
{
Expand Down

0 comments on commit 5c59317

Please sign in to comment.