public async Task WhenGetSecretIsCalledCacheIsUsed()
        {
            // Arrange
            const string   secretName  = "secretname";
            const string   secretValue = "testValue";
            KeyVaultSecret secret      = new KeyVaultSecret(secretName, secretValue, null);

            var mockSecretReader = new Mock <ISecretReader>();

            mockSecretReader
            .Setup(x => x.GetSecretObjectAsync(It.IsAny <string>()))
            .Returns(Task.FromResult((ISecret)secret));

            var cachingSecretReader = new CachingSecretReader(mockSecretReader.Object, int.MaxValue);

            // Act
            var value1 = await cachingSecretReader.GetSecretAsync("secretname");

            var value2 = await cachingSecretReader.GetSecretAsync("secretname");

            // Assert
            mockSecretReader.Verify(x => x.GetSecretObjectAsync(It.IsAny <string>()), Times.Once);
            Assert.Equal(secretValue, value1);
            Assert.Equal(value1, value2);
        }
        private static ISecretInjector GetSecretInjector(IDictionary<string, string> arguments)
        {
            ISecretReader secretReader;

            var vaultName = arguments.GetOrDefault<string>(Arguments.VaultName);
            if (string.IsNullOrEmpty(vaultName))
            {
                secretReader = new EmptySecretReader();
            }
            else
            {
                var clientId = arguments.GetOrThrow<string>(Arguments.ClientId);
                var certificateThumbprint = arguments.GetOrThrow<string>(Arguments.CertificateThumbprint);
                var storeName = arguments.GetOrDefault(Arguments.StoreName, StoreName.My);
                var storeLocation = arguments.GetOrDefault(Arguments.StoreLocation, StoreLocation.LocalMachine);
                var shouldValidateCert = arguments.GetOrDefault(Arguments.ValidateCertificate, false);

                var keyVaultConfig = new KeyVaultConfiguration(vaultName, clientId, certificateThumbprint, storeName, storeLocation, shouldValidateCert);

                secretReader = new CachingSecretReader(new KeyVaultReader(keyVaultConfig),
                    arguments.GetOrDefault(Arguments.RefreshIntervalSec, CachingSecretReader.DefaultRefreshIntervalSec));
            }

            return new SecretInjector(secretReader);
        }
        private static ISecretInjector GetSecretInjector(IDictionary <string, string> arguments)
        {
            ISecretReader secretReader;

            var vaultName = arguments.GetOrDefault <string>(Arguments.VaultName);

            if (string.IsNullOrEmpty(vaultName))
            {
                secretReader = new EmptySecretReader();
            }
            else
            {
                var clientId = arguments.GetOrThrow <string>(Arguments.ClientId);
                var certificateThumbprint = arguments.GetOrThrow <string>(Arguments.CertificateThumbprint);
                var storeName             = arguments.GetOrDefault(Arguments.StoreName, StoreName.My);
                var storeLocation         = arguments.GetOrDefault(Arguments.StoreLocation, StoreLocation.LocalMachine);
                var shouldValidateCert    = arguments.GetOrDefault(Arguments.ValidateCertificate, true);

                var keyVaultCertificate = CertificateUtility.FindCertificateByThumbprint(storeName, storeLocation, certificateThumbprint, shouldValidateCert);
                var keyVaultConfig      = new KeyVaultConfiguration(vaultName, clientId, keyVaultCertificate);

                secretReader = new CachingSecretReader(new KeyVaultReader(keyVaultConfig),
                                                       arguments.GetOrDefault(Arguments.RefreshIntervalSec, CachingSecretReader.DefaultRefreshIntervalSec));
            }

            return(new SecretInjector(secretReader));
        }
        public async Task WhenGetSecretIsCalledCacheIsUsedWithoutLogger()
        {
            // Arrange
            const string   secretName  = "secretname";
            const string   secretValue = "testValue";
            KeyVaultSecret secret      = new KeyVaultSecret(secretName, secretValue, null);

            var mockLogger       = new Mock <ILogger>();
            var mockSecretReader = new Mock <ISecretReader>();

            mockSecretReader
            .Setup(x => x.GetSecretObjectAsync(It.IsAny <string>()))
            .Returns(Task.FromResult((ISecret)secret));

            var cachingSecretReader = new CachingSecretReader(mockSecretReader.Object, int.MaxValue);

            // Act
            var value1 = await cachingSecretReader.GetSecretAsync("secretname");

            var value2 = await cachingSecretReader.GetSecretAsync("secretname");

            // Assert
            mockSecretReader.Verify(x => x.GetSecretObjectAsync(It.IsAny <string>()), Times.Once);
            mockLogger.Verify(x => x.Log(It.IsAny <LogLevel>(),
                                         It.IsAny <EventId>(),
                                         It.IsAny <FormattedLogValues>(),
                                         It.IsAny <Exception>(),
                                         It.IsAny <Func <object, Exception, string> >()), Times.Never);
        }
        public async Task WhenGetSecretIsCalledCacheIsRefreshedIfPastInterval()
        {
            // Arrange
            const string   secretName         = "secretname";
            const string   firstSecretValue   = "secret1";
            const string   secondSecretValue  = "secret2";
            KeyVaultSecret firstSecret        = new KeyVaultSecret(secretName, firstSecretValue, null);
            KeyVaultSecret secondSecret       = new KeyVaultSecret(secretName, secondSecretValue, null);
            const int      refreshIntervalSec = 1;

            var mockSecretReader = new Mock <ISecretReader>();

            mockSecretReader
            .SetupSequence(x => x.GetSecretObjectAsync(It.IsAny <string>()))
            .Returns(Task.FromResult((ISecret)firstSecret))
            .Returns(Task.FromResult((ISecret)secondSecret));
            var mockLogger = new Mock <ILogger>();

            var cachingSecretReader = new CachingSecretReader(mockSecretReader.Object, refreshIntervalSec);

            // Act
            var firstValue1 = await cachingSecretReader.GetSecretAsync(secretName, mockLogger.Object);

            var firstValue2 = await cachingSecretReader.GetSecretAsync(secretName, mockLogger.Object);

            // Assert
            mockSecretReader.Verify(x => x.GetSecretObjectAsync(It.IsAny <string>()), Times.Once);
            mockLogger.Verify(x => x.Log(It.IsAny <LogLevel>(),
                                         It.IsAny <EventId>(),
                                         It.IsAny <FormattedLogValues>(),
                                         It.IsAny <Exception>(),
                                         It.IsAny <Func <object, Exception, string> >()), Times.Once);
            Assert.Equal(firstSecret.Value, firstValue1);
            Assert.Equal(firstSecret.Value, firstValue2);

            // Arrange 2
            // We are now x seconds later after refreshIntervalSec has passed.
            await Task.Delay(TimeSpan.FromSeconds(refreshIntervalSec * 2));

            // Act 2
            var secondValue1 = await cachingSecretReader.GetSecretAsync(secretName, mockLogger.Object);

            var secondValue2 = await cachingSecretReader.GetSecretAsync(secretName, mockLogger.Object);

            // Assert 2
            mockSecretReader.Verify(x => x.GetSecretObjectAsync(It.IsAny <string>()), Times.Exactly(2));
            mockLogger.Verify(x => x.Log(It.IsAny <LogLevel>(),
                                         It.IsAny <EventId>(),
                                         It.IsAny <FormattedLogValues>(),
                                         It.IsAny <Exception>(),
                                         It.IsAny <Func <object, Exception, string> >()), Times.Exactly(2));
            Assert.Equal(secondSecret.Value, secondValue1);
            Assert.Equal(secondSecret.Value, secondValue2);
        }
示例#6
0
        public ISecretReader CreateSecretReader()
        {
            ISecretReader secretReader;

            // Is KeyVault configured?
            if (!_configurationDictionary.TryGetValue(VaultNameKey, out var vaultName) ||
                string.IsNullOrEmpty(vaultName))
            {
                secretReader = new EmptySecretReader();
            }
            else
            {
                KeyVaultConfiguration keyVaultConfiguration;
                if (_configurationDictionary.TryGetValue(UseManagedIdentityKey, out var useManagedIdentityStr) &&
                    bool.TryParse(useManagedIdentityStr, out var useManagedIdentity) &&
                    useManagedIdentity)
                {
                    keyVaultConfiguration = new KeyVaultConfiguration(vaultName);
                }
                else
                {
                    var clientId = _configurationDictionary[ClientIdKey];
                    var certificateThumbprint = _configurationDictionary[CertificateThumbprintKey];
                    var storeLocation         = _configurationDictionary[StoreLocationKey];
                    var storeName             = _configurationDictionary[StoreNameKey];
                    var validateCertificate   = _configurationDictionary[ValidateCertificateKey];
                    var certificate           = CertificateUtility.FindCertificateByThumbprint(
                        (StoreName)Enum.Parse(typeof(StoreName), storeName),
                        (StoreLocation)Enum.Parse(typeof(StoreLocation), storeLocation),
                        certificateThumbprint,
                        bool.Parse(validateCertificate));
                    keyVaultConfiguration = new KeyVaultConfiguration(vaultName, clientId, certificate);
                }

                if (!_configurationDictionary.TryGetValue(CacheRefreshIntervalKey, out var cacheRefresh) ||
                    !int.TryParse(cacheRefresh, out int refreshIntervalSec))
                {
                    refreshIntervalSec = CachingSecretReader.DefaultRefreshIntervalSec;
                }

                secretReader = new KeyVaultReader(keyVaultConfiguration);
                secretReader = new CachingSecretReader(secretReader, refreshIntervalSec);
            }

            return(secretReader);
        }
        public async Task WhenGetSecretIsCalledCacheIsRefreshedIfPastSecretExpiry()
        {
            // Arrange
            const string   secretName             = "secretname";
            const string   firstSecretValue       = "testValue";
            DateTime       firstSecretExpiration  = DateTime.UtcNow.AddSeconds(-1);
            const string   secondSecretValue      = "testValue2";
            DateTime       secondSecretExpiration = DateTime.UtcNow.AddHours(1);
            KeyVaultSecret secret1                        = new KeyVaultSecret(secretName, firstSecretValue, firstSecretExpiration);
            KeyVaultSecret secret2                        = new KeyVaultSecret(secretName, secondSecretValue, secondSecretExpiration);
            int            refreshIntervalSec             = 30;
            int            refreshIntervalBeforeExpirySec = 0;

            var mockSecretReader = new Mock <ISecretReader>();

            mockSecretReader
            .SetupSequence(x => x.GetSecretObjectAsync(It.IsAny <string>()))
            .Returns(Task.FromResult((ISecret)secret1))
            .Returns(Task.FromResult((ISecret)secret2));
            var mockLogger = new Mock <ILogger>();

            var cachingSecretReader = new CachingSecretReader(mockSecretReader.Object, refreshIntervalSec, refreshIntervalBeforeExpirySec);

            // Act
            var secretObject1 = await cachingSecretReader.GetSecretObjectAsync(secretName, mockLogger.Object);

            var secretObject2 = await cachingSecretReader.GetSecretObjectAsync(secretName, mockLogger.Object);

            var secretObject3 = await cachingSecretReader.GetSecretObjectAsync(secretName, mockLogger.Object);

            // Assert
            mockSecretReader.Verify(x => x.GetSecretObjectAsync(It.IsAny <string>()), Times.Exactly(2));
            mockLogger.Verify(x => x.Log(It.IsAny <LogLevel>(),
                                         It.IsAny <EventId>(),
                                         It.IsAny <FormattedLogValues>(),
                                         It.IsAny <Exception>(),
                                         It.IsAny <Func <object, Exception, string> >()), Times.Exactly(2));
            Assert.Equal(secretObject1.Value, firstSecretValue);
            Assert.Equal(secretObject1.Expiration, firstSecretExpiration);
            Assert.Equal(secretObject2.Value, secondSecretValue);
            Assert.Equal(secretObject2.Expiration, secondSecretExpiration);
            Assert.Equal(secretObject3.Value, secondSecretValue);
            Assert.Equal(secretObject3.Expiration, secondSecretExpiration);
        }
示例#8
0
        public async Task WhenGetSecretIsCalledCacheIsUsed()
        {
            // Arrange
            const string secret           = "secret";
            var          mockSecretReader = new Mock <ISecretReader>();

            mockSecretReader.Setup(x => x.GetSecretAsync(It.IsAny <string>())).Returns(Task.FromResult(secret));

            var cachingSecretReader = new CachingSecretReader(mockSecretReader.Object, new DiagnosticsService());

            // Act
            string value = await cachingSecretReader.GetSecretAsync("secretname");

            value = await cachingSecretReader.GetSecretAsync("secretname");

            // Assert
            mockSecretReader.Verify(x => x.GetSecretAsync(It.IsAny <string>()), Times.Once);
            Assert.Equal(secret, value);
        }
        public async Task WhenGetSecretIsCalledCacheIsRefreshedIfPastInterval()
        {
            // Arrange
            const string secretName         = "secretname";
            const string firstSecret        = "secret1";
            const string secondSecret       = "secret2";
            const int    refreshIntervalSec = 1;

            var mockSecretReader = new Mock <ISecretReader>();

            mockSecretReader
            .SetupSequence(x => x.GetSecretAsync(It.IsAny <string>()))
            .Returns(Task.FromResult(firstSecret))
            .Returns(Task.FromResult(secondSecret));

            var cachingSecretReader = new CachingSecretReader(mockSecretReader.Object, refreshIntervalSec);

            // Act
            var firstValue1 = await cachingSecretReader.GetSecretAsync(secretName);

            var firstValue2 = await cachingSecretReader.GetSecretAsync(secretName);

            // Assert
            mockSecretReader.Verify(x => x.GetSecretAsync(It.IsAny <string>()), Times.Once);
            Assert.Equal(firstSecret, firstValue1);
            Assert.Equal(firstSecret, firstValue2);

            // Arrange 2
            // We are now x seconds later after refreshIntervalSec has passed.
            await Task.Delay(TimeSpan.FromSeconds(refreshIntervalSec * 2));

            // Act 2
            var secondValue1 = await cachingSecretReader.GetSecretAsync(secretName);

            var secondValue2 = await cachingSecretReader.GetSecretAsync(secretName);

            // Assert 2
            mockSecretReader.Verify(x => x.GetSecretAsync(It.IsAny <string>()), Times.Exactly(2));
            Assert.Equal(secondSecret, secondValue1);
            Assert.Equal(secondSecret, secondValue2);
        }
示例#10
0
        public async Task GetSecretObjectAsyncReturnsSecretExpiry()
        {
            // Arrange
            const string   secretName       = "secretname";
            const string   secretValue      = "testValue";
            DateTime       secretExpiration = DateTime.UtcNow.AddSeconds(3);
            KeyVaultSecret secret           = new KeyVaultSecret(secretName, secretValue, secretExpiration);

            var mockSecretReader = new Mock <ISecretReader>();

            mockSecretReader
            .SetupSequence(x => x.GetSecretObjectAsync(It.IsAny <string>()))
            .Returns(Task.FromResult((ISecret)secret));

            var cachingSecretReader = new CachingSecretReader(mockSecretReader.Object);

            // Act
            var secretObject = await cachingSecretReader.GetSecretObjectAsync(secretName);

            // Assert
            mockSecretReader.Verify(x => x.GetSecretObjectAsync(It.IsAny <string>()), Times.Once);
            Assert.Equal(secretObject.Value, secretValue);
            Assert.Equal(secretObject.Expiration, secretExpiration);
        }