Esempio n. 1
0
        public async Task AuthenticateAsyncWithModuleCAX509InScopeCacheFails()
        {
            var notBefore = DateTime.Now.Subtract(TimeSpan.FromDays(2));
            var notAfter  = DateTime.Now.AddYears(1);

            var(caCert, caKeyPair) = TestCertificateHelper.GenerateSelfSignedCert("MyTestCA", notBefore, notAfter, true);
            var(issuedClientCert, issuedClientKeyPair) = TestCertificateHelper.GenerateCertificate("MyIssuedTestClient", notBefore, notAfter, caCert, caKeyPair, false, null, null);
            IList <X509Certificate2> issuedClientCertChain = new List <X509Certificate2>()
            {
                caCert
            };
            IList <X509Certificate2> trustBundle = new List <X509Certificate2>()
            {
                caCert
            };
            string deviceId = "d1";
            string moduleId = "MyIssuedTestClient";
            string identity = FormattableString.Invariant($"{deviceId}/{moduleId}");

            var deviceScopeIdentitiesCache = new Mock <IDeviceScopeIdentitiesCache>();
            var clientCredentials          = Mock.Of <ICertificateCredentials>(c =>
                                                                               c.Identity == Mock.Of <IModuleIdentity>(i => i.DeviceId == deviceId && i.ModuleId == moduleId &&
                                                                                                                       i.Id == identity) &&
                                                                               c.AuthenticationType == AuthenticationType.X509Cert &&
                                                                               c.ClientCertificate == issuedClientCert && c.ClientCertificateChain == issuedClientCertChain);

            var serviceIdentity = new ServiceIdentity(deviceId, moduleId, "1234", new string[0],
                                                      new ServiceAuthentication(ServiceAuthenticationType.CertificateAuthority), ServiceIdentityStatus.Enabled);
            var authenticator = new DeviceScopeCertificateAuthenticator(deviceScopeIdentitiesCache.Object, UnderlyingAuthenticator, trustBundle, true);

            deviceScopeIdentitiesCache.Setup(d => d.GetServiceIdentity(It.Is <string>(i => i == identity), false)).ReturnsAsync(Option.Some(serviceIdentity));


            Assert.False(await authenticator.AuthenticateAsync(clientCredentials));
        }
Esempio n. 2
0
        public async Task AuthenticateAsyncWithEmptyChainDeviceCAX509InScopeCacheFails()
        {
            var notBefore        = DateTime.Now.Subtract(TimeSpan.FromDays(2));
            var notAfter         = DateTime.Now.AddYears(1);
            var caCert           = TestCertificateHelper.GenerateSelfSignedCert("MyTestCA", notBefore, notAfter, true);
            var issuedClientCert = TestCertificateHelper.GenerateCertificate("MyIssuedTestClient", notBefore, notAfter, caCert, false, null, null);
            IList <X509Certificate2> issuedClientCertChain = new List <X509Certificate2>()
            {
            };                                                                                // empty chain supplied
            IList <X509Certificate2> trustBundle = new List <X509Certificate2>()
            {
                caCert
            };
            string deviceId = "different from CN";

            var deviceScopeIdentitiesCache = new Mock <IDeviceScopeIdentitiesCache>();
            var clientCredentials          = Mock.Of <ICertificateCredentials>(
                c =>
                c.Identity == Mock.Of <IDeviceIdentity>(i => i.DeviceId == deviceId && i.Id == deviceId) &&
                c.AuthenticationType == AuthenticationType.X509Cert &&
                c.ClientCertificate == issuedClientCert && c.ClientCertificateChain == issuedClientCertChain);

            var serviceIdentity = new ServiceIdentity(
                deviceId,
                "1234",
                new string[0],
                new ServiceAuthentication(ServiceAuthenticationType.CertificateAuthority),
                ServiceIdentityStatus.Enabled);
            var authenticator = new DeviceScopeCertificateAuthenticator(deviceScopeIdentitiesCache.Object, UnderlyingAuthenticator, trustBundle, true);

            deviceScopeIdentitiesCache.Setup(d => d.GetServiceIdentity(It.Is <string>(i => i == deviceId))).ReturnsAsync(Option.Some(serviceIdentity));

            Assert.False(await authenticator.AuthenticateAsync(clientCredentials));
        }
Esempio n. 3
0
        public async Task AuthenticateAsyncWithNonX509CredsFails()
        {
            var deviceScopeIdentitiesCache             = Mock.Of <IDeviceScopeIdentitiesCache>();
            IList <X509Certificate2> trustBundle       = new List <X509Certificate2>();
            IClientCredentials       clientCredentials = Mock.Of <IClientCredentials>();
            var authenticator = new DeviceScopeCertificateAuthenticator(deviceScopeIdentitiesCache, UnderlyingAuthenticator, trustBundle, true);

            Assert.False(await authenticator.AuthenticateAsync(clientCredentials));
        }
        public async Task AuthenticateAsyncWithModuleThumbprintX509InScopeCacheFails()
        {
            string deviceId               = "d1";
            string moduleId               = "m1";
            string identity               = FormattableString.Invariant($"{deviceId}/{moduleId}");
            var    primaryCertificate     = TestCertificateHelper.GenerateSelfSignedCert("primo");
            var    primaryClientCertChain = new List <X509Certificate2>()
            {
                primaryCertificate
            };
            var secondaryCertificate     = TestCertificateHelper.GenerateSelfSignedCert("secondo");
            var secondaryClientCertChain = new List <X509Certificate2>()
            {
                secondaryCertificate
            };

            var deviceScopeIdentitiesCache       = new Mock <IDeviceScopeIdentitiesCache>();
            IList <X509Certificate2> trustBundle = new List <X509Certificate2>();
            var primaryCredentials = Mock.Of <ICertificateCredentials>(
                c =>
                c.Identity == Mock.Of <IModuleIdentity>(
                    i => i.DeviceId == deviceId && i.ModuleId == moduleId &&
                    i.Id == identity) &&
                c.AuthenticationType == AuthenticationType.X509Cert &&
                c.ClientCertificate == primaryCertificate && c.ClientCertificateChain == primaryClientCertChain);

            var secondaryCredentials = Mock.Of <ICertificateCredentials>(
                c =>
                c.Identity == Mock.Of <IModuleIdentity>(
                    i => i.DeviceId == deviceId && i.ModuleId == moduleId &&
                    i.Id == identity) &&
                c.AuthenticationType == AuthenticationType.X509Cert &&
                c.ClientCertificate == secondaryCertificate && c.ClientCertificateChain == secondaryClientCertChain);

            var serviceIdentity = new ServiceIdentity(
                deviceId,
                moduleId,
                "e1",
                new List <string>(),
                "1234",
                new string[0],
                new ServiceAuthentication(new X509ThumbprintAuthentication(primaryCertificate.Thumbprint, secondaryCertificate.Thumbprint)),
                ServiceIdentityStatus.Enabled);
            var authenticator = new DeviceScopeCertificateAuthenticator(deviceScopeIdentitiesCache.Object, UnderlyingAuthenticator, trustBundle, true);

            deviceScopeIdentitiesCache.Setup(d => d.GetServiceIdentity(It.Is <string>(i => i == identity))).ReturnsAsync(Option.Some(serviceIdentity));

            // Assert
            Assert.False(await authenticator.AuthenticateAsync(primaryCredentials));
            Assert.False(await authenticator.AuthenticateAsync(secondaryCredentials));
        }
        public async Task AuthenticateAsyncWithDeviceThumbprintX509InconsistentAuthInScopeCacheFails()
        {
            string deviceId               = "d1";
            var    primaryCertificate     = TestCertificateHelper.GenerateSelfSignedCert("primo");
            var    primaryClientCertChain = new List <X509Certificate2>()
            {
                primaryCertificate
            };
            var secondaryCertificate     = TestCertificateHelper.GenerateSelfSignedCert("secondo");
            var secondaryClientCertChain = new List <X509Certificate2>()
            {
                secondaryCertificate
            };

            var deviceScopeIdentitiesCache       = new Mock <IDeviceScopeIdentitiesCache>();
            IList <X509Certificate2> trustBundle = new List <X509Certificate2>();
            var primaryCredentials = Mock.Of <ICertificateCredentials>(
                c =>
                c.Identity == Mock.Of <IDeviceIdentity>(i => i.DeviceId == deviceId && i.Id == deviceId) &&
                c.AuthenticationType == AuthenticationType.X509Cert &&
                c.ClientCertificate == primaryCertificate && c.ClientCertificateChain == primaryClientCertChain);

            var secondaryCredentials = Mock.Of <ICertificateCredentials>(
                c =>
                c.Identity == Mock.Of <IDeviceIdentity>(i => i.DeviceId == deviceId && i.Id == deviceId) &&
                c.AuthenticationType == AuthenticationType.X509Cert &&
                c.ClientCertificate == secondaryCertificate && c.ClientCertificateChain == secondaryClientCertChain);

            string key             = GetKey();
            var    serviceIdentity = new ServiceIdentity(
                deviceId,
                "1234",
                new string[0],
                new ServiceAuthentication(new SymmetricKeyAuthentication(key, GetKey())),
                ServiceIdentityStatus.Enabled);

            var authenticator = new DeviceScopeCertificateAuthenticator(deviceScopeIdentitiesCache.Object, UnderlyingAuthenticator, trustBundle, true);

            deviceScopeIdentitiesCache.Setup(d => d.GetServiceIdentity(It.Is <string>(i => i == deviceId))).ReturnsAsync(Option.Some(serviceIdentity));

            // Assert
            Assert.False(await authenticator.AuthenticateAsync(secondaryCredentials));
        }
Esempio n. 6
0
        protected override void Load(ContainerBuilder builder)
        {
            // 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"));
                    return(new HttpHsmSignatureProvider(this.edgeHubModuleId, edgeHubGenerationId, workloadUri, 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))
            .As <IRocksDbOptionsProvider>()
            .SingleInstance();

            // IDbStoreProvider
            builder.Register(
                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(!ExceptionEx.IsFatal(ex))
                    {
                        logger.LogError(ex, "Error creating RocksDB store. Falling back to in-memory store.");
                        return(new InMemoryDbStoreProvider());
                    }
                }
                else
                {
                    logger.LogInformation($"Using in-memory store");
                    return(new InMemoryDbStoreProvider());
                }
            })
            .As <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),
                        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();

            // IStoreProvider
            builder.Register(c => new StoreProvider(c.Resolve <IDbStoreProvider>()))
            .As <IStoreProvider>()
            .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();

            // Task<IDeviceScopeIdentitiesCache>
            builder.Register(
                async c =>
            {
                IDeviceScopeIdentitiesCache deviceScopeIdentitiesCache;
                if (this.authenticationMode == AuthenticationMode.CloudAndScope || this.authenticationMode == AuthenticationMode.Scope)
                {
                    var edgeHubTokenProvider = c.ResolveNamed <ITokenProvider>("EdgeHubServiceAuthTokenProvider");
                    IDeviceScopeApiClient securityScopesApiClient = new DeviceScopeApiClient(this.iothubHostName, this.edgeDeviceId, this.edgeHubModuleId, 10, edgeHubTokenProvider);
                    IServiceProxy serviceProxy = new ServiceProxy(securityScopesApiClient);
                    IKeyValueStore <string, string> encryptedStore = await GetEncryptedStore(c, "DeviceScopeCache");
                    deviceScopeIdentitiesCache = await DeviceScopeIdentitiesCache.Create(serviceProxy, encryptedStore, this.scopeCacheRefreshRate);
                }
                else
                {
                    deviceScopeIdentitiesCache = new NullDeviceScopeIdentitiesCache();
                }

                return(deviceScopeIdentitiesCache);
            })
            .As <Task <IDeviceScopeIdentitiesCache> >()
            .AutoActivate()
            .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 = 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);
                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);
                    break;

                default:
                    IAuthenticator cloudTokenAuthenticator = await this.GetCloudTokenAuthenticator(c);
                    tokenAuthenticator = new DeviceScopeTokenAuthenticator(deviceScopeIdentitiesCache, this.iothubHostName, this.edgeDeviceHostName, cloudTokenAuthenticator, true, true);
                    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);
        }
Esempio n. 7
0
        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();

            // IServiceIdentityHierarchy
            builder.Register <IServiceIdentityHierarchy>(
                c =>
            {
                if (this.nestedEdgeEnabled)
                {
                    return(new ServiceIdentityTree(this.edgeDeviceId));
                }
                else
                {
                    return(new ServiceIdentityDictionary(this.edgeDeviceId));
                }
            })
            .As <IServiceIdentityHierarchy>()
            .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 = c.Resolve <IServiceIdentityHierarchy>();

                    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();

            // IClientCredentials "EdgeHubCredentials"
            builder.Register(
                c =>
            {
                var identityFactory = c.Resolve <IClientCredentialsFactory>();
                IClientCredentials edgeHubCredentials = this.edgeHubConnectionString.Map(cs => identityFactory.GetWithConnectionString(cs)).GetOrElse(
                    () => identityFactory.GetWithIotEdged(this.edgeDeviceId, this.edgeHubModuleId));
                return(edgeHubCredentials);
            })
            .Named <IClientCredentials>("EdgeHubCredentials")
            .SingleInstance();

            // ServiceIdentity "EdgeHubIdentity"
            builder.Register(
                c =>
            {
                return(new ServiceIdentity(
                           this.edgeDeviceId,
                           this.edgeHubModuleId,
                           deviceScope: null,
                           parentScopes: new List <string>(),
                           this.edgeHubGenerationId.GetOrElse("0"),
                           capabilities: new List <string>(),
                           new ServiceAuthentication(ServiceAuthenticationType.None),
                           ServiceIdentityStatus.Enabled));
            })
            .Named <ServiceIdentity>("EdgeHubIdentity")
            .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);
        }