public void Update_Test() { ServiceIdentityTree tree = this.SetupTree(); // Re-insert the same node, nothing should have changed tree.AddOrUpdate(this.e2_L2).Wait(); this.CheckValidAuthChains(tree); // Re-parent e3_L2 from e2_L1 to e1_L1 ServiceIdentity updatedIdentity = CreateServiceIdentity( this.e3_L2.DeviceId, null, this.e3_L2.DeviceScope.Expect(() => new InvalidOperationException()), this.e1_L1.DeviceScope.Expect(() => new InvalidOperationException()), true); tree.AddOrUpdate(updatedIdentity).Wait(); // Equality check Option <ServiceIdentity> roundTripIdentity = tree.Get(updatedIdentity.Id).Result; Assert.True(roundTripIdentity.Contains(updatedIdentity)); // The child of e3_L2, leaf2, should also go through a different path for authchain now Option <string> authChainActual = tree.GetAuthChain(this.leaf2.Id).Result; string leaf2_authchain_expected = this.leaf2.Id + ";" + this.e3_L2.Id + ";" + this.e1_L1.Id + ";" + this.root.Id; Assert.True(authChainActual.Contains(leaf2_authchain_expected)); }
public void Remove_Test() { ServiceIdentityTree tree = this.SetupTree(); // Delete a node tree.Remove(this.e2_L1.Id).Wait(); // Auth-chains for everything in its subtree should be invalidated Assert.False(tree.GetAuthChain(this.e2_L1.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e3_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e4_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.leaf2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.mod2.Id).Result.HasValue); // Delete the rest of the subtree tree.Remove(this.e3_L2.Id).Wait(); tree.Remove(this.e4_L2.Id).Wait(); tree.Remove(this.leaf2.Id).Wait(); tree.Remove(this.mod2.Id).Wait(); // Nothing under e2_L1 should remain Assert.False(tree.Get(this.e2_L1.Id).Result.HasValue); Assert.False(tree.Get(this.e3_L2.Id).Result.HasValue); Assert.False(tree.Get(this.e4_L2.Id).Result.HasValue); Assert.False(tree.Get(this.leaf2.Id).Result.HasValue); Assert.False(tree.Get(this.mod2.Id).Result.HasValue); }
public void Insertion_OutOfOrder_Test() { var tree = new ServiceIdentityTree(this.root.Id); // Insert L2 identities tree.AddOrUpdate(this.e1_L2).Wait(); tree.AddOrUpdate(this.e2_L2).Wait(); tree.AddOrUpdate(this.e3_L2).Wait(); tree.AddOrUpdate(this.e4_L2).Wait(); // Should have no valid auth chains Assert.False(tree.GetAuthChain(this.e1_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e2_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e3_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e4_L2.Id).Result.HasValue); // Insert L1 identities tree.AddOrUpdate(this.e1_L1).Wait(); tree.AddOrUpdate(this.e2_L1).Wait(); // Should have no valid auth chains Assert.False(tree.GetAuthChain(this.e1_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e2_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e3_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e4_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e1_L1.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e2_L1.Id).Result.HasValue); // Insert leaf identities tree.AddOrUpdate(this.leaf1).Wait(); tree.AddOrUpdate(this.leaf2).Wait(); tree.AddOrUpdate(this.mod1).Wait(); tree.AddOrUpdate(this.mod2).Wait(); // Should have no valid auth chains Assert.False(tree.GetAuthChain(this.e1_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e2_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e3_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e4_L2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e1_L1.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.e2_L1.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.leaf1.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.leaf2.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.mod1.Id).Result.HasValue); Assert.False(tree.GetAuthChain(this.mod2.Id).Result.HasValue); // Insert root tree.AddOrUpdate(this.root).Wait(); // All auth chains should now be valid because root is available this.CheckValidAuthChains(tree); }
public void GetAuthChain_DisabledDevice_Test() { ServiceIdentityTree tree = this.SetupTree(); // Add another branch with a disabled Edge ServiceIdentity edge_L2 = CreateServiceIdentity("edge_L2", null, "edge_L2_scope", "e1_L1_scope", true, false); ServiceIdentity leaf = CreateServiceIdentity("leaf", null, null, "edge_L2_scope", false); tree.AddOrUpdate(edge_L2).Wait(); tree.AddOrUpdate(leaf).Wait(); // Act Option <string> authChain = tree.GetAuthChain(leaf.Id).Result; // Assert Assert.False(authChain.HasValue); }
public void GetAuthChain_Test() { // Setup our tree ServiceIdentityTree tree = this.SetupTree(); // Check for valid auth chains this.CheckValidAuthChains(tree); // Check non-existent auth chain Assert.False(tree.GetAuthChain("nonexistent").Result.HasValue); // Insert an orphaned node and check for its invalid auth chain ServiceIdentity orphan = CreateServiceIdentity("orphan", null, null, null, false); tree.AddOrUpdate(orphan).Wait(); Assert.False(tree.GetAuthChain(orphan.Id).Result.HasValue); }
internal ServiceIdentityTree SetupTree() { var tree = new ServiceIdentityTree(this.root.Id); tree.AddOrUpdate(this.root).Wait(); tree.AddOrUpdate(this.e1_L1).Wait(); tree.AddOrUpdate(this.e2_L1).Wait(); tree.AddOrUpdate(this.e1_L2).Wait(); tree.AddOrUpdate(this.e2_L2).Wait(); tree.AddOrUpdate(this.e3_L2).Wait(); tree.AddOrUpdate(this.e4_L2).Wait(); tree.AddOrUpdate(this.leaf1).Wait(); tree.AddOrUpdate(this.leaf2).Wait(); tree.AddOrUpdate(this.mod1).Wait(); tree.AddOrUpdate(this.mod2).Wait(); return(tree); }
public async Task GetAllIdsTest() { // Arrage ServiceIdentityTree tree = this.SetupTree(); IList <string> identitiesExpected = new List <string>() { this.root.Id, this.e1_L1.Id, this.e1_L2.Id, this.e2_L1.Id, this.e2_L2.Id, this.e3_L2.Id, this.e4_L2.Id, this.leaf1.Id, this.leaf2.Id, this.mod1.Id, this.mod2.Id }; // Act IList <string> identities = await tree.GetAllIds(); // Assert Assert.Equal(11, identities.Count); foreach (string id in identitiesExpected) { Assert.Contains(id, identities); } }
public async Task TryGetAuthChain_DisabledDevice_Test() { ServiceIdentityTree tree = this.SetupTree(); // Add another branch with a disabled Edge ServiceIdentity edge_L2 = CreateServiceIdentity("edge_L2", null, "edge_L2_scope", "e1_L1_scope", true, false); ServiceIdentity leaf = CreateServiceIdentity("leaf", null, null, "edge_L2_scope", false); var expectedAuthChain = "leaf;edge_L2;e1_L1;root"; tree.AddOrUpdate(edge_L2).Wait(); tree.AddOrUpdate(leaf).Wait(); // Act var authChain = await tree.TryGetAuthChain(leaf.Id); // Assert Assert.True(authChain.Success); Assert.Equal(expectedAuthChain, authChain.Value); }
internal void CheckValidAuthChains(ServiceIdentityTree tree) { // Check leaf1 Option <string> authChainActual = tree.GetAuthChain(this.leaf1.Id).Result; string leaf1_authchain_expected = this.leaf1.Id + ";" + this.e1_L2.Id + ";" + this.e1_L1.Id + ";" + this.root.Id; Assert.True(authChainActual.Contains(leaf1_authchain_expected)); // Check leaf2 authChainActual = tree.GetAuthChain(this.leaf2.Id).Result; string leaf2_authchain_expected = this.leaf2.Id + ";" + this.e3_L2.Id + ";" + this.e2_L1.Id + ";" + this.root.Id; Assert.True(authChainActual.Contains(leaf2_authchain_expected)); // Check mod1 authChainActual = tree.GetAuthChain(this.mod1.Id).Result; string mod1_authchain_expected = this.mod1.Id + ";" + this.e2_L2.Id + ";" + this.e1_L1.Id + ";" + this.root.Id; Assert.True(authChainActual.Contains(mod1_authchain_expected)); // Check mod2 authChainActual = tree.GetAuthChain(this.mod2.Id).Result; string mod2_authchain_expected = this.mod2.Id + ";" + this.e4_L2.Id + ";" + this.e2_L1.Id + ";" + this.root.Id; Assert.True(authChainActual.Contains(mod2_authchain_expected)); }
public async Task TryGetAuthChain_Test() { // Setup our tree ServiceIdentityTree tree = this.SetupTree(); // Check for valid auth chains this.CheckValidAuthChains(tree); // Check non-existent auth chain var authChainTry = await tree.TryGetAuthChain("nonexistent"); Assert.Throws <DeviceInvalidStateException>(() => authChainTry.Value); // Insert an orphaned node and check for its invalid auth chain ServiceIdentity orphan = CreateServiceIdentity("orphan", null, null, null, false); tree.AddOrUpdate(orphan).Wait(); authChainTry = await tree.TryGetAuthChain(orphan.Id); Assert.Throws <DeviceInvalidStateException>(() => authChainTry.Value); }
public void MaxDepth_test() { ServiceIdentityTree tree = this.SetupTree(); // Create an orphaned chain ServiceIdentity e1_L3 = CreateServiceIdentity("e1_L3", null, "e1_L3_scope", null, true); ServiceIdentity e1_L4 = CreateServiceIdentity("e1_L4", null, "e1_L4_scope", "e1_L3_scope", true); ServiceIdentity e1_L5 = CreateServiceIdentity("e1_L5", null, "e1_L5_scope", "e1_L4_scope", true); tree.AddOrUpdate(e1_L3).Wait(); tree.AddOrUpdate(e1_L4).Wait(); tree.AddOrUpdate(e1_L5).Wait(); // Merge this chain into the main tree, this exceeds the maximum depth, // and e1_L5 should have no valid auth chain e1_L3 = CreateServiceIdentity("e1_L3", null, "e1_L3_scope", "e1_L2_scope", true); tree.AddOrUpdate(e1_L3).Wait(); Assert.False(tree.GetAuthChain(e1_L5.Id).Result.HasValue); // Try explicitly adding yet another layer with an Edge device, this shouldn't yield a valid chain tree.AddOrUpdate(e1_L5).Wait(); Assert.False(tree.GetAuthChain(e1_L5.Id).Result.HasValue); // But we should still be able to add a leaf device ServiceIdentity leaf = CreateServiceIdentity("leaf", null, null, "e1_L4_scope", false); tree.AddOrUpdate(leaf).Wait(); Option <string> authChainActual = tree.GetAuthChain(leaf.Id).Result; string leaf_authchain_expected = leaf.Id + ";" + e1_L4.Id + ";" + e1_L3.Id + ";" + this.e1_L2.Id + ";" + this.e1_L1.Id + ";" + this.root.Id; Assert.True(authChainActual.Contains(leaf_authchain_expected)); }
public void Update_NotChanged_Test() { ServiceIdentityTree tree = this.SetupTree(); ServiceIdentity updated = CreateServiceIdentity("e2_L2", null, "e2_L2_scope", "e1_L1_scope", true); ServiceIdentity root = CreateServiceIdentity("root", null, "rootScope", null, true); // Re-insert the same node, nothing should have changed tree.AddOrUpdate(updated).Wait(); tree.AddOrUpdate(root).Wait(); this.CheckValidAuthChains(tree); Option <ServiceIdentity> roundTripIdentity = tree.Get(this.e2_L2.Id).Result; Option <ServiceIdentity> roundTripRoot = tree.Get(this.root.Id).Result; Assert.True(roundTripIdentity.HasValue); Assert.True(ReferenceEquals(roundTripIdentity.OrDefault(), this.e2_L2)); Assert.False(ReferenceEquals(roundTripIdentity.OrDefault(), updated)); Assert.True(roundTripRoot.HasValue); Assert.True(ReferenceEquals(roundTripRoot.OrDefault(), this.root)); Assert.False(ReferenceEquals(roundTripRoot.OrDefault(), root)); }
protected override void Load(ContainerBuilder builder) { // IMetricsListener builder.Register( c => this.metricsConfig.Enabled ? new MetricsListener(this.metricsConfig.ListenerConfig, c.Resolve <IMetricsProvider>()) : new NullMetricsListener() as IMetricsListener) .As <IMetricsListener>() .SingleInstance(); // IMetricsProvider builder.Register( c => this.metricsConfig.Enabled ? new MetricsProvider(MetricsConstants.EdgeHubMetricPrefix, this.iothubHostName, this.edgeDeviceId, this.metricsConfig.HistogramMaxAge) : new NullMetricsProvider() as IMetricsProvider) .As <IMetricsProvider>() .SingleInstance(); // ISignatureProvider builder.Register( c => { ISignatureProvider signatureProvider = this.edgeHubConnectionString.Map( cs => { IotHubConnectionStringBuilder csBuilder = IotHubConnectionStringBuilder.Create(cs); return(new SharedAccessKeySignatureProvider(csBuilder.SharedAccessKey) as ISignatureProvider); }) .GetOrElse( () => { string edgeHubGenerationId = this.edgeHubGenerationId.Expect(() => new InvalidOperationException("Generation ID missing")); string workloadUri = this.workloadUri.Expect(() => new InvalidOperationException("workloadUri is missing")); string workloadApiVersion = this.workloadApiVersion.Expect(() => new InvalidOperationException("workloadUri version is missing")); return(new HttpHsmSignatureProvider(this.edgeHubModuleId, edgeHubGenerationId, workloadUri, workloadApiVersion, Constants.WorkloadApiVersion) as ISignatureProvider); }); return(signatureProvider); }) .As <ISignatureProvider>() .SingleInstance(); // Detect system environment builder.Register(c => new SystemEnvironment()) .As <ISystemEnvironment>() .SingleInstance(); // DataBase options builder.Register(c => new RocksDbOptionsProvider(c.Resolve <ISystemEnvironment>(), this.optimizeForPerformance, this.storageMaxTotalWalSize, this.storageMaxOpenFiles, this.storageLogLevel)) .As <IRocksDbOptionsProvider>() .SingleInstance(); if (!this.usePersistentStorage && this.useBackupAndRestore) { // Backup and restore serialization builder.Register(c => new ProtoBufDataBackupRestore()) .As <IDataBackupRestore>() .SingleInstance(); } // IStorageSpaceChecker builder.Register( c => { IStorageSpaceChecker spaceChecker = !this.usePersistentStorage ? new MemorySpaceChecker(() => 0L) as IStorageSpaceChecker : new NullStorageSpaceChecker(); return(spaceChecker); }) .As <IStorageSpaceChecker>() .SingleInstance(); // IDbStoreProvider builder.Register( async c => { var loggerFactory = c.Resolve <ILoggerFactory>(); ILogger logger = loggerFactory.CreateLogger(typeof(RoutingModule)); if (this.usePersistentStorage) { // Create partitions for messages and twins var partitionsList = new List <string> { Core.Constants.MessageStorePartitionKey, Core.Constants.TwinStorePartitionKey, Core.Constants.CheckpointStorePartitionKey }; try { IDbStoreProvider dbStoreProvider = DbStoreProvider.Create( c.Resolve <IRocksDbOptionsProvider>(), this.storagePath, partitionsList); logger.LogInformation($"Created persistent store at {this.storagePath}"); return(dbStoreProvider); } catch (Exception ex) when(!ex.IsFatal()) { logger.LogError(ex, "Error creating RocksDB store. Falling back to in-memory store."); IDbStoreProvider dbStoreProvider = await this.BuildInMemoryDbStoreProvider(c); return(dbStoreProvider); } } else { logger.LogInformation($"Using in-memory store"); IDbStoreProvider dbStoreProvider = await this.BuildInMemoryDbStoreProvider(c); return(dbStoreProvider); } }) .As <Task <IDbStoreProvider> >() .SingleInstance(); // Task<Option<IEncryptionProvider>> builder.Register( async c => { Option <IEncryptionProvider> encryptionProviderOption = await this.workloadUri .Map( async uri => { var encryptionProvider = await EncryptionProvider.CreateAsync( this.storagePath, new Uri(uri), this.workloadApiVersion.Expect(() => new InvalidOperationException("Missing workload API version")), Constants.WorkloadApiVersion, this.edgeHubModuleId, this.edgeHubGenerationId.Expect(() => new InvalidOperationException("Missing generation ID")), Constants.InitializationVectorFileName) as IEncryptionProvider; return(Option.Some(encryptionProvider)); }) .GetOrElse(() => Task.FromResult(Option.None <IEncryptionProvider>())); return(encryptionProviderOption); }) .As <Task <Option <IEncryptionProvider> > >() .SingleInstance(); // Task<IStoreProvider> builder.Register(async c => { var dbStoreProvider = await c.Resolve <Task <IDbStoreProvider> >(); IStoreProvider storeProvider = new StoreProvider(dbStoreProvider); return(storeProvider); }) .As <Task <IStoreProvider> >() .SingleInstance(); // Task<IMetadataStore> builder.Register( async c => { var storeProvider = await c.Resolve <Task <IStoreProvider> >(); IKeyValueStore <string, string> entityStore = storeProvider.GetEntityStore <string, string>("ProductInfo", "MetadataStore"); IMetadataStore metadataStore = new MetadataStore(entityStore, this.productInfo); return(metadataStore); }) .As <Task <IMetadataStore> >() .SingleInstance(); // ITokenProvider builder.Register(c => new ClientTokenProvider(c.Resolve <ISignatureProvider>(), this.iothubHostName, this.edgeDeviceId, this.edgeHubModuleId, TimeSpan.FromHours(1))) .Named <ITokenProvider>("EdgeHubClientAuthTokenProvider") .SingleInstance(); // ITokenProvider builder.Register( c => { string deviceId = WebUtility.UrlEncode(this.edgeDeviceId); string moduleId = WebUtility.UrlEncode(this.edgeHubModuleId); return(new ClientTokenProvider(c.Resolve <ISignatureProvider>(), this.iothubHostName, deviceId, moduleId, TimeSpan.FromHours(1))); }) .Named <ITokenProvider>("EdgeHubServiceAuthTokenProvider") .SingleInstance(); builder.Register( c => { var loggerFactory = c.Resolve <ILoggerFactory>(); var logger = loggerFactory.CreateLogger <RoutingModule>(); return(Proxy.Parse(this.proxy, logger)); }) .As <Option <IWebProxy> >() .SingleInstance(); // Task<IDeviceScopeIdentitiesCache> builder.Register( async c => { IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache; if (this.authenticationMode == AuthenticationMode.CloudAndScope || this.authenticationMode == AuthenticationMode.Scope) { var edgeHubTokenProvider = c.ResolveNamed <ITokenProvider>("EdgeHubServiceAuthTokenProvider"); var proxy = c.Resolve <Option <IWebProxy> >(); IServiceIdentityHierarchy serviceIdentityHierarchy; if (this.nestedEdgeEnabled) { serviceIdentityHierarchy = new ServiceIdentityTree(this.edgeDeviceId); } else { serviceIdentityHierarchy = new ServiceIdentityDictionary(this.edgeDeviceId); } string hostName = this.gatewayHostName.GetOrElse(this.iothubHostName); IDeviceScopeApiClientProvider securityScopesApiClientProvider = new DeviceScopeApiClientProvider(hostName, this.edgeDeviceId, this.edgeHubModuleId, 10, edgeHubTokenProvider, serviceIdentityHierarchy, proxy); IServiceProxy serviceProxy = new ServiceProxy(securityScopesApiClientProvider, this.nestedEdgeEnabled); IKeyValueStore <string, string> encryptedStore = await GetEncryptedStore(c, "DeviceScopeCache"); deviceScopeIdentitiesCache = await DeviceScopeIdentitiesCache.Create(serviceIdentityHierarchy, serviceProxy, encryptedStore, this.scopeCacheRefreshRate, this.scopeCacheRefreshDelay); } else { deviceScopeIdentitiesCache = new NullDeviceScopeIdentitiesCache(); } return(deviceScopeIdentitiesCache); }) .As <Task <IDeviceScopeIdentitiesCache> >() .AutoActivate() .SingleInstance(); // IRegistryApiClient builder.Register( c => { string upstreamHostname = this.gatewayHostName.GetOrElse(this.iothubHostName); var proxy = c.Resolve <Option <IWebProxy> >(); var edgeHubTokenProvider = c.ResolveNamed <ITokenProvider>("EdgeHubServiceAuthTokenProvider"); return(new RegistryOnBehalfOfApiClient(upstreamHostname, proxy, edgeHubTokenProvider)); }) .As <IRegistryOnBehalfOfApiClient>() .SingleInstance(); // Task<ICredentialsCache> builder.Register( async c => { ICredentialsCache underlyingCredentialsCache; if (this.persistTokens) { IKeyValueStore <string, string> encryptedStore = await GetEncryptedStore(c, "CredentialsCache"); return(new PersistedTokenCredentialsCache(encryptedStore)); } else { underlyingCredentialsCache = new NullCredentialsCache(); } ICredentialsCache credentialsCache; if (this.nestedEdgeEnabled) { credentialsCache = new NestedCredentialsCache(underlyingCredentialsCache); } else { credentialsCache = new CredentialsCache(underlyingCredentialsCache); } return(credentialsCache); }) .As <Task <ICredentialsCache> >() .SingleInstance(); // Task<IAuthenticator> builder.Register( async c => { IAuthenticator tokenAuthenticator; IAuthenticator certificateAuthenticator; IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache; var credentialsCacheTask = c.Resolve <Task <ICredentialsCache> >(); // by default regardless of how the authenticationMode, X.509 certificate validation will always be scoped deviceScopeIdentitiesCache = await c.Resolve <Task <IDeviceScopeIdentitiesCache> >(); certificateAuthenticator = new DeviceScopeCertificateAuthenticator(deviceScopeIdentitiesCache, new NullAuthenticator(), this.trustBundle, true, this.nestedEdgeEnabled); switch (this.authenticationMode) { case AuthenticationMode.Cloud: tokenAuthenticator = await this.GetCloudTokenAuthenticator(c); break; case AuthenticationMode.Scope: tokenAuthenticator = new DeviceScopeTokenAuthenticator(deviceScopeIdentitiesCache, this.iothubHostName, this.edgeDeviceHostName, new NullAuthenticator(), true, true, this.nestedEdgeEnabled); break; default: IAuthenticator cloudTokenAuthenticator = await this.GetCloudTokenAuthenticator(c); tokenAuthenticator = new DeviceScopeTokenAuthenticator(deviceScopeIdentitiesCache, this.iothubHostName, this.edgeDeviceHostName, cloudTokenAuthenticator, true, true, this.nestedEdgeEnabled); break; } ICredentialsCache credentialsCache = await credentialsCacheTask; return(new Authenticator(tokenAuthenticator, certificateAuthenticator, credentialsCache) as IAuthenticator); }) .As <Task <IAuthenticator> >() .SingleInstance(); // IClientCredentialsFactory builder.Register(c => new ClientCredentialsFactory(c.Resolve <IIdentityProvider>(), this.productInfo)) .As <IClientCredentialsFactory>() .SingleInstance(); // ConnectionReauthenticator builder.Register( async c => { var edgeHubCredentials = c.ResolveNamed <IClientCredentials>("EdgeHubCredentials"); var connectionManagerTask = c.Resolve <Task <IConnectionManager> >(); var authenticatorTask = c.Resolve <Task <IAuthenticator> >(); var credentialsCacheTask = c.Resolve <Task <ICredentialsCache> >(); var deviceScopeIdentitiesCacheTask = c.Resolve <Task <IDeviceScopeIdentitiesCache> >(); var deviceConnectivityManager = c.Resolve <IDeviceConnectivityManager>(); IConnectionManager connectionManager = await connectionManagerTask; IAuthenticator authenticator = await authenticatorTask; ICredentialsCache credentialsCache = await credentialsCacheTask; IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache = await deviceScopeIdentitiesCacheTask; var connectionReauthenticator = new ConnectionReauthenticator( connectionManager, authenticator, credentialsCache, deviceScopeIdentitiesCache, TimeSpan.FromMinutes(5), edgeHubCredentials.Identity, deviceConnectivityManager); return(connectionReauthenticator); }) .As <Task <ConnectionReauthenticator> >() .SingleInstance(); base.Load(builder); }