Ejemplo n.º 1
0
        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));
            }
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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));
            }
        }
Ejemplo n.º 4
0
        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());
        }
Ejemplo n.º 5
0
        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));
            }
        }
Ejemplo n.º 6
0
        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));
            }
        }
Ejemplo n.º 7
0
        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));
            }
        }