From 31e29558340d4271e1d2df20f3dfb02236ec842e Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Tue, 17 Sep 2024 07:08:10 +0200 Subject: [PATCH 1/2] chore: remove guard.net from core and keyvault secret provider --- .../Arcus.Security.Core.csproj | 1 - .../Caching/CachedSecretProvider.cs | 79 +++++--- .../CompositeSecretProvider.cs | 173 +++++++++++++----- .../CriticalExceptionFilter.cs | 20 +- src/Arcus.Security.Core/Secret.cs | 5 +- .../SecretNotFoundException.cs | 7 +- .../SecretProviderOptions.cs | 28 ++- src/Arcus.Security.Core/SecretStoreBuilder.cs | 31 ++-- src/Arcus.Security.Core/SecretStoreSource.cs | 15 +- .../ArcusConfigurationProvider.cs | 7 +- .../Configuration/KeyVaultConfiguration.cs | 16 +- .../SecretStoreBuilderExtensions.cs | 99 ++-------- .../KeyVaultCachedSecretProvider.cs | 25 ++- .../KeyVaultSecretProvider.cs | 77 ++++++-- 14 files changed, 335 insertions(+), 248 deletions(-) diff --git a/src/Arcus.Security.Core/Arcus.Security.Core.csproj b/src/Arcus.Security.Core/Arcus.Security.Core.csproj index 10bbd687..c09336cf 100644 --- a/src/Arcus.Security.Core/Arcus.Security.Core.csproj +++ b/src/Arcus.Security.Core/Arcus.Security.Core.csproj @@ -26,7 +26,6 @@ - diff --git a/src/Arcus.Security.Core/Caching/CachedSecretProvider.cs b/src/Arcus.Security.Core/Caching/CachedSecretProvider.cs index e989dec3..53b0dca4 100644 --- a/src/Arcus.Security.Core/Caching/CachedSecretProvider.cs +++ b/src/Arcus.Security.Core/Caching/CachedSecretProvider.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Threading.Tasks; using Arcus.Security.Core.Caching.Configuration; -using GuardNet; using Microsoft.Extensions.Caching.Memory; namespace Arcus.Security.Core.Caching @@ -29,16 +28,15 @@ public class CachedSecretProvider : ICachedSecretProvider, IVersionedSecretProvi /// Thrown when the is not a positive time duration. public CachedSecretProvider(ISecretProvider secretProvider, ICacheConfiguration cacheConfiguration, IMemoryCache memoryCache) { - Guard.NotNull(secretProvider, nameof(secretProvider), "Requires a secret provider instance to include caching while retrieving secrets"); - Guard.NotNull(memoryCache, nameof(memoryCache), "Requires a memory caching implementation to include caching while retrieving secrets"); - Guard.NotNull(cacheConfiguration, nameof(cacheConfiguration), "Requires a configuration instance to influence the caching during the retrieval of secrets"); - Guard.NotLessThan(cacheConfiguration.Duration, TimeSpan.Zero, nameof(cacheConfiguration), - "Requires a positive time duration in the cache configuration in which the caching should take place"); - - _secretProvider = secretProvider; - _cacheConfiguration = cacheConfiguration; - - MemoryCache = memoryCache; + _secretProvider = secretProvider ?? throw new ArgumentNullException(nameof(secretProvider)); + _cacheConfiguration = cacheConfiguration ?? throw new ArgumentNullException(nameof(cacheConfiguration)); + + if (_cacheConfiguration.Duration < TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException(nameof(cacheConfiguration), cacheConfiguration.Duration, "Requires a positive time duration in the cache configuration in which the caching should take place"); + } + + MemoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache)); CacheEntry = new MemoryCacheEntryOptions() // Keep in cache for this time, reset time if accessed. @@ -93,8 +91,11 @@ public CachedSecretProvider(ISecretProvider secretProvider) : /// The secret was not found, using the given name public Task GetRawSecretAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); - + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } + return GetRawSecretAsync(secretName, ignoreCache: false); } @@ -108,7 +109,10 @@ public Task GetRawSecretAsync(string secretName) /// The secret was not found, using the given name public Task GetSecretAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } return GetSecretAsync(secretName, ignoreCache: false); } @@ -124,7 +128,10 @@ public Task GetSecretAsync(string secretName) /// The secret was not found, using the given name public async Task GetRawSecretAsync(string secretName, bool ignoreCache) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } Secret secret = await GetSecretAsync(secretName, ignoreCache); return secret?.Value; @@ -141,7 +148,10 @@ public async Task GetRawSecretAsync(string secretName, bool ignoreCache) /// The secret was not found, using the given name public async Task GetSecretAsync(string secretName, bool ignoreCache) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } if (TryGetValueFromCache(secretName, ignoreCache, out Secret[] cachedSecret)) { @@ -177,8 +187,15 @@ private bool TryGetValueFromCache(string secretName, bool ignoreCache, out Secre /// Thrown when no secret was not found, using the given . public async Task> GetRawSecretsAsync(string secretName, int amountOfVersions) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the versioned secrets"); - Guard.NotLessThan(amountOfVersions, 1, nameof(amountOfVersions), "Requires at least 1 secret version to look up the versioned secrets"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } + + if (amountOfVersions < 1) + { + throw new ArgumentOutOfRangeException(nameof(amountOfVersions), amountOfVersions, "Requires at least 1 secret version to look up the versioned secrets"); + } IEnumerable secrets = await GetSecretsAsync(secretName, amountOfVersions); return secrets?.Select(secret => secret?.Value).ToArray(); @@ -194,8 +211,15 @@ public async Task> GetRawSecretsAsync(string secretName, int /// Thrown when no secret was not found, using the given . public async Task> GetSecretsAsync(string secretName, int amountOfVersions) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the versioned secrets"); - Guard.NotLessThan(amountOfVersions, 1, nameof(amountOfVersions), "Requires at least 1 secret version to look up the versioned secrets"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } + + if (amountOfVersions < 1) + { + throw new ArgumentOutOfRangeException(nameof(amountOfVersions), amountOfVersions, "Requires at least 1 secret version to look up the versioned secrets"); + } if (_secretProvider is IVersionedSecretProvider versionProvider) { @@ -224,7 +248,10 @@ public async Task> GetSecretsAsync(string secretName, int am /// The name of the secret that should be removed from the cache. public Task InvalidateSecretAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to invalidate the cached secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to invalidate the secret", nameof(secretName)); + } MemoryCache.Remove(secretName); return Task.CompletedTask; @@ -239,7 +266,10 @@ public Task InvalidateSecretAsync(string secretName) /// Thrown when the secret was not found, using the given name. public string GetRawSecret(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } Secret secret = GetSecret(secretName); return secret?.Value; @@ -254,7 +284,10 @@ public string GetRawSecret(string secretName) /// Thrown when the secret was not found, using the given name. public Secret GetSecret(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } if (TryGetValueFromCache(secretName, ignoreCache: false, out Secret[] cachedSecrets)) { diff --git a/src/Arcus.Security.Core/CompositeSecretProvider.cs b/src/Arcus.Security.Core/CompositeSecretProvider.cs index 103e8627..497d0b5b 100644 --- a/src/Arcus.Security.Core/CompositeSecretProvider.cs +++ b/src/Arcus.Security.Core/CompositeSecretProvider.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using Arcus.Security.Core.Caching; using Arcus.Security.Core.Caching.Configuration; -using GuardNet; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -17,8 +16,8 @@ namespace Arcus.Security.Core /// internal class CompositeSecretProvider : ICachedSecretProvider, IVersionedSecretProvider, ISecretStore, ISyncSecretProvider { - private readonly IEnumerable _secretProviders; - private readonly IEnumerable _criticalExceptionFilters; + private readonly SecretStoreSource[] _secretProviders; + private readonly CriticalExceptionFilter[] _criticalExceptionFilters; private readonly SecretStoreAuditingOptions _auditingOptions; private readonly IDictionary> _groupedSecretStores; private readonly ILogger _logger; @@ -38,20 +37,36 @@ public CompositeSecretProvider( SecretStoreAuditingOptions auditingOptions, ILogger logger) { - Guard.NotNull(secretProviderSources, nameof(secretProviderSources), "Requires a series of registered secret provider registrations to retrieve secrets"); - Guard.NotNull(criticalExceptionFilters, nameof(criticalExceptionFilters), "Requires a series of registered critical exception filters to determine if a thrown exception is critical"); - Guard.NotNull(auditingOptions, nameof(auditingOptions), "Requires a set of options to configure the auditing of the secret store"); - Guard.For(() => secretProviderSources.Any(source => source is null), new ArgumentException("Requires all registered secret provider registrations to be not 'null'", nameof(secretProviderSources))); - Guard.For(() => criticalExceptionFilters.Any(filter => filter is null), new ArgumentException("Requires all registered critical exception filters to be not 'null'", nameof(criticalExceptionFilters))); - - _secretProviders = secretProviderSources; - _criticalExceptionFilters = criticalExceptionFilters; - _auditingOptions = auditingOptions; + if (secretProviderSources is null) + { + throw new ArgumentNullException(nameof(secretProviderSources)); + } + + if (criticalExceptionFilters is null) + { + throw new InvalidOperationException(nameof(criticalExceptionFilters)); + } + + SecretStoreSource[] sourcesArr = secretProviderSources.ToArray(); + CriticalExceptionFilter[] filtersArr = criticalExceptionFilters.ToArray(); + if (sourcesArr.Any(s => s is null)) + { + throw new ArgumentException("One or more secret sources are 'null'", nameof(secretProviderSources)); + } + + if (filtersArr.Any(f => f is null)) + { + throw new ArgumentException("One or more exception filters are 'null'", nameof(criticalExceptionFilters)); + } + + _secretProviders = sourcesArr; + _criticalExceptionFilters = filtersArr; + _auditingOptions = auditingOptions ?? new SecretStoreAuditingOptions(); _logger = logger ?? NullLogger.Instance; - _groupedSecretStores = CreateGroupedSecretProviders(secretProviderSources, criticalExceptionFilters, auditingOptions, logger); - HasCachedSecretProviders = _secretProviders.Any(provider => provider.CachedSecretProvider != null); - HasSyncSecretProviders = _secretProviders.Any(provider => provider.SyncSecretProvider != null); + _groupedSecretStores = CreateGroupedSecretProviders(sourcesArr, filtersArr, auditingOptions, logger); + HasCachedSecretProviders = sourcesArr.Any(provider => provider.CachedSecretProvider != null); + HasSyncSecretProviders = sourcesArr.Any(provider => provider.SyncSecretProvider != null); } /// @@ -106,7 +121,10 @@ public CompositeSecretProvider( /// Thrown when multiple were registered with the same name. public TSecretProvider GetProvider(string name) where TSecretProvider : ISecretProvider { - Guard.NotNullOrWhitespace(name, nameof(name), "Requires a non-blank name to retrieve the registered named secret provider"); + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentException("Requires a non-blank name to retrieve the registered named secret provider", nameof(name)); + } ISecretProvider provider = GetProvider(name); if (provider is TSecretProvider concreteProvider) @@ -134,7 +152,10 @@ public TSecretProvider GetProvider(string name) where TSecretPr /// Thrown when there was no found in the secret store with the given . public ISecretProvider GetProvider(string name) { - Guard.NotNullOrWhitespace(name, nameof(name), "Requires a non-blank name to retrieve the registered named secret provider"); + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentException("Requires a non-blank name to retrieve the registered named secret provider", nameof(name)); + } ISecretProvider subset = GetSingleOrSubsetSecretProvider(name); return subset; @@ -155,10 +176,16 @@ public ISecretProvider GetProvider(string name) /// Thrown when multiple were registered with the same name. public TCachedSecretProvider GetCachedProvider(string name) where TCachedSecretProvider : ICachedSecretProvider { - Guard.NotNullOrWhitespace(name, nameof(name), "Requires a non-blank name to retrieve the registered named secret provider"); - Guard.For( - () => !HasCachedSecretProviders, - $"Cannot use cached secret store operation because none of the secret providers in the secret store were registered as cached secret providers ({nameof(ICachedSecretProvider)})"); + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentException("Requires a non-blank name to retrieve the registered named secret provider", nameof(name)); + } + + if (!HasCachedSecretProviders) + { + throw new NotSupportedException( + $"Cannot use cached secret store operation because none of the secret providers in the secret store were registered as cached secret providers ({nameof(ICachedSecretProvider)})"); + } ICachedSecretProvider provider = GetCachedProvider(name); if (provider is TCachedSecretProvider concreteProvider) @@ -190,11 +217,17 @@ public TCachedSecretProvider GetCachedProvider(string nam /// public ICachedSecretProvider GetCachedProvider(string name) { - Guard.NotNullOrWhitespace(name, nameof(name), "Requires a non-blank name to retrieve the registered named secret provider"); - Guard.For( - () => !HasCachedSecretProviders, - $"Cannot use cached secret store operation because none of the secret providers in the secret store were registered as cached secret providers ({nameof(ICachedSecretProvider)})"); - + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentException("Requires a non-blank name to retrieve the registered named secret provider", nameof(name)); + } + + if (!HasCachedSecretProviders) + { + throw new NotSupportedException( + $"Cannot use cached secret store operation because none of the secret providers in the secret store were registered as cached secret providers ({nameof(ICachedSecretProvider)})"); + } + ISecretProvider source = GetSingleOrSubsetSecretProvider(name); if (source is ICachedSecretProvider cachedSource) { @@ -226,7 +259,10 @@ private ISecretProvider GetSingleOrSubsetSecretProvider(string name) /// Thrown when the secret was not found, using the given name. public string GetRawSecret(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } return WithSecretStore(secretName, source => { @@ -250,7 +286,10 @@ public string GetRawSecret(string secretName) /// Thrown when the secret was not found, using the given name. public Secret GetSecret(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } return WithSecretStore(secretName, source => { @@ -273,7 +312,10 @@ public Secret GetSecret(string secretName) /// Thrown when no secret was not found, using the given . internal async Task> GetSecretsAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } IEnumerable secretValues = await WithSecretStoreAsync(secretName, async source => @@ -309,7 +351,10 @@ await WithSecretStoreAsync(secretName, async source => /// Thrown when no secret was not found, using the given . internal async Task> GetRawSecretsAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } IEnumerable secretValues = await WithSecretStoreAsync(secretName, async source => @@ -347,8 +392,15 @@ await WithSecretStoreAsync(secretName, async source => /// Thrown when no secret was not found, using the given . public async Task> GetRawSecretsAsync(string secretName, int amountOfVersions) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); - Guard.NotLessThan(amountOfVersions, 1, nameof(amountOfVersions), "Requires at least 1 secret version to retrieve the secret in the secret store"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } + + if (amountOfVersions < 1) + { + throw new ArgumentOutOfRangeException(nameof(amountOfVersions), amountOfVersions, "Requires at least 1 secret version to retrieve the secret in the secret store"); + } IEnumerable secretValues = await WithSecretStoreAsync(secretName, async source => @@ -381,8 +433,15 @@ await WithSecretStoreAsync(secretName, async source => /// Thrown when no secret was not found, using the given . public async Task> GetSecretsAsync(string secretName, int amountOfVersions) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); - Guard.NotLessThan(amountOfVersions, 1, nameof(amountOfVersions), "Requires at least 1 secret version to retrieve the secret in the secret store"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } + + if (amountOfVersions < 1) + { + throw new ArgumentOutOfRangeException(nameof(amountOfVersions), amountOfVersions, "Requires at least 1 secret version to retrieve the secret in the secret store"); + } IEnumerable secretValues = await WithSecretStoreAsync(secretName, async source => @@ -415,7 +474,10 @@ await WithSecretStoreAsync(secretName, async source => /// The secret was not found, using the given name public async Task GetRawSecretAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } string secretValue = await WithSecretStoreAsync( secretName, source => source.SecretProvider.GetRawSecretAsync(secretName)); @@ -433,7 +495,10 @@ public async Task GetRawSecretAsync(string secretName) /// The secret was not found, using the given name public async Task GetSecretAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } Secret secret = await WithSecretStoreAsync( secretName, source => source.SecretProvider.GetSecretAsync(secretName)); @@ -453,7 +518,10 @@ public async Task GetSecretAsync(string secretName) /// Thrown when none of the registered secret providers are registered as instances. public async Task GetRawSecretAsync(string secretName, bool ignoreCache) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } string secretValue = await WithCachedSecretStoreAsync( secretName, source => source.CachedSecretProvider.GetRawSecretAsync(secretName, ignoreCache)); @@ -473,7 +541,10 @@ public async Task GetRawSecretAsync(string secretName, bool ignoreCache) /// Thrown when none of the registered secret providers are registered as instances. public async Task GetSecretAsync(string secretName, bool ignoreCache) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } Secret secret = await WithCachedSecretStoreAsync( secretName, source => source.CachedSecretProvider.GetSecretAsync(secretName, ignoreCache)); @@ -488,7 +559,10 @@ public async Task GetSecretAsync(string secretName, bool ignoreCache) /// The name of the secret that should be removed from the cache. public async Task InvalidateSecretAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to look up the secret"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to look up the secret", nameof(secretName)); + } await WithCachedSecretStoreAsync(secretName, async source => { @@ -508,10 +582,11 @@ private async Task WithCachedSecretStoreAsync( Func> callRegisteredProvider, string eventName = "Get Secret") where T : class { - Guard.For( - () => !HasCachedSecretProviders, - $"Cannot use cached secret store operation because none of the secret providers in the secret store were registered as cached secret providers ({nameof(ICachedSecretProvider)})"); - + if (!HasCachedSecretProviders) + { + throw new NotSupportedException( + $"Cannot use cached secret store operation because none of the secret providers in the secret store were registered as cached secret providers ({nameof(ICachedSecretProvider)})"); + } return await WithSecretStoreAsync(secretName, async source => { if (source.CachedSecretProvider is null) @@ -569,9 +644,11 @@ private T WithSecretStore( Func callRegisteredProvider, string eventName = "Get Secret") where T : class { - Guard.For( - () => !HasSyncSecretProviders, - $"Cannot use synchronous secret store operation because none of the secret providers in the secret store were registered as synchronous secret providers ({nameof(ISyncSecretProvider)})"); + if (!HasSyncSecretProviders) + { + throw new NotSupportedException( + $"Cannot use synchronous secret store operation because none of the secret providers in the secret store were registered as synchronous secret providers ({nameof(ISyncSecretProvider)})"); + } var criticalExceptions = new Collection(); foreach (SecretStoreSource source in _secretProviders) @@ -656,7 +733,7 @@ private void LogSecurityEvent(SecretStoreSource source, string secretName, strin } } - private void LogPossibleCriticalExceptions(string secretName, IEnumerable criticalExceptions) + private void LogPossibleCriticalExceptions(string secretName, IReadOnlyCollection criticalExceptions) { if (criticalExceptions.Any()) { @@ -687,7 +764,7 @@ private bool IsCriticalException(Exception exceptionCandidate) }); } - private Exception DetermineSecretStoreException(string secretName, IEnumerable criticalExceptions) + private Exception DetermineSecretStoreException(string secretName, IReadOnlyCollection criticalExceptions) { if (!criticalExceptions.Any()) { diff --git a/src/Arcus.Security.Core/CriticalExceptionFilter.cs b/src/Arcus.Security.Core/CriticalExceptionFilter.cs index 2b8d7f0c..f872c3d5 100644 --- a/src/Arcus.Security.Core/CriticalExceptionFilter.cs +++ b/src/Arcus.Security.Core/CriticalExceptionFilter.cs @@ -1,5 +1,4 @@ using System; -using GuardNet; namespace Arcus.Security.Core { @@ -20,9 +19,16 @@ public class CriticalExceptionFilter /// Thrown when the or the is null. public CriticalExceptionFilter(Type exceptionType, Func exceptionFilter) { - Guard.NotNull(exceptionType, nameof(exceptionType), "Requires an exception type to create an critical exception filter"); - Guard.NotNull(exceptionFilter, nameof(exceptionFilter), "Requires an exception filter to determine whether an exception is considered critical"); - + if (exceptionType is null) + { + throw new ArgumentNullException(nameof(exceptionType)); + } + + if (exceptionFilter is null) + { + throw new ArgumentNullException(nameof(exceptionFilter)); + } + _exceptionFilter = exceptionFilter; ExceptionType = exceptionType; } @@ -42,7 +48,11 @@ public CriticalExceptionFilter(Type exceptionType, Func excepti /// Thrown when the is null. public bool IsCritical(Exception exception) { - Guard.NotNull(exception, nameof(exception), "Requires an exception instance to determine if it's considered a critical one"); + if (exception is null) + { + throw new ArgumentNullException(nameof(exception)); + } + return _exceptionFilter(exception); } } diff --git a/src/Arcus.Security.Core/Secret.cs b/src/Arcus.Security.Core/Secret.cs index e975f430..51d490ef 100644 --- a/src/Arcus.Security.Core/Secret.cs +++ b/src/Arcus.Security.Core/Secret.cs @@ -15,12 +15,9 @@ public class Secret /// The version of the secret. /// The expiration date of the secret. /// The cannot be null. - /// The cannot be null. public Secret(string value, string version = null, DateTimeOffset? expirationDate = null) { - Guard.NotNull(value, nameof(value)); - - Value = value; + Value = value ?? throw new ArgumentNullException(nameof(value)); Version = version; Expires = expirationDate; } diff --git a/src/Arcus.Security.Core/SecretNotFoundException.cs b/src/Arcus.Security.Core/SecretNotFoundException.cs index 841f3a01..dd4e16ef 100644 --- a/src/Arcus.Security.Core/SecretNotFoundException.cs +++ b/src/Arcus.Security.Core/SecretNotFoundException.cs @@ -1,5 +1,4 @@ using System; -using GuardNet; namespace Arcus.Security.Core { @@ -34,7 +33,11 @@ public SecretNotFoundException(string name) : this(name, null) /// The name must not be null. public SecretNotFoundException(string name, Exception innerException) : base($"The secret {name} was not found.", innerException) { - Guard.NotNullOrEmpty(name, nameof(name)); + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentException("Requires a non-blank secret name", nameof(name)); + } + Name = name; } diff --git a/src/Arcus.Security.Core/SecretProviderOptions.cs b/src/Arcus.Security.Core/SecretProviderOptions.cs index 40eec589..e9d0e094 100644 --- a/src/Arcus.Security.Core/SecretProviderOptions.cs +++ b/src/Arcus.Security.Core/SecretProviderOptions.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using GuardNet; -using Microsoft.Extensions.Hosting; namespace Arcus.Security.Core { @@ -28,10 +26,11 @@ public string Name get => _name; set { - Guard.For( - () => value != null && String.IsNullOrWhiteSpace(value), - "Requires a non-blank value for the name of the secret provider to be registered in the secret store"); - + if (value != null && string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException("Requires a non-blank value for the name of the secret provider to be registered in the secret store", nameof(value)); + } + _name = value; } } @@ -46,8 +45,15 @@ public string Name /// Thrown when the is less than zero. public void AddVersionedSecret(string secretName, int allowedVersions) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to make the secret a versioned secret in the secret store"); - Guard.NotLessThan(allowedVersions, 1, nameof(allowedVersions), "Requires at least 1 secret version to make the secret a versioned secret in the secret store"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to make the secret a versioned secret in the secret store", nameof(secretName)); + } + + if (allowedVersions < 1) + { + throw new ArgumentOutOfRangeException(nameof(allowedVersions), allowedVersions, "Requires at least 1 secret version to make the secret a versioned secret in the secret store"); + } _versionedSecretNames[secretName] = allowedVersions; } @@ -63,7 +69,11 @@ public void AddVersionedSecret(string secretName, int allowedVersions) /// Thrown when the is blank. internal bool TryGetAllowedSecretVersions(string secretName, out int allowedVersions) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to retrieve a versioned secret in the secret store"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to make the secret a versioned secret in the secret store", nameof(secretName)); + } + return _versionedSecretNames.TryGetValue(secretName, out allowedVersions); } } diff --git a/src/Arcus.Security.Core/SecretStoreBuilder.cs b/src/Arcus.Security.Core/SecretStoreBuilder.cs index 99b97ab3..94d064fe 100644 --- a/src/Arcus.Security.Core/SecretStoreBuilder.cs +++ b/src/Arcus.Security.Core/SecretStoreBuilder.cs @@ -4,7 +4,6 @@ using Arcus.Security.Core; using Arcus.Security.Core.Caching; using Arcus.Security.Core.Providers; -using GuardNet; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; @@ -26,8 +25,7 @@ public class SecretStoreBuilder /// Thrown when the is null. public SecretStoreBuilder(IServiceCollection services) { - Guard.NotNull(services, nameof(services), "Requires a sequence of registered services to register the secret providers for the secret store"); - Services = services; + Services = services ?? throw new ArgumentNullException(nameof(services)); } /// @@ -69,9 +67,7 @@ public SecretStoreBuilder(IServiceCollection services) /// Thrown when the is null. public SecretStoreBuilder AddProvider(ISecretProvider secretProvider) { - Guard.NotNull(secretProvider, nameof(secretProvider), "Requires a secret provider to add to the secret store"); - - return AddProvider(secretProvider, configureOptions: null); + return AddProvider(secretProvider ?? throw new ArgumentNullException(nameof(secretProvider)), configureOptions: null); } /// @@ -87,7 +83,10 @@ public SecretStoreBuilder AddProvider( ISecretProvider secretProvider, Action configureOptions) { - Guard.NotNull(secretProvider, nameof(secretProvider), "Requires a secret provider to add to the secret store"); + if (secretProvider is null) + { + throw new ArgumentNullException(nameof(secretProvider)); + } var options = new SecretProviderOptions(); configureOptions?.Invoke(options); @@ -115,9 +114,7 @@ public SecretStoreBuilder AddProvider( /// Thrown when the is null. public SecretStoreBuilder AddProvider(Func createSecretProvider) { - Guard.NotNull(createSecretProvider, nameof(createSecretProvider), "Requires a function to create a secret provider to add to the secret store"); - - return AddProvider(createSecretProvider, configureOptions: null); + return AddProvider(createSecretProvider ?? throw new ArgumentNullException(nameof(createSecretProvider)), configureOptions: null); } /// @@ -133,7 +130,10 @@ public SecretStoreBuilder AddProvider( Func createSecretProvider, Action configureOptions) { - Guard.NotNull(createSecretProvider, nameof(createSecretProvider), "Requires a function to create a secret provider to add to the secret store"); + if (createSecretProvider is null) + { + throw new ArgumentNullException(nameof(createSecretProvider)); + } var options = new SecretProviderOptions(); configureOptions?.Invoke(options); @@ -171,7 +171,10 @@ public SecretStoreBuilder AddCriticalException() where TException : /// Thrown when the is null. public SecretStoreBuilder AddCriticalException(Func exceptionFilter) where TException : Exception { - Guard.NotNull(exceptionFilter, nameof(exceptionFilter), "Requires an exception filter to select only exceptions that match a specific criteria"); + if (exceptionFilter is null) + { + throw new ArgumentNullException(nameof(exceptionFilter)); + } CriticalExceptionFilters.Add(new CriticalExceptionFilter(typeof(TException), exception => { @@ -193,9 +196,7 @@ public SecretStoreBuilder AddCriticalException(FuncThrown when the is null. public SecretStoreBuilder WithAuditing(Action configureOptions) { - Guard.NotNull(configureOptions, nameof(configureOptions), "Requires a function to configure the auditing options"); - - _configureAuditingOptions.Add(configureOptions); + _configureAuditingOptions.Add(configureOptions ?? throw new ArgumentNullException(nameof(configureOptions))); return this; } diff --git a/src/Arcus.Security.Core/SecretStoreSource.cs b/src/Arcus.Security.Core/SecretStoreSource.cs index dd524616..e3cc60a2 100644 --- a/src/Arcus.Security.Core/SecretStoreSource.cs +++ b/src/Arcus.Security.Core/SecretStoreSource.cs @@ -1,6 +1,5 @@ using System; using Arcus.Security.Core.Caching; -using GuardNet; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -27,9 +26,7 @@ public SecretStoreSource( Func createSecretProvider, SecretProviderOptions options) { - Guard.NotNull(createSecretProvider, nameof(createSecretProvider), "Requires a function to create an secret provider instance to register it in the secret store"); - - _createSecretProvider = createSecretProvider; + _createSecretProvider = createSecretProvider ?? throw new ArgumentNullException(nameof(createSecretProvider)); Options = options ?? new SecretProviderOptions(); } @@ -42,9 +39,7 @@ public SecretStoreSource( /// Thrown when the is null. public SecretStoreSource(ISecretProvider secretProvider, SecretProviderOptions options) { - Guard.NotNull(secretProvider, nameof(secretProvider), "Requires a secret provider instance to register it in the secret store"); - - AssignSecretProvider(secretProvider); + AssignSecretProvider(secretProvider ?? throw new ArgumentNullException(nameof(secretProvider))); Options = options ?? new SecretProviderOptions(); } @@ -98,8 +93,10 @@ public ISecretProvider SecretProvider /// Thrown when the is null. public void EnsureSecretProviderCreated(IServiceProvider serviceProvider) { - Guard.NotNull(serviceProvider, nameof(serviceProvider), - $"Requires an instance to provide the registered services to create the {nameof(ISecretProvider)} and possible {nameof(ICachedSecretProvider)}"); + if (serviceProvider is null) + { + throw new ArgumentNullException(nameof(serviceProvider)); + } if (_secretProvider is null) { diff --git a/src/Arcus.Security.Providers.AzureKeyVault/Configuration/ArcusConfigurationProvider.cs b/src/Arcus.Security.Providers.AzureKeyVault/Configuration/ArcusConfigurationProvider.cs index 4b0a7b0d..35a5ce7f 100644 --- a/src/Arcus.Security.Providers.AzureKeyVault/Configuration/ArcusConfigurationProvider.cs +++ b/src/Arcus.Security.Providers.AzureKeyVault/Configuration/ArcusConfigurationProvider.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Arcus.Security.Core; using Microsoft.Extensions.Configuration; using GuardNet; @@ -18,9 +19,7 @@ internal class ArcusConfigurationProvider : ConfigurationProvider /// The provider to retrieve secret values for configuration tokens. internal ArcusConfigurationProvider(ISecretProvider secretProvider) { - Guard.NotNull(secretProvider, nameof(secretProvider), $"Requires a {nameof(ISecretProvider)} instance"); - - _secretProvider = secretProvider; + _secretProvider = secretProvider ?? throw new ArgumentNullException(nameof(secretProvider)); } /// diff --git a/src/Arcus.Security.Providers.AzureKeyVault/Configuration/KeyVaultConfiguration.cs b/src/Arcus.Security.Providers.AzureKeyVault/Configuration/KeyVaultConfiguration.cs index fbcdca88..abff7573 100644 --- a/src/Arcus.Security.Providers.AzureKeyVault/Configuration/KeyVaultConfiguration.cs +++ b/src/Arcus.Security.Providers.AzureKeyVault/Configuration/KeyVaultConfiguration.cs @@ -1,6 +1,4 @@ using System; -using System.Text.RegularExpressions; -using GuardNet; namespace Arcus.Security.Providers.AzureKeyVault.Configuration { @@ -9,10 +7,6 @@ namespace Arcus.Security.Providers.AzureKeyVault.Configuration /// public class KeyVaultConfiguration : IKeyVaultConfiguration { - private const string VaultUriPattern = "^https:\\/\\/[0-9a-zA-Z\\-]{3,24}\\.vault.azure.net(\\/)?$"; - - private readonly Regex _vaultUriRegex = new Regex(VaultUriPattern, RegexOptions.Compiled); - /// /// The Uri of the Azure Key Vault you want to connect to. /// @@ -27,15 +21,7 @@ public class KeyVaultConfiguration : IKeyVaultConfiguration /// Thrown when the is not using https. public KeyVaultConfiguration(Uri vaultUri) { - Guard.NotNull(vaultUri, nameof(vaultUri)); - Guard.For( - () => vaultUri.Scheme != Uri.UriSchemeHttps, - "Requires the vault URI to have a 'https' scheme"); - Guard.For( - () => !_vaultUriRegex.IsMatch(vaultUri.ToString()), - "Requires the Azure Key Vault host to be in the right format, see https://docs.microsoft.com/en-us/azure/key-vault/general/about-keys-secrets-certificates#objects-identifiers-and-versioning"); - - VaultUri = vaultUri; + VaultUri = vaultUri ?? throw new ArgumentNullException(nameof(vaultUri)); } /// diff --git a/src/Arcus.Security.Providers.AzureKeyVault/Extensions/SecretStoreBuilderExtensions.cs b/src/Arcus.Security.Providers.AzureKeyVault/Extensions/SecretStoreBuilderExtensions.cs index 05394bf8..137ea038 100644 --- a/src/Arcus.Security.Providers.AzureKeyVault/Extensions/SecretStoreBuilderExtensions.cs +++ b/src/Arcus.Security.Providers.AzureKeyVault/Extensions/SecretStoreBuilderExtensions.cs @@ -7,7 +7,6 @@ using Azure; using Azure.Core; using Azure.Identity; -using GuardNet; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -36,12 +35,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithCertificate( string clientId, X509Certificate2 certificate) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(tenantId, nameof(tenantId), "Requires a non-blank tenant ID of the directory where the client or application is located"); - Guard.NotNullOrWhitespace(clientId, nameof(clientId), "Requires a non-blank client ID of the application requesting the authentication token that has read permissions on the Azure Key Vault to add a secret provider to the secret store"); - Guard.NotNull(certificate, nameof(certificate), "Requires a certificate that is being used as credential on the Azure Key Vault to add the secret provider to the secret store"); - return AddAzureKeyVaultWithCertificate( builder, rawVaultUri, @@ -72,12 +65,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithCertificate( X509Certificate2 certificate, ICacheConfiguration cacheConfiguration) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(tenantId, nameof(tenantId), "Requires a non-blank tenant ID of the directory where the client or application is located"); - Guard.NotNullOrWhitespace(clientId, nameof(clientId), "Requires a non-blank client ID of the application requesting the authentication token that has read permissions on the Azure Key Vault to add a secret provider to the secret store"); - Guard.NotNull(certificate, nameof(certificate), "Requires a certificate that is being used as credential on the Azure Key Vault to add the secret provider to the secret store"); - return AddAzureKeyVaultWithCertificate( builder, rawVaultUri, @@ -117,12 +104,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithCertificate( string name, Func mutateSecretName) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(tenantId, nameof(tenantId), "Requires a non-blank tenant ID of the directory where the client or application is located"); - Guard.NotNullOrWhitespace(clientId, nameof(clientId), "Requires a non-blank client ID of the application requesting the authentication token that has read permissions on the Azure Key Vault to add a secret provider to the secret store"); - Guard.NotNull(certificate, nameof(certificate), "Requires a certificate that is being used as credential on the Azure Key Vault to add the secret provider to the secret store"); - return AddAzureKeyVaultWithCertificate( builder, rawVaultUri, @@ -163,12 +144,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithCertificate( Action configureOptions, Action configureProviderOptions) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(tenantId, nameof(tenantId), "Requires a non-blank tenant ID of the directory where the client or application is located"); - Guard.NotNullOrWhitespace(clientId, nameof(clientId), "Requires a non-blank client ID of the application requesting the authentication token that has read permissions on the Azure Key Vault to add a secret provider to the secret store"); - Guard.NotNull(certificate, nameof(certificate), "Requires a certificate that is being used as credential on the Azure Key Vault to add the secret provider to the secret store"); - return AddAzureKeyVault( builder, new ClientCertificateCredential(tenantId, clientId, certificate), @@ -189,9 +164,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity( this SecretStoreBuilder builder, string rawVaultUri) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - return AddAzureKeyVaultWithManagedIdentity( builder, rawVaultUri, @@ -214,9 +186,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity( string rawVaultUri, string clientId) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - return AddAzureKeyVaultWithManagedIdentity( builder, rawVaultUri, @@ -240,9 +209,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity( string rawVaultUri, ICacheConfiguration cacheConfiguration) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - return AddAzureKeyVaultWithManagedIdentity( builder, rawVaultUri, @@ -267,9 +233,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity( ICacheConfiguration cacheConfiguration, string clientId) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - return AddAzureKeyVaultWithManagedIdentity( builder, rawVaultUri, @@ -299,9 +262,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity( string name, Func mutateSecretName) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - return AddAzureKeyVaultWithManagedIdentity( builder, rawVaultUri, @@ -335,9 +295,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity( string name, Func mutateSecretName) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - return AddAzureKeyVaultWithManagedIdentity( builder, rawVaultUri, @@ -372,9 +329,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithManagedIdentity( Action configureOptions, Action configureProviderOptions) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - return AddAzureKeyVault( builder, new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = clientId }), @@ -401,12 +355,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithServicePrincipal( string clientId, string clientKey) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(tenantId, nameof(tenantId), "Requires a non-blank tenant ID of the directory where the Service Principal is located"); - Guard.NotNullOrWhitespace(clientId, nameof(clientId), "Requires a non-blank client ID of the Service Principal that has permissions to read the secrets in the Azure Key Vault to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(clientKey, nameof(clientKey), "Requires a non-blank client access key of the Service Principal that has permissions to read the secrets in the Azure Key Vault to add to the secret provider to the secret store"); - return AddAzureKeyVaultWithServicePrincipal( builder, rawVaultUri, @@ -437,12 +385,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithServicePrincipal( string clientKey, ICacheConfiguration cacheConfiguration) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(tenantId, nameof(tenantId), "Requires a non-blank tenant ID of the directory where the Service Principal is located"); - Guard.NotNullOrWhitespace(clientId, nameof(clientId), "Requires a non-blank client ID of the Service Principal that has permissions to read the secrets in the Azure Key Vault to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(clientKey, nameof(clientKey), "Requires a non-blank client access key of the Service Principal that has permissions to read the secrets in the Azure Key Vault to add to the secret provider to the secret store"); - return AddAzureKeyVaultWithServicePrincipal( builder, rawVaultUri, @@ -484,12 +426,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithServicePrincipal( string name, Func mutateSecretName) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(tenantId, nameof(tenantId), "Requires a non-blank tenant ID of the directory where the Service Principal is located"); - Guard.NotNullOrWhitespace(clientId, nameof(clientId), "Requires a non-blank client ID of the Service Principal that has permissions to read the secrets in the Azure Key Vault to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(clientKey, nameof(clientKey), "Requires a non-blank client access key of the Service Principal that has permissions to read the secrets in the Azure Key Vault to add to the secret provider to the secret store"); - return AddAzureKeyVaultWithServicePrincipal( builder, rawVaultUri, @@ -532,12 +468,6 @@ public static SecretStoreBuilder AddAzureKeyVaultWithServicePrincipal( Action configureOptions, Action configureProviderOptions) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNullOrWhitespace(rawVaultUri, nameof(rawVaultUri), "Requires a non-blank URI of the Azure Key Vault instance to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(tenantId, nameof(tenantId), "Requires a non-blank tenant ID of the directory where the Service Principal is located"); - Guard.NotNullOrWhitespace(clientId, nameof(clientId), "Requires a non-blank client ID of the Service Principal that has permissions to read the secrets in the Azure Key Vault to add the secret provider to the secret store"); - Guard.NotNullOrWhitespace(clientKey, nameof(clientKey), "Requires a non-blank client access key of the Service Principal that has permissions to read the secrets in the Azure Key Vault to add to the secret provider to the secret store"); - return AddAzureKeyVault( builder, new ClientSecretCredential(tenantId, clientId, clientKey), @@ -561,10 +491,6 @@ public static SecretStoreBuilder AddAzureKeyVault( IKeyVaultConfiguration configuration, ICacheConfiguration cacheConfiguration) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNull(tokenCredential, nameof(tokenCredential), "Requires an Azure Key Vault authentication instance to add the secret provider to the secret store"); - Guard.NotNull(configuration, nameof(configuration), "Requires an Azure Key Vault configuration instance to add the secret provider to the secret store"); - return AddAzureKeyVault( builder, tokenCredential, @@ -587,10 +513,6 @@ public static SecretStoreBuilder AddAzureKeyVault( TokenCredential tokenCredential, IKeyVaultConfiguration configuration) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNull(tokenCredential, nameof(tokenCredential), "Requires an Azure Key Vault authentication instance to add the secret provider to the secret store"); - Guard.NotNull(configuration, nameof(configuration), "Requires an Azure Key Vault configuration instance to add the secret provider to the secret store"); - return AddAzureKeyVault( builder, tokenCredential, @@ -618,10 +540,6 @@ public static SecretStoreBuilder AddAzureKeyVault( string name, Func mutateSecretName) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNull(tokenCredential, nameof(tokenCredential), "Requires an Azure Key Vault authentication instance to add the secret provider to the secret store"); - Guard.NotNull(configuration, nameof(configuration), "Requires an Azure Key Vault configuration instance to add the secret provider to the secret store"); - return AddAzureKeyVault( builder, tokenCredential, @@ -653,9 +571,20 @@ public static SecretStoreBuilder AddAzureKeyVault( Action configureOptions, Action configureProviderOptions) { - Guard.NotNull(builder, nameof(builder), "Requires a secret store builder to add the Azure Key Vault secret provider"); - Guard.NotNull(tokenCredential, nameof(tokenCredential), "Requires an Azure Key Vault authentication instance to add the secret provider to the secret store"); - Guard.NotNull(configuration, nameof(configuration), "Requires an Azure Key Vault configuration instance to add the secret provider to the secret store"); + if (builder is null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (tokenCredential is null) + { + throw new ArgumentNullException(nameof(tokenCredential)); + } + + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } // Thrown during failure with Key Vault authorization. builder.AddCriticalException(exception => diff --git a/src/Arcus.Security.Providers.AzureKeyVault/KeyVaultCachedSecretProvider.cs b/src/Arcus.Security.Providers.AzureKeyVault/KeyVaultCachedSecretProvider.cs index 4a759381..0f057a74 100644 --- a/src/Arcus.Security.Providers.AzureKeyVault/KeyVaultCachedSecretProvider.cs +++ b/src/Arcus.Security.Providers.AzureKeyVault/KeyVaultCachedSecretProvider.cs @@ -3,7 +3,6 @@ using Arcus.Security.Core; using Arcus.Security.Core.Caching; using Arcus.Security.Core.Caching.Configuration; -using GuardNet; using Microsoft.Extensions.Caching.Memory; namespace Arcus.Security.Providers.AzureKeyVault @@ -27,11 +26,7 @@ public class KeyVaultCachedSecretProvider : CachedSecretProvider public KeyVaultCachedSecretProvider(KeyVaultSecretProvider secretProvider, ICacheConfiguration cacheConfiguration, IMemoryCache memoryCache) : base(secretProvider, cacheConfiguration, memoryCache) { - Guard.NotNull(secretProvider, nameof(secretProvider), "Requires an Azure Key Vault secret provider to provide additional caching operations"); - Guard.NotNull(cacheConfiguration, nameof(cacheConfiguration), "Requires a custom caching configuration instance for the cached Azure Key Vault secret provider"); - Guard.NotNull(memoryCache, nameof(memoryCache), "Requires a custom memory cache implementation to store the Azure Key Vault secrets in memory"); - - _secretProvider = secretProvider; + _secretProvider = secretProvider ?? throw new ArgumentNullException(nameof(secretProvider)); } /// @@ -44,9 +39,7 @@ public KeyVaultCachedSecretProvider(KeyVaultSecretProvider secretProvider, ICach public KeyVaultCachedSecretProvider(KeyVaultSecretProvider secretProvider, ICacheConfiguration cacheConfiguration) : base(secretProvider, cacheConfiguration) { - Guard.NotNull(secretProvider, nameof(secretProvider), "Requires an Azure Key Vault secret provider to provide additional caching operations"); - Guard.NotNull(cacheConfiguration, nameof(cacheConfiguration), "Requires a custom caching configuration instance for the cached Azure Key Vault secret provider"); - _secretProvider = secretProvider; + _secretProvider = secretProvider ?? throw new ArgumentNullException(nameof(secretProvider)); } /// @@ -57,8 +50,7 @@ public KeyVaultCachedSecretProvider(KeyVaultSecretProvider secretProvider, ICach /// Thrown when the is null. public KeyVaultCachedSecretProvider(KeyVaultSecretProvider secretProvider) : base(secretProvider) { - Guard.NotNull(secretProvider, nameof(secretProvider), "Requires an Azure Key Vault secret provider to provide additional caching operations"); - _secretProvider = secretProvider; + _secretProvider = secretProvider ?? throw new ArgumentNullException(nameof(secretProvider)); } /// @@ -71,8 +63,15 @@ public KeyVaultCachedSecretProvider(KeyVaultSecretProvider secretProvider) : bas /// Thrown when the secret was not found, using the given . public virtual async Task StoreSecretAsync(string secretName, string secretValue) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to request a secret in Azure Key Vault"); - Guard.NotNullOrWhitespace(secretValue, nameof(secretValue), "Requires a non-blank secret value to store a secret in Azure Key Vault"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to store a secret in Azure Key Vault", nameof(secretName)); + } + + if (string.IsNullOrWhiteSpace(secretValue)) + { + throw new ArgumentException("Requires a non-blank secret value to store a secret in Azure Key Vault", nameof(secretName)); + } Secret secret = await _secretProvider.StoreSecretAsync(secretName, secretValue); MemoryCache.Set(secretName, new [] { secret }, CacheEntry); diff --git a/src/Arcus.Security.Providers.AzureKeyVault/KeyVaultSecretProvider.cs b/src/Arcus.Security.Providers.AzureKeyVault/KeyVaultSecretProvider.cs index b119a654..87b0d20c 100644 --- a/src/Arcus.Security.Providers.AzureKeyVault/KeyVaultSecretProvider.cs +++ b/src/Arcus.Security.Providers.AzureKeyVault/KeyVaultSecretProvider.cs @@ -9,7 +9,6 @@ using Azure; using Azure.Core; using Azure.Security.KeyVault.Secrets; -using GuardNet; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Polly; @@ -49,8 +48,15 @@ public KeyVaultSecretProvider(TokenCredential tokenCredential, IKeyVaultConfigur /// The cannot be null. public KeyVaultSecretProvider(TokenCredential tokenCredential, IKeyVaultConfiguration vaultConfiguration, KeyVaultOptions options, ILogger logger) { - Guard.NotNull(vaultConfiguration, nameof(vaultConfiguration), "Requires a Azure Key Vault configuration to setup the secret provider"); - Guard.NotNull(tokenCredential, nameof(tokenCredential), "Requires an Azure Key Vault authentication instance to authenticate with the vault"); + if (vaultConfiguration is null) + { + throw new ArgumentNullException(nameof(vaultConfiguration)); + } + + if (tokenCredential is null) + { + throw new ArgumentNullException(nameof(tokenCredential)); + } VaultUri = $"{vaultConfiguration.VaultUri.Scheme}://{vaultConfiguration.VaultUri.Host}"; @@ -79,7 +85,10 @@ public KeyVaultSecretProvider(TokenCredential tokenCredential, IKeyVaultConfigur /// Thrown when the secret was not found, using the given name. public virtual string GetRawSecret(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to request a secret in Azure Key Vault"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to request a secret in Azure Key Vault", nameof(secretName)); + } Secret secret = GetSecret(secretName); return secret?.Value; @@ -94,7 +103,10 @@ public virtual string GetRawSecret(string secretName) /// Thrown when the secret was not found, using the given name. public virtual Secret GetSecret(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to request a secret in Azure Key Vault"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to request a secret in Azure Key Vault", nameof(secretName)); + } Secret secret = InteractWithKeyVault(secretName, client => client.GetSecret(secretName)); return secret; @@ -110,7 +122,10 @@ public virtual Secret GetSecret(string secretName) /// The secret was not found, using the given name public virtual async Task GetRawSecretAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to request a secret in Azure Key Vault"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to request a secret in Azure Key Vault", nameof(secretName)); + } Secret secret = await GetSecretAsync(secretName); return secret?.Value; @@ -126,7 +141,10 @@ public virtual async Task GetRawSecretAsync(string secretName) /// The secret was not found, using the given name public virtual async Task GetSecretAsync(string secretName) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to request a secret in Azure Key Vault"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to request a secret in Azure Key Vault", nameof(secretName)); + } Logger.LogTrace("Getting a secret {SecretName} from Azure Key Vault {VaultUri}...", secretName, VaultUri); Secret secret = await InteractWithKeyVaultAsync( @@ -149,8 +167,15 @@ public virtual async Task GetSecretAsync(string secretName) /// The secret was not found, using the given name public virtual async Task StoreSecretAsync(string secretName, string secretValue) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to request a secret in Azure Key Vault"); - Guard.NotNullOrWhitespace(secretValue, nameof(secretValue), "Requires a non-blank secret value to store a secret in Azure Key Vault"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to request a secret in Azure Key Vault", nameof(secretName)); + } + + if (string.IsNullOrWhiteSpace(secretValue)) + { + throw new ArgumentException("Requires a non-blank secret value to store a secret in Azure Key Vault", nameof(secretValue)); + } Logger.LogTrace("Storing secret {SecretName} from Azure Key Vault {VaultUri}...", secretName, VaultUri); Secret secret = await InteractWithKeyVaultAsync( @@ -212,8 +237,15 @@ private Secret InteractWithKeyVault( /// Thrown when no secret was not found, using the given . public virtual async Task> GetRawSecretsAsync(string secretName, int amountOfVersions) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to request a secret in Azure Key Vault"); - Guard.NotLessThan(amountOfVersions, 1, nameof(amountOfVersions), "Requires at least 1 secret version to make the secret a versioned secret in the secret store"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to request a secret in Azure Key Vault", nameof(secretName)); + } + + if (amountOfVersions < 1) + { + throw new ArgumentOutOfRangeException(nameof(amountOfVersions), amountOfVersions, "Requires at least 1 secret version to make the secret a versioned secret in the secret store"); + } IEnumerable secrets = await GetSecretsAsync(secretName, amountOfVersions); return secrets.Select(secret => secret.Value); @@ -229,8 +261,15 @@ public virtual async Task> GetRawSecretsAsync(string secretN /// Thrown when no secret was not found, using the given . public virtual async Task> GetSecretsAsync(string secretName, int amountOfVersions) { - Guard.NotNullOrWhitespace(secretName, nameof(secretName), "Requires a non-blank secret name to request a secret in Azure Key Vault"); - Guard.NotLessThan(amountOfVersions, 1, nameof(amountOfVersions), "Requires at least 1 secret version to make the secret a versioned secret in the secret store"); + if (string.IsNullOrWhiteSpace(secretName)) + { + throw new ArgumentException("Requires a non-blank secret name to request a secret in Azure Key Vault", nameof(secretName)); + } + + if (amountOfVersions < 1) + { + throw new ArgumentOutOfRangeException(nameof(amountOfVersions), amountOfVersions, "Requires at least 1 secret version to make the secret a versioned secret in the secret store"); + } string[] versions = await DetermineVersionsAsync(secretName); var secrets = new Collection(); @@ -345,7 +384,11 @@ protected SecretClient GetSecretClient() /// protected static Task> ThrottleTooManyRequestsAsync(Func>> secretOperation) { - Guard.NotNull(secretOperation, nameof(secretOperation), "Requires a function to throttle against too many requests exceptions"); + if (secretOperation is null) + { + throw new ArgumentNullException(nameof(secretOperation)); + } + return GetExponentialBackOffRetryAsyncPolicy((RequestFailedException ex) => ex.Status == 429) .ExecuteAsync(secretOperation); } @@ -394,7 +437,11 @@ private static AsyncRetryPolicy GetExponentialBackOffRetryAsyncPolicy protected static Response ThrottleTooManyRequests(Func> secretOperation) { - Guard.NotNull(secretOperation, nameof(secretOperation), "Requires a function to throttle against too many requests exceptions"); + if (secretOperation is null) + { + throw new ArgumentNullException(nameof(secretOperation)); + } + return GetExponentialBackOffRetrySyncPolicy((RequestFailedException ex) => ex.Status == 429) .Execute(secretOperation); } From bb8d16cd7093780cd6d1cc86373d8148c694abca Mon Sep 17 00:00:00 2001 From: stijnmoreels <9039753+stijnmoreels@users.noreply.github.com> Date: Tue, 17 Sep 2024 07:26:40 +0200 Subject: [PATCH 2/2] pr-fix: fix remaining expected exception types --- .../Configuration/KeyVaultConfiguration.cs | 8 ++++- .../SecretStoreBuilderExtensions.cs | 15 ++++++++ .../KeyVaultConfigurationTests.cs | 36 +++---------------- 3 files changed, 26 insertions(+), 33 deletions(-) diff --git a/src/Arcus.Security.Providers.AzureKeyVault/Configuration/KeyVaultConfiguration.cs b/src/Arcus.Security.Providers.AzureKeyVault/Configuration/KeyVaultConfiguration.cs index abff7573..1d5ba10d 100644 --- a/src/Arcus.Security.Providers.AzureKeyVault/Configuration/KeyVaultConfiguration.cs +++ b/src/Arcus.Security.Providers.AzureKeyVault/Configuration/KeyVaultConfiguration.cs @@ -29,8 +29,14 @@ public KeyVaultConfiguration(Uri vaultUri) /// /// The Uri of the Azure Key Vault you want to connect to. /// Thrown when the is not using https. - public KeyVaultConfiguration(string rawVaultUri) : this(new Uri(rawVaultUri)) + public KeyVaultConfiguration(string rawVaultUri) { + if (string.IsNullOrWhiteSpace(rawVaultUri)) + { + throw new ArgumentException("Requires a non-blank Azure Key vault URI", nameof(rawVaultUri)); + } + + VaultUri = new Uri(rawVaultUri); } } } \ No newline at end of file diff --git a/src/Arcus.Security.Providers.AzureKeyVault/Extensions/SecretStoreBuilderExtensions.cs b/src/Arcus.Security.Providers.AzureKeyVault/Extensions/SecretStoreBuilderExtensions.cs index 137ea038..30c474cf 100644 --- a/src/Arcus.Security.Providers.AzureKeyVault/Extensions/SecretStoreBuilderExtensions.cs +++ b/src/Arcus.Security.Providers.AzureKeyVault/Extensions/SecretStoreBuilderExtensions.cs @@ -144,6 +144,11 @@ public static SecretStoreBuilder AddAzureKeyVaultWithCertificate( Action configureOptions, Action configureProviderOptions) { + if (string.IsNullOrWhiteSpace(clientId)) + { + throw new ArgumentException("Requires a non-blank client ID to authenticate the Azure Key vault secret provider with a certificate", nameof(clientId)); + } + return AddAzureKeyVault( builder, new ClientCertificateCredential(tenantId, clientId, certificate), @@ -468,6 +473,16 @@ public static SecretStoreBuilder AddAzureKeyVaultWithServicePrincipal( Action configureOptions, Action configureProviderOptions) { + if (string.IsNullOrWhiteSpace(clientId)) + { + throw new ArgumentException("Requires a non-blank client ID to authenticate the Azure Key vault secret provider", nameof(clientId)); + } + + if (string.IsNullOrWhiteSpace(clientKey)) + { + throw new ArgumentException("Requires a non-blank client secret to authenticate the Azure Key vault secret provider", nameof(clientKey)); + } + return AddAzureKeyVault( builder, new ClientSecretCredential(tenantId, clientId, clientKey), diff --git a/src/Arcus.Security.Tests.Unit/KeyVault/Configuration/KeyVaultConfigurationTests.cs b/src/Arcus.Security.Tests.Unit/KeyVault/Configuration/KeyVaultConfigurationTests.cs index d63f4e2b..0d2a06f7 100644 --- a/src/Arcus.Security.Tests.Unit/KeyVault/Configuration/KeyVaultConfigurationTests.cs +++ b/src/Arcus.Security.Tests.Unit/KeyVault/Configuration/KeyVaultConfigurationTests.cs @@ -6,13 +6,6 @@ namespace Arcus.Security.Tests.Unit.KeyVault.Configuration { public class KeyVaultConfigurationTests { - [Fact] - public void Constructor_UriWithoutVaultSuffix_Fails() - { - Assert.ThrowsAny( - () => new KeyVaultConfiguration("https://something-without-azure-vault-suffix")); - } - [Fact] public void Constructor_ValidRawUri_Succeeds() { @@ -42,27 +35,6 @@ public void Constructor_ValidUri_Succeeds() Assert.Equal(expectedVaultUri, keyVaultConfiguration.VaultUri); } - [Fact] - public void Constructor_RawUriWithHttp_ThrowsUriFormatException() - { - // Arrange - string vaultUri = $"http://{Guid.NewGuid():N}.vault.azure.net/"; - - // Act & Assert - Assert.Throws(() => new KeyVaultConfiguration(vaultUri)); - } - - [Fact] - public void Constructor_UriWithHttp_ThrowsUriFormatException() - { - // Arrange - string vaultUri = $"http://{Guid.NewGuid():N}.vault.azure.net/"; - var expectedVaultUri = new Uri(vaultUri); - - // Act & Assert - Assert.Throws(() => new KeyVaultConfiguration(expectedVaultUri)); - } - [Fact] public void Constructor_NoUriSpecified_ThrowsArgumentNullException() { @@ -70,7 +42,7 @@ public void Constructor_NoUriSpecified_ThrowsArgumentNullException() Uri vaultUri = null; // Act & Assert - Assert.Throws(() => new KeyVaultConfiguration(vaultUri)); + Assert.ThrowsAny(() => new KeyVaultConfiguration(vaultUri)); } [Fact] @@ -80,7 +52,7 @@ public void Constructor_NoRawUriSpecified_ThrowsArgumentNullException() string rawVaultUri = null; // Act & Assert - Assert.Throws(() => new KeyVaultConfiguration(rawVaultUri)); + Assert.ThrowsAny(() => new KeyVaultConfiguration(rawVaultUri)); } [Fact] @@ -90,7 +62,7 @@ public void Constructor_EmptyRawUriSpecified_ThrowsUriFormatException() string rawVaultUri = string.Empty; // Act & Assert - Assert.Throws(() => new KeyVaultConfiguration(rawVaultUri)); + Assert.ThrowsAny(() => new KeyVaultConfiguration(rawVaultUri)); } [Fact] @@ -100,7 +72,7 @@ public void Constructor_RawUriWithSpaceSpecified_ThrowsUriFormatException() string rawVaultUri = " "; // Act & Assert - Assert.Throws(() => new KeyVaultConfiguration(rawVaultUri)); + Assert.ThrowsAny(() => new KeyVaultConfiguration(rawVaultUri)); } } }