Example #1
0
        private static async Task <string> BuildConnectionStringAsync(RegistryManager registryManager, DeviceItem deviceItem, TraceWriter log)
        {
            var iotHubConnectionString = IotHubConnectionStringBuilder.Create(Environment.GetEnvironmentVariable("IoTHubConnectionString"));
            var device = await registryManager.GetDeviceAsync(deviceItem.Name);

            var deviceKeyInfo          = new DeviceAuthenticationWithRegistrySymmetricKey(deviceItem.Name, device.Authentication.SymmetricKey.PrimaryKey);
            var deviceConnectionString = ClientIotHubConnectionStringBuilder.Create(iotHubConnectionString.HostName, deviceKeyInfo);

            return(deviceConnectionString.ToString());
        }
        /// <summary>
        /// Populates an <see cref="IotHubConnectionStringBuilder"/> instance based on the properties of the current instance.
        /// </summary>
        /// <param name="iotHubConnectionStringBuilder">Instance to populate.</param>
        /// <returns>The populated <see cref="IotHubConnectionStringBuilder"/> instance.</returns>
        public IotHubConnectionStringBuilder Populate(IotHubConnectionStringBuilder iotHubConnectionStringBuilder)
        {
            if (iotHubConnectionStringBuilder == null)
            {
                throw new ArgumentNullException("iotHubConnectionStringBuilder");
            }

            iotHubConnectionStringBuilder.DeviceId              = this.DeviceId;
            iotHubConnectionStringBuilder.UsingX509Cert         = true;
            iotHubConnectionStringBuilder.Certificate           = this.Certificate;
            iotHubConnectionStringBuilder.SharedAccessSignature = null;
            iotHubConnectionStringBuilder.SharedAccessKey       = null;
            iotHubConnectionStringBuilder.SharedAccessKeyName   = null;

            return(iotHubConnectionStringBuilder);
        }
Example #3
0
        /// <summary>
        /// Create a DeviceClient from individual parameters
        /// </summary>
        /// <param name="hostname">The fully-qualified DNS hostname of IoT Hub</param>
        /// <param name="authenticationMethod">The authentication method that is used</param>
        /// <param name="transportType">The transportType used (Http1 or Amqp)</param>
        /// <returns>DeviceClient</returns>
        public static DeviceClient Create(string hostname, IAuthenticationMethod authenticationMethod, TransportType transportType)
        {
            if (hostname == null)
            {
                throw new ArgumentNullException("hostname");
            }

            if (authenticationMethod == null)
            {
                throw new ArgumentNullException("authMethod");
            }

            var connectionStringBuilder = IotHubConnectionStringBuilder.Create(hostname, authenticationMethod);

            return(CreateFromConnectionString(connectionStringBuilder.ToString(), transportType));
        }
Example #4
0
        /// <summary>
        /// Create a InternalClient from individual parameters
        /// </summary>
        /// <param name="hostname">The fully-qualified DNS hostname of IoT Hub</param>
        /// <param name="gatewayHostname">The fully-qualified DNS hostname of Gateway</param>
        /// <param name="authenticationMethod">The authentication method that is used</param>
        /// <param name="transportType">The transportType used (Http1, Amqp or Mqtt), <see cref="TransportType"/></param>
        /// <param name="options">The options that allow configuration of the device client instance during initialization.</param>
        /// <returns>InternalClient</returns>
        public static InternalClient Create(string hostname, string gatewayHostname, IAuthenticationMethod authenticationMethod, TransportType transportType, ClientOptions options = default)
        {
            if (hostname == null)
            {
                throw new ArgumentNullException(nameof(hostname));
            }

            if (authenticationMethod == null)
            {
                throw new ArgumentNullException(nameof(authenticationMethod));
            }

            IotHubConnectionStringBuilder connectionStringBuilder = IotHubConnectionStringBuilder.Create(hostname, gatewayHostname, authenticationMethod);

            if (authenticationMethod is DeviceAuthenticationWithX509Certificate)
            {
                if (connectionStringBuilder.Certificate == null)
                {
                    throw new ArgumentException("certificate must be present in DeviceAuthenticationWithX509Certificate");
                }

                // If the file upload transport settings hasn't been specified, we will create one using the client certificate on the connection string
                if (options?.FileUploadTransportSettings == null)
                {
                    var fileUploadTransportSettings = new Http1TransportSettings {
                        ClientCertificate = connectionStringBuilder.Certificate
                    };
                    if (options == null)
                    {
                        options = new ClientOptions {
                            FileUploadTransportSettings = fileUploadTransportSettings
                        };
                    }
                    else
                    {
                        options.FileUploadTransportSettings = fileUploadTransportSettings;
                    }
                }

                InternalClient dc = CreateFromConnectionString(connectionStringBuilder.ToString(), PopulateCertificateInTransportSettings(connectionStringBuilder, transportType), options);
                dc.Certificate = connectionStringBuilder.Certificate;

                return(dc);
            }

            return(CreateFromConnectionString(connectionStringBuilder.ToString(), authenticationMethod, transportType, null, options));
        }
Example #5
0
        /// <summary>
        /// Create a InternalClient from individual parameters
        /// </summary>
        /// <param name="hostname">The fully-qualified DNS hostname of IoT hub</param>
        /// <param name="gatewayHostname">The fully-qualified DNS hostname of Gateway</param>
        /// <param name="authenticationMethod">The authentication method that is used</param>
        /// <param name="transportSettings">Prioritized list of transportTypes and their settings</param>
        /// <param name="options">The options that allow configuration of the device client instance during initialization.</param>
        /// <returns>InternalClient</returns>
        internal static InternalClient Create(
            string hostname,
            string gatewayHostname,
            IAuthenticationMethod authenticationMethod,
            ITransportSettings[] transportSettings,
            ClientOptions options = default)
        {
            if (hostname == null)
            {
                throw new ArgumentNullException(nameof(hostname));
            }

            if (authenticationMethod == null)
            {
                throw new ArgumentNullException(nameof(authenticationMethod));
            }

            if (!string.IsNullOrWhiteSpace(options?.ModelId) &&
                transportSettings.Any(x => x.GetTransportType() == TransportType.Http1))
            {
                throw new InvalidOperationException("Plug and Play is not supported over the HTTP transport.");
            }

            var connectionStringBuilder = IotHubConnectionStringBuilder.Create(hostname, gatewayHostname, authenticationMethod);

            // Make sure client options is initialized with the correct transport setting.
            EnsureOptionsIsSetup(connectionStringBuilder.Certificate, ref options);

            if (authenticationMethod is DeviceAuthenticationWithX509Certificate)
            {
                if (connectionStringBuilder.Certificate == null)
                {
                    throw new ArgumentException("No certificate was found. To use certificate authentication certificate must be present.");
                }

                InternalClient dc = CreateFromConnectionString(
                    connectionStringBuilder.ToString(),
                    PopulateCertificateInTransportSettings(connectionStringBuilder, transportSettings),
                    options);
                dc.Certificate = connectionStringBuilder.Certificate;
                return(dc);
            }

            return(CreateFromConnectionString(connectionStringBuilder.ToString(), authenticationMethod, transportSettings, null, options));
        }
        internal static IAuthenticationMethod GetAuthenticationMethod(IotHubConnectionStringBuilder csBuilder)
        {
            if (csBuilder.SharedAccessKeyName != null)
            {
                return(new DeviceAuthenticationWithSharedAccessPolicyKey(
                           csBuilder.DeviceId,
                           csBuilder.SharedAccessKeyName,
                           csBuilder.SharedAccessKey));
            }
            else if (csBuilder.SharedAccessKey != null)
            {
                if (csBuilder.ModuleId != null)
                {
                    return(new ModuleAuthenticationWithRegistrySymmetricKey(
                               csBuilder.DeviceId,
                               csBuilder.ModuleId,
                               csBuilder.SharedAccessKey));
                }
                else
                {
                    return(new DeviceAuthenticationWithRegistrySymmetricKey(
                               csBuilder.DeviceId,
                               csBuilder.SharedAccessKey));
                }
            }
            else if (csBuilder.SharedAccessSignature != null)
            {
                return(csBuilder.ModuleId == null
                    ? (IAuthenticationMethod) new DeviceAuthenticationWithToken(
                           csBuilder.DeviceId,
                           csBuilder.SharedAccessSignature)
                    : new ModuleAuthenticationWithToken(
                           csBuilder.DeviceId,
                           csBuilder.ModuleId,
                           csBuilder.SharedAccessSignature));
            }
            else if (csBuilder.UsingX509Cert)
            {
                return(new DeviceAuthenticationWithX509Certificate(csBuilder.DeviceId, csBuilder.Certificate));
            }

            throw new InvalidOperationException($"Unsupported authentication method in '{csBuilder}'.");
        }
Example #7
0
        static internal IAuthenticationMethod GetAuthenticationMethod(IotHubConnectionStringBuilder iotHubConnectionStringBuilder)
        {
            if (iotHubConnectionStringBuilder.SharedAccessKeyName != null)
            {
                return(new DeviceAuthenticationWithSharedAccessPolicyKey(
                           iotHubConnectionStringBuilder.DeviceId, iotHubConnectionStringBuilder.SharedAccessKeyName, iotHubConnectionStringBuilder.SharedAccessKey));
            }
            else if (iotHubConnectionStringBuilder.SharedAccessKey != null)
            {
                return(new DeviceAuthenticationWithRegistrySymmetricKey(
                           iotHubConnectionStringBuilder.DeviceId, iotHubConnectionStringBuilder.SharedAccessKey));
            }
            else if (iotHubConnectionStringBuilder.SharedAccessSignature != null)
            {
                return(new DeviceAuthenticationWithToken(iotHubConnectionStringBuilder.DeviceId, iotHubConnectionStringBuilder.SharedAccessSignature));
            }

            throw new InvalidOperationException("Unsupported Authentication Method {0}".FormatInvariant(iotHubConnectionStringBuilder));
        }
Example #8
0
        public IotHubConnectionString(IotHubConnectionStringBuilder builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException("builder");
            }

            this.HostName              = builder.HostName;
            this.SharedAccessKeyName   = builder.SharedAccessKeyName;
            this.SharedAccessKey       = builder.SharedAccessKey;
            this.SharedAccessSignature = builder.SharedAccessSignature;
            this.IotHubName            = builder.IotHubName;
            this.DeviceId              = builder.DeviceId;
#if WINDOWS_UWP
            this.HttpsEndpoint = new UriBuilder("https", builder.HostName).Uri;
#else
            this.HttpsEndpoint = new UriBuilder(Uri.UriSchemeHttps, builder.HostName).Uri;
#endif
#if !WINDOWS_UWP
            this.AmqpEndpoint = new UriBuilder(CommonConstants.AmqpsScheme, builder.HostName, AmqpConstants.DefaultSecurePort).Uri;
#endif
        }
        public IotHubConnectionString(IotHubConnectionStringBuilder builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException("builder");
            }

            this.Audience              = builder.HostName;
            this.HostName              = builder.GatewayHostName == null || builder.GatewayHostName == "" ? builder.HostName : builder.GatewayHostName;
            this.SharedAccessKeyName   = builder.SharedAccessKeyName;
            this.SharedAccessKey       = builder.SharedAccessKey;
            this.SharedAccessSignature = builder.SharedAccessSignature;
            this.IotHubName            = builder.IotHubName;
            this.DeviceId              = builder.DeviceId;
            this.ModuleId              = builder.ModuleId;

#if NETSTANDARD1_3
            this.HttpsEndpoint = new UriBuilder("https", this.HostName).Uri;
#elif !NETMF
            this.HttpsEndpoint = new UriBuilder(Uri.UriSchemeHttps, this.HostName).Uri;
#elif NETMF
            this.HttpsEndpoint = new Uri("https://" + this.HostName);
#endif

#if !NETMF
            this.AmqpEndpoint = new UriBuilder(CommonConstants.AmqpsScheme, this.HostName, AmqpConstants.DefaultSecurePort).Uri;

            if (builder.AuthenticationMethod is AuthenticationWithTokenRefresh)
            {
                this.TokenRefresher = (AuthenticationWithTokenRefresh)builder.AuthenticationMethod;
            }
            else if (!string.IsNullOrEmpty(this.SharedAccessKey))
            {
                this.TokenRefresher = this.ModuleId.IsNullOrWhiteSpace()
                    ? new DeviceAuthenticationWithSakRefresh(this.DeviceId, this)
                    : new ModuleAuthenticationWithSakRefresh(this.DeviceId, this.ModuleId, this) as AuthenticationWithTokenRefresh;
            }
#endif
        }
Example #10
0
        static ITransportSettings[] PopulateCertificateInTransportSettings(IotHubConnectionStringBuilder connectionStringBuilder, ITransportSettings[] transportSettings)
        {
            foreach (var transportSetting in  transportSettings)
            {
                switch (transportSetting.GetTransportType())
                {
                case TransportType.Amqp_WebSocket_Only:
                case TransportType.Amqp_Tcp_Only:
                    ((AmqpTransportSettings)transportSetting).ClientCertificate = connectionStringBuilder.Certificate;
                    break;

                case TransportType.Http1:
                    ((Http1TransportSettings)transportSetting).ClientCertificate = connectionStringBuilder.Certificate;
                    break;

                case TransportType.Mqtt:
                    throw new InvalidOperationException("Unsupported Transport {0}".FormatInvariant(transportSetting.GetTransportType()));
                }
            }

            return(transportSettings);
        }
        internal static IotHubConnectionStringBuilder CreateWithIAuthenticationOverride(
            string iotHubConnectionString,
            IAuthenticationMethod authenticationMethod)
        {
            var iotHubConnectionStringBuilder = new IotHubConnectionStringBuilder
            {
                HostName = "TEMP.HUB",
            };

            if (authenticationMethod == null)
            {
                iotHubConnectionStringBuilder.Parse(iotHubConnectionString);
                iotHubConnectionStringBuilder.AuthenticationMethod =
                    AuthenticationMethodFactory.GetAuthenticationMethod(iotHubConnectionStringBuilder);
            }
            else
            {
                iotHubConnectionStringBuilder.AuthenticationMethod = authenticationMethod;
                iotHubConnectionStringBuilder.Parse(iotHubConnectionString);
            }

            return(iotHubConnectionStringBuilder);
        }
Example #12
0
        private static ITransportSettings[] PopulateCertificateInTransportSettings(IotHubConnectionStringBuilder connectionStringBuilder, TransportType transportType)
        {
            switch (transportType)
            {
            case TransportType.Amqp:
                return(new ITransportSettings[]
                {
                    new AmqpTransportSettings(TransportType.Amqp_Tcp_Only)
                    {
                        ClientCertificate = connectionStringBuilder.Certificate
                    },
                    new AmqpTransportSettings(TransportType.Amqp_WebSocket_Only)
                    {
                        ClientCertificate = connectionStringBuilder.Certificate
                    }
                });

            case TransportType.Amqp_Tcp_Only:
                return(new ITransportSettings[]
                {
                    new AmqpTransportSettings(TransportType.Amqp_Tcp_Only)
                    {
                        ClientCertificate = connectionStringBuilder.Certificate
                    }
                });

            case TransportType.Amqp_WebSocket_Only:
                return(new ITransportSettings[]
                {
                    new AmqpTransportSettings(TransportType.Amqp_WebSocket_Only)
                    {
                        ClientCertificate = connectionStringBuilder.Certificate
                    }
                });

            case TransportType.Http1:
                return(new ITransportSettings[]
                {
                    new Http1TransportSettings()
                    {
                        ClientCertificate = connectionStringBuilder.Certificate
                    }
                });

            case TransportType.Mqtt:
                return(new ITransportSettings[]
                {
                    new MqttTransportSettings(TransportType.Mqtt_Tcp_Only)
                    {
                        ClientCertificate = connectionStringBuilder.Certificate
                    },
                    new MqttTransportSettings(TransportType.Mqtt_WebSocket_Only)
                    {
                        ClientCertificate = connectionStringBuilder.Certificate
                    }
                });

            case TransportType.Mqtt_Tcp_Only:
                return(new ITransportSettings[]
                {
                    new MqttTransportSettings(TransportType.Mqtt_Tcp_Only)
                    {
                        ClientCertificate = connectionStringBuilder.Certificate
                    }
                });

            case TransportType.Mqtt_WebSocket_Only:
                return(new ITransportSettings[]
                {
                    new MqttTransportSettings(TransportType.Mqtt_WebSocket_Only)
                    {
                        ClientCertificate = connectionStringBuilder.Certificate
                    }
                });

            default:
                throw new InvalidOperationException("Unsupported Transport {0}".FormatInvariant(transportType));
            }
        }
Example #13
0
        internal static InternalClient CreateFromConnectionString(
            string connectionString,
            IAuthenticationMethod authenticationMethod,
            ITransportSettings[] transportSettings,
            IDeviceClientPipelineBuilder pipelineBuilder,
            ClientOptions options = default)
        {
            if (connectionString == null)
            {
                throw new ArgumentNullException(nameof(connectionString));
            }

            if (transportSettings == null)
            {
                throw new ArgumentNullException(nameof(transportSettings));
            }

            if (transportSettings.Length == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(connectionString), "Must specify at least one TransportSettings instance");
            }

            var builder = IotHubConnectionStringBuilder.CreateWithIAuthenticationOverride(
                connectionString,
                authenticationMethod);

            IotHubConnectionString iotHubConnectionString = builder.ToIotHubConnectionString();

            foreach (ITransportSettings transportSetting in transportSettings)
            {
                switch (transportSetting.GetTransportType())
                {
                case TransportType.Amqp_WebSocket_Only:
                case TransportType.Amqp_Tcp_Only:
                    if (!(transportSetting is AmqpTransportSettings))
                    {
                        throw new InvalidOperationException("Unknown implementation of ITransportSettings type");
                    }
                    break;

                case TransportType.Http1:
                    if (!(transportSetting is Http1TransportSettings))
                    {
                        throw new InvalidOperationException("Unknown implementation of ITransportSettings type");
                    }
                    break;

                case TransportType.Mqtt_WebSocket_Only:
                case TransportType.Mqtt_Tcp_Only:
                    if (!(transportSetting is MqttTransportSettings))
                    {
                        throw new InvalidOperationException("Unknown implementation of ITransportSettings type");
                    }
                    break;

                default:
                    throw new InvalidOperationException("Unsupported Transport Type {0}".FormatInvariant(transportSetting.GetTransportType()));
                }
            }

            pipelineBuilder = pipelineBuilder ?? BuildPipeline();

            // Defer concrete InternalClient creation to OpenAsync
            var client = new InternalClient(iotHubConnectionString, transportSettings, pipelineBuilder, options);

            if (Logging.IsEnabled)
            {
                Logging.CreateFromConnectionString(client, $"HostName={iotHubConnectionString.HostName};DeviceId={iotHubConnectionString.DeviceId};ModuleId={iotHubConnectionString.ModuleId}", transportSettings, options);
            }
            return(client);
        }
        public IotHubConnectionString(IotHubConnectionStringBuilder builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException("builder");
            }

            this.Audience              = builder.HostName;
            this.HostName              = builder.GatewayHostName == null || builder.GatewayHostName == "" ? builder.HostName : builder.GatewayHostName;
            this.SharedAccessKeyName   = builder.SharedAccessKeyName;
            this.SharedAccessKey       = builder.SharedAccessKey;
            this.SharedAccessSignature = builder.SharedAccessSignature;
            this.IotHubName            = builder.IotHubName;
            this.DeviceId              = builder.DeviceId;
            this.ModuleId              = builder.ModuleId;

#if NETSTANDARD1_3
            this.HttpsEndpoint = new UriBuilder("https", this.HostName).Uri;
#elif !NETMF
            this.HttpsEndpoint = new UriBuilder(Uri.UriSchemeHttps, this.HostName).Uri;
#elif NETMF
            this.HttpsEndpoint = new Uri("https://" + this.HostName);
#endif

#if !NETMF
            this.AmqpEndpoint = new UriBuilder(CommonConstants.AmqpsScheme, this.HostName, DefaultSecurePort).Uri;

            if (builder.AuthenticationMethod is AuthenticationWithTokenRefresh)
            {
                this.TokenRefresher = (AuthenticationWithTokenRefresh)builder.AuthenticationMethod;
                if (Logging.IsEnabled)
                {
                    Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(AuthenticationWithTokenRefresh)}: {Logging.IdOf(TokenRefresher)}");
                }
                if (Logging.IsEnabled)
                {
                    Logging.Associate(this, TokenRefresher, nameof(TokenRefresher));
                }
                Debug.Assert(TokenRefresher != null);
            }
            else if (!string.IsNullOrEmpty(this.SharedAccessKey))
            {
                if (this.ModuleId.IsNullOrWhiteSpace())
                {
                    this.TokenRefresher = new DeviceAuthenticationWithSakRefresh(this.DeviceId, this) as AuthenticationWithTokenRefresh;
                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(DeviceAuthenticationWithSakRefresh)}: {Logging.IdOf(TokenRefresher)}");
                    }
                }
                else
                {
                    this.TokenRefresher = new ModuleAuthenticationWithSakRefresh(this.DeviceId, this.ModuleId, this) as AuthenticationWithTokenRefresh;
                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(ModuleAuthenticationWithSakRefresh)}: {Logging.IdOf(TokenRefresher)}");
                    }
                }

                if (Logging.IsEnabled)
                {
                    Logging.Associate(this, TokenRefresher, nameof(TokenRefresher));
                }
                Debug.Assert(TokenRefresher != null);
            }
#endif
        }
Example #15
0
        public static IotHubConnectionString Parse(string connectionString)
        {
            var builder = IotHubConnectionStringBuilder.Create(connectionString);

            return(builder.ToIotHubConnectionString());
        }
        public IotHubConnectionString(IotHubConnectionStringBuilder builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            Audience       = builder.HostName;
            IsUsingGateway = !string.IsNullOrEmpty(builder.GatewayHostName);
            HostName       = IsUsingGateway
                ? builder.GatewayHostName
                : builder.HostName;
            SharedAccessKeyName = builder.SharedAccessKeyName;
            SharedAccessKey     = builder.SharedAccessKey;
            IotHubName          = builder.IotHubName;
            DeviceId            = builder.DeviceId;
            ModuleId            = builder.ModuleId;

            HttpsEndpoint = new UriBuilder(Uri.UriSchemeHttps, HostName).Uri;

            AmqpEndpoint = new UriBuilder(CommonConstants.AmqpsScheme, HostName, DefaultSecurePort).Uri;

            if (builder.AuthenticationMethod is AuthenticationWithTokenRefresh authWithTokenRefresh)
            {
                TokenRefresher = authWithTokenRefresh;
                if (Logging.IsEnabled)
                {
                    Logging.Info(
                        this,
                        $"{nameof(IAuthenticationMethod)} is {nameof(AuthenticationWithTokenRefresh)}: {Logging.IdOf(TokenRefresher)}");
                    Logging.Associate(this, TokenRefresher, nameof(TokenRefresher));
                }

                Debug.Assert(TokenRefresher != null);
            }
            else if (!string.IsNullOrEmpty(SharedAccessKey))
            {
                if (ModuleId.IsNullOrWhiteSpace())
                {
                    // Since the SDK creates the instance of disposable DeviceAuthenticationWithSakRefresh, the SDK needs to
                    // dispose it once the client is disposed.
                    TokenRefresher = new DeviceAuthenticationWithSakRefresh(
                        DeviceId,
                        this,
                        builder.SasTokenTimeToLive,
                        builder.SasTokenRenewalBuffer,
                        disposeWithClient: true);

                    if (Logging.IsEnabled)
                    {
                        Logging.Info(
                            this,
                            $"{nameof(IAuthenticationMethod)} is {nameof(DeviceAuthenticationWithSakRefresh)}: {Logging.IdOf(TokenRefresher)}");
                    }
                }
                else
                {
                    // Since the SDK creates the instance of disposable ModuleAuthenticationWithSakRefresh, the SDK needs to
                    // dispose it once the client is disposed.
                    TokenRefresher = new ModuleAuthenticationWithSakRefresh(
                        DeviceId,
                        ModuleId,
                        this,
                        builder.SasTokenTimeToLive,
                        builder.SasTokenRenewalBuffer,
                        disposeWithClient: true);

                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(ModuleAuthenticationWithSakRefresh)}: {Logging.IdOf(TokenRefresher)}");
                    }
                }

                if (Logging.IsEnabled)
                {
                    Logging.Associate(this, TokenRefresher, nameof(TokenRefresher));
                }

                Debug.Assert(TokenRefresher != null);
            }
            // SharedAccessSignature should be set only if it is non-null and the authentication method of the device client is
            // not of type AuthenticationWithTokenRefresh.
            // Setting the sas value for an AuthenticationWithTokenRefresh authentication type will result in tokens not being renewed.
            // This flow can be hit if the same authentication method is always used to initialize the client;
            // as in, on disposal and reinitialization. This is because the value of the sas token computed is stored within the authentication method,
            // and on reinitialization the client is incorrectly identified as a fixed-sas-token-initialized client,
            // instead of being identified as a sas-token-refresh-enabled-client.
            else if (!string.IsNullOrWhiteSpace(builder.SharedAccessSignature))
            {
                SharedAccessSignature = builder.SharedAccessSignature;
            }
        }
Example #17
0
        /// <summary>
        /// Create a InternalClient from individual parameters
        /// </summary>
        /// <param name="hostname">The fully-qualified DNS hostname of IoT hub</param>
        /// <param name="gatewayHostname">The fully-qualified DNS hostname of Gateway</param>
        /// <param name="authenticationMethod">The authentication method that is used</param>
        /// <param name="transportType">The transportType used (Http1, Amqp or Mqtt), <see cref="TransportType"/></param>
        /// <param name="options">The options that allow configuration of the device client instance during initialization.</param>
        /// <returns>InternalClient</returns>
        internal static InternalClient Create(
            string hostname,
            string gatewayHostname,
            IAuthenticationMethod authenticationMethod,
            TransportType transportType,
            ClientOptions options = default)
        {
            if (hostname == null)
            {
                throw new ArgumentNullException(nameof(hostname));
            }

            if (authenticationMethod == null)
            {
                throw new ArgumentNullException(nameof(authenticationMethod));
            }

            if (transportType != TransportType.Amqp_Tcp_Only &&
                transportType != TransportType.Mqtt_Tcp_Only &&
                authenticationMethod is DeviceAuthenticationWithX509Certificate certificate &&
                certificate.ChainCertificates != null)
            {
                throw new ArgumentException("Certificate chains are only supported on Amqp_Tcp_Only and Mqtt_Tcp_Only");
            }

            if (!string.IsNullOrWhiteSpace(options?.ModelId) &&
                transportType == TransportType.Http1)
            {
                throw new InvalidOperationException("Plug and Play is not supported over the HTTP transport.");
            }

            var connectionStringBuilder = IotHubConnectionStringBuilder.Create(hostname, gatewayHostname, authenticationMethod);

            // Make sure client options is initialized with the correct transport setting.
            EnsureOptionsIsSetup(connectionStringBuilder.Certificate, ref options);

            if (authenticationMethod is DeviceAuthenticationWithX509Certificate)
            {
                if (connectionStringBuilder.Certificate == null)
                {
                    throw new ArgumentException("No certificate was found. To use certificate authentication certificate must be present.");
                }

                InternalClient internalClient = CreateFromConnectionString(
                    connectionStringBuilder.ToString(),
                    authenticationMethod,
                    PopulateCertificateInTransportSettings(connectionStringBuilder, transportType),
                    null,
                    options);

                internalClient.Certificate = connectionStringBuilder.Certificate;

                // Install all the intermediate certificates in the chain if specified.
                if (connectionStringBuilder.ChainCertificates != null)
                {
                    try
                    {
                        CertificateInstaller.EnsureChainIsInstalled(connectionStringBuilder.ChainCertificates);
                    }
                    catch (Exception ex)
                    {
                        if (Logging.IsEnabled)
                        {
                            Logging.Error(null, $"{nameof(CertificateInstaller)} failed to read or write to cert store due to: {ex}");
                        }

                        throw new UnauthorizedException($"Failed to provide certificates in the chain - {ex.Message}", ex);
                    }
                }

                return(internalClient);
            }

            return(CreateFromConnectionString(connectionStringBuilder.ToString(), authenticationMethod, transportType, null, options));
        }
Example #18
0
        public IotHubConnectionString(IotHubConnectionStringBuilder builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            Audience = builder.HostName;
            HostName = string.IsNullOrEmpty(builder.GatewayHostName)
                ? builder.HostName
                : builder.GatewayHostName;
            SharedAccessKeyName   = builder.SharedAccessKeyName;
            SharedAccessKey       = builder.SharedAccessKey;
            SharedAccessSignature = builder.SharedAccessSignature;
            IotHubName            = builder.IotHubName;
            DeviceId = builder.DeviceId;
            ModuleId = builder.ModuleId;

            HttpsEndpoint = new UriBuilder(Uri.UriSchemeHttps, HostName).Uri;

            AmqpEndpoint = new UriBuilder(CommonConstants.AmqpsScheme, HostName, DefaultSecurePort).Uri;

            if (builder.AuthenticationMethod is AuthenticationWithTokenRefresh)
            {
                TokenRefresher = (AuthenticationWithTokenRefresh)builder.AuthenticationMethod;
                if (Logging.IsEnabled)
                {
                    Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(AuthenticationWithTokenRefresh)}: {Logging.IdOf(TokenRefresher)}");
                }

                if (Logging.IsEnabled)
                {
                    Logging.Associate(this, TokenRefresher, nameof(TokenRefresher));
                }

                Debug.Assert(TokenRefresher != null);
            }
            else if (!string.IsNullOrEmpty(SharedAccessKey))
            {
                if (ModuleId.IsNullOrWhiteSpace())
                {
                    TokenRefresher = new DeviceAuthenticationWithSakRefresh(DeviceId, this) as AuthenticationWithTokenRefresh;
                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(DeviceAuthenticationWithSakRefresh)}: {Logging.IdOf(TokenRefresher)}");
                    }
                }
                else
                {
                    TokenRefresher = new ModuleAuthenticationWithSakRefresh(DeviceId, ModuleId, this) as AuthenticationWithTokenRefresh;
                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, $"{nameof(IAuthenticationMethod)} is {nameof(ModuleAuthenticationWithSakRefresh)}: {Logging.IdOf(TokenRefresher)}");
                    }
                }

                if (Logging.IsEnabled)
                {
                    Logging.Associate(this, TokenRefresher, nameof(TokenRefresher));
                }

                Debug.Assert(TokenRefresher != null);
            }
        }
        static async Task Main(string[] args)
        {
            var interval         = 1;
            var connectionString = "";
            var registryManager  = RegistryManager.CreateFromConnectionString(connectionString);
            var numberOfDevices  = Enumerable.Range(1, 50);

            var devices = new ConcurrentBag <DeviceItem>();

            await ForEachAsync(numberOfDevices, 10, async (deviceNumber) =>
            {
                var deviceName = $"SimulatedFridge-{deviceNumber:0000}";

                Console.WriteLine($"Registering device ({deviceName})");
                var device = await registryManager.GetDeviceAsync(deviceName);
                if (device == null)
                {
                    device = await registryManager.AddDeviceAsync(new Device(deviceName));
                }

                devices.Add(new DeviceItem()
                {
                    Id = deviceName,
                });

                var twin = new Twin()
                {
                    Tags = { ["IsSimulated"] = "Y" }
                };

                await registryManager.UpdateTwinAsync(device.Id, twin, "*");
            });

            await ForEachAsync(numberOfDevices, 10, async (deviceNumber) =>
            {
                var deviceName = $"SimulatedLightBulbs-{deviceNumber:0000}";

                Console.WriteLine($"Registering device ({deviceName})");
                var device = await registryManager.GetDeviceAsync(deviceName);
                if (device == null)
                {
                    device = await registryManager.AddDeviceAsync(new Device(deviceName));
                }

                devices.Add(new DeviceItem()
                {
                    Id = deviceName,
                });

                var twin = new Twin()
                {
                    Tags = { ["IsSimulated"] = "Y" }
                };

                await registryManager.UpdateTwinAsync(device.Id, twin, "*");
            });

            await ForEachAsync(devices, 100, async (deviceItem) =>
            {
                var device = await registryManager.GetDeviceAsync(deviceItem.Id);
                var iotHubConnectionString        = IotHubConnectionStringBuilder.Create(connectionString);
                var deviceKeyInfo                 = new DeviceAuthenticationWithRegistrySymmetricKey(deviceItem.Id, device.Authentication.SymmetricKey.PrimaryKey);
                var deviceConnectionStringBuilder = ClientIotHubConnectionStringBuilder.Create(iotHubConnectionString.HostName, deviceKeyInfo);
                var deviceConnectionString        = deviceConnectionStringBuilder.ToString();

                var deviceClient = DeviceClient.CreateFromConnectionString(deviceConnectionString);
                await deviceClient.OpenAsync();

                var message = FetchClientMessage(deviceItem);
                while (true)
                {
                    await deviceClient.SendEventAsync(message);
                    Console.WriteLine($"Sent data for ({deviceItem.Id})");

                    await Task.Delay(interval * 1000);
                    message = FetchClientMessage(deviceItem);
                }
            });

            await Task.Delay(1000);

            Console.ReadKey();
        }
Example #20
0
 /// <summary>
 /// Populates an <see cref="IotHubConnectionStringBuilder"/> instance based on a snapshot of the properties of
 /// the current instance.
 /// </summary>
 /// <param name="iotHubConnectionStringBuilder">Instance to populate.</param>
 /// <returns>The populated <see cref="IotHubConnectionStringBuilder"/> instance.</returns>
 public override IotHubConnectionStringBuilder Populate(IotHubConnectionStringBuilder iotHubConnectionStringBuilder)
 {
     iotHubConnectionStringBuilder          = base.Populate(iotHubConnectionStringBuilder);
     iotHubConnectionStringBuilder.DeviceId = DeviceId;
     return(iotHubConnectionStringBuilder);
 }
Example #21
0
        internal static InternalClient CreateFromConnectionString(
            string connectionString,
            IAuthenticationMethod authenticationMethod,
            ITransportSettings[] transportSettings,
            IDeviceClientPipelineBuilder pipelineBuilder,
            ClientOptions options = default)
        {
            if (connectionString == null)
            {
                throw new ArgumentNullException(nameof(connectionString));
            }

            if (transportSettings == null)
            {
                throw new ArgumentNullException(nameof(transportSettings));
            }

            if (transportSettings.Length == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(connectionString), "Must specify at least one TransportSettings instance");
            }

            if (!string.IsNullOrWhiteSpace(options?.ModelId) &&
                transportSettings.Any(x => x.GetTransportType() == TransportType.Http1))
            {
                throw new InvalidOperationException("Plug and Play is not supported over the HTTP transport.");
            }

            var builder = IotHubConnectionStringBuilder.CreateWithIAuthenticationOverride(
                connectionString,
                authenticationMethod);

            // Clients that derive their authentication method from AuthenticationWithTokenRefresh will need to specify
            // the token time to live and renewal buffer values through the corresponding AuthenticationWithTokenRefresh
            // implementation constructors instead, and these values are irrelevant for cert-based auth.
            if (!(builder.AuthenticationMethod is AuthenticationWithTokenRefresh) &&
                !(builder.AuthenticationMethod is DeviceAuthenticationWithX509Certificate))
            {
                builder.SasTokenTimeToLive    = options?.SasTokenTimeToLive ?? default;
                builder.SasTokenRenewalBuffer = options?.SasTokenRenewalBuffer ?? default;
            }

            var iotHubConnectionString = builder.ToIotHubConnectionString();

            foreach (ITransportSettings transportSetting in transportSettings)
            {
                switch (transportSetting.GetTransportType())
                {
                case TransportType.Amqp_WebSocket_Only:
                case TransportType.Amqp_Tcp_Only:
                    if (!(transportSetting is AmqpTransportSettings))
                    {
                        throw new InvalidOperationException("Unknown implementation of ITransportSettings type");
                    }
                    break;

                case TransportType.Http1:
                    if (!(transportSetting is Http1TransportSettings))
                    {
                        throw new InvalidOperationException("Unknown implementation of ITransportSettings type");
                    }
                    break;

                case TransportType.Mqtt_WebSocket_Only:
                case TransportType.Mqtt_Tcp_Only:
                    if (!(transportSetting is MqttTransportSettings))
                    {
                        throw new InvalidOperationException("Unknown implementation of ITransportSettings type");
                    }
                    break;

                default:
                    throw new InvalidOperationException(
                              $"Unsupported Transport Type {transportSetting.GetTransportType()}");
                }
            }

            if (authenticationMethod is DeviceAuthenticationWithX509Certificate &&
                builder.Certificate == null)
            {
                throw new ArgumentException("No certificate was found. To use certificate authentication certificate must be present.");
            }

            // Make sure client options is initialized with the correct transport setting.
            EnsureOptionsIsSetup(builder.Certificate, ref options);

            pipelineBuilder ??= BuildPipeline();

            // Defer concrete InternalClient creation to OpenAsync
            var client = new InternalClient(iotHubConnectionString, transportSettings, pipelineBuilder, options);

            if (Logging.IsEnabled)
            {
                Logging.CreateFromConnectionString(
                    client,
                    $"HostName={iotHubConnectionString.HostName};DeviceId={iotHubConnectionString.DeviceId};ModuleId={iotHubConnectionString.ModuleId}",
                    transportSettings,
                    options);
            }

            return(client);
        }