Skip to content

Commit

Permalink
Adding RBAC support for provisioning SDK (#2262)
Browse files Browse the repository at this point in the history
* Added types for different credentials

* Altered code to work with new types

* Fixed Managers

* removed unneeded #if !NET451

* Filled in method summaries

* refactored GetHeaderProvider

* Added documentation

* Formatting fixes to address comments
  • Loading branch information
dylanbulfinMS authored Jan 10, 2022
1 parent 823fbec commit 7a26eda
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 43 deletions.
27 changes: 27 additions & 0 deletions provisioning/service/src/Auth/ProvisioningSasCredential.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Azure;
using Microsoft.Azure.Devices.Common.Service.Auth;

namespace Microsoft.Azure.Devices.Provisioning.Service.Auth
{
/// <summary>
/// Allows authentication to the API using a Shared Access Key provided by custom implementation.
/// The PnP client is auto generated from swagger and needs to implement a specific class to pass to the protocol layer
/// unlike the rest of the clients which are hand-written. So, this implementation for authentication is specific to digital twin (PnP).
/// </summary>
internal class ProvisioningSasCredential: IAuthorizationHeaderProvider
{
private readonly AzureSasCredential _azureSasCredential;

public ProvisioningSasCredential(AzureSasCredential azureSasCredential)
{
_azureSasCredential = azureSasCredential;
}

public string GetAuthorizationHeader()
{
return _azureSasCredential.Signature;
}
}
}
43 changes: 43 additions & 0 deletions provisioning/service/src/Auth/ProvisioningTokenCredential.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Threading;
using Azure.Core;
using Microsoft.Azure.Devices.Common.Service.Auth;

namespace Microsoft.Azure.Devices.Provisioning.Service.Auth
{
/// <summary>
/// Allows authentication to the API using a JWT token generated for Azure active directory.
/// The PnP client is auto generated from swagger and needs to implement a specific class to pass to the protocol layer
/// unlike the rest of the clients which are hand-written. so, this implementation for authentication is specific to digital twin (PnP).
/// </summary>
internal class ProvisioningTokenCredential : IAuthorizationHeaderProvider
{
private readonly TokenCredential _credential;
private readonly object _tokenLock = new object();
private AccessToken? _cachedAccessToken;

public ProvisioningTokenCredential(TokenCredential credential)
{
_credential = credential;
}

// The HTTP protocol uses this method to get the bearer token for authentication.
public string GetAuthorizationHeader()
{
lock (_tokenLock)
{
// A new token is generated if it is the first time or the cached token is close to expiry.
if (!_cachedAccessToken.HasValue
|| TokenHelper.IsCloseToExpiry(_cachedAccessToken.Value.ExpiresOn))
{
_cachedAccessToken = _credential.GetToken(
new TokenRequestContext(new string[] { "https://azure-devices-provisioning.net/.default" }),
new CancellationToken());
}
}

return $"Bearer {_cachedAccessToken.Value.Token}";
}
}
}
21 changes: 21 additions & 0 deletions provisioning/service/src/Auth/TokenHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;

namespace Microsoft.Azure.Devices.Provisioning.Service.Auth
{
internal static class TokenHelper
{
/// <summary>
/// Determines if the given token expiry date time is close to expiry. The date and time is
/// considered close to expiry if it has less than 10 minutes relative to the current time.
/// </summary>
/// <param name="expiry">The token expiration date and time.</param>
/// <returns>True if the token expiry has less than 10 minutes relative to the current time, otherwise false.</returns>
public static bool IsCloseToExpiry(DateTimeOffset expiry)
{
TimeSpan timeToExpiry = expiry - DateTimeOffset.UtcNow;
return timeToExpiry.TotalMinutes < 10;
}
}
}
5 changes: 3 additions & 2 deletions provisioning/service/src/Manager/EnrollmentGroupManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ await contractApiHttp.RequestAsync(
}

internal static Query CreateQuery(
ServiceConnectionString provisioningConnectionString,
string hostName,
IAuthorizationHeaderProvider headerProvider,
QuerySpecification querySpecification,
HttpTransportSettings httpTransportSettings,
CancellationToken cancellationToken,
Expand All @@ -128,7 +129,7 @@ internal static Query CreateQuery(

/* SRS_ENROLLMENT_GROUP_MANAGER_28_015: [The CreateQuery shall return a new Query for EnrollmentGroup.] */

return new Query(provisioningConnectionString, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken);
return new Query(hostName, headerProvider, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken);
}

private static Uri GetEnrollmentUri(string enrollmentGroupId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ await contractApiHttp.RequestAsync(
}

internal static Query CreateQuery(
ServiceConnectionString provisioningConnectionString,
string hostName,
IAuthorizationHeaderProvider headerProvider,
QuerySpecification querySpecification,
HttpTransportSettings httpTransportSettings,
CancellationToken cancellationToken,
Expand All @@ -168,7 +169,7 @@ internal static Query CreateQuery(
}

/* SRS_INDIVIDUAL_ENROLLMENT_MANAGER_21_015: [The CreateQuery shall return a new Query for IndividualEnrollments.] */
return new Query(provisioningConnectionString, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken);
return new Query(hostName, headerProvider, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken);
}

private static Uri GetEnrollmentUri(string registrationId)
Expand Down
6 changes: 4 additions & 2 deletions provisioning/service/src/Manager/RegistrationStatusManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ await contractApiHttp.RequestAsync(
[SuppressMessage("Microsoft.Design", "CA1068",
Justification = "Public API cannot change parameter order.")]
internal static Query CreateEnrollmentGroupQuery(
ServiceConnectionString provisioningConnectionString,
string hostName,
IAuthorizationHeaderProvider headerProvider,
QuerySpecification querySpecification,
HttpTransportSettings httpTransportSettings,
CancellationToken cancellationToken,
Expand All @@ -102,7 +103,8 @@ internal static Query CreateEnrollmentGroupQuery(

/* SRS_REGISTRATION_STATUS_MANAGER_28_010: [The CreateQuery shall return a new Query for DeviceRegistrationState.] */
return new Query(
provisioningConnectionString,
hostName,
headerProvider,
GetGetDeviceRegistrationStatus(enrollmentGroupId),
querySpecification,
httpTransportSettings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Azure.Core" Version="1.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Loading

0 comments on commit 7a26eda

Please sign in to comment.