Skip to content

Commit

Permalink
tests(service-client): E2E tests for aad auth on all our clients (#1800)
Browse files Browse the repository at this point in the history
  • Loading branch information
vinagesh committed Mar 22, 2021
1 parent cad4159 commit 3e65f4a
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 11 deletions.
1 change: 1 addition & 0 deletions e2e/test/E2ETests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<!-- NetCore and .NET 4.7.2 -->
<ItemGroup Condition=" '$(TargetFramework)' != 'net451' ">
<PackageReference Include="Microsoft.Azure.Storage.Blob" Version="11.1.3" />
<PackageReference Include="Azure.Identity" Version="1.3.0" />
</ItemGroup>

<ItemGroup Condition=" '$(AZURE_IOT_LOCALPACKAGES)' == '' ">
Expand Down
33 changes: 29 additions & 4 deletions e2e/test/config/Configuration.IoTHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@

using System;
using System.Security.Cryptography.X509Certificates;

#if !NET451

using Azure.Identity;

#endif

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Azure.Devices.E2ETests
Expand All @@ -14,6 +21,24 @@ public static partial class IoTHub
public static string ConnectionString => GetValue("IOTHUB_CONN_STRING_CSHARP");
public static string X509ChainDeviceName => GetValue("IOTHUB_X509_CHAIN_DEVICE_NAME");

public static string GetIotHubHostName()
{
ConnectionStringParser connectionString = new ConnectionStringParser(ConnectionString);
return connectionString.IotHubHostName;
}

#if !NET451

public static ClientSecretCredential GetClientSecretCredential()
{
return new ClientSecretCredential(
GetValue("IOTHUB_TENANT_ID"),
GetValue("IOTHUB_CLIENT_ID"),
GetValue("IOTHUB_CLIENT_SECRET"));
}

#endif

public static X509Certificate2 GetCertificateWithPrivateKey()
{
const string hubPfxCert = "IOTHUB_X509_PFX_CERTIFICATE";
Expand Down Expand Up @@ -65,9 +90,9 @@ public static X509Certificate2 GetIntermediate2Certificate()
/// </summary>
public const string InvalidProxyServerAddress = "127.0.0.1:1234";

public class DeviceConnectionStringParser
public class ConnectionStringParser
{
public DeviceConnectionStringParser(string connectionString)
public ConnectionStringParser(string connectionString)
{
string[] parts = connectionString.Split(';');
foreach (string part in parts)
Expand All @@ -77,7 +102,7 @@ public DeviceConnectionStringParser(string connectionString)
switch (tv[0].ToUpperInvariant())
{
case "HOSTNAME":
IoTHub = part.Substring("HOSTNAME=".Length);
IotHubHostName = part.Substring("HOSTNAME=".Length);
break;

case "SHAREDACCESSKEY":
Expand All @@ -94,7 +119,7 @@ public DeviceConnectionStringParser(string connectionString)
}
}

public string IoTHub
public string IotHubHostName
{
get;
private set;
Expand Down
2 changes: 1 addition & 1 deletion e2e/test/iothub/ConnectionStatusChangeHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ private async Task DeviceClient_Gives_ConnectionStatus_DeviceDisabled_Base(
TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, DevicePrefix + $"_{Guid.NewGuid()}").ConfigureAwait(false);
string deviceConnectionString = testDevice.ConnectionString;

var config = new Configuration.IoTHub.DeviceConnectionStringParser(deviceConnectionString);
var config = new Configuration.IoTHub.ConnectionStringParser(deviceConnectionString);
string deviceId = config.DeviceID;

ConnectionStatus? status = null;
Expand Down
12 changes: 6 additions & 6 deletions e2e/test/iothub/DeviceTokenRefreshE2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public async Task DeviceClient_Not_Exist_AMQP()
{
TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, DevicePrefix).ConfigureAwait(false);

var config = new Configuration.IoTHub.DeviceConnectionStringParser(testDevice.ConnectionString);
using (DeviceClient deviceClient = DeviceClient.CreateFromConnectionString($"HostName={config.IoTHub};DeviceId=device_id_not_exist;SharedAccessKey={config.SharedAccessKey}", Client.TransportType.Amqp_Tcp_Only))
var config = new Configuration.IoTHub.ConnectionStringParser(testDevice.ConnectionString);
using (DeviceClient deviceClient = DeviceClient.CreateFromConnectionString($"HostName={config.IotHubHostName};DeviceId=device_id_not_exist;SharedAccessKey={config.SharedAccessKey}", Client.TransportType.Amqp_Tcp_Only))
{
await deviceClient.OpenAsync().ConfigureAwait(false);
}
Expand All @@ -43,9 +43,9 @@ public async Task DeviceClient_Bad_Credentials_AMQP()
{
TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, DevicePrefix).ConfigureAwait(false);

var config = new Configuration.IoTHub.DeviceConnectionStringParser(testDevice.ConnectionString);
var config = new Configuration.IoTHub.ConnectionStringParser(testDevice.ConnectionString);
string invalidKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("invalid_key"));
using (DeviceClient deviceClient = DeviceClient.CreateFromConnectionString($"HostName={config.IoTHub};DeviceId={config.DeviceID};SharedAccessKey={invalidKey}", Client.TransportType.Amqp_Tcp_Only))
using (DeviceClient deviceClient = DeviceClient.CreateFromConnectionString($"HostName={config.IotHubHostName};DeviceId={config.DeviceID};SharedAccessKey={invalidKey}", Client.TransportType.Amqp_Tcp_Only))
{
await deviceClient.OpenAsync().ConfigureAwait(false);
}
Expand Down Expand Up @@ -82,8 +82,8 @@ public async Task DeviceClient_TokenConnectionDoubleRelease_Ok()

string deviceConnectionString = testDevice.ConnectionString;

var config = new Configuration.IoTHub.DeviceConnectionStringParser(deviceConnectionString);
string iotHub = config.IoTHub;
var config = new Configuration.IoTHub.ConnectionStringParser(deviceConnectionString);
string iotHub = config.IotHubHostName;
string deviceId = config.DeviceID;
string key = config.SharedAccessKey;

Expand Down
151 changes: 151 additions & 0 deletions e2e/test/iothub/TokenCredentialAuthenticationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Azure.Devices.Client;
using Microsoft.Azure.Devices.Common.Exceptions;
using Microsoft.Azure.Devices.E2ETests.Helpers;
using Microsoft.Azure.Devices.Shared;
using Microsoft.VisualStudio.TestTools.UnitTesting;

#if !NET451

using Microsoft.Rest;
using Azure.Core;
using Azure.Identity;

#endif

using ClientOptions = Microsoft.Azure.Devices.Client.ClientOptions;

namespace Microsoft.Azure.Devices.E2ETests.iothub
{
/// <summary>
/// Tests to ensure authentication using Azure active directory succeeds in all the clients.
/// </summary>
[TestClass]
[TestCategory("E2E")]
[TestCategory("IoTHub")]
public class TokenCredentialAuthenticationTests : E2EMsTestBase
{
private readonly string _devicePrefix = $"E2E_{nameof(TokenCredentialAuthenticationTests)}_";

#if !NET451

[Ignore]
[LoggedTestMethod]
public async Task RegistryManager_Http_TokenCredentialAuth_Success()
{
// arrange
using var registryManager = RegistryManager.Create(
Configuration.IoTHub.GetIotHubHostName(),
Configuration.IoTHub.GetClientSecretCredential());

var device = new Device(Guid.NewGuid().ToString());

// act
Device createdDevice = await registryManager.AddDeviceAsync(device).ConfigureAwait(false);

// assert
Assert.IsNotNull(createdDevice);

// cleanup
await registryManager.RemoveDeviceAsync(device.Id).ConfigureAwait(false);
}

[Ignore]
[LoggedTestMethod]
public async Task JobClient_Http_TokenCredentialAuth_Success()
{
// arrange
using var jobClient = JobClient.Create(
Configuration.IoTHub.GetIotHubHostName(),
Configuration.IoTHub.GetClientSecretCredential());

string jobId = "JOBSAMPLE" + Guid.NewGuid().ToString();
string jobDeviceId = "JobsSample_Device";
string query = $"DeviceId IN ['{jobDeviceId}']";
Twin twin = new Twin(jobDeviceId);

try
{
// act
JobResponse createJobResponse = await jobClient
.ScheduleTwinUpdateAsync(
jobId,
query,
twin,
DateTime.UtcNow,
(long)TimeSpan.FromMinutes(2).TotalSeconds)
.ConfigureAwait(false);
}
catch (ThrottlingException)
{
// Concurrent jobs can be rejected, but it still means authentication was successful. Ignore the exception.
}
}

[Ignore]
[LoggedTestMethod]
public async Task DigitalTwinClient_Http_TokenCredentialAuth_Success()
{
// arrange
TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, _devicePrefix).ConfigureAwait(false);
string thermostatModelId = "dtmi:com:example:TemperatureController;1";

// Create a device client instance initializing it with the "Thermostat" model.
var options = new ClientOptions
{
ModelId = thermostatModelId,
};
using DeviceClient deviceClient = testDevice.CreateDeviceClient(Client.TransportType.Mqtt, options);

// Call openAsync() to open the device's connection, so that the ModelId is sent over Mqtt CONNECT packet.
await deviceClient.OpenAsync().ConfigureAwait(false);

using var digitalTwinClient = DigitalTwinClient.Create(
Configuration.IoTHub.GetIotHubHostName(),
Configuration.IoTHub.GetClientSecretCredential());

// act
HttpOperationResponse<ThermostatTwin, DigitalTwinGetHeaders> response = await digitalTwinClient
.GetDigitalTwinAsync<ThermostatTwin>(testDevice.Id)
.ConfigureAwait(false);
ThermostatTwin twin = response.Body;

// assert
twin.Metadata.ModelId.Should().Be(thermostatModelId);

// cleanup
await testDevice.RemoveDeviceAsync().ConfigureAwait(false);
}

[Ignore]
[LoggedTestMethod]
public async Task Service_Amqp_TokenCredentialAuth_Success()
{
// arrange
TestDevice testDevice = await TestDevice.GetTestDeviceAsync(Logger, _devicePrefix).ConfigureAwait(false);
using DeviceClient deviceClient = testDevice.CreateDeviceClient(Client.TransportType.Mqtt);
await deviceClient.OpenAsync().ConfigureAwait(false);

using var serviceClient = ServiceClient.Create(
Configuration.IoTHub.GetIotHubHostName(),
Configuration.IoTHub.GetClientSecretCredential(),
TransportType.Amqp);

// act
await serviceClient.OpenAsync().ConfigureAwait(false);
using var message = new Message(Encoding.ASCII.GetBytes("Hello, Cloud!"));
await serviceClient.SendAsync(testDevice.Id, message);

// cleanup
await testDevice.RemoveDeviceAsync().ConfigureAwait(false);
}

#endif
}
}

0 comments on commit 3e65f4a

Please sign in to comment.