public async Task GetFromPersistedCacheTest() { // Arrange var identity1 = Mock.Of <IIdentity>(i => i.Id == "d1"); var identity2 = Mock.Of <IIdentity>(i => i.Id == "d2/m2"); var identity3 = Mock.Of <IIdentity>(i => i.Id == "d3"); var identity4 = Mock.Of <IIdentity>(i => i.Id == "d4"); var edgeHub = Mock.Of <IIdentity>(i => i.Id == "edge1/$edgeHub"); var creds1 = Mock.Of <ITokenCredentials>(c => c.Identity == identity1); var creds2 = Mock.Of <IClientCredentials>(c => c.Identity == identity2); var creds3 = Mock.Of <IClientCredentials>(c => c.Identity == edgeHub && c.AuthChain == Option.Some("d3;edge1")); var creds4 = Mock.Of <IClientCredentials>(c => c.Identity == edgeHub && c.AuthChain == Option.Some("d4;edge1")); var underlyingCredentialsCache = new Mock <ICredentialsCache>(); underlyingCredentialsCache.Setup(u => u.Get(identity1)).ReturnsAsync(Option.Some((IClientCredentials)creds1)); underlyingCredentialsCache.Setup(u => u.Get(identity2)).ReturnsAsync(Option.Some(creds2)); underlyingCredentialsCache.Setup(u => u.Get(identity3)).ReturnsAsync(Option.Some(creds3)); underlyingCredentialsCache.Setup(u => u.Get(identity4)).ReturnsAsync(Option.Some(creds4)); var credentialsCache = new NestedCredentialsCache(underlyingCredentialsCache.Object); // Act Option <IClientCredentials> receivedClientCredentials1_1 = await credentialsCache.Get(identity1); Option <IClientCredentials> receivedClientCredentials2_1 = await credentialsCache.Get(identity2); Option <IClientCredentials> receivedClientCredentials1_2 = await credentialsCache.Get(identity1); Option <IClientCredentials> receivedClientCredentials2_2 = await credentialsCache.Get(identity2); Option <IClientCredentials> receivedClientCredentials3 = await credentialsCache.Get(identity3); Option <IClientCredentials> receivedClientCredentials4 = await credentialsCache.Get(identity4); // Assert Assert.True(receivedClientCredentials1_1.HasValue); Assert.True(receivedClientCredentials2_1.HasValue); Assert.Equal(creds1, receivedClientCredentials1_1.OrDefault()); Assert.Equal(creds2, receivedClientCredentials2_1.OrDefault()); Assert.True(receivedClientCredentials1_2.HasValue); Assert.True(receivedClientCredentials2_2.HasValue); Assert.Equal(creds1, receivedClientCredentials1_2.OrDefault()); Assert.Equal(creds2, receivedClientCredentials2_2.OrDefault()); underlyingCredentialsCache.Verify(u => u.Get(identity1), Times.Once); underlyingCredentialsCache.Verify(u => u.Get(identity2), Times.Once); Assert.True(receivedClientCredentials3.HasValue); Assert.True(receivedClientCredentials4.HasValue); Assert.Equal(creds3, receivedClientCredentials3.OrDefault()); Assert.Equal(creds4, receivedClientCredentials4.OrDefault()); }
public async Task OnBehalfOfCredentialsUpdateTest() { // Arrange var underlyingCredentialsCache = new NullCredentialsCache(); var credentialsCache = new NestedCredentialsCache(underlyingCredentialsCache); var identity1 = Mock.Of <IIdentity>(i => i.Id == "d1"); var identity2 = Mock.Of <IIdentity>(i => i.Id == "d2"); var edgeHub = Mock.Of <IIdentity>(i => i.Id == "edge1/$edgeHub"); var creds1 = new TokenCredentials(edgeHub, "edgeHubToken1", "productinfo1", Option.Some("modelId1"), Option.Some("d1;edge1"), true); var creds2 = new TokenCredentials(edgeHub, "edgeHubToken1", "productinfo2", Option.Some("modelId2"), Option.Some("d2;edge1"), true); var newActorCreds = new TokenCredentials(edgeHub, "edgeHubToken2", "productinfo3", Option.Some("modelId3"), Option.None <string>(), true); // Act await credentialsCache.Add(creds1); await credentialsCache.Add(creds2); await credentialsCache.Add(newActorCreds); Option <IClientCredentials> receivedClientCredentials1 = await credentialsCache.Get(identity1); Option <IClientCredentials> receivedClientCredentials2 = await credentialsCache.Get(identity2); // Assert Assert.True(receivedClientCredentials1.HasValue); Assert.True(receivedClientCredentials2.HasValue); var receivedToken1 = receivedClientCredentials1.OrDefault() as ITokenCredentials; Assert.Equal(newActorCreds.Identity, receivedToken1.Identity); Assert.Equal(newActorCreds.Token, receivedToken1.Token); Assert.Equal(creds1.AuthChain, receivedToken1.AuthChain); Assert.Equal(creds1.ProductInfo, receivedToken1.ProductInfo); Assert.Equal(creds1.ModelId, receivedToken1.ModelId); var receivedToken2 = receivedClientCredentials2.OrDefault() as ITokenCredentials; Assert.Equal(newActorCreds.Identity, receivedToken2.Identity); Assert.Equal(newActorCreds.Token, receivedToken2.Token); Assert.Equal(creds2.AuthChain, receivedToken2.AuthChain); Assert.Equal(creds2.ProductInfo, receivedToken2.ProductInfo); Assert.Equal(creds2.ModelId, receivedToken2.ModelId); }
public async Task RoundtripTest() { // Arrange var underlyingCredentialsCache = new NullCredentialsCache(); var credentialsCache = new NestedCredentialsCache(underlyingCredentialsCache); var identity1 = Mock.Of <IIdentity>(i => i.Id == "d1"); var identity2 = Mock.Of <IIdentity>(i => i.Id == "d2/m2"); var identity3 = Mock.Of <IIdentity>(i => i.Id == "d3"); var identity4 = Mock.Of <IIdentity>(i => i.Id == "d4"); var edgeHub = Mock.Of <IIdentity>(i => i.Id == "edge1/$edgeHub"); var creds1 = Mock.Of <ITokenCredentials>(c => c.Identity == identity1); var creds2 = Mock.Of <IClientCredentials>(c => c.Identity == identity2); var creds3 = Mock.Of <IClientCredentials>(c => c.Identity == edgeHub && c.AuthChain == Option.Some("d3;edge1")); var creds4 = Mock.Of <IClientCredentials>(c => c.Identity == edgeHub && c.AuthChain == Option.Some("d4;edge1")); // Act await credentialsCache.Add(creds1); await credentialsCache.Add(creds2); await credentialsCache.Add(creds3); await credentialsCache.Add(creds4); Option <IClientCredentials> receivedClientCredentials1 = await credentialsCache.Get(identity1); Option <IClientCredentials> receivedClientCredentials2 = await credentialsCache.Get(identity2); Option <IClientCredentials> receivedClientCredentials3 = await credentialsCache.Get(identity3); Option <IClientCredentials> receivedClientCredentials4 = await credentialsCache.Get(identity4); // Assert Assert.True(receivedClientCredentials1.HasValue); Assert.True(receivedClientCredentials2.HasValue); Assert.True(receivedClientCredentials3.HasValue); Assert.True(receivedClientCredentials4.HasValue); Assert.Equal(creds1, receivedClientCredentials1.OrDefault()); Assert.Equal(creds2, receivedClientCredentials2.OrDefault()); Assert.Equal(creds3, receivedClientCredentials3.OrDefault()); Assert.Equal(creds4, receivedClientCredentials4.OrDefault()); }
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); }