-
Notifications
You must be signed in to change notification settings - Fork 493
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add OnBehalfOf authentication to V2 for edgehub (#3353)
* add onBehalfOf and update sas utils * added test file * fix test errors p1 * comments * unit tests * misc * variable names * misc
- Loading branch information
Showing
3 changed files
with
140 additions
and
0 deletions.
There are no files selected for viewing
60 changes: 60 additions & 0 deletions
60
iothub/device/src/Authentication/ClientAuthenticationForEdgeHubOnBehalfOf.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// 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.Threading.Tasks; | ||
|
||
namespace Microsoft.Azure.Devices.Client.Authentication | ||
{ | ||
/// <summary> | ||
/// Authentication method that generates shared access signature (SAS) token with refresh, based on a provided shared access key (SAK). | ||
/// Build for using $edgeHub in IoT Edge to authenticate on behalf of leaf devices or modules only. | ||
/// </summary> | ||
public class ClientAuthenticationForEdgeHubOnBehalfOf : ClientAuthenticationWithSharedAccessKeyRefresh | ||
{ | ||
/// <summary> | ||
/// Creates an instance of this class. | ||
/// </summary> | ||
/// <param name="sharedAccessKey">Shared access key value for the $edgehub module.</param> | ||
/// <param name="parentDeviceId">Identifier of the higher-layer parent device that connects directly to IoT Hub.</param> | ||
/// <param name="deviceId">Device identifier of the lower-layer device that authenticates through the parent IoT device.</param> | ||
/// <param name="moduleId">Module identifier.</param> | ||
/// <param name="sasTokenTimeToLive"> | ||
/// The suggested time to live value for the generated SAS tokens. | ||
/// The default value is 1 hour. | ||
/// </param> | ||
/// <param name="sasTokenRenewalBuffer"> | ||
/// The time buffer before expiry when the token should be renewed, expressed as a percentage of the time to live. | ||
/// The default behavior is that the token will be renewed when it has 15% or less of its lifespan left. | ||
/// </param> | ||
public ClientAuthenticationForEdgeHubOnBehalfOf( | ||
string sharedAccessKey, | ||
string parentDeviceId, | ||
string deviceId, | ||
string moduleId = null, | ||
TimeSpan sasTokenTimeToLive = default, | ||
int sasTokenRenewalBuffer = default) | ||
: base( | ||
sharedAccessKey, | ||
deviceId, | ||
moduleId, | ||
sasTokenTimeToLive, | ||
sasTokenRenewalBuffer) | ||
{ | ||
ParentDeviceId = parentDeviceId; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the shared access key name. | ||
/// </summary> | ||
public string ParentDeviceId { get; private set; } | ||
|
||
///<inheritdoc/> | ||
protected override Task<string> SafeCreateNewTokenAsync(string iotHub, TimeSpan suggestedTimeToLive) | ||
{ | ||
string audience = SharedAccessSignatureBuilder.BuildAudience(iotHub, ParentDeviceId, "$edgeHub"); | ||
string sasToken = SharedAccessSignatureBuilder.BuildSignature(null, SharedAccessKey, null, TimeSpan.FromMinutes(60), audience, null, null); | ||
return Task.FromResult(sasToken); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
iothub/device/tests/Authentication/EdgeDeviceOnBehalfOfTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using Microsoft.Azure.Devices.Client; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using System; | ||
using FluentAssertions; | ||
using Microsoft.Azure.Devices.Client.Authentication; | ||
|
||
namespace Microsoft.Azure.Devices.Client.Tests.OnBehalfOf | ||
{ | ||
[TestClass] | ||
public class EdgeDeviceOnBehalfOfTests | ||
{ | ||
private static string _testKey => Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.Empty.ToString("N"))); | ||
|
||
[TestMethod] | ||
[DataRow("test-edge-device", "test-leaf-device", "test-leaf-device-module")] | ||
[DataRow("test-edge-device", null, "test-edge-module")] | ||
public async Task ConnectDeviceOnBehalfOf_Amqp(string edgeDeviceId, string leafDeviceId, string edgeModuleId) | ||
{ | ||
var edgeHubCs = new IotHubConnectionString("e4k-hub.azure-devices.net", null, edgeDeviceId, edgeModuleId, null, _testKey, null); | ||
leafDeviceId ??= edgeDeviceId; | ||
|
||
IAuthenticationMethod leafAuth = new ClientAuthenticationForEdgeHubOnBehalfOf( | ||
edgeHubCs.SharedAccessKey!, | ||
edgeHubCs.DeviceId!, | ||
leafDeviceId, | ||
edgeModuleId, | ||
TimeSpan.FromMinutes(10), | ||
5); | ||
|
||
IotHubModuleClient leafClient = new(edgeHubCs.IotHubHostName, leafAuth, | ||
new IotHubClientOptions( | ||
new IotHubClientAmqpSettings | ||
{ | ||
ConnectionPoolSettings = new AmqpConnectionPoolSettings() | ||
{ | ||
UsePooling = true, | ||
MaxPoolSize = 10 | ||
} | ||
})); | ||
|
||
await leafClient.OpenAsync(); | ||
long tick = Environment.TickCount; | ||
await leafClient.UpdateReportedPropertiesAsync(new ReportedProperties { ["tick"] = tick }); | ||
var twin = await leafClient.GetTwinPropertiesAsync(); | ||
twin.Should().NotBeNull(); | ||
twin.Reported.Should().NotBeNull(); | ||
twin.Reported["tick"].Should().NotBeNull(); | ||
tick.Should().Be((long)twin.Reported["tick"]); | ||
await leafClient.CloseAsync(); | ||
await leafClient.DisposeAsync(); | ||
} | ||
} | ||
} |