public void GetConfig_SecondTime_CertificateLoadingThrewException_ErrorLogged() { var builder = new ConfigurationBuilder(); var proxyConfig = builder.AddInMemoryCollection(new Dictionary <string, string> { ["Clusters:cluster1:Destinations:destinationA:Address"] = "https://localhost:10001/destC", ["Routes:0:RouteId"] = "routeA", ["Routes:0:ClusterId"] = "cluster1", ["Routes:0:Order"] = "1", ["Routes:0:Match:Hosts:0"] = "host-B", }).Build(); var certLoader = new Mock <ICertificateConfigLoader>(MockBehavior.Strict); using var certificate = TestResources.GetTestCertificate(); certLoader.Setup(l => l.LoadCertificate(It.IsAny <IConfigurationSection>())).Throws(new FileNotFoundException()); var logger = new Mock <ILogger <ConfigurationConfigProvider> >(); logger.Setup(l => l.IsEnabled(LogLevel.Error)).Returns(true); var provider = new ConfigurationConfigProvider(logger.Object, proxyConfig, certLoader.Object); var firstSnapshot = provider.GetConfig(); logger.Verify(l => l.Log(LogLevel.Error, It.IsAny <EventId>(), It.IsAny <string>(), It.IsAny <Exception>(), It.IsAny <Func <string, Exception, string> >()), Times.Never); // Add configuration entry here and trigger a change proxyConfig["Clusters:cluster1:HttpClient:ClientCertificate:Path"] = "mycert.pfx"; TriggerOnChange(proxyConfig); var secondSnapshot = provider.GetConfig(); Assert.Same(firstSnapshot, secondSnapshot); logger.Verify(l => l.Log(LogLevel.Error, EventIds.ConfigurationDataConversionFailed, It.IsAny <It.IsAnyType>(), It.IsAny <Exception>(), (Func <It.IsAnyType, Exception, string>)It.IsAny <object>()), Times.Once); }
public void CachedCertificateIsDisposed_RemoveItFromCache() { var builder = new ConfigurationBuilder(); var proxyConfig = builder.AddInMemoryCollection(new Dictionary <string, string> { ["Clusters:cluster1:Destinations:destinationA:Address"] = "https://localhost:10001/destC", ["Clusters:cluster1:HttpClient:ClientCertificate:Path"] = "testCert.pfx", ["Routes:0:RouteId"] = "routeA", ["Routes:0:ClusterId"] = "cluster1", ["Routes:0:Order"] = "1", ["Routes:0:Match:Hosts:0"] = "host-B", }).Build(); var certLoader = new Mock <ICertificateConfigLoader>(MockBehavior.Strict); using var certificate = TestResources.GetTestCertificate(); certLoader.Setup(l => l.LoadCertificate(It.IsAny <IConfigurationSection>())).Returns(() => TestResources.GetTestCertificate()); var logger = new Mock <ILogger <ConfigurationConfigProvider> >(); logger.Setup(l => l.IsEnabled(LogLevel.Error)).Returns(true); var provider = new ConfigurationConfigProvider(logger.Object, proxyConfig, certLoader.Object); // Get several certificates. var certificateConfig = new List <X509Certificate2>(); for (var i = 0; i < 5; i++) { certificateConfig.AddRange(provider.GetConfig().Clusters.Select(c => c.HttpClient.ClientCertificate)); if (i < 4) { TriggerOnChange(proxyConfig); } } // Verify cache contents match the configuration objects. var cachedCertificates = GetCachedCertificates(provider); Assert.Equal(certificateConfig.Count, cachedCertificates.Length); for (var i = 0; i < certificateConfig.Count; i++) { Assert.Same(certificateConfig[i], cachedCertificates[i]); } // Get several certificates. certificateConfig[1].Dispose(); certificateConfig[3].Dispose(); // Trigger cache compaction. TriggerOnChange(proxyConfig); // Verify disposed certificates were purged out. cachedCertificates = GetCachedCertificates(provider); Assert.Equal(4, cachedCertificates.Length); Assert.Same(certificateConfig[0], cachedCertificates[0]); Assert.Same(certificateConfig[2], cachedCertificates[1]); Assert.Same(certificateConfig[4], cachedCertificates[2]); }
public void GetConfig_ValidSerializedConfiguration_ConvertToAbstractionsSuccessfully() { var builder = new ConfigurationBuilder(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(_validJsonConfig)); var proxyConfig = builder.AddJsonStream(stream).Build(); var certLoader = new Mock <ICertificateConfigLoader>(MockBehavior.Strict); using var certificate = TestResources.GetTestCertificate(); certLoader.Setup(l => l.LoadCertificate(It.Is <IConfigurationSection>(o => o["Path"] == "mycert.pfx" && o["Password"] == "myPassword1234"))).Returns(certificate); var logger = new Mock <ILogger <ConfigurationConfigProvider> >(); var provider = new ConfigurationConfigProvider(logger.Object, proxyConfig, certLoader.Object); Assert.NotNull(provider); var abstractConfig = provider.GetConfig(); VerifyValidAbstractConfig(_validConfigurationData, certificate, abstractConfig); }
public void GetConfig_FirstTime_CertificateLoadingThrewException_Throws() { var builder = new ConfigurationBuilder(); var proxyConfig = builder.AddInMemoryCollection(new Dictionary <string, string> { ["Clusters:cluster1:Destinations:destinationA:Address"] = "https://localhost:10001/destC", ["Clusters:cluster1:HttpClient:ClientCertificate:Path"] = "mycert.pfx", ["Routes:0:RouteId"] = "routeA", ["Routes:0:ClusterId"] = "cluster1", ["Routes:0:Order"] = "1", ["Routes:0:Match:Hosts:0"] = "host-B", }).Build(); var certLoader = new Mock <ICertificateConfigLoader>(MockBehavior.Strict); using var certificate = TestResources.GetTestCertificate(); certLoader.Setup(l => l.LoadCertificate(It.IsAny <IConfigurationSection>())).Throws(new FileNotFoundException()); var logger = new Mock <ILogger <ConfigurationConfigProvider> >(); var provider = new ConfigurationConfigProvider(logger.Object, proxyConfig, certLoader.Object); Assert.ThrowsAny <FileNotFoundException>(() => provider.GetConfig()); }
public void GetConfig_ValidConfiguration_AllAbstractionsPropertiesAreSet() { var builder = new ConfigurationBuilder(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(_validJsonConfig)); var proxyConfig = builder.AddJsonStream(stream).Build(); var certLoader = new Mock <ICertificateConfigLoader>(MockBehavior.Strict); using var certificate = TestResources.GetTestCertificate(); certLoader.Setup(l => l.LoadCertificate(It.Is <IConfigurationSection>(o => o["Path"] == "mycert.pfx" && o["Password"] == "myPassword1234"))).Returns(certificate); var logger = new Mock <ILogger <ConfigurationConfigProvider> >(); var provider = new ConfigurationConfigProvider(logger.Object, proxyConfig, certLoader.Object); var abstractConfig = (ConfigurationSnapshot)provider.GetConfig(); var abstractionsNamespace = typeof(Cluster).Namespace; // Removed incompletely filled out instances. abstractConfig.Clusters = abstractConfig.Clusters.Where(c => c.Id == "cluster1").ToList(); abstractConfig.Routes = abstractConfig.Routes.Where(r => r.RouteId == "routeA").ToList(); VerifyAllPropertiesAreSet(abstractConfig); void VerifyFullyInitialized(object obj, string name) { switch (obj) { case null: Assert.True(false, $"Property {name} is not initialized."); break; case Enum m: Assert.NotEqual(0, (int)(object)m); break; case string str: Assert.NotEmpty(str); break; case ValueType v: var equals = Equals(Activator.CreateInstance(v.GetType()), v); Assert.False(equals, $"Property {name} is not initialized."); if (v.GetType().Namespace == abstractionsNamespace) { VerifyAllPropertiesAreSet(v); } break; case IDictionary d: Assert.NotEmpty(d); foreach (var value in d.Values) { VerifyFullyInitialized(value, name); } break; case IEnumerable e: Assert.NotEmpty(e); foreach (var item in e) { VerifyFullyInitialized(item, name); } var type = e.GetType(); if (!type.IsArray && type.Namespace == abstractionsNamespace) { VerifyAllPropertiesAreSet(e); } break; case object o: if (o.GetType().Namespace == abstractionsNamespace) { VerifyAllPropertiesAreSet(o); } break; } } void VerifyAllPropertiesAreSet(object obj) { var properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Cast <PropertyInfo>(); foreach (var property in properties) { VerifyFullyInitialized(property.GetValue(obj), $"{property.DeclaringType.Name}.{property.Name}"); } } }