/// <summary>
        /// Gets the registered named <see cref="ICachedSecretProvider"/> from the secret store.
        /// </summary>
        /// <param name="name">The name that was used to register the <see cref="ICachedSecretProvider"/> in the secret store.</param>
        /// <typeparam name="TCachedSecretProvider">The concrete <see cref="ICachedSecretProvider"/> type.</typeparam>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="name"/> is blank.</exception>
        /// <exception cref="KeyNotFoundException">Thrown when there was no <see cref="ICachedSecretProvider"/> found in the secret store with the given <paramref name="name"/>.</exception>
        /// <exception cref="NotSupportedException">
        ///     Thrown when their was either none of the registered secret providers are registered as <see cref="ICachedSecretProvider"/> instances
        ///     or there was an <see cref="ISecretProvider"/> registered but not with caching.
        /// </exception>
        /// <exception cref="InvalidCastException">Thrown when the registered <see cref="ICachedSecretProvider"/> cannot be cast to the specific <typeparamref name="TCachedSecretProvider"/>.</exception>
        /// <exception cref="InvalidOperationException">Thrown when multiple <see cref="ICachedSecretProvider"/> were registered with the same name.</exception>
        public TCachedSecretProvider GetCachedProvider <TCachedSecretProvider>(string name) where TCachedSecretProvider : ICachedSecretProvider
        {
            Guard.NotNullOrWhitespace(name, nameof(name), "Requires a non-blank name to retrieve the registered named secret provider");
            Guard.For <NotSupportedException>(
                () => !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)})");

            ICachedSecretProvider provider = GetCachedProvider(name);

            if (provider is TCachedSecretProvider concreteProvider)
            {
                return(concreteProvider);
            }

            if (provider is CompositeSecretProvider)
            {
                throw new InvalidOperationException(
                          $"Cannot cast registered {nameof(ICachedSecretProvider)} with name '{name}' to type '{typeof(TCachedSecretProvider).Name}' " +
                          $"because multiple secret providers were registered with the name '{name}', " +
                          $"use the non-generic '{nameof(GetCachedProvider)}' to retrieve them");
            }

            throw new InvalidCastException(
                      $"Cannot cast registered {nameof(ICachedSecretProvider)} with name '{name}' to type '{typeof(TCachedSecretProvider).Name}'");
        }
Exemplo n.º 2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SecretStoreSource"/> class.
        /// </summary>
        public SecretStoreSource(ICachedSecretProvider secretProvider)
        {
            Guard.NotNull(secretProvider, nameof(secretProvider));

            SecretProvider       = secretProvider;
            CachedSecretProvider = secretProvider;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="InvalidateKeyVaultSecretHandler"/> class.
        /// </summary>
        public InvalidateKeyVaultSecretHandler(ICachedSecretProvider secretProvider, ILogger <InvalidateKeyVaultSecretHandler> logger)
        {
            Guard.NotNull(secretProvider, nameof(secretProvider));
            Guard.NotNull(logger, nameof(logger));

            _cachedSecretProvider = secretProvider;
            _logger = logger;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="MutatedSecretNameSecretProvider"/> class.
 /// </summary>
 /// <param name="implementation">The actual <see cref="ISecretProvider"/> implementation to look up the secret.</param>
 /// <param name="mutateSecretName">The function to mutate the name of the secret before looking up the secret.</param>
 /// <param name="logger">The instance to log diagnostic messages during the secret name mutation.</param>
 /// <exception cref="ArgumentNullException">
 ///     Thrown when the <paramref name="implementation"/> or the <paramref name="mutateSecretName"/> is <c>null</c>.
 /// </exception>
 public MutatedSecretNameCachedSecretProvider(
     ICachedSecretProvider implementation,
     Func <string, string> mutateSecretName,
     ILogger logger)
     : base(implementation, mutateSecretName, logger)
 {
     Guard.NotNull(implementation, nameof(implementation), "Requires an secret provider instance to pass the mutated secret name to");
     _implementation = implementation;
 }
Exemplo n.º 5
0
        /// <summary>
        /// Removes the secret with the given <paramref name="secretName"/> from the cache;
        /// so the next time <see cref="CachedSecretProvider.GetSecretAsync(string)"/> is called, a new version of the secret will be added back to the cache.
        /// </summary>
        /// <param name="secretName">The name of the secret that should be removed from the cache.</param>
        public async Task InvalidateSecretAsync(string secretName)
        {
            Guard.NotNullOrWhitespace(secretName, nameof(secretName));

            ICachedSecretProvider provider = await WithCachedSecretStoreAsync(secretName, async source =>
            {
                Secret secret = await source.CachedSecretProvider.GetSecretAsync(secretName);
                return(secret is null ? null : source.CachedSecretProvider);
            });

            await provider.InvalidateSecretAsync(secretName);
        }
        /// <summary>
        /// Gets the registered named <see cref="ICachedSecretProvider"/> from the secret store.
        /// </summary>
        /// <param name="name">The name that was used to register the <see cref="ICachedSecretProvider"/> in the secret store.</param>
        /// <typeparam name="TCachedSecretProvider">The concrete <see cref="ICachedSecretProvider"/> type.</typeparam>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="name"/> is blank.</exception>
        /// <exception cref="KeyNotFoundException">
        ///     Thrown when there was no <see cref="ICachedSecretProvider"/> found in the secret store with the given <paramref name="name"/>,
        ///     or there were multiple <see cref="ICachedSecretProvider"/> instances registered with the same name.
        /// </exception>
        /// <exception cref="NotSupportedException">Thrown when there was an <see cref="ICachedSecretProvider"/> registered but not with caching.</exception>
        /// <exception cref="InvalidCastException">Thrown when the registered <see cref="ICachedSecretProvider"/> cannot be cast to the specific <typeparamref name="TCachedSecretProvider"/>.</exception>
        public TCachedSecretProvider GetCachedProvider <TCachedSecretProvider>(string name) where TCachedSecretProvider : ICachedSecretProvider
        {
            Guard.NotNullOrWhitespace(name, nameof(name), "Requires a non-blank name to retrieve the registered named secret provider");

            ICachedSecretProvider provider = GetCachedProvider(name);

            if (provider is TCachedSecretProvider concreteProvider)
            {
                return(concreteProvider);
            }

            throw new InvalidCastException($"Cannot cast registered {nameof(ICachedSecretProvider)} with name '{name}' to type '{typeof(TCachedSecretProvider).Name}'");
        }
        public async Task SecretProviderCachingExtensions_TwoCallsWithinCacheInterval_ShouldGetSameValueTwice()
        {
            // Arrange
            string secretKeyValue     = Guid.NewGuid().ToString("N");
            var    testSecretProvider = new TestSecretProviderStub(secretKeyValue);
            string keyName            = "MyValue";

            // Act
            ICachedSecretProvider cachedSecretProvider = testSecretProvider.WithCaching(TimeSpan.FromSeconds(3));
            var firstValue = await cachedSecretProvider.GetRawSecretAsync(keyName);

            testSecretProvider.SecretValue = Guid.NewGuid().ToString("N"); // Change actual value on the internal secret provider !
            var secondValue = await cachedSecretProvider.GetRawSecretAsync(keyName);

            // Assert
            Assert.Equal(firstValue, secondValue);
            Assert.Equal(1, testSecretProvider.CallsMadeSinceCreation);
        }
        public async Task SecretProviderCachingExtensions_TwoCallsOutsideCacheInterval_ShouldGetDifferentValue()
        {
            // Arrange
            string secretKeyValue     = Guid.NewGuid().ToString("N");
            var    testSecretProvider = new TestSecretProviderStub(secretKeyValue);

            string keyName = "MyValue";

            // Act
            ICachedSecretProvider cachedSecretProvider = testSecretProvider.WithCaching(TimeSpan.FromMilliseconds(100));
            var firstValue = await cachedSecretProvider.GetRawSecretAsync(keyName);

            await Task.Delay(TimeSpan.FromMilliseconds(150));

            string newSecretValue = Guid.NewGuid().ToString("N");

            testSecretProvider.SecretValue = newSecretValue; // Change actual value on the internal secret provider !
            var secondValue = await cachedSecretProvider.GetRawSecretAsync(keyName);

            // Assert
            Assert.Equal(secretKeyValue, firstValue);
            Assert.Equal(newSecretValue, secondValue);
            Assert.Equal(2, testSecretProvider.CallsMadeSinceCreation);
        }
Exemplo n.º 9
0
 public SecretsWithCachingController(ICachedSecretProvider secretProvider, ITelemetryProvider telemetryProvider)
 {
     this.secretProvider    = secretProvider;
     this.telemetryProvider = telemetryProvider;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="AuthorizedSecretProvider"/> class.
 /// </summary>
 /// <param name="permittedRole">The role that is required to access the <paramref name="cachedSecretProvider"/>.</param>
 /// <param name="authorization">The instance to determine if the <paramref name="permittedRole"/> is considered authorized.</param>
 /// <param name="cachedSecretProvider">The actual provider to access the secrets.</param>
 /// <exception cref="ArgumentNullException">Thrown when the <paramref name="authorization"/> or <paramref name="cachedSecretProvider"/> is <c>null</c>.</exception>
 /// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="permittedRole"/> is outside the bounds of the enumeration.</exception>
 public AuthorizedCachedSecretProvider(Role permittedRole, IRoleAuthorization authorization, ICachedSecretProvider cachedSecretProvider)
     : base(permittedRole, authorization, cachedSecretProvider)
 {
     Guard.NotNull(cachedSecretProvider, nameof(cachedSecretProvider), "Requires an instance to access the authorized secrets");
     _cachedSecretProvider = cachedSecretProvider;
 }