public async Task DigitalTwinClient_Http_TokenCredentialAuth_Success() { // arrange TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, _devicePrefix).ConfigureAwait(false); string thermostatModelId = "dtmi:com:example:TemperatureController;1"; // Create a device client instance initializing it with the "Thermostat" model. var options = new ClientOptions { ModelId = thermostatModelId, }; using DeviceClient deviceClient = testDevice.CreateDeviceClient(Client.TransportType.Mqtt, options); // Call openAsync() to open the device's connection, so that the ModelId is sent over Mqtt CONNECT packet. await deviceClient.OpenAsync().ConfigureAwait(false); using var digitalTwinClient = DigitalTwinClient.Create( Configuration.IoTHub.GetIotHubHostName(), Configuration.IoTHub.GetClientSecretCredential()); // act HttpOperationResponse <ThermostatTwin, DigitalTwinGetHeaders> response = await digitalTwinClient .GetDigitalTwinAsync <ThermostatTwin>(testDevice.Id) .ConfigureAwait(false); ThermostatTwin twin = response.Body; // assert twin.Metadata.ModelId.Should().Be(thermostatModelId); // cleanup await testDevice.RemoveDeviceAsync().ConfigureAwait(false); }
/// <summary> /// Create a InternalClient using Amqp transport from the specified connection string /// </summary> /// <param name="connectionString">Connection string for the IoT hub (including DeviceId)</param> /// <param name="options">The options that allow configuration of the device client instance during initialization.</param> /// <returns>InternalClient</returns> internal static InternalClient CreateFromConnectionString(string connectionString, ClientOptions options = default) { return(CreateFromConnectionString(connectionString, TransportType.Amqp, options)); }
/// <summary> /// Creates a disposable DeviceClient from the specified 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="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>A disposable DeviceClient instance</returns> public static DeviceClient Create(string hostname, IAuthenticationMethod authenticationMethod, ITransportSettings[] transportSettings, ClientOptions options = default) { return(Create(() => ClientFactory.Create(hostname, authenticationMethod, transportSettings, options))); }
/// <summary> /// Create a disposable DeviceClient from the specified 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>A disposable DeviceClient instance</returns> public static DeviceClient Create(string hostname, string gatewayHostname, IAuthenticationMethod authenticationMethod, TransportType transportType, ClientOptions options = default) { return(Create(() => ClientFactory.Create(hostname, gatewayHostname, authenticationMethod, transportType, options))); }
/// <summary> /// Creates a disposable DeviceClient from the specified connection string using the prioritized list of transports /// </summary> /// <param name="connectionString">Connection string for the IoT hub (without DeviceId)</param> /// <param name="deviceId">Id of the device</param> /// <param name="transportSettings">Prioritized list of transportTypes and their settings</param> /// <returns>A disposable DeviceClient instance</returns> public static DeviceClient CreateFromConnectionString(string connectionString, string deviceId, ITransportSettings[] transportSettings, ClientOptions options = default) { return(Create(() => ClientFactory.CreateFromConnectionString(connectionString, deviceId, transportSettings, options))); }
/// <summary> /// Creates a disposable DeviceClient from the specified connection string using the specified transport type /// </summary> /// <param name="connectionString">Connection string for the IoT hub (including DeviceId)</param> /// <param name="transportType">Specifies whether Http1, Amqp or Mqtt transport is used, <see cref="TransportType"/></param> /// <param name="options">The options that allow configuration of the device client instance during initialization.</param> /// <returns>A disposable DeviceClient instance</returns> public static DeviceClient CreateFromConnectionString(string connectionString, TransportType transportType, ClientOptions options = default) { return(Create(() => ClientFactory.CreateFromConnectionString(connectionString, transportType, options))); }
/// <summary> /// Create a InternalClient 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, 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, IAuthenticationMethod authenticationMethod, TransportType transportType, ClientOptions options = default) { return(Create(hostname, null, authenticationMethod, transportType, options)); }
/// <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)); }
/// <summary> /// Creates a ModuleClient instance in an IoT Edge deployment /// based on environment variables. /// </summary> /// <param name="transportType">Specifies whether Amqp or Http transport is used</param> /// <param name="options">The options that allow configuration of the module client instance during initialization.</param> /// <returns>ModuleClient instance</returns> public static Task <ModuleClient> CreateFromEnvironmentAsync(TransportType transportType, ClientOptions options = default) { return(CreateFromEnvironmentAsync(ClientFactory.GetTransportSettings(transportType), options)); }
/// <summary> /// Creates a ModuleClient instance in an IoT Edge deployment /// based on environment variables. /// </summary> /// <param name="options">The options that allow configuration of the module client instance during initialization.</param> /// <returns>ModuleClient instance</returns> public static Task <ModuleClient> CreateFromEnvironmentAsync(ClientOptions options = default) { return(CreateFromEnvironmentAsync(TransportType.Amqp, options)); }
/// <summary> /// Create a ModuleClient using Amqp transport from the specified connection string /// </summary> /// <param name="connectionString">Connection string for the IoT hub (including DeviceId)</param> /// <param name="options">The options that allow configuration of the module client instance during initialization.</param> /// <returns>ModuleClient</returns> public static ModuleClient CreateFromConnectionString(string connectionString, ClientOptions options = default) { return(Create(() => ClientFactory.CreateFromConnectionString(connectionString, options))); }
/// <summary> /// Create InternalClient from the specified connection string using the prioritized list of transports /// </summary> /// <param name="connectionString">Connection string for the IoT hub (without DeviceId)</param> /// <param name="deviceId">Id of the device</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 CreateFromConnectionString(string connectionString, string deviceId, ITransportSettings[] transportSettings, ClientOptions options = default) { if (connectionString == null) { throw new ArgumentNullException(nameof(connectionString)); } if (deviceId == null) { throw new ArgumentNullException(nameof(deviceId)); } if (s_deviceIdParameterRegex.IsMatch(connectionString)) { throw new ArgumentException("Connection string must not contain DeviceId keyvalue parameter", nameof(connectionString)); } return(CreateFromConnectionString(connectionString + ";" + DeviceId + "=" + deviceId, transportSettings, options)); }
/// <summary> /// Create InternalClient from the specified connection string using a prioritized list of transports /// </summary> /// <param name="connectionString">Connection string for the IoT hub (with DeviceId)</param> /// <param name="transportSettings">Prioritized list of transports 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 CreateFromConnectionString(string connectionString, ITransportSettings[] transportSettings, ClientOptions options = default) { return(CreateFromConnectionString(connectionString, null, transportSettings, null, options)); }
/// <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)); } if (transportType != TransportType.Amqp_Tcp_Only && transportType != TransportType.Mqtt_Tcp_Only && authenticationMethod is DeviceAuthenticationWithX509Certificate && ((DeviceAuthenticationWithX509Certificate)authenticationMethod).ChainCertificates != null) { throw new ArgumentException("Certificate chains are only supported on Amqp_Tcp_Only and Mqtt_Tcp_Only"); } IotHubConnectionStringBuilder 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."); } #pragma warning disable CA2000 // This is returned to client so cannot be disposed here. InternalClient dc = CreateFromConnectionString(connectionStringBuilder.ToString(), PopulateCertificateInTransportSettings(connectionStringBuilder, transportType), options); #pragma warning restore CA2000 dc.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(dc); } return(CreateFromConnectionString(connectionStringBuilder.ToString(), authenticationMethod, transportType, null, options)); }
/// <summary> /// Create an Amqp InternalClient 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="options">The options that allow configuration of the device client instance during initialization.</param> /// <returns>InternalClient</returns> internal static InternalClient Create(string hostname, IAuthenticationMethod authenticationMethod, ClientOptions options = default) { return(Create(hostname, authenticationMethod, TransportType.Amqp, options)); }
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); }
/// <summary> /// Creates a ModuleClient instance in an IoT Edge deployment /// based on environment variables. /// </summary> /// <param name="transportSettings">Prioritized list of transports and their settings</param> /// <param name="options">The options that allow configuration of the module client instance during initialization.</param> /// <returns>ModuleClient instance</returns> public static Task <ModuleClient> CreateFromEnvironmentAsync(ITransportSettings[] transportSettings, ClientOptions options = default) { return(new EdgeModuleClientFactory(transportSettings, new TrustBundleProvider(), options).CreateAsync()); }
/// <summary> /// Create an Amqp ModuleClient 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="gatewayHostname">The fully-qualified DNS hostname of Gateway</param> /// <param name="options">The options that allow configuration of the module client instance during initialization.</param> /// <returns>ModuleClient</returns> public static ModuleClient Create(string hostname, string gatewayHostname, IAuthenticationMethod authenticationMethod, ClientOptions options = default) { return(Create(() => ClientFactory.Create(hostname, gatewayHostname, authenticationMethod, options))); }
/// <summary> /// Create InternalClient from the specified connection string using the specified transport type /// </summary> /// <param name="connectionString">Connection string for the IoT hub (including DeviceId)</param> /// <param name="transportType">Specifies whether Http1, Amqp or Mqtt transport is used, <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 CreateFromConnectionString(string connectionString, TransportType transportType, ClientOptions options = default) { if (string.IsNullOrEmpty(connectionString)) { throw new ArgumentNullException(nameof(connectionString)); } return(CreateFromConnectionString(connectionString, null, transportType, null, options)); }