Skip to content

Commit

Permalink
update to use sourceid as key in cached secret dictionary
Browse files Browse the repository at this point in the history
  • Loading branch information
amerjusupovic committed Sep 25, 2024
1 parent 9aaf6b5 commit bd6930c
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,15 @@ public void InvalidateCache(ConfigurationSetting setting = null)
}
else
{
_secretProvider.RemoveSecretFromCache(setting.Key);
if (CanProcess(setting))
{
string secretRefUri = ParseSecretReferenceUri(setting);

if (!string.IsNullOrEmpty(secretRefUri) && Uri.TryCreate(secretRefUri, UriKind.Absolute, out Uri secretUri) && KeyVaultSecretIdentifier.TryCreate(secretUri, out KeyVaultSecretIdentifier secretIdentifier))
{
_secretProvider.RemoveSecretFromCache(secretIdentifier.SourceId);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -16,14 +15,14 @@ internal class AzureKeyVaultSecretProvider
{
private readonly AzureAppConfigurationKeyVaultOptions _keyVaultOptions;
private readonly IDictionary<string, SecretClient> _secretClients;
private readonly Dictionary<string, CachedKeyVaultSecret> _cachedKeyVaultSecrets;
private string _nextRefreshKey;
private readonly Dictionary<Uri, CachedKeyVaultSecret> _cachedKeyVaultSecrets;
private Uri _nextRefreshSourceId;
private DateTimeOffset? _nextRefreshTime;

public AzureKeyVaultSecretProvider(AzureAppConfigurationKeyVaultOptions keyVaultOptions = null)
{
_keyVaultOptions = keyVaultOptions ?? new AzureAppConfigurationKeyVaultOptions();
_cachedKeyVaultSecrets = new Dictionary<string, CachedKeyVaultSecret>(StringComparer.OrdinalIgnoreCase);
_cachedKeyVaultSecrets = new Dictionary<Uri, CachedKeyVaultSecret>();
_secretClients = new Dictionary<string, SecretClient>(StringComparer.OrdinalIgnoreCase);

if (_keyVaultOptions.SecretClients != null)
Expand All @@ -40,8 +39,7 @@ public async Task<string> GetSecretValue(KeyVaultSecretIdentifier secretIdentifi
{
string secretValue = null;

if (_cachedKeyVaultSecrets.TryGetValue(key, out CachedKeyVaultSecret cachedSecret) &&
(cachedSecret.SourceId == secretIdentifier.SourceId) &&
if (_cachedKeyVaultSecrets.TryGetValue(secretIdentifier.SourceId, out CachedKeyVaultSecret cachedSecret) &&
(!cachedSecret.RefreshAt.HasValue || DateTimeOffset.UtcNow < cachedSecret.RefreshAt.Value))
{
return cachedSecret.SecretValue;
Expand Down Expand Up @@ -75,7 +73,7 @@ public async Task<string> GetSecretValue(KeyVaultSecretIdentifier secretIdentifi
}
finally
{
SetSecretInCache(key, cachedSecret, success);
SetSecretInCache(secretIdentifier.SourceId, key, cachedSecret, success);
}

return secretValue;
Expand All @@ -88,19 +86,19 @@ public bool ShouldRefreshKeyVaultSecrets()

public void ClearCache()
{
var keysToRemove = new List<string>();
var sourceIdsToRemove = new List<Uri>();

foreach (KeyValuePair<string, CachedKeyVaultSecret> secret in _cachedKeyVaultSecrets)
foreach (KeyValuePair<Uri, CachedKeyVaultSecret> secret in _cachedKeyVaultSecrets)
{
if (secret.Value.LastRefreshTime + RefreshConstants.MinimumSecretRefreshInterval < DateTimeOffset.UtcNow)
{
keysToRemove.Add(secret.Key);
sourceIdsToRemove.Add(secret.Key);
}
}

foreach (string key in keysToRemove)
foreach (Uri sourceId in sourceIdsToRemove)
{
_cachedKeyVaultSecrets.Remove(key);
_cachedKeyVaultSecrets.Remove(sourceId);
}

if (_cachedKeyVaultSecrets.Any())
Expand All @@ -109,11 +107,11 @@ public void ClearCache()
}
}

public void RemoveSecretFromCache(string key)
public void RemoveSecretFromCache(Uri sourceId)
{
_cachedKeyVaultSecrets.Remove(key);
_cachedKeyVaultSecrets.Remove(sourceId);

if (key == _nextRefreshKey)
if (sourceId == _nextRefreshSourceId)
{
UpdateNextRefreshableSecretFromCache();
}
Expand Down Expand Up @@ -143,39 +141,39 @@ private SecretClient GetSecretClient(Uri secretUri)
return client;
}

private void SetSecretInCache(string key, CachedKeyVaultSecret cachedSecret, bool success = true)
private void SetSecretInCache(Uri sourceId, string key, CachedKeyVaultSecret cachedSecret, bool success = true)
{
if (cachedSecret == null)
{
cachedSecret = new CachedKeyVaultSecret();
}

UpdateCacheExpirationTimeForSecret(key, cachedSecret, success);
_cachedKeyVaultSecrets[key] = cachedSecret;
_cachedKeyVaultSecrets[sourceId] = cachedSecret;

if (key == _nextRefreshKey)
if (sourceId == _nextRefreshSourceId)
{
UpdateNextRefreshableSecretFromCache();
}
else if ((cachedSecret.RefreshAt.HasValue && _nextRefreshTime.HasValue && cachedSecret.RefreshAt.Value < _nextRefreshTime.Value)
|| (cachedSecret.RefreshAt.HasValue && !_nextRefreshTime.HasValue))
{
_nextRefreshKey = key;
_nextRefreshSourceId = sourceId;
_nextRefreshTime = cachedSecret.RefreshAt.Value;
}
}

private void UpdateNextRefreshableSecretFromCache()
{
_nextRefreshKey = null;
_nextRefreshSourceId = null;
_nextRefreshTime = DateTimeOffset.MaxValue;

foreach (KeyValuePair<string, CachedKeyVaultSecret> secret in _cachedKeyVaultSecrets)
foreach (KeyValuePair<Uri, CachedKeyVaultSecret> secret in _cachedKeyVaultSecrets)
{
if (secret.Value.RefreshAt.HasValue && secret.Value.RefreshAt.Value < _nextRefreshTime)
{
_nextRefreshTime = secret.Value.RefreshAt;
_nextRefreshKey = secret.Key;
_nextRefreshSourceId = secret.Key;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public static async Task<KeyValueChange> GetKeyValueChange(this ConfigurationCli
return new KeyValueChange
{
ChangeType = KeyValueChangeType.Modified,
Previous = setting,
Current = response.Value,
Key = setting.Key,
Label = setting.Label
Expand All @@ -47,6 +48,7 @@ public static async Task<KeyValueChange> GetKeyValueChange(this ConfigurationCli
return new KeyValueChange
{
ChangeType = KeyValueChangeType.Deleted,
Previous = setting,
Current = null,
Key = setting.Key,
Label = setting.Label
Expand All @@ -56,6 +58,7 @@ public static async Task<KeyValueChange> GetKeyValueChange(this ConfigurationCli
return new KeyValueChange
{
ChangeType = KeyValueChangeType.None,
Previous = setting,
Current = setting,
Key = setting.Key,
Label = setting.Label
Expand Down Expand Up @@ -158,6 +161,7 @@ await TracingUtils.CallWithRequestTracing(options.RequestTracingEnabled, Request
ChangeType = KeyValueChangeType.Modified,
Key = setting.Key,
Label = options.Label.NormalizeNull(),
Previous = null,
Current = setting
});
string key = setting.Key.Substring(FeatureManagementConstants.FeatureFlagMarker.Length);
Expand All @@ -176,6 +180,7 @@ await TracingUtils.CallWithRequestTracing(options.RequestTracingEnabled, Request
ChangeType = KeyValueChangeType.Deleted,
Key = kvp.Key,
Label = options.Label.NormalizeNull(),
Previous = null,
Current = null
});
string key = kvp.Key.Substring(FeatureManagementConstants.FeatureFlagMarker.Length);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ internal struct KeyValueChange
public string Label { get; set; }

public ConfigurationSetting Current { get; set; }

public ConfigurationSetting Previous { get; set; }
}
}

0 comments on commit bd6930c

Please sign in to comment.