public async Task <Try <ICloudConnection> > Connect(IClientCredentials clientCredentials, Action <string, CloudConnectionStatus> connectionStatusChangedHandler) { Preconditions.CheckNotNull(clientCredentials, nameof(clientCredentials)); try { Events.CreatingCloudConnectionUsingClientCredentials(clientCredentials); var cloudListener = new CloudListener(this.edgeHub.Expect(() => new InvalidOperationException("EdgeHub reference should not be null")), clientCredentials.Identity.Id); string productInfo = await this.productInfoStore.GetEdgeProductInfo(clientCredentials.Identity.Id); Option <string> modelId = await this.modelIdStore.GetModelId(clientCredentials.Identity.Id); if (this.edgeHubIdentity.Id.Equals(clientCredentials.Identity.Id)) { ICloudConnection cc = await CloudConnection.Create( clientCredentials.Identity, connectionStatusChangedHandler, this.transportSettings, this.messageConverterProvider, this.clientProvider, cloudListener, this.edgeHubTokenProvider, this.idleTimeout, this.closeOnIdleTimeout, this.operationTimeout, productInfo, modelId); Events.SuccessCreatingCloudConnection(clientCredentials.Identity); return(Try.Success(cc)); } else if (clientCredentials is ITokenCredentials clientTokenCredentails) { ICloudConnection cc = await ClientTokenCloudConnection.Create( clientTokenCredentails, connectionStatusChangedHandler, this.transportSettings, this.messageConverterProvider, this.clientProvider, cloudListener, this.idleTimeout, this.closeOnIdleTimeout, this.operationTimeout, productInfo, modelId); Events.SuccessCreatingCloudConnection(clientCredentials.Identity); return(Try.Success(cc)); } else { throw new InvalidOperationException($"Cannot connect using client credentials of type {clientCredentials.AuthenticationType} for identity {clientCredentials.Identity.Id}"); } } catch (Exception ex) { Events.ErrorCreatingCloudConnection(clientCredentials.Identity, ex); return(Try <ICloudConnection> .Failure(ex)); } }
public async Task CloudConnectionTest() { ICloudConnection cloudConnectionMock = GetCloudConnectionMock(); var cloudProviderMock = new Mock <ICloudConnectionProvider>(); cloudProviderMock.Setup(p => p.Connect(It.IsAny <IClientCredentials>(), It.IsAny <Action <string, CloudConnectionStatus> >())).ReturnsAsync(() => Try.Success(cloudConnectionMock)); // ReSharper disable once PossibleUnintendedReferenceComparison var deviceCredentials = Mock.Of <IClientCredentials>(c => c.Identity == Mock.Of <IIdentity>(d => d.Id == "Device1")); IConnectionManager connectionManager = new ConnectionManager(cloudProviderMock.Object); Option <ICloudProxy> returnedValue = connectionManager.GetCloudConnection(deviceCredentials.Identity.Id); Assert.False(returnedValue.HasValue); Try <ICloudProxy> cloudProxy1 = await connectionManager.CreateCloudConnectionAsync(deviceCredentials); Assert.True(cloudProxy1.Success); Assert.True(cloudProxy1.Value.IsActive); returnedValue = connectionManager.GetCloudConnection(deviceCredentials.Identity.Id); Assert.True(returnedValue.HasValue); Assert.Equal(cloudProxy1.Value, returnedValue.OrDefault()); Try <ICloudProxy> cloudProxy2 = await connectionManager.CreateCloudConnectionAsync(deviceCredentials); Assert.True(cloudProxy2.Success); Assert.True(cloudProxy2.Value.IsActive); await connectionManager.RemoveDeviceConnection(deviceCredentials.Identity.Id); returnedValue = connectionManager.GetCloudConnection(deviceCredentials.Identity.Id); Assert.False(returnedValue.HasValue); }
public async Task <Try <ICloudConnection> > Connect(IIdentity identity, Action <string, CloudConnectionStatus> connectionStatusChangedHandler) { Preconditions.CheckNotNull(identity, nameof(identity)); try { var cloudListener = new CloudListener(this.edgeHub.Expect(() => new InvalidOperationException("EdgeHub reference should not be null")), identity.Id); Option <ServiceIdentity> serviceIdentity = (await this.deviceScopeIdentitiesCache.GetServiceIdentity(identity.Id)) .Filter(s => s.Status == ServiceIdentityStatus.Enabled); return(await serviceIdentity .Map( async si => { Events.CreatingCloudConnectionOnBehalfOf(identity); ConnectionMetadata connectionMetadata = await this.metadataStore.GetMetadata(identity.Id); string productInfo = connectionMetadata.EdgeProductInfo; Option <string> modelId = connectionMetadata.ModelId; ICloudConnection cc = await CloudConnection.Create( identity, connectionStatusChangedHandler, this.transportSettings, this.messageConverterProvider, this.clientProvider, cloudListener, this.edgeHubTokenProvider, this.idleTimeout, this.closeOnIdleTimeout, this.operationTimeout, productInfo, modelId); Events.SuccessCreatingCloudConnection(identity); return Try.Success(cc); }) .GetOrElse( async() => { Events.ServiceIdentityNotFound(identity); Option <IClientCredentials> clientCredentials = await this.credentialsCache.Get(identity); return await clientCredentials .Map(cc => this.Connect(cc, connectionStatusChangedHandler)) .GetOrElse(() => throw new InvalidOperationException($"Unable to find identity {identity.Id} in device scopes cache or credentials cache")); })); } catch (Exception ex) { Events.ErrorCreatingCloudConnection(identity, ex); return(Try <ICloudConnection> .Failure(ex)); } }
public void SetUp() { sdkConfigFactory = Substitute.For <SdkConfig.Factory>(); credentialManager = Substitute.For <ICredentialManager>(); cloudConnection = Substitute.For <ICloudConnection>(); funcToRun = Substitute.For <GrpcProjectFunction>(); // Since a channel doesn't initialize the connection until an API is called, and since // we don't call any APIs we can use a real channel object. Use an empty host - if // this behaviour changes in the future, the channel will fail to connect. var channel = new Channel("", ChannelCredentials.Insecure); cloudConnection.CreateChannel(Arg.Any <string>(), Arg.Any <string>()).Returns(channel); cloudRunner = new CloudRunner(sdkConfigFactory, credentialManager, cloudConnection, new GgpSDKUtil()); }
async Task <Try <ICloudConnection> > TryCreateCloudConnectionFromServiceIdentity(IIdentity identity, Action <string, CloudConnectionStatus> connectionStatusChangedHandler, bool refreshOutOfDateCache, CloudListener cloudListener, string authChain) { Events.CreatingCloudConnectionOnBehalfOf(identity); ConnectionMetadata connectionMetadata = await this.metadataStore.GetMetadata(identity.Id); string productInfo = connectionMetadata.EdgeProductInfo; Option <string> modelId = connectionMetadata.ModelId; ITransportSettings[] transportSettings = GetTransportSettings( this.upstreamProtocol, this.connectionPoolSize, this.proxy, this.useServerHeartbeat, authChain); try { ICloudConnection cc = await CloudConnection.Create( identity, connectionStatusChangedHandler, transportSettings, this.messageConverterProvider, this.clientProvider, cloudListener, this.edgeHubTokenProvider, this.idleTimeout, this.closeOnIdleTimeout, this.operationTimeout, productInfo, modelId); Events.SuccessCreatingCloudConnection(identity); return(Try.Success(cc)); } catch (UnauthorizedException ex) when(this.trackDeviceState) { return(await this.TryRecoverCloudConnection(identity, connectionStatusChangedHandler, refreshOutOfDateCache, ex)); } }
public async Task <Try <ICloudConnection> > Connect(IClientCredentials clientCredentials, Action <string, CloudConnectionStatus> connectionStatusChangedHandler) { Preconditions.CheckNotNull(clientCredentials, nameof(clientCredentials)); try { Events.CreatingCloudConnectionUsingClientCredentials(clientCredentials); var cloudListener = new CloudListener(this.edgeHub.Expect(() => new InvalidOperationException("EdgeHub reference should not be null")), clientCredentials.Identity.Id); ConnectionMetadata connectionMetadata = await this.metadataStore.GetMetadata(clientCredentials.Identity.Id); string productInfo = connectionMetadata.EdgeProductInfo; Option <string> modelId = clientCredentials.ModelId.HasValue ? clientCredentials.ModelId : connectionMetadata.ModelId; string authChain = string.Empty; if (this.nestedEdgeEnabled) { Option <string> authChainMaybe = await this.deviceScopeIdentitiesCache.GetAuthChain(clientCredentials.Identity.Id); // It's possible to have no auth-chain for out-of-scope leaf devices connecting through // us as a gateway. In this case we let the upstream connection happen anyways, as any // unauthorized attempt here would be denied by IoTHub. authChain = authChainMaybe.OrDefault(); } // Get the transport settings ITransportSettings[] transportSettings = GetTransportSettings( this.upstreamProtocol, this.connectionPoolSize, this.proxy, this.useServerHeartbeat, authChain); if (this.edgeHubIdentity.Id.Equals(clientCredentials.Identity.Id)) { ICloudConnection cc = await CloudConnection.Create( clientCredentials.Identity, connectionStatusChangedHandler, transportSettings, this.messageConverterProvider, this.clientProvider, cloudListener, this.edgeHubTokenProvider, this.idleTimeout, this.closeOnIdleTimeout, this.operationTimeout, productInfo, modelId); Events.SuccessCreatingCloudConnection(clientCredentials.Identity); return(Try.Success(cc)); } else if (clientCredentials is ITokenCredentials clientTokenCredentails) { ICloudConnection cc = await ClientTokenCloudConnection.Create( clientTokenCredentails, connectionStatusChangedHandler, transportSettings, this.messageConverterProvider, this.clientProvider, cloudListener, this.idleTimeout, this.closeOnIdleTimeout, this.operationTimeout, productInfo, modelId); Events.SuccessCreatingCloudConnection(clientCredentials.Identity); return(Try.Success(cc)); } else { throw new InvalidOperationException($"Cannot connect using client credentials of type {clientCredentials.AuthenticationType} for identity {clientCredentials.Identity.Id}"); } } catch (Exception ex) { Events.ErrorCreatingCloudConnection(clientCredentials.Identity, ex); return(Try <ICloudConnection> .Failure(ex)); } }
async Task <Try <ICloudConnection> > ConnectInternal(IIdentity identity, Action <string, CloudConnectionStatus> connectionStatusChangedHandler) { Preconditions.CheckNotNull(identity, nameof(identity)); try { var cloudListener = new CloudListener(this.edgeHub.Expect(() => new InvalidOperationException("EdgeHub reference should not be null")), identity.Id); Option <ServiceIdentity> serviceIdentity = (await this.deviceScopeIdentitiesCache.GetServiceIdentity(identity.Id)) .Filter(s => s.Status == ServiceIdentityStatus.Enabled); string authChain = string.Empty; if (this.nestedEdgeEnabled) { Option <string> authChainMaybe = await this.deviceScopeIdentitiesCache.GetAuthChain(identity.Id); authChain = authChainMaybe.Expect(() => new InvalidOperationException($"No auth chain for the client identity: {identity.Id}")); } ITransportSettings[] transportSettings = GetTransportSettings( this.upstreamProtocol, this.connectionPoolSize, this.proxy, this.useServerHeartbeat, authChain); return(await serviceIdentity .Map( async si => { Events.CreatingCloudConnectionOnBehalfOf(identity); ConnectionMetadata connectionMetadata = await this.metadataStore.GetMetadata(identity.Id); string productInfo = connectionMetadata.EdgeProductInfo; Option <string> modelId = connectionMetadata.ModelId; ICloudConnection cc = await CloudConnection.Create( identity, connectionStatusChangedHandler, transportSettings, this.messageConverterProvider, this.clientProvider, cloudListener, this.edgeHubTokenProvider, this.idleTimeout, this.closeOnIdleTimeout, this.operationTimeout, productInfo, modelId); Events.SuccessCreatingCloudConnection(identity); return Try.Success(cc); }) .GetOrElse( async() => { // allow to use credential cache when auth mode is not Scope only (could be CloudAndScope or Cloud) or identity is for edgeHub if (!this.scopeAuthenticationOnly || this.edgeHubIdentity.Id.Equals(identity.Id)) { Events.ServiceIdentityNotFound(identity); Option <IClientCredentials> clientCredentials = await this.credentialsCache.Get(identity); var clientCredential = clientCredentials.Expect(() => new InvalidOperationException($"Unable to find identity {identity.Id} in device scopes cache or credentials cache")); return await this.Connect(clientCredential, connectionStatusChangedHandler); } else { throw new InvalidOperationException($"Unable to find identity {identity.Id} in device scopes cache"); } })); } catch (Exception ex) { Events.ErrorCreatingCloudConnection(identity, ex); return(Try <ICloudConnection> .Failure(ex)); } }