Skip to content

Commit 378f151

Browse files
authored
Add option to omit Vault Key name in Configuration Data (#10)
* Add option to omit Vault Key name in Configuration Data * Add tests
1 parent e37c717 commit 378f151

File tree

3 files changed

+105
-2
lines changed

3 files changed

+105
-2
lines changed

Source/VaultSharp.Extensions.Configuration/VaultConfigurationProvider.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ private async Task LoadVaultDataAsync(IVaultClient vaultClient)
106106

107107
if (shouldSetValue)
108108
{
109-
this.SetData(data, key);
109+
this.SetData(data, this.ConfigurationSource.Options.OmitVaultKeyName ? string.Empty : key);
110+
110111
this._versionsCache[key] = secretData.SecretData.Metadata.Version;
111112
}
112113
}

Source/VaultSharp.Extensions.Configuration/VaultOptions.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,23 @@ public class VaultOptions
1414
/// <param name="vaultRoleId">Vault Role ID.</param>
1515
/// <param name="reloadOnChange">Reload secrets if changed in Vault.</param>
1616
/// <param name="reloadCheckIntervalSeconds">Interval in seconds to check Vault for any changes.</param>
17+
/// <param name="omitVaultKeyName">Omit Vault Key Name in Configuration Keys.</param>
1718
public VaultOptions(
1819
string vaultAddress,
1920
string? vaultToken,
2021
string? vaultSecret = null,
2122
string? vaultRoleId = null,
2223
bool reloadOnChange = false,
23-
int reloadCheckIntervalSeconds = 300)
24+
int reloadCheckIntervalSeconds = 300,
25+
bool omitVaultKeyName = false)
2426
{
2527
this.VaultAddress = vaultAddress;
2628
this.VaultToken = vaultToken;
2729
this.VaultSecret = vaultSecret;
2830
this.VaultRoleId = vaultRoleId;
2931
this.ReloadOnChange = reloadOnChange;
3032
this.ReloadCheckIntervalSeconds = reloadCheckIntervalSeconds;
33+
this.OmitVaultKeyName = omitVaultKeyName;
3134
}
3235

3336
/// <summary>
@@ -60,5 +63,10 @@ public VaultOptions(
6063
/// Gets interval in seconds to check Vault for any changes.
6164
/// </summary>
6265
public int ReloadCheckIntervalSeconds { get; }
66+
67+
/// <summary>
68+
/// Gets a value indicating whether the Vault key should be ommited when generation Configuration key names.
69+
/// </summary>
70+
public bool OmitVaultKeyName { get; }
6371
}
6472
}

Tests/VaultSharp.Extensions.Configuration.Test/IntegrationTests.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace VaultSharp.Extensions.Configuration.Test
1010
using FluentAssertions;
1111
using Microsoft.Extensions.Configuration;
1212
using Microsoft.VisualStudio.TestPlatform.TestHost;
13+
using Newtonsoft.Json;
1314
using Serilog;
1415
using Serilog.Core;
1516
using Serilog.Extensions.Logging;
@@ -64,6 +65,17 @@ await vaultClient.V1.Secrets.KeyValue.V2.WriteSecretAsync(sectionPair.Key, data)
6465
}
6566
}
6667

68+
private async Task LoadDataAsync(string secretPath, string jsonData)
69+
{
70+
var authMethod = new TokenAuthMethodInfo("root");
71+
72+
var vaultClientSettings = new VaultClientSettings("http://localhost:8200", authMethod);
73+
IVaultClient vaultClient = new VaultClient(vaultClientSettings);
74+
75+
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonData);
76+
await vaultClient.V1.Secrets.KeyValue.V2.WriteSecretAsync(secretPath, dictionary).ConfigureAwait(false);
77+
}
78+
6779
[Fact]
6880
public async Task Success_SimpleTest_TokenAuth()
6981
{
@@ -132,6 +144,35 @@ public async Task Success_SimpleTest_TokenAuth()
132144
}
133145
}
134146

147+
[Fact]
148+
public async Task Success_SimpleTestOmitVaultKey_TokenAuth()
149+
{
150+
string jsonData = @"{""option1"": ""value1"",""subsection"":{""option2"": ""value2""}}";
151+
var container = this.PrepareVaultContainer();
152+
try
153+
{
154+
await container.StartAsync().ConfigureAwait(false);
155+
await this.LoadDataAsync("myservice-config", jsonData).ConfigureAwait(false);
156+
157+
// act
158+
ConfigurationBuilder builder = new ConfigurationBuilder();
159+
builder.AddVaultConfiguration(
160+
() => new VaultOptions("http://localhost:8200", "root", omitVaultKeyName: true),
161+
"myservice-config",
162+
"secret",
163+
this._logger);
164+
var configurationRoot = builder.Build();
165+
166+
// assert
167+
configurationRoot.GetValue<string>("option1").Should().Be("value1");
168+
configurationRoot.GetSection("subsection").GetValue<string>("option2").Should().Be("value2");
169+
}
170+
finally
171+
{
172+
await container.DisposeAsync().ConfigureAwait(false);
173+
}
174+
}
175+
135176
[Fact]
136177
public async Task Success_WatcherTest_TokenAuth()
137178
{
@@ -193,6 +234,59 @@ public async Task Success_WatcherTest_TokenAuth()
193234
await container.DisposeAsync().ConfigureAwait(false);
194235
}
195236
}
237+
238+
[Fact]
239+
public async Task Success_WatcherTest_OmitVaultKey_TokenAuth()
240+
{
241+
// arrange
242+
using CancellationTokenSource cts = new CancellationTokenSource();
243+
string jsonData = @"{""option1"": ""value1"",""subsection"":{""option2"": ""value2""}}";
244+
245+
var container = this.PrepareVaultContainer();
246+
try
247+
{
248+
await container.StartAsync().ConfigureAwait(false);
249+
await this.LoadDataAsync("myservice-config", jsonData).ConfigureAwait(false);
250+
251+
252+
// act
253+
ConfigurationBuilder builder = new ConfigurationBuilder();
254+
builder.AddVaultConfiguration(
255+
() => new VaultOptions("http://localhost:8200", "root", reloadOnChange: true, reloadCheckIntervalSeconds: 10, omitVaultKeyName: true),
256+
"myservice-config",
257+
"secret",
258+
this._logger);
259+
var configurationRoot = builder.Build();
260+
VaultChangeWatcher changeWatcher = new VaultChangeWatcher(configurationRoot, this._logger);
261+
await changeWatcher.StartAsync(cts.Token).ConfigureAwait(false);
262+
var reloadToken = configurationRoot.GetReloadToken();
263+
264+
// assert
265+
configurationRoot.GetValue<string>("option1").Should().Be("value1");
266+
configurationRoot.GetSection("subsection").GetValue<string>("option2").Should().Be("value2");
267+
reloadToken.HasChanged.Should().BeFalse();
268+
269+
// load new data and wait for reload
270+
jsonData =
271+
@"{""option1"": ""value1_new"",""subsection"": {""option2"": ""value2_new""},""subsection3"": {""option3"": ""value3_new""}}";
272+
273+
await this.LoadDataAsync("myservice-config", jsonData).ConfigureAwait(false);
274+
await Task.Delay(TimeSpan.FromSeconds(15)).ConfigureAwait(true);
275+
276+
reloadToken.HasChanged.Should().BeTrue();
277+
configurationRoot.GetValue<string>("option1").Should().Be("value1_new");
278+
configurationRoot.GetSection("subsection").GetValue<string>("option2").Should().Be("value2_new");
279+
configurationRoot.GetSection("subsection3").GetValue<string>("option3").Should().Be("value3_new");
280+
281+
changeWatcher.Dispose();
282+
}
283+
finally
284+
{
285+
cts.Cancel();
286+
await container.DisposeAsync().ConfigureAwait(false);
287+
}
288+
}
289+
196290
}
197291

198292
public class TestConfigObject

0 commit comments

Comments
 (0)