diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ConnectionStringCredentials.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ConnectionStringCredentials.cs new file mode 100644 index 00000000000..cf66e8b8722 --- /dev/null +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ConnectionStringCredentials.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.Azure.Devices.Edge.Agent.Core +{ + public class ConnectionStringCredentials : ICredentials + { + public ConnectionStringCredentials(string connectionString) + { + this.CredentialsType = CredentialType.ConnectionString; + this.ConnectionString = connectionString; + } + + public string ConnectionString { get; } + + public CredentialType CredentialsType { get; } + } +} diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Constants.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Constants.cs index c6d3a97bd0e..0f06261e8ff 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Constants.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/Constants.cs @@ -50,6 +50,20 @@ public static class Constants public const string ModuleIdentityEdgeManagedByValue = "IotEdge"; + public const string EdgeletUriVariableName = "IOTEDGE_IOTEDGEDURI"; + + public const string EdgeletVersionVariableName = "IOTEDGE_IOTEDGEDVERSION"; + + public const string IotHubHostnameVariableName = "IOTEDGE_IOTHUBHOSTNAME"; + + public const string GatewayHostnameVariableName = "IOTEDGE_GATEWAYHOSTNAME"; + + public const string DeviceIdVariableName = "IOTEDGE_DEVICEID"; + + public const string ModuleIdVariableName = "IOTEDGE_MODULEID"; + + public const string EdgeletAuthSchemeVariableName = "IOTEDGE_AUTHSCHEME"; + public static class Labels { public const string Version = "net.azure-devices.edge.version"; diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/CredentialType.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/CredentialType.cs new file mode 100644 index 00000000000..94a1d0b73f4 --- /dev/null +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/CredentialType.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.Azure.Devices.Edge.Agent.Core +{ + public enum CredentialType + { + None, + ConnectionString, + IdentityProviderService + } +} diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ICredentials.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ICredentials.cs new file mode 100644 index 00000000000..490a5348f0a --- /dev/null +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ICredentials.cs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.Azure.Devices.Edge.Agent.Core +{ + public interface ICredentials + { + CredentialType CredentialsType { get; } + } +} diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/IModuleIdentity.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/IModuleIdentity.cs index 66d8ca920fd..a2015d9fc0c 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/IModuleIdentity.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/IModuleIdentity.cs @@ -2,12 +2,16 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Core { - using System; - - public interface IModuleIdentity : IEquatable + public interface IModuleIdentity { - string Name { get; } + string IotHubHostname { get; } + + string GatewayHostname { get; } + + string DeviceId { get; } + + string ModuleId { get; } - string ConnectionString { get; } + ICredentials Credentials { get; } } } diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/IdentityProviderServiceCredentials.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/IdentityProviderServiceCredentials.cs new file mode 100644 index 00000000000..52394352ae4 --- /dev/null +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/IdentityProviderServiceCredentials.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.Azure.Devices.Edge.Agent.Core +{ + using Microsoft.Azure.Devices.Edge.Util; + + public class IdentityProviderServiceCredentials : ICredentials + { + const string DefaultAuthScheme = "sasToken"; + + public IdentityProviderServiceCredentials(string providerUri) : this(providerUri, DefaultAuthScheme) + { + } + + public IdentityProviderServiceCredentials(string providerUri, string authScheme) : this(providerUri, authScheme, Option.None()) + { + } + + public IdentityProviderServiceCredentials(string providerUri, string authScheme, Option providerVersion) + { + this.CredentialsType = CredentialType.IdentityProviderService; + this.ProviderUri = Preconditions.CheckNonWhiteSpace(providerUri, nameof(providerUri)); + this.AuthScheme = Preconditions.CheckNonWhiteSpace(authScheme, nameof(authScheme)); + this.Version = Preconditions.CheckNotNull(providerVersion, nameof(providerVersion)); + } + + public string ProviderUri { get; } + + public Option Version { get; } + + public string AuthScheme { get; } + + public CredentialType CredentialsType { get; } + } +} diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleConnectionString.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleConnectionString.cs new file mode 100644 index 00000000000..cfd496af730 --- /dev/null +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleConnectionString.cs @@ -0,0 +1,103 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.Azure.Devices.Edge.Agent.Core +{ + using System; + using System.Text; + using Microsoft.Azure.Devices.Edge.Util; + + public class ModuleConnectionString + { + const string HostNamePropertyName = "HostName"; + const string GatewayHostNamePropertyName = "GatewayHostName"; + const string DeviceIdPropertyName = "DeviceId"; + const string ModuleIdPropertyname = "ModuleId"; + const string SharedAccessKeyPropertyName = "SharedAccessKey"; + const char ValuePairDelimiter = ';'; + + readonly string sasKey; + + ModuleConnectionString(string iotHubHostName, string gatewayHostName, string deviceId, string moduleId, string sasKey) + { + this.IotHubHostName = Preconditions.CheckNonWhiteSpace(iotHubHostName, nameof(iotHubHostName)); + this.GatewayHostName = gatewayHostName; + this.DeviceId = Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId)); + this.ModuleId = Preconditions.CheckNonWhiteSpace(moduleId, nameof(moduleId)); + this.sasKey = sasKey; + } + + public string IotHubHostName { get; } + + public string DeviceId { get; } + + public string ModuleId { get; } + + public string GatewayHostName { get; } + + public override string ToString() + { + if (string.IsNullOrEmpty(this.ModuleId)) + { + throw new ArgumentException("Required parameter moduleId has not been set"); + } + + var connectionString = new StringBuilder(); + this.AppendIfNotEmpty(connectionString, HostNamePropertyName, this.IotHubHostName); + this.AppendIfNotEmpty(connectionString, DeviceIdPropertyName, this.DeviceId); + this.AppendIfNotEmpty(connectionString, ModuleIdPropertyname, this.ModuleId); + this.AppendIfNotEmpty(connectionString, SharedAccessKeyPropertyName, this.sasKey); + this.AppendIfNotEmpty(connectionString, GatewayHostNamePropertyName, this.GatewayHostName); + return connectionString.ToString(); + } + + void AppendIfNotEmpty(StringBuilder stringBuilder, string propertyName, string propertyValue) + { + if (!string.IsNullOrEmpty(propertyValue)) + { + if (stringBuilder.Length > 0) + { + stringBuilder.Append(ValuePairDelimiter); + } + + stringBuilder.Append($"{propertyName}={propertyValue}"); + } + } + + public static implicit operator string(ModuleConnectionString moduleConnectionStringBuilder) => moduleConnectionStringBuilder.ToString(); + + public class ModuleConnectionStringBuilder + { + readonly string iotHubHostName; + readonly string deviceId; + string moduleId; + string gatewayHostname; + string sasKey; + + public ModuleConnectionStringBuilder(string iotHubHostName, string deviceId) + { + this.iotHubHostName = Preconditions.CheckNonWhiteSpace(iotHubHostName, nameof(iotHubHostName)); + this.deviceId = Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId)); + } + + public ModuleConnectionStringBuilder WithModuleId(string moduleId) + { + this.moduleId = Preconditions.CheckNonWhiteSpace(moduleId, nameof(moduleId)); + return this; + } + + public ModuleConnectionStringBuilder WithGatewayHostName(string gatewayHostName) + { + this.gatewayHostname = Preconditions.CheckNonWhiteSpace(gatewayHostName, nameof(gatewayHostName)); + return this; + } + + public ModuleConnectionStringBuilder WithSharedAccessKey(string sasKey) + { + this.sasKey = Preconditions.CheckNonWhiteSpace(sasKey, nameof(sasKey)); + return this; + } + + public ModuleConnectionString Build() => new ModuleConnectionString(this.iotHubHostName, this.gatewayHostname, this.deviceId, this.moduleId, this.sasKey); + } + } +} diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleConnectionStringBuilder.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleConnectionStringBuilder.cs deleted file mode 100644 index 8ec8d9a737f..00000000000 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleConnectionStringBuilder.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -namespace Microsoft.Azure.Devices.Edge.Agent.Core -{ - using System; - using System.Text; - using Microsoft.Azure.Devices.Edge.Util; - - public class ModuleConnectionStringBuilder - { - const string HostNamePropertyName = "HostName"; - const string GatewayHostNamePropertyName = "GatewayHostName"; - const string DeviceIdPropertyName = "DeviceId"; - const string ModuleIdPropertyname = "ModuleId"; - const string SharedAccessKeyPropertyName = "SharedAccessKey"; - const char ValuePairDelimiter = ';'; - - readonly string iotHubHostName; - readonly string deviceId; - - public ModuleConnectionStringBuilder(string iotHubHostName, string deviceId) - { - this.iotHubHostName = Preconditions.CheckNonWhiteSpace(iotHubHostName, nameof(iotHubHostName)); - this.deviceId = Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId)); - } - - public ModuleConnectionString Create(string moduleId) => new ModuleConnectionString(this.iotHubHostName, this.deviceId, Preconditions.CheckNonWhiteSpace(moduleId, nameof(moduleId))); - - static void AppendIfNotEmpty(StringBuilder stringBuilder, string propertyName, string propertyValue) - { - if (!string.IsNullOrEmpty(propertyValue)) - { - if (stringBuilder.Length > 0) - { - stringBuilder.Append(ValuePairDelimiter); - } - stringBuilder.Append($"{propertyName}={propertyValue}"); - } - } - - public class ModuleConnectionString - { - readonly string iotHubHostName; - readonly string deviceId; - readonly string moduleId; - string gatewayHostName; - string sasKey; - - public ModuleConnectionString(string iotHubHostName, string deviceId, string moduleId) - { - this.iotHubHostName = iotHubHostName; - this.deviceId = deviceId; - this.moduleId = moduleId; - } - - public ModuleConnectionString WithGatewayHostName(string gatewayHostName) - { - this.gatewayHostName = Preconditions.CheckNonWhiteSpace(gatewayHostName, nameof(gatewayHostName)); - return this; - } - - public ModuleConnectionString WithSharedAccessKey(string sasKey) - { - this.sasKey = Preconditions.CheckNonWhiteSpace(sasKey, nameof(sasKey)); - return this; - } - - public string Build() - { - if (string.IsNullOrEmpty(this.moduleId)) - { - throw new ArgumentException("Required parameter moduleId has not been set"); - } - - var connectionString = new StringBuilder(); - AppendIfNotEmpty(connectionString, HostNamePropertyName, this.iotHubHostName); - AppendIfNotEmpty(connectionString, DeviceIdPropertyName, this.deviceId); - AppendIfNotEmpty(connectionString, ModuleIdPropertyname, this.moduleId); - AppendIfNotEmpty(connectionString, SharedAccessKeyPropertyName, this.sasKey); - AppendIfNotEmpty(connectionString, GatewayHostNamePropertyName, this.gatewayHostName); - return connectionString.ToString(); - } - - public static implicit operator string(ModuleConnectionString moduleConnectionStringBuilder) => moduleConnectionStringBuilder.Build(); - } - } -} diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleIdentity.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleIdentity.cs index badd063473d..a3c106684f6 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleIdentity.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleIdentity.cs @@ -6,35 +6,23 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Core public class ModuleIdentity : IModuleIdentity { - public ModuleIdentity(string moduleId, string connectionString) + public ModuleIdentity(string iotHubHostname, string gatewayHostname, string deviceId, string moduleId, ICredentials credentials) { - this.ConnectionString = Preconditions.CheckNotNull(connectionString, nameof(connectionString)); - this.Name = Preconditions.CheckNotNull(moduleId, nameof(moduleId)); + this.IotHubHostname = Preconditions.CheckNonWhiteSpace(iotHubHostname, nameof(this.IotHubHostname)); + this.GatewayHostname = gatewayHostname; + this.DeviceId = Preconditions.CheckNonWhiteSpace(deviceId, nameof(this.DeviceId)); + this.ModuleId = Preconditions.CheckNonWhiteSpace(moduleId, nameof(this.ModuleId)); + this.Credentials = Preconditions.CheckNotNull(credentials, nameof(this.Credentials)); } - public string Name { get; } + public string IotHubHostname { get; } - public string ConnectionString { get; } + public string GatewayHostname { get; } - public override bool Equals(object obj) => this.Equals(obj as ModuleIdentity); + public string DeviceId { get; } - public bool Equals(IModuleIdentity other) - { - if (ReferenceEquals(null, other)) - return false; - if (ReferenceEquals(this, other)) - return true; - - return string.Equals(this.Name, other.Name) - && string.Equals(this.ConnectionString, other.ConnectionString); - } + public string ModuleId { get; } - public override int GetHashCode() - { - unchecked - { - return ((this.Name != null ? this.Name.GetHashCode() : 0) * 397) ^ (this.ConnectionString != null ? this.ConnectionString.GetHashCode() : 0); - } - } + public ICredentials Credentials { get; } } } diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleIdentityProviderServiceBuilder.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleIdentityProviderServiceBuilder.cs new file mode 100644 index 00000000000..ace5c334e37 --- /dev/null +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Core/ModuleIdentityProviderServiceBuilder.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.Azure.Devices.Edge.Agent.Core +{ + using Microsoft.Azure.Devices.Edge.Util; + + public class ModuleIdentityProviderServiceBuilder + { + readonly string iotHubHostName; + readonly string deviceId; + readonly string gatewayHostname; + + public ModuleIdentityProviderServiceBuilder(string iotHubHostName, string deviceId, string gatewayHostname) + { + this.iotHubHostName = Preconditions.CheckNonWhiteSpace(iotHubHostName, nameof(iotHubHostName)); + this.deviceId = Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId)); + this.gatewayHostname = gatewayHostname; + } + + public IModuleIdentity Create(string moduleId, string providerUri) + { + Preconditions.CheckNonWhiteSpace(moduleId, nameof(moduleId)); + Preconditions.CheckNonWhiteSpace(providerUri, nameof(providerUri)); + + ICredentials credentials = new IdentityProviderServiceCredentials(providerUri); + return new ModuleIdentity(this.iotHubHostName, this.gatewayHostname, this.deviceId, moduleId, credentials); + } + + public IModuleIdentity Create(string moduleId, string providerUri, string authScheme) + { + Preconditions.CheckNonWhiteSpace(moduleId, nameof(moduleId)); + Preconditions.CheckNonWhiteSpace(providerUri, nameof(providerUri)); + Preconditions.CheckNonWhiteSpace(authScheme, nameof(authScheme)); + + ICredentials credentials = new IdentityProviderServiceCredentials(providerUri, authScheme); + return new ModuleIdentity(this.iotHubHostName, this.gatewayHostname, this.deviceId, moduleId, credentials); + } + } +} diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Docker/commands/CreateCommand.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Docker/commands/CreateCommand.cs index 89a0d45b637..a65831b9d29 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Docker/commands/CreateCommand.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Docker/commands/CreateCommand.cs @@ -92,10 +92,10 @@ static void InjectConfig(CreateContainerParameters createContainerParameters, IM var envVars = new List(); // Inject the connection string as an environment variable - if (!string.IsNullOrWhiteSpace(identity.ConnectionString)) + if ((identity.Credentials is ConnectionStringCredentials creds) && ((!string.IsNullOrWhiteSpace(creds.ConnectionString)))) { string connectionStringKey = injectForEdgeHub ? Constants.IotHubConnectionStringKey : Constants.EdgeHubConnectionStringKey; - envVars.Add($"{connectionStringKey}={identity.ConnectionString}"); + envVars.Add($"{connectionStringKey}={creds.ConnectionString}"); } if (injectForEdgeHub) diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/ModuleIdentityLifecycleManager.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/ModuleIdentityLifecycleManager.cs index 914c8532503..30a8ad8173c 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/ModuleIdentityLifecycleManager.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/ModuleIdentityLifecycleManager.cs @@ -14,14 +14,14 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Edgelet public class ModuleIdentityLifecycleManager : IModuleIdentityLifecycleManager { readonly IIdentityManager identityManager; - readonly ModuleConnectionStringBuilder connectionStringBuilder; - readonly string gatewayHostName; + readonly ModuleIdentityProviderServiceBuilder identityProviderServiceBuilder; + readonly string edgeletUri; - public ModuleIdentityLifecycleManager(IIdentityManager identityManager, ModuleConnectionStringBuilder connectionStringBuilder, string gatewayHostName) + public ModuleIdentityLifecycleManager(IIdentityManager identityManager, ModuleIdentityProviderServiceBuilder identityProviderServiceBuilder, string edgeletUri) { this.identityManager = Preconditions.CheckNotNull(identityManager, nameof(identityManager)); - this.connectionStringBuilder = Preconditions.CheckNotNull(connectionStringBuilder, nameof(connectionStringBuilder)); - this.gatewayHostName = Preconditions.CheckNonWhiteSpace(gatewayHostName, nameof(gatewayHostName)); + this.identityProviderServiceBuilder = Preconditions.CheckNotNull(identityProviderServiceBuilder, nameof(identityProviderServiceBuilder)); + this.edgeletUri = Preconditions.CheckNonWhiteSpace(edgeletUri, nameof(edgeletUri)); } public async Task> GetModuleIdentitiesAsync(ModuleSet desired, ModuleSet current) @@ -47,12 +47,11 @@ public async Task> GetModuleIdenti Identity[] createdIdentities = await Task.WhenAll(createIdentities.Select(i => this.identityManager.CreateIdentityAsync(i))); IEnumerable moduleIdentities = createdIdentities.Concat(identities.Values) - .Select(m => new ModuleIdentity(m.ModuleId, this.GetModuleConnectionString(m))); - return moduleIdentities.ToImmutableDictionary(m => ModuleIdentityHelper.GetModuleName(m.Name)); + .Select(m => this.GetModuleIdentity(m)); + return moduleIdentities.ToImmutableDictionary(m => ModuleIdentityHelper.GetModuleName(m.ModuleId)); } - string GetModuleConnectionString(Identity identity) => identity.ModuleId.Equals(Constants.EdgeHubModuleIdentityName, StringComparison.OrdinalIgnoreCase) - ? this.connectionStringBuilder.Create(identity.ModuleId) - : this.connectionStringBuilder.Create(identity.ModuleId).WithGatewayHostName(this.gatewayHostName); + IModuleIdentity GetModuleIdentity(Identity identity) => + this.identityProviderServiceBuilder.Create(identity.ModuleId, this.edgeletUri); } } diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/commands/CreateOrUpdateCommand.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/commands/CreateOrUpdateCommand.cs index 5fb7a56c4f1..5f35acdbe4f 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/commands/CreateOrUpdateCommand.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Edgelet/commands/CreateOrUpdateCommand.cs @@ -73,11 +73,40 @@ static IEnumerable GetEnvVars(IModuleIdentity identity, IConfigSource co { var envVars = new List(); - // Inject the connection string as an environment variable - if (!string.IsNullOrWhiteSpace(identity.ConnectionString)) + // Inject the connection details as an environment variable + if (identity.Credentials is IdentityProviderServiceCredentials creds) { - string connectionStringKey = isEdgeHub ? Constants.IotHubConnectionStringKey : Constants.EdgeHubConnectionStringKey; - envVars.Add(new EnvVar { Key = connectionStringKey, Value = identity.ConnectionString }); + if (!string.IsNullOrWhiteSpace(creds.ProviderUri)) + { + envVars.Add(new EnvVar { Key = Constants.EdgeletUriVariableName, Value = creds.ProviderUri }); + } + + creds.Version.ForEach(v => envVars.Add(new EnvVar { Key = Constants.EdgeletVersionVariableName, Value = v })); + + if (!string.IsNullOrWhiteSpace(creds.AuthScheme)) + { + envVars.Add(new EnvVar { Key = Constants.EdgeletAuthSchemeVariableName, Value = creds.AuthScheme }); + } + } + + if (!string.IsNullOrWhiteSpace(identity.IotHubHostname)) + { + envVars.Add(new EnvVar { Key = Constants.IotHubHostnameVariableName, Value = identity.IotHubHostname }); + } + + if (!string.IsNullOrWhiteSpace(identity.GatewayHostname) && !isEdgeHub) + { + envVars.Add(new EnvVar { Key = Constants.GatewayHostnameVariableName, Value = identity.GatewayHostname }); + } + + if (!string.IsNullOrWhiteSpace(identity.DeviceId)) + { + envVars.Add(new EnvVar { Key = Constants.DeviceIdVariableName, Value = identity.DeviceId }); + } + + if (!string.IsNullOrWhiteSpace(identity.ModuleId)) + { + envVars.Add(new EnvVar { Key = Constants.ModuleIdVariableName, Value = identity.ModuleId }); } envVars.Add(new EnvVar { Key = Logger.RuntimeLogLevelEnvKey, Value = Logger.GetLogLevel().ToString() }); diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/DeviceClient.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/DeviceClient.cs index 564b5434772..960426da266 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/DeviceClient.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/DeviceClient.cs @@ -8,6 +8,7 @@ namespace Microsoft.Azure.Devices.Edge.Agent.IoTHub using Microsoft.Azure.Devices.Client; using Microsoft.Azure.Devices.Client.Exceptions; using Microsoft.Azure.Devices.Edge.Agent.Core; + using Microsoft.Azure.Devices.Edge.ClientWrapper; using Microsoft.Azure.Devices.Edge.Util; using Microsoft.Azure.Devices.Edge.Util.TransientFaultHandling; using Microsoft.Azure.Devices.Shared; @@ -34,23 +35,36 @@ public class DeviceClient : IDeviceClient this.deviceClient = deviceClient; } - public static async Task Create(string connectionString, + public static Task Create(Option upstreamProtocol, + ConnectionStatusChangesHandler statusChangedHandler, + Func initialize) + { + return Create(upstreamProtocol, initialize, t => CreateAndOpenDeviceClient(t, statusChangedHandler)); + } + + public static Task Create(string connectionString, Option upstreamProtocol, ConnectionStatusChangesHandler statusChangedHandler, Func initialize) + { + return Create(upstreamProtocol, initialize, t => CreateAndOpenDeviceClient(t, connectionString, statusChangedHandler)); + } + + static async Task Create(Option upstreamProtocol, Func initialize, Func> deviceClientCreator) { try { return await ExecuteWithRetry( async () => { - Client.DeviceClient dc = await CreateDeviceClientForUpstreamProtocol(upstreamProtocol, t => CreateAndOpenDeviceClient(t, connectionString, statusChangedHandler)); + Client.DeviceClient dc = await CreateDeviceClientForUpstreamProtocol(upstreamProtocol, deviceClientCreator); Events.DeviceClientCreated(); var deviceClient = new DeviceClient(dc); if (initialize != null) { await initialize(deviceClient); } + return deviceClient; }, Events.RetryingDeviceClientConnection); @@ -84,17 +98,31 @@ public static async Task Create(string connectionString, return result.Value; }); + static async Task CreateAndOpenDeviceClient(TransportType transport, ConnectionStatusChangesHandler statusChangedHandler) + { + Events.AttemptingConnectionWithTransport(transport); + Client.DeviceClient deviceClient = new DeviceClientFactory(transport).Create(); + await OpenAsync(statusChangedHandler, deviceClient); + Events.ConnectedWithTransport(transport); + return deviceClient; + } + static async Task CreateAndOpenDeviceClient(TransportType transport, string connectionString, ConnectionStatusChangesHandler statusChangedHandler) { Events.AttemptingConnectionWithTransport(transport); Client.DeviceClient deviceClient = Client.DeviceClient.CreateFromConnectionString(connectionString, transport); + await OpenAsync(statusChangedHandler, deviceClient); + Events.ConnectedWithTransport(transport); + return deviceClient; + } + + static async Task OpenAsync(ConnectionStatusChangesHandler statusChangedHandler, Client.DeviceClient deviceClient) + { // note: it's important to set the status-changed handler and // timeout value *before* we open a connection to the hub deviceClient.OperationTimeoutInMilliseconds = DeviceClientTimeout; deviceClient.SetConnectionStatusChangesHandler(statusChangedHandler); await deviceClient.OpenAsync(); - Events.ConnectedWithTransport(transport); - return deviceClient; } static Task ExecuteWithRetry(Func> func, Action onRetry) diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/EnvironmentDeviceClientProvider.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/EnvironmentDeviceClientProvider.cs new file mode 100644 index 00000000000..69f5a06241a --- /dev/null +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/EnvironmentDeviceClientProvider.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft. All rights reserved. +namespace Microsoft.Azure.Devices.Edge.Agent.IoTHub +{ + using System; + using System.Threading.Tasks; + using Microsoft.Azure.Devices.Client; + using Microsoft.Azure.Devices.Edge.Agent.Core; + using Microsoft.Azure.Devices.Edge.Util; + + public class EnvironmentDeviceClientProvider : IDeviceClientProvider + { + readonly Option upstreamProtocol; + + public EnvironmentDeviceClientProvider(Option upstreamProtocol) + { + this.upstreamProtocol = upstreamProtocol; + } + + public Task Create( + ConnectionStatusChangesHandler statusChangedHandler, + Func initialize) => + DeviceClient.Create(this.upstreamProtocol, statusChangedHandler, initialize); + } +} diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/Microsoft.Azure.Devices.Edge.Agent.IoTHub.csproj b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/Microsoft.Azure.Devices.Edge.Agent.IoTHub.csproj index f7d9aabce34..a12d65cec38 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/Microsoft.Azure.Devices.Edge.Agent.IoTHub.csproj +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/Microsoft.Azure.Devices.Edge.Agent.IoTHub.csproj @@ -20,10 +20,11 @@ - + + diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/ModuleIdentityLifecycleManager.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/ModuleIdentityLifecycleManager.cs index b504375f1dc..97ea681b768 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/ModuleIdentityLifecycleManager.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.IoTHub/ModuleIdentityLifecycleManager.cs @@ -13,10 +13,10 @@ namespace Microsoft.Azure.Devices.Edge.Agent.IoTHub public class ModuleIdentityLifecycleManager : IModuleIdentityLifecycleManager { readonly IServiceClient serviceClient; - readonly ModuleConnectionStringBuilder moduleConnectionStringBuilder; + readonly ModuleConnectionString.ModuleConnectionStringBuilder moduleConnectionStringBuilder; readonly string gatewayHostName; - public ModuleIdentityLifecycleManager(IServiceClient serviceClient, ModuleConnectionStringBuilder moduleConnectionStringBuilder, string gatewayHostName) + public ModuleIdentityLifecycleManager(IServiceClient serviceClient, ModuleConnectionString.ModuleConnectionStringBuilder moduleConnectionStringBuilder, string gatewayHostName) { this.serviceClient = Preconditions.CheckNotNull(serviceClient, nameof(serviceClient)); this.moduleConnectionStringBuilder = Preconditions.CheckNotNull(moduleConnectionStringBuilder, nameof(moduleConnectionStringBuilder)); @@ -85,23 +85,31 @@ public async Task> GetModuleIdenti List updatedModulesIndentity = (await this.UpdateServiceModulesIdentityAsync(removeIdentities, createIdentities, updateIdentities)).ToList(); ImmutableDictionary updatedDict = updatedModulesIndentity.ToImmutableDictionary(p => p.Id); - IEnumerable moduleIdentities = updatedModulesIndentity.Concat(modules.Where(p => !updatedDict.ContainsKey(p.Id))).Select(p => new ModuleIdentity(p.Id, this.GetModuleConnectionString(p))); - return moduleIdentities.ToImmutableDictionary(m => ModuleIdentityHelper.GetModuleName(m.Name)); + IEnumerable moduleIdentities = updatedModulesIndentity.Concat(modules.Where(p => !updatedDict.ContainsKey(p.Id))).Select(p => + { + ModuleConnectionString cs = this.GetModuleConnectionString(p); + return new ModuleIdentity(cs.IotHubHostName, cs.GatewayHostName, cs.DeviceId, cs.ModuleId, new ConnectionStringCredentials(cs.ToString())); + }); + return moduleIdentities.ToImmutableDictionary(m => ModuleIdentityHelper.GetModuleName(m.ModuleId)); } - string GetModuleConnectionString(Module module) + ModuleConnectionString GetModuleConnectionString(Module module) { if (module.Authentication.Type != AuthenticationType.Sas) { throw new ArgumentException($"Authentication type {module.Authentication.Type} is not supported."); } - ModuleConnectionStringBuilder.ModuleConnectionString moduleConnectionString = this.moduleConnectionStringBuilder.Create(module.Id) + ModuleConnectionString.ModuleConnectionStringBuilder builder = this.moduleConnectionStringBuilder + .WithModuleId(module.Id) .WithSharedAccessKey(module.Authentication.SymmetricKey.PrimaryKey); - return module.Id.Equals(Constants.EdgeHubModuleIdentityName, StringComparison.OrdinalIgnoreCase) - ? moduleConnectionString - : moduleConnectionString.WithGatewayHostName(this.gatewayHostName); + if (!module.Id.Equals(Constants.EdgeHubModuleIdentityName, StringComparison.OrdinalIgnoreCase)) + { + builder.WithGatewayHostName(this.gatewayHostName); + } + + return builder.Build(); } async Task UpdateServiceModulesIdentityAsync(IEnumerable removeIdentities, IEnumerable createIdentities, IEnumerable updateIdentities) diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/Program.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/Program.cs index 5e4d35c127c..7aa459d8021 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/Program.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/Program.cs @@ -11,6 +11,7 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Service using Autofac; using global::Docker.DotNet.Models; using Microsoft.Azure.Devices.Edge.Agent.Core; + using Microsoft.Azure.Devices.Edge.Agent.IoTHub; using Microsoft.Azure.Devices.Edge.Agent.Service.Modules; using Microsoft.Azure.Devices.Edge.Util; using Microsoft.Extensions.Configuration; @@ -66,8 +67,6 @@ public static async Task MainAsync(IConfiguration configuration) int coolOffTimeUnitInSeconds; bool usePersistentStorage; string storagePath; - string deviceConnectionString; - string edgeAgentConnectionString; string edgeDeviceHostName; string dockerLoggingDriver; Dictionary dockerLoggingOptions; @@ -85,8 +84,6 @@ public static async Task MainAsync(IConfiguration configuration) coolOffTimeUnitInSeconds = configuration.GetValue("CoolOffTimeUnitInSeconds"); usePersistentStorage = configuration.GetValue("UsePersistentStorage", true); storagePath = usePersistentStorage ? GetStoragePath(configuration) : string.Empty; - deviceConnectionString = configuration.GetValue("DeviceConnectionString"); - edgeAgentConnectionString = configuration.GetValue("ModuleConnectionString", string.Empty); edgeDeviceHostName = configuration.GetValue(Constants.EdgeDeviceHostNameKey); dockerLoggingDriver = configuration.GetValue("DockerLoggingDriver"); dockerLoggingOptions = configuration.GetSection("DockerLoggingOptions").Get>() ?? new Dictionary(); @@ -105,16 +102,18 @@ public static async Task MainAsync(IConfiguration configuration) builder.RegisterModule(new AgentModule(maxRestartCount, intensiveCareTime, coolOffTimeUnitInSeconds, usePersistentStorage, storagePath)); builder.RegisterModule(new LoggingModule(dockerLoggingDriver, dockerLoggingOptions)); - switch(mode.ToLower()) + Option upstreamProtocol = configuration.GetValue(Constants.UpstreamProtocolKey).ToUpstreamProtocol(); + switch (mode.ToLower()) { case "docker": - IConfiguration dockerConfig = configuration.GetSection("DockerConfig"); - edgeAgentConnectionString = $"{deviceConnectionString};{Constants.ModuleIdKey}={Constants.EdgeAgentModuleIdentityName}"; - builder.RegisterModule(new DockerModule(deviceConnectionString, edgeDeviceHostName, dockerUri, dockerAuthConfig)); + string deviceConnectionString = configuration.GetValue("DeviceConnectionString"); + builder.RegisterModule(new DockerModule(deviceConnectionString, edgeDeviceHostName, dockerUri, dockerAuthConfig, upstreamProtocol)); break; case "edgelet": - builder.RegisterModule(new EdgeletModule(edgeAgentConnectionString, edgeDeviceHostName, edgeletUrl, dockerAuthConfig)); + string iothubHostname = configuration.GetValue(Constants.IotHubHostnameVariableName); + string deviceId = configuration.GetValue(Constants.DeviceIdVariableName); + builder.RegisterModule(new EdgeletModule(iothubHostname, edgeDeviceHostName, deviceId, edgeletUrl, dockerAuthConfig, upstreamProtocol)); break; default: @@ -124,7 +123,7 @@ public static async Task MainAsync(IConfiguration configuration) switch (configSourceConfig.ToLower()) { case "twin": - builder.RegisterModule(new TwinConfigSourceModule(edgeAgentConnectionString, backupConfigFilePath, configuration, versionInfo)); + builder.RegisterModule(new TwinConfigSourceModule(backupConfigFilePath, configuration, versionInfo)); break; case "local": diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/appsettings_agent.json b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/appsettings_agent.json index ca5fade8394..11505f9a6a1 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/appsettings_agent.json +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/appsettings_agent.json @@ -3,7 +3,6 @@ "DockerUri": "http://localhost:2375", "EdgeletUrl": "http://localhost:50002", "DeviceConnectionString": "", - "ModuleConnectionString": "", "ConfigSource": "twin", "DockerLoggingDriver": "json-file", "DockerLoggingOptions": {}, diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/DockerModule.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/DockerModule.cs index e091a0f7277..ff375078ce0 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/DockerModule.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/DockerModule.cs @@ -23,8 +23,9 @@ public class DockerModule : Module readonly string gatewayHostName; readonly Uri dockerHostname; readonly IEnumerable dockerAuthConfig; + readonly Option upstreamProtocol; - public DockerModule(string edgeDeviceConnectionString, string gatewayHostName, Uri dockerHostname, IEnumerable dockerAuthConfig) + public DockerModule(string edgeDeviceConnectionString, string gatewayHostName, Uri dockerHostname, IEnumerable dockerAuthConfig, Option upstreamProtocol) { this.edgeDeviceConnectionString = Preconditions.CheckNonWhiteSpace(edgeDeviceConnectionString, nameof(edgeDeviceConnectionString)); this.gatewayHostName = Preconditions.CheckNonWhiteSpace(gatewayHostName, nameof(gatewayHostName)); @@ -33,17 +34,25 @@ public DockerModule(string edgeDeviceConnectionString, string gatewayHostName, U this.iotHubHostName = connectionStringParser.HostName; this.dockerHostname = Preconditions.CheckNotNull(dockerHostname, nameof(dockerHostname)); this.dockerAuthConfig = Preconditions.CheckNotNull(dockerAuthConfig, nameof(dockerAuthConfig)); + this.upstreamProtocol = Preconditions.CheckNotNull(upstreamProtocol, nameof(upstreamProtocol)); } protected override void Load(ContainerBuilder builder) { + // IDeviceClientProvider + string edgeAgentConnectionString = $"{this.edgeDeviceConnectionString};{Constants.ModuleIdKey}={Constants.EdgeAgentModuleIdentityName}"; + builder.Register(c => new DeviceClientProvider(edgeAgentConnectionString, this.upstreamProtocol)) + .As() + .SingleInstance(); + // IServiceClient builder.Register(c => new RetryingServiceClient(new ServiceClient(this.edgeDeviceConnectionString, this.deviceId))) .As() .SingleInstance(); // IModuleIdentityLifecycleManager - builder.Register(c => new ModuleIdentityLifecycleManager(c.Resolve(), new ModuleConnectionStringBuilder(this.iotHubHostName, this.deviceId), this.gatewayHostName)) + var identityBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(this.iotHubHostName, this.deviceId); + builder.Register(c => new ModuleIdentityLifecycleManager(c.Resolve(), identityBuilder, this.gatewayHostName)) .As() .SingleInstance(); diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/EdgeletModule.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/EdgeletModule.cs index deae4faaff3..40019dbecc7 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/EdgeletModule.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/EdgeletModule.cs @@ -9,9 +9,11 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Service.Modules using Microsoft.Azure.Devices.Edge.Agent.Core; using Microsoft.Azure.Devices.Edge.Agent.Docker; using Microsoft.Azure.Devices.Edge.Agent.Edgelet; + using Microsoft.Azure.Devices.Edge.Agent.IoTHub; using Microsoft.Azure.Devices.Edge.Storage; using Microsoft.Azure.Devices.Edge.Util; using Microsoft.Extensions.Logging; + using ModuleIdentityLifecycleManager = Microsoft.Azure.Devices.Edge.Agent.Edgelet.ModuleIdentityLifecycleManager; /// /// Initializes Edgelet specific types. @@ -25,20 +27,25 @@ public class EdgeletModule : Module readonly string gatewayHostName; readonly string edgeletUrl; readonly IEnumerable dockerAuthConfig; + readonly Option upstreamProtocol; - public EdgeletModule(string edgeDeviceConnectionString, string gatewayHostName, string edgeletUri, IEnumerable dockerAuthConfig) + public EdgeletModule(string iotHubHostname, string gatewayHostName, string deviceId, string edgeletUri, IEnumerable dockerAuthConfig, Option upstreamProtocol) { - Preconditions.CheckNonWhiteSpace(edgeDeviceConnectionString, nameof(edgeDeviceConnectionString)); + this.iotHubHostName = Preconditions.CheckNonWhiteSpace(iotHubHostname, nameof(iotHubHostname)); this.gatewayHostName = Preconditions.CheckNonWhiteSpace(gatewayHostName, nameof(gatewayHostName)); - IotHubConnectionStringBuilder connectionStringParser = IotHubConnectionStringBuilder.Create(edgeDeviceConnectionString); - this.deviceId = connectionStringParser.DeviceId; - this.iotHubHostName = connectionStringParser.HostName; + this.deviceId = Preconditions.CheckNonWhiteSpace(deviceId, nameof(deviceId)); this.edgeletUrl = Preconditions.CheckNonWhiteSpace(edgeletUri, nameof(edgeletUri)); this.dockerAuthConfig = Preconditions.CheckNotNull(dockerAuthConfig, nameof(dockerAuthConfig)); + this.upstreamProtocol = Preconditions.CheckNotNull(upstreamProtocol, nameof(upstreamProtocol)); } protected override void Load(ContainerBuilder builder) { + // IDeviceClientProvider + builder.Register(c => new EnvironmentDeviceClientProvider(this.upstreamProtocol)) + .As() + .SingleInstance(); + // IModuleManager builder.Register(c => new ModuleManagementHttpClient(this.edgeletUrl)) .As() @@ -46,7 +53,8 @@ protected override void Load(ContainerBuilder builder) .SingleInstance(); // IModuleIdentityLifecycleManager - builder.Register(c => new ModuleIdentityLifecycleManager(c.Resolve(), new ModuleConnectionStringBuilder(this.iotHubHostName, this.deviceId), this.gatewayHostName)) + var identityBuilder = new ModuleIdentityProviderServiceBuilder(this.iotHubHostName, this.deviceId, this.gatewayHostName); + builder.Register(c => new ModuleIdentityLifecycleManager(c.Resolve(), identityBuilder, this.edgeletUrl)) .As() .SingleInstance(); diff --git a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/TwinConfigSourceModule.cs b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/TwinConfigSourceModule.cs index 8c8af8a0c03..ae721afd544 100644 --- a/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/TwinConfigSourceModule.cs +++ b/edge-agent/src/Microsoft.Azure.Devices.Edge.Agent.Service/modules/TwinConfigSourceModule.cs @@ -18,20 +18,16 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Service.Modules public class TwinConfigSourceModule : Module { - readonly string edgeAgentConnectionString; readonly string backupConfigFilePath; const string DockerType = "docker"; readonly IConfiguration configuration; readonly VersionInfo versionInfo; - public TwinConfigSourceModule( - string edgeAgentConnectionString, - string backupConfigFilePath, + public TwinConfigSourceModule(string backupConfigFilePath, IConfiguration config, VersionInfo versionInfo ) { - this.edgeAgentConnectionString = Preconditions.CheckNonWhiteSpace(edgeAgentConnectionString, nameof(edgeAgentConnectionString)); this.backupConfigFilePath = Preconditions.CheckNonWhiteSpace(backupConfigFilePath, nameof(backupConfigFilePath)); this.configuration = Preconditions.CheckNotNull(config, nameof(config)); this.versionInfo = Preconditions.CheckNotNull(versionInfo, nameof(versionInfo)); @@ -39,11 +35,6 @@ VersionInfo versionInfo protected override void Load(ContainerBuilder builder) { - // IDeviceClientProvider - builder.Register(c => new DeviceClientProvider(this.edgeAgentConnectionString, this.configuration.GetValue(Constants.UpstreamProtocolKey).ToUpstreamProtocol())) - .As() - .SingleInstance(); - // IEdgeAgentConnection builder.Register( c => diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleConnectionStringBuilderTest.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleConnectionStringBuilderTest.cs index 34ec9adce30..1c6f4a897e9 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleConnectionStringBuilderTest.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleConnectionStringBuilderTest.cs @@ -18,21 +18,22 @@ public class ModuleConnectionStringBuilderTest public void CreateConnectionStringTest(string expectedConnectionString, string iotHubHostName, string deviceId, string moduleId, string sasKey = null, string gatewayHostName = null) { // Arrange - var builder = new ModuleConnectionStringBuilder(iotHubHostName, deviceId); - ModuleConnectionStringBuilder.ModuleConnectionString moduleConnectionString = builder.Create(moduleId); + var builder = new ModuleConnectionString.ModuleConnectionStringBuilder(iotHubHostName, deviceId).WithModuleId(moduleId); if (!string.IsNullOrEmpty(sasKey)) { - moduleConnectionString.WithSharedAccessKey(sasKey); + builder.WithSharedAccessKey(sasKey); } if (!string.IsNullOrEmpty(gatewayHostName)) { - moduleConnectionString.WithGatewayHostName(gatewayHostName); + builder.WithGatewayHostName(gatewayHostName); } + ModuleConnectionString moduleConnectionString = builder.Build(); + // Act - string connectionString = moduleConnectionString.Build(); + string connectionString = moduleConnectionString.ToString(); // Assert Assert.Equal(expectedConnectionString, connectionString); @@ -42,9 +43,10 @@ public void CreateConnectionStringTest(string expectedConnectionString, string i public void ImplicitOperatorTest() { // Arrange/Act - var builder = new ModuleConnectionStringBuilder("foo.azure.com", "device1"); - string connectionString = builder.Create("module1") - .WithGatewayHostName("localhost"); + var builder = new ModuleConnectionString.ModuleConnectionStringBuilder("foo.azure.com", "device1").WithModuleId("module1"); + string connectionString = builder + .WithGatewayHostName("localhost") + .Build(); Assert.Equal("HostName=foo.azure.com;DeviceId=device1;ModuleId=module1;GatewayHostName=localhost", connectionString); } @@ -52,15 +54,16 @@ public void ImplicitOperatorTest() [Fact] public void InvalidInputsTest() { - Assert.Throws(() => new ModuleConnectionStringBuilder(null, "1")); - Assert.Throws(() => new ModuleConnectionStringBuilder("", "1")); - Assert.Throws(() => new ModuleConnectionStringBuilder("iothub", null)); - Assert.Throws(() => new ModuleConnectionStringBuilder("iothub", "")); + Assert.Throws(() => new ModuleConnectionString.ModuleConnectionStringBuilder(null, "1")); + Assert.Throws(() => new ModuleConnectionString.ModuleConnectionStringBuilder("", "1")); + Assert.Throws(() => new ModuleConnectionString.ModuleConnectionStringBuilder("iothub", null)); + Assert.Throws(() => new ModuleConnectionString.ModuleConnectionStringBuilder("iothub", "")); - var builder = new ModuleConnectionStringBuilder("foo.azure.com", "device1"); - Assert.Throws(() => builder.Create(null)); - Assert.Throws(() => builder.Create("m1").WithGatewayHostName(null)); - Assert.Throws(() => builder.Create("m1").WithSharedAccessKey(null)); + var builder = new ModuleConnectionString.ModuleConnectionStringBuilder("foo.azure.com", "device1"); + Assert.Throws(() => builder.Build()); + Assert.Throws(() => builder.WithModuleId(null).Build()); + Assert.Throws(() => builder.WithGatewayHostName(null).Build()); + Assert.Throws(() => builder.WithSharedAccessKey(null).Build()); } } } diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleIdentityProviderServiceBuilderTest.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleIdentityProviderServiceBuilderTest.cs new file mode 100644 index 00000000000..fece789c6a3 --- /dev/null +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleIdentityProviderServiceBuilderTest.cs @@ -0,0 +1,81 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.Azure.Devices.Edge.Agent.Core.Test +{ + using System; + using Microsoft.Azure.Devices.Edge.Agent.Core; + using Microsoft.Azure.Devices.Edge.Util; + using Microsoft.Azure.Devices.Edge.Util.Test.Common; + using Xunit; + + [Unit] + public class ModuleIdentityProviderServiceBuilderTest + { + [Theory] + [InlineData("foo.azure.com", "d1", "m1", "localhost")] + [InlineData("foo.azure.com", "d1", "m1", "localhost", "gateway")] + public void TestCreateIdentity_WithEdgelet_DefaultAuthScheme_ShouldCreateIdentity(string iotHubHostName, string deviceId, string moduleId, string edgeletUri, string gatewayHostName = null) + { + // Arrange + string defaultAuthScheme = "sasToken"; + var builder = new ModuleIdentityProviderServiceBuilder(iotHubHostName, deviceId, gatewayHostName); + + // Act + IModuleIdentity identity = builder.Create(moduleId, edgeletUri); + + + // Assert + Assert.Equal(iotHubHostName, identity.IotHubHostname); + Assert.Equal(gatewayHostName, identity.GatewayHostname); + Assert.Equal(deviceId, identity.DeviceId); + Assert.Equal(moduleId, identity.ModuleId); + var creds = identity.Credentials as IdentityProviderServiceCredentials; + Assert.NotNull(creds); + Assert.Equal(edgeletUri, creds.ProviderUri); + Assert.Equal(defaultAuthScheme, creds.AuthScheme); + Assert.Equal(Option.None(), creds.Version); + } + + [Theory] + [InlineData("foo.azure.com", "d1", "m1", "localhost")] + [InlineData("foo.azure.com", "d1", "m1", "localhost", "x509")] + [InlineData("foo.azure.com", "d1", "m1", "localhost", "x509", "gateway")] + public void TestCreateIdentity_WithEdgelet_SetAuthScheme_ShouldCreateIdentity(string iotHubHostName, string deviceId, string moduleId, string edgeletUri, string authScheme = "sasToken", string gatewayHostName = null) + { + // Arrange + var builder = new ModuleIdentityProviderServiceBuilder(iotHubHostName, deviceId, gatewayHostName); + + // Act + IModuleIdentity identity = builder.Create(moduleId, edgeletUri, authScheme); + + + // Assert + Assert.Equal(iotHubHostName, identity.IotHubHostname); + Assert.Equal(gatewayHostName, identity.GatewayHostname); + Assert.Equal(deviceId, identity.DeviceId); + Assert.Equal(moduleId, identity.ModuleId); + var creds = identity.Credentials as IdentityProviderServiceCredentials; + Assert.NotNull(creds); + Assert.Equal(edgeletUri, creds.ProviderUri); + Assert.Equal(authScheme, creds.AuthScheme); + Assert.Equal(Option.None(), creds.Version); + } + + [Fact] + public void InvalidInputsTest() + { + Assert.Throws(() => new ModuleIdentityProviderServiceBuilder(null, "1", "gateway")); + Assert.Throws(() => new ModuleIdentityProviderServiceBuilder("", "1", "gateway")); + Assert.Throws(() => new ModuleIdentityProviderServiceBuilder("iothub", null, "gateway")); + Assert.Throws(() => new ModuleIdentityProviderServiceBuilder("iothub", "", "gateway")); + + var builder = new ModuleIdentityProviderServiceBuilder("foo.azure.com", "device1", "gateway"); + + Assert.Throws(() => builder.Create(null, "xyz")); + Assert.Throws(() => builder.Create("localhost", null)); + Assert.Throws(() => builder.Create(null, "localhost", "sasToken")); + Assert.Throws(() => builder.Create("module1", null, "sasToken")); + Assert.Throws(() => builder.Create("module1", "localhost", null)); + } + } +} diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleIdentityTest.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleIdentityTest.cs index b2518c7e21b..08a5b4f01bb 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleIdentityTest.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/ModuleIdentityTest.cs @@ -14,52 +14,15 @@ public void TestCreateInstance_ShouldThrowWhithNullArguments() { string connectionString = "fake"; string moduleName = "module1"; - - Assert.Throws(() => new ModuleIdentity(null, connectionString)); - Assert.Throws(() => new ModuleIdentity(moduleName, null)); + string gatewayHostname = "gateway.local"; + string iothubHostname = "iothub.local"; + string deviceId = "device1"; + + Assert.Throws(() => new ModuleIdentity(null, gatewayHostname, deviceId, moduleName, new ConnectionStringCredentials(connectionString))); + Assert.NotNull(new ModuleIdentity(iothubHostname, null, deviceId, moduleName, new ConnectionStringCredentials(connectionString))); + Assert.Throws(() => new ModuleIdentity(iothubHostname, gatewayHostname, null, moduleName, new ConnectionStringCredentials(connectionString))); + Assert.Throws(() => new ModuleIdentity(iothubHostname, gatewayHostname, deviceId, null, new ConnectionStringCredentials(connectionString))); + Assert.Throws(() => new ModuleIdentity(iothubHostname, gatewayHostname, deviceId, moduleName, null)); } - - [Fact] - [Unit] - public void TestEquals_ShouldReturnTrue() - { - string moduleName = "module1"; - string authMechanism = "fake"; - - var m1 = new ModuleIdentity(moduleName, authMechanism); - var m2 = new ModuleIdentity(moduleName, authMechanism); - - Assert.True(m1.Equals(m2)); - Assert.True(m2.Equals(m1)); - } - - [Fact] - [Unit] - public void TestEquals_SameReference_ShouldReturnTrue() - { - string moduleName = "module1"; - string authMechanism = "fake"; - - var m1 = new ModuleIdentity(moduleName, authMechanism); - ModuleIdentity m2 = m1; - - Assert.True(m1.Equals(m2)); - Assert.True(m2.Equals(m1)); - } - - [Fact] - [Unit] - public void TestEquals_WithDifferentModuleId_ShouldReturnFalse() - { - string moduleName = "module"; - string authMechanism = "fake"; - - var m1 = new ModuleIdentity(moduleName + "1", authMechanism); - var m2 = new ModuleIdentity(moduleName + "2", authMechanism); - - Assert.False(m1.Equals(m2)); - Assert.False(m2.Equals(m1)); - } - } } diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/planners/HealthRestartPlannerTest.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/planners/HealthRestartPlannerTest.cs index 0e4043b7899..0c810d9d368 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/planners/HealthRestartPlannerTest.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/planners/HealthRestartPlannerTest.cs @@ -894,13 +894,13 @@ public async Task TestResetStatsForHealthyModules() static IImmutableDictionary GetModuleIdentities(IList modules) { - string credential = "fake"; + ICredentials credential = new ConnectionStringCredentials("fake"); IDictionary identities = new Dictionary(); foreach (IModule module in modules) { var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(credential); - identity.Setup(id => id.Name).Returns(module.Name); + identity.Setup(id => id.Credentials).Returns(credential); + identity.Setup(id => id.ModuleId).Returns(module.Name); identities.Add(module.Name, identity.Object); } diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/planners/RestartPlannerTest.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/planners/RestartPlannerTest.cs index c2832812d75..88362a2b064 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/planners/RestartPlannerTest.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Core.Test/planners/RestartPlannerTest.cs @@ -206,13 +206,13 @@ public async void RestartPlannerAddRemoveUpdate() static IImmutableDictionary GetModuleIdentities(IList modules) { - string credential = "fake"; + var credential = new ConnectionStringCredentials("fake"); IDictionary identities = new Dictionary(); foreach (IModule module in modules) { var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(credential); - identity.Setup(id => id.Name).Returns(module.Name); + identity.Setup(id => id.Credentials).Returns(credential); + identity.Setup(id => id.ModuleId).Returns(module.Name); identities.Add(module.Name, identity.Object); } diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.E2E.Test/AgentTests.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.E2E.Test/AgentTests.cs index 162747e330b..1dcba159d5c 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.E2E.Test/AgentTests.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.E2E.Test/AgentTests.cs @@ -98,10 +98,10 @@ public async Task AgentStartsUpModules(TestConfig testConfig) IEnvironmentProvider environmentProvider = await DockerEnvironmentProvider.CreateAsync(runtimeInfoProvider, restartStateStore, restartManager); var commandFactory = new LoggingCommandFactory(dockerCommandFactory, loggerFactory); - string credential = "fake"; + var credential = new ConnectionStringCredentials("fake"); var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(credential); - identity.Setup(id => id.Name).Returns(testConfig.Name); + identity.Setup(id => id.Credentials).Returns(credential); + identity.Setup(id => id.ModuleId).Returns(testConfig.Name); IImmutableDictionary identities = new Dictionary() { [testConfig.Name] = identity.Object diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.Test/RuntimeInfoProviderTest.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.Test/RuntimeInfoProviderTest.cs index f909c4bfe8d..a13db21107b 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.Test/RuntimeInfoProviderTest.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.Test/RuntimeInfoProviderTest.cs @@ -91,9 +91,9 @@ public async Task TestFilters() configSource.Setup(cs => cs.Configuration).Returns(configRoot); configSource.Setup(cs => cs.GetDeploymentConfigInfoAsync()).ReturnsAsync(deploymentConfigInfo); - string credential = "fake"; + var credential = new ConnectionStringCredentials("fake"); var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(credential); + identity.Setup(id => id.Credentials).Returns(credential); ICommand create = await CreateCommand.BuildAsync(Client, module, identity.Object, loggingConfig, configSource.Object, false); @@ -156,9 +156,9 @@ public async Task TestEnvVars() configSource.Setup(cs => cs.Configuration).Returns(configRoot); configSource.Setup(cs => cs.GetDeploymentConfigInfoAsync()).ReturnsAsync(deploymentConfigInfo); - string credential = "fake"; + var credential = new ConnectionStringCredentials("fake"); var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(credential); + identity.Setup(id => id.Credentials).Returns(credential); ICommand create = await CreateCommand.BuildAsync(Client, module, identity.Object, loggingConfig, configSource.Object, false); diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.Test/commands/CreateCommandTest.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.Test/commands/CreateCommandTest.cs index cc0bffbe0b1..62b59d04726 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.Test/commands/CreateCommandTest.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Docker.Test/commands/CreateCommandTest.cs @@ -67,7 +67,7 @@ public async Task SmokeTest() configSource.Setup(cs => cs.GetDeploymentConfigInfoAsync()).ReturnsAsync(deploymentConfigInfo); var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(fakeConnectionString); + identity.Setup(id => id.Credentials).Returns(new ConnectionStringCredentials(fakeConnectionString)); ICommand command = await CreateCommand.BuildAsync(DockerHelper.Client, module, identity.Object, loggingConfig, configSource.Object, false); @@ -138,7 +138,7 @@ public async Task TestUdpModuleConfig() string credential = "fake"; var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(credential); + identity.Setup(id => id.Credentials).Returns(new ConnectionStringCredentials(credential)); ICommand command = await CreateCommand.BuildAsync(DockerHelper.Client, module, identity.Object, loggingConfig, configSource.Object, false); @@ -216,7 +216,7 @@ public async Task EdgeHubLaunch() configSource.Setup(cs => cs.GetDeploymentConfigInfoAsync()).ReturnsAsync(deploymentConfigInfo); var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(fakeConnectionString); + identity.Setup(id => id.Credentials).Returns(new ConnectionStringCredentials(fakeConnectionString)); ICommand command = await CreateCommand.BuildAsync(DockerHelper.Client, module, identity.Object, loggingConfig, configSource.Object, true); @@ -299,7 +299,7 @@ public async Task EdgeHubLaunchWithBadLogOptions() configSource.Setup(cs => cs.GetDeploymentConfigInfoAsync()).ReturnsAsync(deploymentConfigInfo); var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(fakeConnectionString); + identity.Setup(id => id.Credentials).Returns(new ConnectionStringCredentials(fakeConnectionString)); ICommand command = await CreateCommand.BuildAsync(DockerHelper.Client, module, identity.Object, loggingConfig, configSource.Object, true); @@ -367,8 +367,8 @@ public async Task TestMountEdgeHubVolume() .Returns(containerOperations.Object); var moduleIdentity = new Mock(); - moduleIdentity.SetupGet(i => i.ConnectionString) - .Returns(string.Empty); + moduleIdentity.SetupGet(i => i.Credentials) + .Returns(new ConnectionStringCredentials(string.Empty)); var runtimeInfo = new Mock>(); runtimeInfo.SetupGet(r => r.Config) @@ -435,8 +435,8 @@ public async Task TestMountModuleVolume() .Returns(containerOperations.Object); var moduleIdentity = new Mock(); - moduleIdentity.SetupGet(i => i.ConnectionString) - .Returns(string.Empty); + moduleIdentity.SetupGet(i => i.Credentials) + .Returns(new ConnectionStringCredentials(string.Empty)); var runtimeInfo = new Mock>(); runtimeInfo.SetupGet(r => r.Config) @@ -677,7 +677,7 @@ public async Task UpstreamProtocolTest() configSource.Setup(cs => cs.GetDeploymentConfigInfoAsync()).ReturnsAsync(deploymentConfigInfo); var identity = new Mock(); - identity.Setup(id => id.ConnectionString).Returns(fakeConnectionString); + identity.Setup(id => id.Credentials).Returns(new ConnectionStringCredentials(fakeConnectionString)); ICommand command = await CreateCommand.BuildAsync(DockerHelper.Client, module, identity.Object, loggingConfig, configSource.Object, false); diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Edgelet.Test/ModuleIdentityLifecycleManagerTest.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Edgelet.Test/ModuleIdentityLifecycleManagerTest.cs index 9ba99586b80..bcbbc1953d5 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Edgelet.Test/ModuleIdentityLifecycleManagerTest.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.Edgelet.Test/ModuleIdentityLifecycleManagerTest.cs @@ -11,6 +11,7 @@ namespace Microsoft.Azure.Devices.Edge.Agent.Edgelet.Test using Microsoft.Azure.Devices.Edge.Agent.Core.Test; using Microsoft.Azure.Devices.Edge.Agent.Edgelet; using Microsoft.Azure.Devices.Edge.Agent.Edgelet.GeneratedCode; + using Microsoft.Azure.Devices.Edge.Util; using Microsoft.Azure.Devices.Edge.Util.Test.Common; using Moq; using Xunit; @@ -21,15 +22,16 @@ public class ModuleIdentityLifecycleManagerTest const string IothubHostName = "test.azure-devices.net"; const string DeviceId = "edgeDevice1"; const string GatewayHostName = "edgedevicehost"; + const string EdgeletUri = "localhost"; static readonly ConfigurationInfo DefaultConfigurationInfo = new ConfigurationInfo("1"); - static readonly ModuleConnectionStringBuilder ModuleConnectionStringBuilder = new ModuleConnectionStringBuilder(IothubHostName, DeviceId); + static readonly ModuleIdentityProviderServiceBuilder ModuleIdentityProviderServiceBuilder = new ModuleIdentityProviderServiceBuilder(IothubHostName, DeviceId, GatewayHostName); [Fact] public async Task TestGetModulesIdentity_WithEmptyDiff_ShouldReturnEmptyIdentities() { // Arrange var identityManager = Mock.Of(m => m.GetIdentities() == Task.FromResult(Enumerable.Empty())); - var moduleIdentityLifecycleManager = new ModuleIdentityLifecycleManager(identityManager, ModuleConnectionStringBuilder, GatewayHostName); + var moduleIdentityLifecycleManager = new ModuleIdentityLifecycleManager(identityManager, ModuleIdentityProviderServiceBuilder, EdgeletUri); // Act IImmutableDictionary modulesIdentities = await moduleIdentityLifecycleManager.GetModuleIdentitiesAsync(ModuleSet.Empty, ModuleSet.Empty); @@ -56,7 +58,7 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_ShouldCreateIdentiti m.GetIdentities() == Task.FromResult(Enumerable.Empty()) && m.CreateIdentityAsync(Name) == Task.FromResult(identity)); - var moduleIdentityLifecycleManager = new ModuleIdentityLifecycleManager(identityManager, ModuleConnectionStringBuilder, GatewayHostName); + var moduleIdentityLifecycleManager = new ModuleIdentityLifecycleManager(identityManager, ModuleIdentityProviderServiceBuilder, EdgeletUri); var module = new TestModule(Name, "v1", "test", ModuleStatus.Running, new TestConfig("image"), RestartPolicy.OnUnhealthy, DefaultConfigurationInfo); // Act @@ -65,8 +67,10 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_ShouldCreateIdentiti // Assert Assert.True(modulesIdentities.Count() == 1); Assert.True(modulesIdentities.TryGetValue(Name, out IModuleIdentity moduleIdentity)); - Assert.Equal(moduleIdentity.Name, Name); - Assert.Equal(moduleIdentity.ConnectionString, $"HostName={IothubHostName};DeviceId={DeviceId};ModuleId={Name};GatewayHostName={GatewayHostName}"); + Assert.Equal(moduleIdentity.ModuleId, Name); + Assert.IsType(moduleIdentity.Credentials); + Assert.Equal(EdgeletUri, ((IdentityProviderServiceCredentials)moduleIdentity.Credentials).ProviderUri); + Assert.Equal(Option.None(), ((IdentityProviderServiceCredentials)moduleIdentity.Credentials).Version); Mock.Get(identityManager).Verify(); } @@ -104,7 +108,7 @@ public async Task TestGetModulesIdentity_WithRemovedModules_ShouldRemove() m.CreateIdentityAsync(Module1) == Task.FromResult(identity1) && m.DeleteIdentityAsync(Module3) == Task.FromResult(identity3)); - var moduleIdentityLifecycleManager = new ModuleIdentityLifecycleManager(identityManager, ModuleConnectionStringBuilder, GatewayHostName); + var moduleIdentityLifecycleManager = new ModuleIdentityLifecycleManager(identityManager, ModuleIdentityProviderServiceBuilder, EdgeletUri); var desiredModule = new TestModule(Module1, "v1", "test", ModuleStatus.Running, new TestConfig("image"), RestartPolicy.OnUnhealthy, DefaultConfigurationInfo); var currentModule1 = new TestModule(Module2, "v1", "test", ModuleStatus.Running, new TestConfig("image"), RestartPolicy.OnUnhealthy, DefaultConfigurationInfo); var currentModule2 = new TestModule(Module3, "v1", "test", ModuleStatus.Running, new TestConfig("image"), RestartPolicy.OnUnhealthy, DefaultConfigurationInfo); @@ -117,8 +121,10 @@ public async Task TestGetModulesIdentity_WithRemovedModules_ShouldRemove() // Assert Assert.NotNull(moduleIdentities); Assert.True(moduleIdentities.TryGetValue(Module1, out IModuleIdentity module1Identity)); - Assert.Equal(Module1, module1Identity.Name); - Assert.Equal($"HostName={IothubHostName};DeviceId={DeviceId};ModuleId={Module1};GatewayHostName={GatewayHostName}", module1Identity.ConnectionString); + Assert.Equal(Module1, module1Identity.ModuleId); + Assert.IsType(module1Identity.Credentials); + Assert.Equal(EdgeletUri, ((IdentityProviderServiceCredentials)module1Identity.Credentials).ProviderUri); + Assert.Equal(Option.None(), ((IdentityProviderServiceCredentials)module1Identity.Credentials).Version); Mock.Get(identityManager).Verify(); } } diff --git a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.IoTHub.Test/ModuleIdentityLifecycleManagerTest.cs b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.IoTHub.Test/ModuleIdentityLifecycleManagerTest.cs index 2f328a09072..a5b4ae15d67 100644 --- a/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.IoTHub.Test/ModuleIdentityLifecycleManagerTest.cs +++ b/edge-agent/test/Microsoft.Azure.Devices.Edge.Agent.IoTHub.Test/ModuleIdentityLifecycleManagerTest.cs @@ -26,7 +26,7 @@ public async Task TestGetModulesIdentity_WithEmptyDiff_ShouldReturnEmptyIdentiti string hostname = "hostname"; string deviceId = "deviceId"; string gatewayHostName = "localhost"; - var moduleConnectionStringBuilder = new ModuleConnectionStringBuilder(hostname, deviceId); + var moduleConnectionStringBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(hostname, deviceId); IImmutableDictionary modulesIdentities = await new ModuleIdentityLifecycleManager(serviceClient.Object, moduleConnectionStringBuilder, gatewayHostName) .GetModuleIdentitiesAsync(ModuleSet.Empty, ModuleSet.Empty); @@ -46,7 +46,7 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_NoServiceIdentity_Sh string deviceSharedAccessKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("primaryDeviceAccessKey")); string moduleSharedAccessKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("primaryModuleAccessKey")); string gatewayHostName = "localhost"; - var moduleConnectionStringBuilder = new ModuleConnectionStringBuilder(hostname, deviceId); + var moduleIdentityBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(hostname, deviceId); serviceClient.Setup(sc => sc.GetModules()).Returns(Task.FromResult(ImmutableList.Empty.AsEnumerable())); @@ -63,7 +63,7 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_NoServiceIdentity_Sh var module = new TestModule(Name, "v1", "test", ModuleStatus.Running, new TestConfig("image"), RestartPolicy.OnUnhealthy, DefaultConfigurationInfo); - IImmutableDictionary modulesIdentities = await new ModuleIdentityLifecycleManager(serviceClient.Object, moduleConnectionStringBuilder, gatewayHostName) + IImmutableDictionary modulesIdentities = await new ModuleIdentityLifecycleManager(serviceClient.Object, moduleIdentityBuilder, gatewayHostName) .GetModuleIdentitiesAsync(ModuleSet.Create(new IModule[] { module }), ModuleSet.Empty); // If we change to IList Mock doesn't recognize and making it a non Lambda would add a lot of complexity on this code. @@ -88,7 +88,7 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_NoAccessKey_ShouldUp string deviceId = "deviceId"; string sharedAccessKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("primarySymmetricKey")); string gatewayHostName = "localhost"; - var moduleConnectionStringBuilder = new ModuleConnectionStringBuilder(hostname, deviceId); + var moduleIdentityBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(hostname, deviceId); var serviceIdentities = new[] { serviceModuleIdentity }; serviceClient.Setup(sc => sc.GetModules()).Returns(Task.FromResult(serviceIdentities.AsEnumerable())); @@ -104,7 +104,7 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_NoAccessKey_ShouldUp var module = new TestModule(Name, "v1", "test", ModuleStatus.Running, new TestConfig("image"), RestartPolicy.OnUnhealthy, DefaultConfigurationInfo); - IImmutableDictionary modulesIdentities = await new ModuleIdentityLifecycleManager(serviceClient.Object, moduleConnectionStringBuilder, gatewayHostName) + IImmutableDictionary modulesIdentities = await new ModuleIdentityLifecycleManager(serviceClient.Object, moduleIdentityBuilder, gatewayHostName) .GetModuleIdentitiesAsync(ModuleSet.Create(new IModule[] { module }), ModuleSet.Empty); serviceClient.Verify(sc => sc.UpdateModules(It.IsAny>()), Times.Once()); @@ -125,7 +125,7 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_AuthTypeNull_ShouldU string deviceId = "deviceId"; string sharedAccessKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("primarySymmetricKey")); string gatewayHostName = "localhost"; - var moduleConnectionStringBuilder = new ModuleConnectionStringBuilder(hostname, deviceId); + var moduleIdentityBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(hostname, deviceId); var serviceIdentities = new[] { serviceModuleIdentity }; serviceClient.Setup(sc => sc.GetModules()).Returns(Task.FromResult(serviceIdentities.AsEnumerable())); @@ -141,12 +141,14 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_AuthTypeNull_ShouldU var module = new TestModule(Name, "v1", "test", ModuleStatus.Running, new TestConfig("image"), RestartPolicy.OnUnhealthy, DefaultConfigurationInfo); - IImmutableDictionary modulesIdentities = await new ModuleIdentityLifecycleManager(serviceClient.Object, moduleConnectionStringBuilder, gatewayHostName) + IImmutableDictionary modulesIdentities = await new ModuleIdentityLifecycleManager(serviceClient.Object, moduleIdentityBuilder, gatewayHostName) .GetModuleIdentitiesAsync(ModuleSet.Create(new IModule[] { module }), ModuleSet.Empty); serviceClient.Verify(sc => sc.UpdateModules(It.IsAny>()), Times.Once()); Assert.True(modulesIdentities.Count() == 1); - IotHubConnectionStringBuilder connectionString = IotHubConnectionStringBuilder.Create(modulesIdentities.First().Value.ConnectionString); + var creds = modulesIdentities.First().Value.Credentials as ConnectionStringCredentials; + Assert.NotNull(creds); + IotHubConnectionStringBuilder connectionString = IotHubConnectionStringBuilder.Create(creds.ConnectionString); Assert.NotNull(connectionString.SharedAccessKey); } @@ -172,7 +174,7 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_AuthTypeNotSas_Shoul string deviceId = "deviceId"; string sharedAccessKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("test")); string gatewayHostName = "localhost"; - var moduleConnectionStringBuilder = new ModuleConnectionStringBuilder(hostname, deviceId); + var moduleConnectionStringBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(hostname, deviceId); var serviceIdentities = new[] { serviceModuleIdentity }; serviceClient.Setup(sc => sc.GetModules()).Returns(Task.FromResult(serviceIdentities.AsEnumerable())); @@ -193,7 +195,9 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_AuthTypeNotSas_Shoul serviceClient.Verify(sc => sc.UpdateModules(It.IsAny>()), Times.Once()); Assert.True(modulesIdentities.Count() == 1); - IotHubConnectionStringBuilder connectionString = IotHubConnectionStringBuilder.Create(modulesIdentities.First().Value.ConnectionString); + var creds = modulesIdentities.First().Value.Credentials as ConnectionStringCredentials; + Assert.NotNull(creds); + IotHubConnectionStringBuilder connectionString = IotHubConnectionStringBuilder.Create(creds.ConnectionString); Assert.NotNull(connectionString.SharedAccessKey); } @@ -213,7 +217,7 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_SymmKeyNull_ShouldUp string deviceId = "deviceId"; string sharedAccessKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("primaryAccessKey")); string gatewayHostName = "localhost"; - var moduleConnectionStringBuilder = new ModuleConnectionStringBuilder(hostname, deviceId); + var moduleConnectionStringBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(hostname, deviceId); var serviceIdentities = new[] { serviceModuleIdentity }; serviceClient.Setup(sc => sc.GetModules()).Returns(Task.FromResult(serviceIdentities.AsEnumerable())); @@ -234,7 +238,9 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_SymmKeyNull_ShouldUp serviceClient.Verify(sc => sc.UpdateModules(It.IsAny>()), Times.Once()); Assert.True(modulesIdentities.Count() == 1); - IotHubConnectionStringBuilder connectionString = IotHubConnectionStringBuilder.Create(modulesIdentities.First().Value.ConnectionString); + var creds = modulesIdentities.First().Value.Credentials as ConnectionStringCredentials; + Assert.NotNull(creds); + IotHubConnectionStringBuilder connectionString = IotHubConnectionStringBuilder.Create(creds.ConnectionString); Assert.NotNull(connectionString.SharedAccessKey); } @@ -257,7 +263,7 @@ public async Task TestGetModulesIdentity_WithUpdatedModules_HasAccessKey_ShouldN string deviceId = "deviceId"; string sharedAccessKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("test")); string gatewayHostName = "localhost"; - var moduleConnectionStringBuilder = new ModuleConnectionStringBuilder(hostname, deviceId); + var moduleConnectionStringBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(hostname, deviceId); var serviceIdentities = new[] { serviceModuleIdentity }; serviceClient.Setup(sc => sc.GetModules()).Returns(Task.FromResult(serviceIdentities.AsEnumerable())); @@ -289,7 +295,7 @@ public async Task TestGetModulesIdentity_WithRemovedModules_ShouldRemove() string deviceId = "deviceId"; string sharedAccessKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("test")); string gatewayHostName = "localhost"; - var moduleConnectionStringBuilder = new ModuleConnectionStringBuilder(hostname, deviceId); + var moduleConnectionStringBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(hostname, deviceId); var serviceIdentities = new List(); serviceIdentities.Add(serviceModuleIdentity); @@ -323,7 +329,7 @@ public async Task TestGetModulesIdentity_WithRemovedModules_NotEdgeHubManaged_Sh string deviceId = "deviceId"; string sharedAccessKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("test")); string gatewayHostName = "localhost"; - var moduleConnectionStringBuilder = new ModuleConnectionStringBuilder(hostname, deviceId); + var moduleConnectionStringBuilder = new ModuleConnectionString.ModuleConnectionStringBuilder(hostname, deviceId); var serviceIdentities = new List(); serviceIdentities.Add(serviceModuleIdentity); diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/CloudConnection.cs b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/CloudConnection.cs index ba1f3d8814c..54045193967 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/CloudConnection.cs +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/CloudConnection.cs @@ -189,6 +189,14 @@ IDeviceClient CreateDeviceClient(IClientCredentials newCredentials, ITransportSe IAuthenticationMethod authenticationMethod = this.GetAuthenticationMethod(tokenAuthentication.Identity, tokenAuthentication.Token); return this.deviceClientProvider.Create(newCredentials.Identity.IotHubHostName, authenticationMethod, settings); + case AuthenticationType.IoTEdged: + if (!(newCredentials is IotEdgedCredentials)) + { + throw new ArgumentException($"IoTEdged credential should be of type {nameof(IotEdgedCredentials)}"); + } + + return this.deviceClientProvider.Create(settings); + default: throw new InvalidOperationException($"Unsupported authentication type {newCredentials.AuthenticationType}"); } diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/DeviceClientProvider.cs b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/DeviceClientProvider.cs index ce84cc4a76c..9a278aca52f 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/DeviceClientProvider.cs +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/DeviceClientProvider.cs @@ -3,6 +3,7 @@ namespace Microsoft.Azure.Devices.Edge.Hub.CloudProxy { using Microsoft.Azure.Devices.Client; + using Microsoft.Azure.Devices.Edge.ClientWrapper; public class DeviceClientProvider : IDeviceClientProvider { @@ -17,5 +18,11 @@ public IDeviceClient Create(string connectionString, ITransportSettings[] transp DeviceClient deviceClient = DeviceClient.CreateFromConnectionString(connectionString, transportSettings); return new DeviceClientWrapper(deviceClient); } + + public IDeviceClient Create(ITransportSettings[] transportSettings) + { + DeviceClient deviceClient = new DeviceClientFactory(transportSettings).Create(); + return new DeviceClientWrapper(deviceClient); + } } } diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/IDeviceClientProvider.cs b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/IDeviceClientProvider.cs index 622e30ed920..43dffaef8a3 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/IDeviceClientProvider.cs +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/IDeviceClientProvider.cs @@ -9,5 +9,7 @@ public interface IDeviceClientProvider IDeviceClient Create(string hostName, IAuthenticationMethod authenticationMethod, ITransportSettings[] transportSettings); IDeviceClient Create(string connectionString, ITransportSettings[] transportSettings); + + IDeviceClient Create(ITransportSettings[] transportSettings); } } diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/Microsoft.Azure.Devices.Edge.Hub.CloudProxy.csproj b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/Microsoft.Azure.Devices.Edge.Hub.CloudProxy.csproj index 8b65dc673a2..0032735cd49 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/Microsoft.Azure.Devices.Edge.Hub.CloudProxy.csproj +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.CloudProxy/Microsoft.Azure.Devices.Edge.Hub.CloudProxy.csproj @@ -23,6 +23,7 @@ + diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/Microsoft.Azure.Devices.Edge.Hub.Core.csproj b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/Microsoft.Azure.Devices.Edge.Hub.Core.csproj index c2432edcc87..7b6bc373e0b 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/Microsoft.Azure.Devices.Edge.Hub.Core.csproj +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/Microsoft.Azure.Devices.Edge.Hub.Core.csproj @@ -27,7 +27,7 @@ - + diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/AuthenticationType.cs b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/AuthenticationType.cs index 5a661481f05..41fe0b75aa9 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/AuthenticationType.cs +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/AuthenticationType.cs @@ -6,6 +6,7 @@ public enum AuthenticationType None, SasKey, Token, - X509Cert + X509Cert, + IoTEdged } } diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/ClientCredentialsFactory.cs b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/ClientCredentialsFactory.cs index ae1b54ea4ae..3ab6896dd03 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/ClientCredentialsFactory.cs +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/ClientCredentialsFactory.cs @@ -49,6 +49,11 @@ public IClientCredentials GetWithConnectionString(string connectionString) return new SharedKeyCredentials(identity, connectionString, this.callerProductInfo); } + public IClientCredentials GetWithIotEdged(string deviceId, string moduleId) + { + return new IotEdgedCredentials(this.GetIdentity(deviceId, moduleId), this.callerProductInfo); + } + IIdentity GetIdentity(string deviceId, string moduleId) { IIdentity identity = string.IsNullOrWhiteSpace(moduleId) diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/IClientCredentialsFactory.cs b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/IClientCredentialsFactory.cs index b563a5f84da..0f8f07dc55c 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/IClientCredentialsFactory.cs +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/IClientCredentialsFactory.cs @@ -9,5 +9,7 @@ public interface IClientCredentialsFactory IClientCredentials GetWithSasToken(string deviceId, string moduleId, string deviceClientType, string token); IClientCredentials GetWithConnectionString(string connectionString); + + IClientCredentials GetWithIotEdged(string deviceId, string moduleId); } } diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/IotEdgedCredentials.cs b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/IotEdgedCredentials.cs new file mode 100644 index 00000000000..804f7a005c9 --- /dev/null +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Core/identity/IotEdgedCredentials.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft. All rights reserved. + +namespace Microsoft.Azure.Devices.Edge.Hub.Core.Identity +{ + using Microsoft.Azure.Devices.Edge.Util; + + public class IotEdgedCredentials : IClientCredentials + { + public IotEdgedCredentials(IIdentity identity, string productInfo) + { + this.Identity = Preconditions.CheckNotNull(identity, nameof(identity)); + this.ProductInfo = productInfo ?? string.Empty; + this.AuthenticationType = AuthenticationType.IoTEdged; + } + + public IIdentity Identity { get; } + + public AuthenticationType AuthenticationType { get; } + + public string ProductInfo { get; } + } +} diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Service/Startup.cs b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Service/Startup.cs index 1a3139b39a7..fe099a06141 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Service/Startup.cs +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Service/Startup.cs @@ -14,6 +14,7 @@ namespace Microsoft.Azure.Devices.Edge.Hub.Service using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; + using Microsoft.Azure.Devices.Client; using Microsoft.Azure.Devices.Edge.Hub.CloudProxy; using Microsoft.Azure.Devices.Edge.Hub.Core.Config; using Microsoft.Azure.Devices.Edge.Hub.Http; @@ -29,8 +30,14 @@ namespace Microsoft.Azure.Devices.Edge.Hub.Service public class Startup : IStartup { - readonly Client.IotHubConnectionStringBuilder iotHubConnectionStringBuilder; - readonly string edgeHubConnectionString; + const string IotHubConnectionStringVariableName = "IotHubConnectionString"; + const string IotHubHostnameVariableName = "IOTEDGE_IOTHUBHOSTNAME"; + const string DeviceIdVariableName = "IOTEDGE_DEVICEID"; + const string ModuleIdVariableName = "IOTEDGE_MODULEID"; + readonly string iotHubHostname; + readonly string edgeDeviceId; + readonly string edgeModuleId; + readonly Option connectionString; // ReSharper disable once UnusedParameter.Local public Startup(IHostingEnvironment env) @@ -40,8 +47,23 @@ public Startup(IHostingEnvironment env) .AddEnvironmentVariables() .Build(); - this.edgeHubConnectionString = this.Configuration.GetValue("IotHubConnectionString"); - this.iotHubConnectionStringBuilder = Client.IotHubConnectionStringBuilder.Create(this.edgeHubConnectionString); + string edgeHubConnectionString = this.Configuration.GetValue(IotHubConnectionStringVariableName); + if (!string.IsNullOrWhiteSpace(edgeHubConnectionString)) + { + IotHubConnectionStringBuilder iotHubConnectionStringBuilder = Client.IotHubConnectionStringBuilder.Create(edgeHubConnectionString); + this.iotHubHostname = iotHubConnectionStringBuilder.HostName; + this.edgeDeviceId = iotHubConnectionStringBuilder.DeviceId; + this.edgeModuleId = iotHubConnectionStringBuilder.ModuleId; + this.connectionString = Option.Some(edgeHubConnectionString); + } + else + { + this.iotHubHostname = this.Configuration.GetValue(IotHubHostnameVariableName); + this.edgeDeviceId = this.Configuration.GetValue(DeviceIdVariableName); + this.edgeModuleId = this.Configuration.GetValue(ModuleIdVariableName); + this.connectionString = Option.None(); + } + this.VersionInfo = VersionInfo.Get(Constants.VersionInfoFileName); } @@ -117,13 +139,14 @@ IContainer BuildContainer(IServiceCollection services) builder.RegisterModule( new CommonModule( this.GetProductInfo(), - this.iotHubConnectionStringBuilder.HostName, - this.iotHubConnectionStringBuilder.DeviceId)); + this.iotHubHostname, + this.edgeDeviceId)); builder.RegisterModule( new RoutingModule( - this.iotHubConnectionStringBuilder.HostName, - this.iotHubConnectionStringBuilder.DeviceId, - this.edgeHubConnectionString, + this.iotHubHostname, + this.edgeDeviceId, + this.edgeModuleId, + this.connectionString, routes, storeAndForward.isEnabled, storeAndForward.usePersistentStorage, @@ -135,7 +158,7 @@ IContainer BuildContainer(IServiceCollection services) upstreamProtocolOption)); builder.RegisterModule(new MqttModule(mqttSettingsConfiguration, topics, tlsCertificate, storeAndForward.isEnabled, clientCertAuthEnabled, caChainPath)); - builder.RegisterModule(new AmqpModule(amqpSettings["scheme"], amqpSettings.GetValue("port"), tlsCertificate, this.iotHubConnectionStringBuilder.HostName)); + builder.RegisterModule(new AmqpModule(amqpSettings["scheme"], amqpSettings.GetValue("port"), tlsCertificate, this.iotHubHostname)); builder.RegisterModule(new HttpModule()); builder.RegisterInstance(this); @@ -149,7 +172,7 @@ public void Configure(IApplicationBuilder app) app.UseWebSockets(); app.UseWebSocketHandlingMiddleware(webSocketListenerRegistry); - app.UseAuthenticationMiddleware(this.iotHubConnectionStringBuilder.HostName); + app.UseAuthenticationMiddleware(this.iotHubHostname); app.UseMvc(); } diff --git a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Service/modules/RoutingModule.cs b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Service/modules/RoutingModule.cs index 26cc3d43d37..5db1a11e1ee 100644 --- a/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Service/modules/RoutingModule.cs +++ b/edge-hub/src/Microsoft.Azure.Devices.Edge.Hub.Service/modules/RoutingModule.cs @@ -29,20 +29,22 @@ public class RoutingModule : Module { readonly string iotHubName; readonly string edgeDeviceId; + readonly string edgeModuleId; + readonly Option connectionString; readonly IDictionary routes; readonly StoreAndForwardConfiguration storeAndForwardConfiguration; readonly int connectionPoolSize; readonly bool isStoreAndForwardEnabled; readonly bool usePersistentStorage; readonly string storagePath; - readonly string edgeHubConnectionString; readonly bool useTwinConfig; readonly VersionInfo versionInfo; readonly Option upstreamProtocol; public RoutingModule(string iotHubName, string edgeDeviceId, - string edgeHubConnectionString, + string edgeModuleId, + Option connectionString, IDictionary routes, bool isStoreAndForwardEnabled, bool usePersistentStorage, @@ -55,9 +57,10 @@ public RoutingModule(string iotHubName, { this.iotHubName = Preconditions.CheckNonWhiteSpace(iotHubName, nameof(iotHubName)); this.edgeDeviceId = Preconditions.CheckNonWhiteSpace(edgeDeviceId, nameof(edgeDeviceId)); - this.edgeHubConnectionString = Preconditions.CheckNonWhiteSpace(edgeHubConnectionString, nameof(edgeHubConnectionString)); + this.connectionString = Preconditions.CheckNotNull(connectionString, nameof(connectionString)); this.routes = Preconditions.CheckNotNull(routes, nameof(routes)); this.storeAndForwardConfiguration = Preconditions.CheckNotNull(storeAndForwardConfiguration, nameof(storeAndForwardConfiguration)); + this.edgeModuleId = edgeModuleId; this.isStoreAndForwardEnabled = isStoreAndForwardEnabled; this.usePersistentStorage = usePersistentStorage; this.storagePath = storagePath; @@ -326,7 +329,8 @@ protected override void Load(ContainerBuilder builder) if (this.useTwinConfig) { var identityFactory = c.Resolve(); - IClientCredentials edgeHubIdentity = identityFactory.GetWithConnectionString(this.edgeHubConnectionString); + IClientCredentials edgeHubIdentity = this.connectionString.Map(cs => identityFactory.GetWithConnectionString(cs)).GetOrElse( + () => identityFactory.GetWithIotEdged(this.edgeDeviceId, this.edgeModuleId)); var connectionManager = c.Resolve(); var twinCollectionMessageConverter = c.Resolve>(); var twinMessageConverter = c.Resolve>(); diff --git a/edge-hub/test/Microsoft.Azure.Devices.Edge.Hub.E2E.Test/ProtocolHeadFixture.cs b/edge-hub/test/Microsoft.Azure.Devices.Edge.Hub.E2E.Test/ProtocolHeadFixture.cs index 7df3ba43bd3..69750325fc0 100644 --- a/edge-hub/test/Microsoft.Azure.Devices.Edge.Hub.E2E.Test/ProtocolHeadFixture.cs +++ b/edge-hub/test/Microsoft.Azure.Devices.Edge.Hub.E2E.Test/ProtocolHeadFixture.cs @@ -132,7 +132,8 @@ async Task StartProtocolHead(IDictionary routesInput, Action() ) diff --git a/edge-modules/SimulatedTemperatureSensor/SimulatedTemperatureSensor.csproj b/edge-modules/SimulatedTemperatureSensor/SimulatedTemperatureSensor.csproj index e5b7d7eedc6..cde1d79af1d 100644 --- a/edge-modules/SimulatedTemperatureSensor/SimulatedTemperatureSensor.csproj +++ b/edge-modules/SimulatedTemperatureSensor/SimulatedTemperatureSensor.csproj @@ -25,7 +25,7 @@ - + diff --git a/edge-modules/TemperatureFilter/TemperatureFilter.csproj b/edge-modules/TemperatureFilter/TemperatureFilter.csproj index a9b7098f963..28e24d65c12 100644 --- a/edge-modules/TemperatureFilter/TemperatureFilter.csproj +++ b/edge-modules/TemperatureFilter/TemperatureFilter.csproj @@ -20,7 +20,7 @@ - + diff --git a/edge-modules/functions/binding/src/Microsoft.Azure.Devices.Edge.Functions.Binding/Microsoft.Azure.Devices.Edge.Functions.Binding.csproj b/edge-modules/functions/binding/src/Microsoft.Azure.Devices.Edge.Functions.Binding/Microsoft.Azure.Devices.Edge.Functions.Binding.csproj index 82869456b5f..27f26890529 100644 --- a/edge-modules/functions/binding/src/Microsoft.Azure.Devices.Edge.Functions.Binding/Microsoft.Azure.Devices.Edge.Functions.Binding.csproj +++ b/edge-modules/functions/binding/src/Microsoft.Azure.Devices.Edge.Functions.Binding/Microsoft.Azure.Devices.Edge.Functions.Binding.csproj @@ -21,7 +21,7 @@ - + diff --git a/edge-util/src/Microsoft.Azure.Devices.Edge.ClientWrapper/DeviceClientFactory.cs b/edge-util/src/Microsoft.Azure.Devices.Edge.ClientWrapper/DeviceClientFactory.cs index 8fd830c5830..c1ff3719980 100644 --- a/edge-util/src/Microsoft.Azure.Devices.Edge.ClientWrapper/DeviceClientFactory.cs +++ b/edge-util/src/Microsoft.Azure.Devices.Edge.ClientWrapper/DeviceClientFactory.cs @@ -8,13 +8,13 @@ namespace Microsoft.Azure.Devices.Edge.ClientWrapper public class DeviceClientFactory { - const string EdgeletUriVariableName = "IotEdge_EdgeletUri"; - const string EdgeletApiVersionVariableName = "IotEdge_EdgeletVersion"; - const string HostnameVariableName = "IotEdge_IotHubHostname"; - const string GatewayVariableName = "IotEdge_Gateway"; - const string DeviceIdVariableName = "IotEdge_DeviceId"; - const string ModuleIdVariableName = "IotEdge_ModuleId"; - const string AuthSchemeVariableName = "IotEdge_AuthScheme"; + const string EdgeletUriVariableName = "IOTEDGE_IOTEDGEDURI"; + const string EdgeletApiVersionVariableName = "IOTEDGE_IOTEDGEDVERSION"; + const string IotHubHostnameVariableName = "IOTEDGE_IOTHUBHOSTNAME"; + const string GatewayHostnameVariableName = "IOTEDGE_GATEWAYHOSTNAME"; + const string DeviceIdVariableName = "IOTEDGE_DEVICEID"; + const string ModuleIdVariableName = "IOTEDGE_MODULEID"; + const string AuthSchemeVariableName = "IOTEDGE_AUTHSCHEME"; const string SasTokenAuthScheme = "SasToken"; const string EdgehubConnectionstringVariableName = "EdgeHubConnectionString"; const string IothubConnectionstringVariableName = "IotHubConnectionString"; @@ -57,9 +57,9 @@ DeviceClient CreateDeviceClientFromEnvironment() string edgeletUri = this.GetValueFromEnvironment(envVariables, EdgeletUriVariableName) ?? throw new InvalidOperationException($"Environement variable {EdgeletUriVariableName} is required."); string deviceId = this.GetValueFromEnvironment(envVariables, DeviceIdVariableName) ?? throw new InvalidOperationException($"Environement variable {DeviceIdVariableName} is required."); string moduleId = this.GetValueFromEnvironment(envVariables, ModuleIdVariableName) ?? throw new InvalidOperationException($"Environement variable {ModuleIdVariableName} is required."); - string hostname = this.GetValueFromEnvironment(envVariables, HostnameVariableName) ?? throw new InvalidOperationException($"Environement variable {HostnameVariableName} is required."); + string hostname = this.GetValueFromEnvironment(envVariables, IotHubHostnameVariableName) ?? throw new InvalidOperationException($"Environement variable {IotHubHostnameVariableName} is required."); string authScheme = this.GetValueFromEnvironment(envVariables, AuthSchemeVariableName) ?? throw new InvalidOperationException($"Environement variable {AuthSchemeVariableName} is required."); - string gateway = this.GetValueFromEnvironment(envVariables, GatewayVariableName); + string gateway = this.GetValueFromEnvironment(envVariables, GatewayHostnameVariableName); string apiVersion = this.GetValueFromEnvironment(envVariables, EdgeletApiVersionVariableName); if (!string.Equals(authScheme, SasTokenAuthScheme, StringComparison.OrdinalIgnoreCase)) @@ -93,18 +93,17 @@ DeviceClient CreateDeviceClientFromConnectionString(string connectionString) DeviceClient CreateDeviceClientFromAuthenticationMethod(string hostname, string gateway, IAuthenticationMethod authMethod) { - //TODO: modify DeviceSdk to set gateway when using create with IAuthMethod if (this.transportSettings != null) { - return DeviceClient.Create(hostname, authMethod, this.transportSettings); + return DeviceClient.Create(hostname, gateway, authMethod, this.transportSettings); } if (this.transportType.HasValue) { - return DeviceClient.Create(hostname, authMethod, this.transportType.Value); + return DeviceClient.Create(hostname, gateway, authMethod, this.transportType.Value); } - return DeviceClient.Create(hostname, authMethod); + return DeviceClient.Create(hostname, gateway, authMethod); } string GetValueFromEnvironment(IDictionary envVariables, string variableName) diff --git a/edge-util/src/Microsoft.Azure.Devices.Edge.ClientWrapper/Microsoft.Azure.Devices.Edge.ClientWrapper.csproj b/edge-util/src/Microsoft.Azure.Devices.Edge.ClientWrapper/Microsoft.Azure.Devices.Edge.ClientWrapper.csproj index cf5a3a7bf3a..77c02e15d01 100644 --- a/edge-util/src/Microsoft.Azure.Devices.Edge.ClientWrapper/Microsoft.Azure.Devices.Edge.ClientWrapper.csproj +++ b/edge-util/src/Microsoft.Azure.Devices.Edge.ClientWrapper/Microsoft.Azure.Devices.Edge.ClientWrapper.csproj @@ -5,7 +5,7 @@ - + diff --git a/edge-util/test/Microsoft.Azure.Devices.Edge.ClientWrapper.Test/DeviceClientFactoryTest.cs b/edge-util/test/Microsoft.Azure.Devices.Edge.ClientWrapper.Test/DeviceClientFactoryTest.cs index d7a306d1363..7fbbe052518 100644 --- a/edge-util/test/Microsoft.Azure.Devices.Edge.ClientWrapper.Test/DeviceClientFactoryTest.cs +++ b/edge-util/test/Microsoft.Azure.Devices.Edge.ClientWrapper.Test/DeviceClientFactoryTest.cs @@ -15,6 +15,14 @@ public class DeviceClientFactoryTest : IClassFixture readonly byte[] sasKey = System.Text.Encoding.UTF8.GetBytes("key"); readonly string iotHubConnectionString; + const string EdgehubConnectionstringVariableName = "EdgeHubConnectionString"; + const string EdgeletUriVariableName = "IOTEDGE_IOTEDGEDURI"; + const string IotHubHostnameVariableName = "IOTEDGE_IOTHUBHOSTNAME"; + const string GatewayHostnameVariableName = "IOTEDGE_GATEWAYHOSTNAME"; + const string DeviceIdVariableName = "IOTEDGE_DEVICEID"; + const string ModuleIdVariableName = "IOTEDGE_MODULEID"; + const string AuthSchemeVariableName = "IOTEDGE_AUTHSCHEME"; + public DeviceClientFactoryTest(EdgeletFixture fixture) { this.serverUrl = fixture.ServiceUrl; @@ -24,18 +32,18 @@ public DeviceClientFactoryTest(EdgeletFixture fixture) [Fact] public void TestCreate_FromConnectionStringEnvironment_ShouldCreateClient() { - Environment.SetEnvironmentVariable("EdgeHubConnectionString", this.iotHubConnectionString); + Environment.SetEnvironmentVariable(EdgehubConnectionstringVariableName, this.iotHubConnectionString); DeviceClient dc = new DeviceClientFactory().Create(); Assert.NotNull(dc); - Environment.SetEnvironmentVariable("EdgeHubConnectionString", null); + Environment.SetEnvironmentVariable(EdgehubConnectionstringVariableName, null); } [Fact] public void TestCreate_FromConnectionStringEnvironment_SetTransportType_ShouldCreateClient() { - Environment.SetEnvironmentVariable("EdgeHubConnectionString", this.iotHubConnectionString); + Environment.SetEnvironmentVariable(EdgehubConnectionstringVariableName, this.iotHubConnectionString); DeviceClient dc = new DeviceClientFactory(TransportType.Mqtt_Tcp_Only).Create(); Assert.NotNull(dc); @@ -44,8 +52,8 @@ public void TestCreate_FromConnectionStringEnvironment_SetTransportType_ShouldCr [Fact] public void TestCreate_FromConnectionStringEnvironment_SetTransportSettings_ShouldCreateClient() { - Environment.SetEnvironmentVariable("EdgeHubConnectionString", this.iotHubConnectionString); - DeviceClient dc = new DeviceClientFactory(new ITransportSettings[1] { new MqttTransportSettings(TransportType.Mqtt_Tcp_Only) } ).Create(); + Environment.SetEnvironmentVariable(EdgehubConnectionstringVariableName, this.iotHubConnectionString); + DeviceClient dc = new DeviceClientFactory(new ITransportSettings[] { new MqttTransportSettings(TransportType.Mqtt_Tcp_Only) } ).Create(); Assert.NotNull(dc); } @@ -55,111 +63,111 @@ public void TestCreate_FromEdgeletEnvironment_MissingVariable_ShouldThrow() { Assert.Throws(() => new DeviceClientFactory().Create()); - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", this.serverUrl); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, this.serverUrl); Assert.Throws(() => new DeviceClientFactory().Create()); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", "iothub.test"); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, "iothub.test"); Assert.Throws(() => new DeviceClientFactory().Create()); - Environment.SetEnvironmentVariable("IotEdge_Gateway", "localhost"); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, "localhost"); Assert.Throws(() => new DeviceClientFactory().Create()); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", "device1"); + Environment.SetEnvironmentVariable(DeviceIdVariableName, "device1"); Assert.Throws(() => new DeviceClientFactory().Create()); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", "module1"); + Environment.SetEnvironmentVariable(ModuleIdVariableName, "module1"); Assert.Throws(() => new DeviceClientFactory().Create()); - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", null); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", null); - Environment.SetEnvironmentVariable("IotEdge_Gateway", null); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", null); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", null); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, null); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, null); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, null); + Environment.SetEnvironmentVariable(DeviceIdVariableName, null); + Environment.SetEnvironmentVariable(ModuleIdVariableName, null); } [Fact] public void TestCreate_FromEdgeletEnvironment_UnsupportedAuth_ShouldThrow() { - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", this.serverUrl); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", "iothub.test"); - Environment.SetEnvironmentVariable("IotEdge_Gateway", "localhost"); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", "device1"); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", "module1"); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, this.serverUrl); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, "iothub.test"); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, "localhost"); + Environment.SetEnvironmentVariable(DeviceIdVariableName, "device1"); + Environment.SetEnvironmentVariable(ModuleIdVariableName, "module1"); - Environment.SetEnvironmentVariable("IotEdge_AuthScheme", "x509Cert"); + Environment.SetEnvironmentVariable(AuthSchemeVariableName, "x509Cert"); Assert.Throws(() => new DeviceClientFactory().Create()); - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", null); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", null); - Environment.SetEnvironmentVariable("IotEdge_Gateway", null); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", null); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", null); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, null); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, null); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, null); + Environment.SetEnvironmentVariable(DeviceIdVariableName, null); + Environment.SetEnvironmentVariable(ModuleIdVariableName, null); } [Fact] public void TestCreate_FromEdgeletEnvironment_ShouldCreateClient() { - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", this.serverUrl); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", "iothub.test"); - Environment.SetEnvironmentVariable("IotEdge_Gateway", "localhost"); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", "device1"); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", "module1"); - Environment.SetEnvironmentVariable("IotEdge_AuthScheme", "sasToken"); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, this.serverUrl); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, "iothub.test"); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, "localhost"); + Environment.SetEnvironmentVariable(DeviceIdVariableName, "device1"); + Environment.SetEnvironmentVariable(ModuleIdVariableName, "module1"); + Environment.SetEnvironmentVariable(AuthSchemeVariableName, "sasToken"); DeviceClient dc = new DeviceClientFactory().Create(); Assert.NotNull(dc); - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", null); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", null); - Environment.SetEnvironmentVariable("IotEdge_Gateway", null); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", null); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", null); - Environment.SetEnvironmentVariable("IotEdge_AuthScheme", null); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, null); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, null); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, null); + Environment.SetEnvironmentVariable(DeviceIdVariableName, null); + Environment.SetEnvironmentVariable(ModuleIdVariableName, null); + Environment.SetEnvironmentVariable(AuthSchemeVariableName, null); } [Fact] public void TestCreate_FromEdgeletEnvironment_SetTransportType_ShouldCreateClient() { - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", this.serverUrl); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", "iothub.test"); - Environment.SetEnvironmentVariable("IotEdge_Gateway", "localhost"); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", "device1"); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", "module1"); - Environment.SetEnvironmentVariable("IotEdge_AuthScheme", "sasToken"); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, this.serverUrl); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, "iothub.test"); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, "localhost"); + Environment.SetEnvironmentVariable(DeviceIdVariableName, "device1"); + Environment.SetEnvironmentVariable(ModuleIdVariableName, "module1"); + Environment.SetEnvironmentVariable(AuthSchemeVariableName, "sasToken"); DeviceClient dc = new DeviceClientFactory(TransportType.Mqtt_Tcp_Only).Create(); Assert.NotNull(dc); - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", null); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", null); - Environment.SetEnvironmentVariable("IotEdge_Gateway", null); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", null); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", null); - Environment.SetEnvironmentVariable("IotEdge_AuthScheme", null); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, null); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, null); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, null); + Environment.SetEnvironmentVariable(DeviceIdVariableName, null); + Environment.SetEnvironmentVariable(ModuleIdVariableName, null); + Environment.SetEnvironmentVariable(AuthSchemeVariableName, null); } [Fact] public void TestCreate_FromEdgeletEnvironment_SetTransportSettings_ShouldCreateClient() { - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", this.serverUrl); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", "iothub.test"); - Environment.SetEnvironmentVariable("IotEdge_Gateway", "localhost"); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", "device1"); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", "module1"); - Environment.SetEnvironmentVariable("IotEdge_AuthScheme", "sasToken"); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, this.serverUrl); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, "iothub.test"); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, "localhost"); + Environment.SetEnvironmentVariable(DeviceIdVariableName, "device1"); + Environment.SetEnvironmentVariable(ModuleIdVariableName, "module1"); + Environment.SetEnvironmentVariable(AuthSchemeVariableName, "sasToken"); - DeviceClient dc = new DeviceClientFactory(new ITransportSettings[1] { new MqttTransportSettings(TransportType.Mqtt_Tcp_Only) }).Create(); + DeviceClient dc = new DeviceClientFactory(new ITransportSettings[] { new MqttTransportSettings(TransportType.Mqtt_Tcp_Only) }).Create(); Assert.NotNull(dc); - Environment.SetEnvironmentVariable("IotEdge_EdgeletUri", null); - Environment.SetEnvironmentVariable("IotEdge_IotHubHostname", null); - Environment.SetEnvironmentVariable("IotEdge_Gateway", null); - Environment.SetEnvironmentVariable("IotEdge_DeviceId", null); - Environment.SetEnvironmentVariable("IotEdge_ModuleId", null); - Environment.SetEnvironmentVariable("IotEdge_AuthScheme", null); + Environment.SetEnvironmentVariable(EdgeletUriVariableName, null); + Environment.SetEnvironmentVariable(IotHubHostnameVariableName, null); + Environment.SetEnvironmentVariable(GatewayHostnameVariableName, null); + Environment.SetEnvironmentVariable(DeviceIdVariableName, null); + Environment.SetEnvironmentVariable(ModuleIdVariableName, null); + Environment.SetEnvironmentVariable(AuthSchemeVariableName, null); } } }